1 /* src/vm/optimizing/bytecode_escape.c
3 Copyright (C) 1996-2011
4 CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 #include "mm/dumpmemory.hpp"
31 #include "mm/memory.hpp"
33 #include "toolbox/bitvector.h"
35 #include "vm/class.hpp"
36 #include "vm/descriptor.hpp"
37 #include "vm/global.h"
38 #include "vm/references.h"
39 #include "vm/resolve.hpp"
41 #include "vm/jit/ir/bytecode.h"
42 #include "vm/jit/optimizing/escape.h"
47 #define BC_ESCAPE_VERBOSE !defined(NDEBUG)
49 /*** dprintf *****************************************************************/
51 #if BC_ESCAPE_VERBOSE && 0
52 void dprintf(int depth, const char *fmt, ...) {
66 #define dprintf(x, ...) printf(__VA_ARGS__)
68 /*** op_stack_slot **********************************************************/
71 OP_STACK_SLOT_TYPE_PARAM = 0,
72 OP_STACK_SLOT_TYPE_UNKNOWN = 1
73 } op_stack_slot_type_t;
80 const op_stack_slot_t OP_STACK_SLOT_UNKNOWN = {
81 OP_STACK_SLOT_TYPE_UNKNOWN,
85 static inline op_stack_slot_t op_stack_slot_create_param(s4 index) {
87 res.type = OP_STACK_SLOT_TYPE_PARAM;
92 static inline bool op_stack_slot_is_unknown(const op_stack_slot_t slot) {
93 return slot.type == OP_STACK_SLOT_TYPE_UNKNOWN;
96 static inline bool op_stack_slot_is_param(const op_stack_slot_t slot) {
97 return slot.type == OP_STACK_SLOT_TYPE_PARAM;
100 /*** op_stack *****************************************************************/
104 +---+---+---+---+ push 1
107 +---+---+-1-+---+ push 2
110 +---+---+-1-+-2-+ pop 2
113 +---+---+-1-+---+ pop 1
121 op_stack_slot_t *elements;
122 op_stack_slot_t *start;
123 op_stack_slot_t *end;
124 op_stack_slot_t *ptr;
125 op_stack_slot_t *bottom;
130 static void op_stack_init(op_stack_t *stack, unsigned max, bool *perror_flag) {
133 stack->elements = DMNEW(op_stack_slot_t, max * 2);
135 stack->start = stack->elements + max;
136 stack->end = stack->elements + max + max;
138 for (it = stack->elements; it != stack->start; ++it) {
139 *it = OP_STACK_SLOT_UNKNOWN;
142 stack->ptr = stack->start;
143 stack->bottom = stack->start;
145 stack->perror_flag = perror_flag;
148 static void op_stack_set_error(op_stack_t *stack) {
149 *(stack->perror_flag) = true;
150 #if BC_ESCAPE_VERBOSE
151 printf("%s: error.\n", __FUNCTION__);
155 static bool op_stack_test_position(op_stack_t *stack, op_stack_slot_t *pos) {
156 if (!(stack->elements <= pos)) {
157 op_stack_set_error(stack);
159 } else if (!(pos < stack->end)) {
160 op_stack_set_error(stack);
167 static void op_stack_reset(op_stack_t *stack) {
170 /* Clear bottom half. */
172 for (it = stack->bottom; it != stack->elements + stack->max; ++it) {
173 *it = OP_STACK_SLOT_UNKNOWN;
176 /* Reset pointers. */
178 stack->ptr = stack->start;
179 stack->bottom = stack->start;
182 static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
185 if (! op_stack_test_position(stack, stack->ptr)) {
186 return OP_STACK_SLOT_UNKNOWN;
189 if (stack->ptr < stack->bottom) {
190 stack->bottom = stack->ptr;
195 static void op_stack_push(op_stack_t *stack, op_stack_slot_t element) {
196 if (op_stack_test_position(stack, stack->ptr)) {
197 *(stack->ptr) = element;
202 static op_stack_slot_t op_stack_get(const op_stack_t *stack, int offset) {
203 if (op_stack_test_position(stack, stack->ptr - offset)) {
204 return *(stack->ptr - offset);
206 return OP_STACK_SLOT_UNKNOWN;
210 static void op_stack_set(op_stack_t *stack, int offset, op_stack_slot_t value) {
211 if (op_stack_test_position(stack, stack->ptr - offset)) {
212 *(stack->ptr - offset) = value;
216 static inline void op_stack_push_unknown(op_stack_t *stack) {
217 op_stack_push(stack, OP_STACK_SLOT_UNKNOWN);
220 static void op_stack_print(const op_stack_t *stack, FILE *f) {
224 for (it = stack->bottom; it < stack->ptr; ++it) {
225 if (it == stack->start) {
230 if (op_stack_slot_is_unknown(*it)) {
231 fprintf(f, "%c----", sep);
233 fprintf(f, "%cP%3d", sep, it->index);
240 static bool op_stack_is_empty(const op_stack_t *stack) {
241 return !(stack->bottom < stack->ptr);
244 static s4 op_stack_element_count(const op_stack_t *stack) {
245 return (stack->ptr - stack->bottom);
248 /*** bit_vector **************************************************************/
255 static void bit_vector_init(bit_vector_t *bv, s4 size) {
256 bv->bv = bv_new(size);
260 static s4 bit_vector_size(const bit_vector_t *bv) {
264 static void bit_vector_set(bit_vector_t *bv, s4 bit) {
265 assert(0 <= bit && bit < bv->size);
266 bv_set_bit(bv->bv, bit);
269 static bool bit_vector_get(const bit_vector_t *bv, s4 bit) {
270 assert(0 <= bit && bit < bv->size);
271 return bv_get_bit(bv->bv, bit);
274 /*** basicblock_work_list ***********************************************/
276 typedef struct basicblock_work_item {
278 struct basicblock_work_item *next;
279 } basicblock_work_item_t;
282 basicblock_work_item_t *first;
283 basicblock_work_item_t *last;
284 } basicblock_work_list_t;
286 void basicblock_work_list_init(basicblock_work_list_t *lst) {
291 #define FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) \
292 for ((it) = (lst)->first; (it); (it) = (it)->next)
294 void basicblock_work_list_insert(basicblock_work_list_t *lst, s4 bytecode_index) {
295 basicblock_work_item_t *it, *item;
297 /* If the destination is already present in the list, do nothing. */
299 FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) {
300 if (it->bytecode_index == bytecode_index) {
305 item = DNEW(basicblock_work_item_t);
306 item->bytecode_index = bytecode_index;
309 if (lst->first == NULL) {
313 lst->last->next = item;
318 /*** value_category *****************************************************/
325 /*** jcode **************************************************************/
331 u1 *instruction_start;
336 static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset, bool *perror_flag) {
338 jc->end = jc->start + length;
341 jc->perror_flag = perror_flag;
344 static void jcode_set_error(jcode_t *jc) {
345 *(jc->perror_flag) = true;
346 #if BC_ESCAPE_VERBOSE
347 printf("%s: error.\n", __FUNCTION__);
351 static void jcode_move_to_index(jcode_t *jc, s4 index) {
352 jc->pos = jc->start + (index - jc->offset);
355 static bool jcode_end(const jcode_t *jc) {
356 return (jc->pos >= jc->end);
359 static void jcode_record_instruction_start(jcode_t *jc) {
360 jc->instruction_start = jc->pos;
363 static void jcode_rewind_instruction(jcode_t *jc) {
364 jc->pos = jc->instruction_start;
367 static s4 jcode_get_instruction_length(const jcode_t *jc) {
368 return (jc->pos - jc->instruction_start);
371 static void jcode_align_bytecode_index(jcode_t *jc, s4 align) {
374 idx = jc->offset + (jc->pos - jc->start);
375 aidx = MEMORY_ALIGN(idx, align);
377 jc->pos += (aidx - idx);
380 static void jcode_forward_instruction_relative(jcode_t *jc, s4 n) {
381 jc->pos = jc->instruction_start + n;
384 static s4 jcode_get_index(const jcode_t *jc) {
385 return jc->offset + (jc->pos - jc->start);
388 bool jcode_test_has_bytes(jcode_t *jc, s4 n) {
389 if ((jc->pos + n) <= jc->end) {
397 static u1 jcode_get_u1(jcode_t *jc) {
399 if (jcode_test_has_bytes(jc, 1)) {
408 static s2 jcode_get_s2(jcode_t *jc) {
410 if (jcode_test_has_bytes(jc, 2)) {
411 ret = (jc->pos[0] << 8) | (jc->pos[1]);
419 static u2 jcode_get_u2(jcode_t *jc) {
421 if (jcode_test_has_bytes(jc, 2)) {
422 ret = (jc->pos[0] << 8) | (jc->pos[1]);
430 static s4 jcode_get_s4(jcode_t *jc) {
432 if (jcode_test_has_bytes(jc, 4)) {
433 ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
441 static s4 jcode_get_branch_target(jcode_t *jc) {
442 s2 off = jcode_get_s2(jc);
443 return jc->offset + (jc->instruction_start - jc->start) + off;
446 static s4 jcode_get_branch_target_wide(jcode_t *jc) {
447 s4 off = jcode_get_s4(jc);
448 return jc->offset + (jc->instruction_start - jc->start) + off;
451 static s4 jcode_get_fall_through_target(jcode_t *jc) {
452 int length = bytecode[*jc->instruction_start].length;
456 return jc->offset + (jc->instruction_start - jc->start) + length;
459 /*** bc_escape_analysis *************************************************/
464 basicblock_work_list_t *basicblocks;
466 op_stack_slot_t *local_to_adr_param;
467 s4 local_to_adr_param_size;
470 s4 param_escape_size;
472 bit_vector_t *adr_param_dirty;
473 bit_vector_t *adr_param_returned;
475 s4 non_escaping_adr_params;
477 #if BC_ESCAPE_VERBOSE
483 } bc_escape_analysis_t;
485 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth);
487 static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, bool verbose, int depth) {
498 be->stack = DNEW(op_stack_t);
499 op_stack_init(be->stack, m->maxstack, &(be->fatal_error));
501 be->basicblocks = DNEW(basicblock_work_list_t);
502 basicblock_work_list_init(be->basicblocks);
504 be->local_to_adr_param_size = m->parseddesc->paramslots;
505 be->local_to_adr_param = DMNEW(op_stack_slot_t, m->parseddesc->paramslots);
507 /* Count number of address parameters a. */
509 for (p = 0, l = 0, a = 0; p < m->parseddesc->paramcount; ++p) {
510 t = m->parseddesc->paramtypes[p].type;
512 be->local_to_adr_param[l] = op_stack_slot_create_param(a);
515 } else if (IS_2_WORD_TYPE(t)) {
516 be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
517 be->local_to_adr_param[l + 1] = OP_STACK_SLOT_UNKNOWN;
520 be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
525 assert(l == be->local_to_adr_param_size);
527 ret_val_is_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
529 /* Allocate param_escape on heap. */
531 be->param_escape_size = a;
532 n = a + ret_val_is_adr;
535 /* Use some non-NULL value. */
536 be->param_escape = (u1 *)1;
538 be->param_escape = MNEW(u1, n);
539 be->param_escape += ret_val_is_adr;
542 for (ite = be->param_escape; ite != be->param_escape + n; ++ite) {
543 *ite = escape_state_to_u1(ESCAPE_NONE);
546 if (ret_val_is_adr) {
547 be->param_escape[-1] = escape_state_to_u1(ESCAPE_NONE);
550 be->adr_param_dirty = DNEW(bit_vector_t);
551 bit_vector_init(be->adr_param_dirty, a);
553 be->adr_param_returned= DNEW(bit_vector_t);
554 bit_vector_init(be->adr_param_returned, a);
556 be->non_escaping_adr_params = be->param_escape_size;
558 #if BC_ESCAPE_VERBOSE
559 be->verbose = verbose;
564 be->fatal_error = false;
567 static void bc_escape_analysis_branch_target(bc_escape_analysis_t *be, s4 branch_target) {
568 basicblock_work_list_insert(be->basicblocks, branch_target);
571 static void bc_escape_analysis_adjust_state(
572 bc_escape_analysis_t *be,
573 op_stack_slot_t adr_param,
574 escape_state_t escape_state
578 if (op_stack_slot_is_param(adr_param)) {
579 if (0 <= adr_param.index && adr_param.index < be->param_escape_size) {
580 old = (escape_state_t)be->param_escape[adr_param.index];
581 if (old < escape_state) {
583 /* Adjust escape state. */
584 be->param_escape[adr_param.index] = (u1)escape_state;
586 /* If the parameter has just escaped, decrement number of non-escaping
590 old < ESCAPE_GLOBAL &&
591 escape_state >= ESCAPE_GLOBAL
593 be->non_escaping_adr_params -= 1;
600 static void bc_escape_analysis_dirty(bc_escape_analysis_t *be, s4 local) {
601 op_stack_slot_t adr_param;
603 if (0 <= local && local < be->local_to_adr_param_size) {
604 adr_param = be->local_to_adr_param[local];
605 if (op_stack_slot_is_param(adr_param)) {
606 bit_vector_set(be->adr_param_dirty, adr_param.index);
611 static void bc_escape_analysis_dirty_2(bc_escape_analysis_t *be, s4 local) {
612 bc_escape_analysis_dirty(be, local);
613 bc_escape_analysis_dirty(be, local + 1);
616 static void bc_escape_analysis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
617 if (op_stack_slot_is_param(value)) {
618 /* A parameter is returned, mark it as being returned. */
619 bit_vector_set(be->adr_param_returned, value.index);
620 /* The escape state of the return value will be adjusted later. */
622 /* Adjust escape state of return value. */
623 if (be->method->parseddesc->returntype.type == TYPE_ADR) {
624 be->param_escape[-1] = escape_state_to_u1(ESCAPE_GLOBAL);
626 bc_escape_analysis_adjust_state(be, value, ESCAPE_GLOBAL);
630 op_stack_slot_t bc_escape_analysis_address_local(bc_escape_analysis_t *be, s4 local) {
631 if (0 <= local && local < be->local_to_adr_param_size) {
632 return be->local_to_adr_param[local];
634 return OP_STACK_SLOT_UNKNOWN;
638 value_category_t bc_escape_analysis_value_category(bc_escape_analysis_t *be, s4 index) {
639 constant_FMIref *fmi;
640 fmi = class_getconstant(be->method->clazz, index, CONSTANT_Fieldref);
647 switch (fmi->parseddesc.fd->type) {
650 return VALUE_CATEGORY_2;
652 return VALUE_CATEGORY_1;
656 static void bc_escape_analysis_push_return_value(
657 bc_escape_analysis_t *be,
660 switch (md->returntype.type) {
663 op_stack_push_unknown(be->stack);
664 op_stack_push_unknown(be->stack);
670 op_stack_push_unknown(be->stack);
675 static void bc_escape_analysis_adjust_invoke_parameters(
676 bc_escape_analysis_t *be,
680 methoddesc *md = mi->parseddesc;
681 u1 *paramescape = mi->paramescape;
682 s4 stack_depth = md->paramslots;
683 unsigned num_params_returned = 0;
684 op_stack_slot_t param_returned;
686 /* Process parameters.
687 * The first parameter is at the highest depth on the stack.
690 for (i = 0; i < md->paramcount; ++i) {
691 switch (md->paramtypes[i].type) {
693 if (*paramescape & 0x80) {
694 num_params_returned += 1;
695 param_returned = op_stack_get(be->stack, stack_depth);
697 bc_escape_analysis_adjust_state(
699 op_stack_get(be->stack, stack_depth),
700 escape_state_from_u1(*paramescape++)
714 /* Pop all parameters. */
716 for (i = 0; i < md->paramslots; ++i) {
717 op_stack_pop(be->stack);
720 /* Push return value. */
722 if (md->returntype.type == TYPE_ADR) {
723 if ((num_params_returned == 1) && (mi->paramescape[-1] < ESCAPE_GLOBAL)) {
724 /* Only a single argument can be returned by the method,
725 and the retun value does not escape otherwise. */
726 op_stack_push(be->stack, param_returned);
728 op_stack_push_unknown(be->stack);
731 bc_escape_analysis_push_return_value(be, md);
735 static void bc_escape_analysis_escape_invoke_parameters(
736 bc_escape_analysis_t *be,
740 for (i = 0; i < md->paramslots; ++i) {
741 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
744 bc_escape_analysis_push_return_value(be, md);
747 static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *jc) {
748 constant_FMIref *fmi;
753 resolve_result_t result;
756 opc = jcode_get_u1(jc);
757 cp_index = jcode_get_u2(jc);
759 /* Get method reference */
761 if (opc == BC_invokeinterface) {
762 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_InterfaceMethodref);
764 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_Methodref);
772 md = fmi->parseddesc.md;
776 /* Parse parameters if not done yet. */
778 descriptor_params_from_paramtypes(md, opc == BC_invokestatic ? ACC_STATIC : 0);
780 /* Try to lazyly resolve method. */
782 result = resolve_method_lazy(be->method, fmi, opc == BC_invokespecial);
784 if (result == resolveSucceeded) {
787 #if BC_ESCAPE_VERBOSE
791 "Succefully resolved callee %s/%s. Recursing.\n",
792 mi->clazz->name->text,
799 #if BC_ESCAPE_VERBOSE
803 "Failed to resolve callee %s/%s.\n",
804 (IS_FMIREF_RESOLVED(fmi) ? "ERR" : fmi->p.classref->name->text),
811 /* If we could resolve the method, either reuse available escape inormation
812 or recurse into callee.
813 Otherwise we must assume, that all parameters escape. */
815 if (mi != NULL && escape_is_monomorphic(be->method, mi)) {
817 if (mi->paramescape == NULL) {
818 bc_escape_analysis_perform_intern(mi, be->depth + 1);
821 if (mi->paramescape == NULL) {
822 /* No escape information. */
823 bc_escape_analysis_escape_invoke_parameters(be, md);
825 /* Adjust escape state of parameters. */
826 bc_escape_analysis_adjust_invoke_parameters(be, mi);
830 bc_escape_analysis_escape_invoke_parameters(be, md);
834 static void bc_escape_analysis_parse_tableswitch(
835 bc_escape_analysis_t *be,
841 jcode_get_u1(jc); /* opcode */
843 jcode_align_bytecode_index(jc, 4);
845 def = jcode_get_s4(jc);
846 low = jcode_get_s4(jc);
847 high = jcode_get_s4(jc);
850 for (i = 0; i < (high - low + 1); ++i) {
851 bc_escape_analysis_branch_target(
853 jcode_get_branch_target_wide(jc)
860 static void bc_escape_analysis_parse_lookupswitch(
861 bc_escape_analysis_t *be,
867 jcode_get_u1(jc); /* opcode */
869 jcode_align_bytecode_index(jc, 4);
873 bc_escape_analysis_branch_target(
875 jcode_get_branch_target_wide(jc)
880 npairs = jcode_get_s4(jc);
882 for (i = 0; i < npairs; ++i) {
887 bc_escape_analysis_branch_target(
889 jcode_get_branch_target_wide(jc)
895 static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcode_t *jc) {
897 op_stack_slot_t value1, value2, value3, value4;
902 #if BC_ESCAPE_VERBOSE
904 dprintf(be->depth, "Processing basicblock at offset %d.\n", jcode_get_index(jc));
908 op_stack_reset(be->stack);
910 /* TODO end if all parameters escape */
911 /* TODO move code into process_instruction or the like */
913 while ((! jcode_end(jc)) && (! bb_end) && (! be->fatal_error)) {
915 jcode_record_instruction_start(jc);
917 opc = jcode_get_u1(jc);
919 length = bytecode[opc].length;
921 #if BC_ESCAPE_VERBOSE
923 dprintf(be->depth, "* %s, ", bytecode[opc].mnemonic);
924 op_stack_print(be->stack, stdout);
944 op_stack_push_unknown(be->stack);
951 op_stack_push_unknown(be->stack);
952 op_stack_push_unknown(be->stack);
957 op_stack_push_unknown(be->stack);
962 op_stack_push_unknown(be->stack);
966 op_stack_push_unknown(be->stack);
967 op_stack_push_unknown(be->stack);
980 op_stack_push_unknown(be->stack);
993 op_stack_push_unknown(be->stack);
994 op_stack_push_unknown(be->stack);
998 op_stack_push(be->stack, bc_escape_analysis_address_local(be, jcode_get_u1(jc)));
1002 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 0));
1006 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 1));
1010 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 2));
1014 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 3));
1022 op_stack_pop(be->stack);
1023 op_stack_pop(be->stack);
1024 op_stack_push_unknown(be->stack);
1029 op_stack_pop(be->stack);
1030 op_stack_pop(be->stack);
1031 op_stack_push_unknown(be->stack);
1032 op_stack_push_unknown(be->stack);
1036 op_stack_pop(be->stack);
1037 op_stack_pop(be->stack);
1038 op_stack_push_unknown(be->stack);
1043 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1044 op_stack_pop(be->stack);
1049 bc_escape_analysis_dirty(be, 0);
1050 op_stack_pop(be->stack);
1055 bc_escape_analysis_dirty(be, 1);
1056 op_stack_pop(be->stack);
1061 bc_escape_analysis_dirty(be, 2);
1062 op_stack_pop(be->stack);
1067 bc_escape_analysis_dirty(be, 3);
1068 op_stack_pop(be->stack);
1073 bc_escape_analysis_dirty_2(be, jcode_get_u1(jc));
1074 op_stack_pop(be->stack);
1075 op_stack_pop(be->stack);
1080 bc_escape_analysis_dirty_2(be, 0);
1081 op_stack_pop(be->stack);
1082 op_stack_pop(be->stack);
1087 bc_escape_analysis_dirty_2(be, 1);
1088 op_stack_pop(be->stack);
1089 op_stack_pop(be->stack);
1094 bc_escape_analysis_dirty_2(be, 2);
1095 op_stack_pop(be->stack);
1096 op_stack_pop(be->stack);
1101 bc_escape_analysis_dirty_2(be, 3);
1102 op_stack_pop(be->stack);
1103 op_stack_pop(be->stack);
1107 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1108 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1112 bc_escape_analysis_dirty(be, 0);
1113 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1117 bc_escape_analysis_dirty(be, 1);
1118 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1122 bc_escape_analysis_dirty(be, 2);
1123 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1127 bc_escape_analysis_dirty(be, 3);
1128 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1136 op_stack_pop(be->stack);
1137 op_stack_pop(be->stack);
1138 op_stack_pop(be->stack);
1143 op_stack_pop(be->stack);
1144 op_stack_pop(be->stack);
1145 op_stack_pop(be->stack);
1146 op_stack_pop(be->stack);
1150 op_stack_pop(be->stack);
1151 op_stack_pop(be->stack);
1152 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1156 op_stack_pop(be->stack);
1160 op_stack_pop(be->stack);
1161 op_stack_pop(be->stack);
1165 value1 = op_stack_get(be->stack, 1);
1166 op_stack_push(be->stack, value1);
1170 value1 = op_stack_pop(be->stack);
1171 value2 = op_stack_pop(be->stack);
1172 op_stack_push(be->stack, value1);
1173 op_stack_push(be->stack, value2);
1174 op_stack_push(be->stack, value1);
1178 value1 = op_stack_pop(be->stack);
1179 value2 = op_stack_pop(be->stack);
1180 value3 = op_stack_pop(be->stack);
1181 op_stack_push(be->stack, value1);
1182 op_stack_push(be->stack, value3);
1183 op_stack_push(be->stack, value2);
1184 op_stack_push(be->stack, value1);
1188 value1 = op_stack_get(be->stack, 1);
1189 value2 = op_stack_get(be->stack, 2);
1190 op_stack_push(be->stack, value2);
1191 op_stack_push(be->stack, value1);
1195 value1 = op_stack_pop(be->stack);
1196 value2 = op_stack_pop(be->stack);
1197 value3 = op_stack_pop(be->stack);
1198 op_stack_push(be->stack, value2);
1199 op_stack_push(be->stack, value1);
1200 op_stack_push(be->stack, value3);
1201 op_stack_push(be->stack, value2);
1202 op_stack_push(be->stack, value1);
1206 value1 = op_stack_pop(be->stack);
1207 value2 = op_stack_pop(be->stack);
1208 value3 = op_stack_pop(be->stack);
1209 value4 = op_stack_pop(be->stack);
1210 op_stack_push(be->stack, value2);
1211 op_stack_push(be->stack, value1);
1212 op_stack_push(be->stack, value4);
1213 op_stack_push(be->stack, value3);
1214 op_stack_push(be->stack, value2);
1215 op_stack_push(be->stack, value1);
1219 value1 = op_stack_get(be->stack, 1);
1220 value2 = op_stack_get(be->stack, 2);
1221 op_stack_set(be->stack, 1, value2);
1222 op_stack_set(be->stack, 2, value1);
1240 op_stack_pop(be->stack);
1241 op_stack_pop(be->stack);
1242 op_stack_push_unknown(be->stack);
1260 op_stack_pop(be->stack);
1261 op_stack_pop(be->stack);
1262 op_stack_pop(be->stack);
1263 op_stack_pop(be->stack);
1264 op_stack_push_unknown(be->stack);
1265 op_stack_push_unknown(be->stack);
1279 op_stack_pop(be->stack);
1280 op_stack_pop(be->stack);
1281 op_stack_push_unknown(be->stack);
1287 op_stack_pop(be->stack);
1288 op_stack_pop(be->stack);
1289 /* Second operand is int. */
1290 op_stack_pop(be->stack);
1291 op_stack_push_unknown(be->stack);
1292 op_stack_push_unknown(be->stack);
1298 op_stack_pop(be->stack);
1299 op_stack_pop(be->stack);
1300 op_stack_push_unknown(be->stack);
1306 op_stack_pop(be->stack);
1307 op_stack_pop(be->stack);
1308 op_stack_pop(be->stack);
1309 op_stack_pop(be->stack);
1310 op_stack_push_unknown(be->stack);
1311 op_stack_push_unknown(be->stack);
1315 /* Not stack operation. */
1316 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1321 op_stack_pop(be->stack);
1322 op_stack_push_unknown(be->stack);
1323 op_stack_push_unknown(be->stack);
1327 op_stack_pop(be->stack);
1328 op_stack_push_unknown(be->stack);
1333 op_stack_pop(be->stack);
1334 op_stack_pop(be->stack);
1335 op_stack_push_unknown(be->stack);
1339 op_stack_pop(be->stack);
1340 op_stack_pop(be->stack);
1341 op_stack_push_unknown(be->stack);
1342 op_stack_push_unknown(be->stack);
1346 op_stack_pop(be->stack);
1347 op_stack_push_unknown(be->stack);
1352 op_stack_pop(be->stack);
1353 op_stack_push_unknown(be->stack);
1354 op_stack_push_unknown(be->stack);
1359 op_stack_pop(be->stack);
1360 op_stack_pop(be->stack);
1361 op_stack_push_unknown(be->stack);
1365 op_stack_pop(be->stack);
1366 op_stack_pop(be->stack);
1367 op_stack_push_unknown(be->stack);
1368 op_stack_push_unknown(be->stack);
1374 op_stack_pop(be->stack);
1375 op_stack_push_unknown(be->stack);
1380 op_stack_pop(be->stack);
1381 op_stack_pop(be->stack);
1382 op_stack_push_unknown(be->stack);
1388 op_stack_pop(be->stack);
1389 op_stack_pop(be->stack);
1390 op_stack_pop(be->stack);
1391 op_stack_pop(be->stack);
1392 op_stack_push_unknown(be->stack);
1401 op_stack_pop(be->stack);
1402 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1403 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1413 op_stack_pop(be->stack);
1414 op_stack_pop(be->stack);
1415 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1416 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1422 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1423 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1424 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1425 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1430 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1435 op_stack_push_unknown(be->stack);
1436 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1443 case BC_tableswitch:
1444 op_stack_pop(be->stack);
1445 jcode_rewind_instruction(jc);
1446 bc_escape_analysis_parse_tableswitch(be, jc);
1447 length = jcode_get_instruction_length(jc);
1451 case BC_lookupswitch:
1452 op_stack_pop(be->stack);
1453 jcode_rewind_instruction(jc);
1454 bc_escape_analysis_parse_lookupswitch(be, jc);
1455 length = jcode_get_instruction_length(jc);
1465 op_stack_pop(be->stack);
1471 op_stack_pop(be->stack);
1472 op_stack_pop(be->stack);
1478 bc_escape_analysis_returned(be, op_stack_pop(be->stack));
1483 op_stack_pop(be->stack);
1488 bc_escape_analysis_value_category(be, jcode_get_s2(jc)) ==
1491 op_stack_push_unknown(be->stack);
1493 op_stack_push_unknown(be->stack);
1499 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1502 op_stack_pop(be->stack);
1504 op_stack_pop(be->stack);
1505 op_stack_pop(be->stack);
1507 value2 = op_stack_pop(be->stack);
1508 value1 = op_stack_pop(be->stack);
1509 bc_escape_analysis_adjust_state(be, value2, ESCAPE_GLOBAL);
1515 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1518 op_stack_pop(be->stack);
1519 op_stack_pop(be->stack);
1521 value1 = op_stack_pop(be->stack);
1522 bc_escape_analysis_adjust_state(be, value1, ESCAPE_GLOBAL);
1526 case BC_invokevirtual:
1527 case BC_invokespecial:
1528 case BC_invokestatic:
1529 case BC_invokeinterface:
1530 jcode_rewind_instruction(jc);
1531 bc_escape_analysis_parse_invoke(be, jc);
1535 op_stack_push_unknown(be->stack);
1540 op_stack_pop(be->stack);
1541 op_stack_push_unknown(be->stack);
1544 case BC_arraylength:
1545 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1546 op_stack_push_unknown(be->stack);
1550 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1555 value1 = op_stack_get(be->stack, 1);
1556 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1560 value1 = op_stack_pop(be->stack);
1561 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1562 op_stack_push_unknown(be->stack);
1565 case BC_monitorenter:
1566 case BC_monitorexit:
1567 value1 = op_stack_pop(be->stack);
1568 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1573 /* All except iinc have a length of 4. */
1576 switch (jcode_get_u1(jc)) {
1579 op_stack_push_unknown(be->stack);
1584 op_stack_push_unknown(be->stack);
1585 op_stack_push_unknown(be->stack);
1591 bc_escape_analysis_address_local(
1600 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1601 op_stack_pop(be->stack);
1606 bc_escape_analysis_dirty_2(be, jcode_get_u2(jc));
1607 op_stack_pop(be->stack);
1608 op_stack_pop(be->stack);
1612 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1613 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1621 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1628 case BC_multianewarray:
1630 dim = jcode_get_u1(jc);
1632 op_stack_pop(be->stack);
1634 op_stack_push_unknown(be->stack);
1639 value1 = op_stack_pop(be->stack);
1640 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1641 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1642 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1647 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1652 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1665 jcode_forward_instruction_relative(jc, length);
1667 #if BC_ESCAPE_VERBOSE
1669 op_stack_print(be->stack, stdout);
1675 #if BC_ESCAPE_VERBOSE
1677 dprintf(be->depth, "Elements left on stack: %d\n", op_stack_element_count(be->stack));
1681 while ((! op_stack_is_empty(be->stack)) && (! be->fatal_error)) {
1682 #if BC_ESCAPE_VERBOSE
1684 dprintf(be->depth, "Stack element: ");
1685 op_stack_print(be->stack, stdout);
1689 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1690 #if BC_ESCAPE_VERBOSE
1692 op_stack_print(be->stack, stdout);
1698 if (be->fatal_error) {
1699 #if BC_ESCAPE_VERBOSE
1701 printf("Fatal error while processing basic block. Aborting.\n");
1708 static void bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
1709 escape_state_t re, pe;
1712 /* Only calculate, if return value is of type address. */
1714 if (be->method->parseddesc->returntype.type != TYPE_ADR) {
1718 /* If a parameter can be returned, adjust to its escape state. */
1720 for (i = 0; i < be->param_escape_size; ++i) {
1721 if (bit_vector_get(be->adr_param_returned, i)) {
1722 be->param_escape[i] |= 0x80;
1724 pe = escape_state_from_u1(be->param_escape[i]);
1725 re = escape_state_from_u1(be->param_escape[-1]);
1728 be->param_escape[-1] = escape_state_to_u1(pe);
1734 static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
1735 raw_exception_entry *itee;
1736 basicblock_work_item_t *bb;
1739 /* Add root as basic block. */
1741 bc_escape_analysis_branch_target(be, 0);
1743 /* Add each exception handler as basic block. */
1746 itee = be->method->rawexceptiontable;
1747 itee != be->method->rawexceptiontable + be->method->rawexceptiontablelength;
1750 bc_escape_analysis_branch_target(be, itee->handlerpc);
1753 /* Init jcode parser. */
1758 be->method->jcodelength,
1763 /* Process basicblock by basicblock. */
1765 for (bb = be->basicblocks->first; bb; bb = bb->next) {
1766 jcode_move_to_index(&jc, bb->bytecode_index);
1767 bc_escape_analysis_process_basicblock(
1773 /* Calculate escape of return value. */
1775 bc_escape_analysis_adjust_return_value(be);
1777 /* Export escape of parameters. */
1779 be->method->paramescape = be->param_escape;
1782 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
1783 bc_escape_analysis_t *be;
1784 bool verbose = false;
1786 #if BC_ESCAPE_VERBOSE
1790 "=== BC escape analysis of %s/%s at depth %d ===\n",
1791 m->clazz->name->text,
1802 if (m->paramescape != NULL) {
1803 #if BC_ESCAPE_VERBOSE
1805 dprintf(depth, "Escape info for method already available.\n");
1811 if ((m->flags & ACC_METHOD_EA) != 0) {
1812 #if BC_ESCAPE_VERBOSE
1814 dprintf(depth, "Detected recursion, aborting.\n");
1820 if (m->jcode == NULL) {
1821 #if BC_ESCAPE_VERBOSE
1823 dprintf(depth, "No bytecode for callee.\n");
1829 if (m->jcodelength > 250) {
1830 #if BC_ESCAPE_VERBOSE
1832 dprintf(depth, "Bytecode too long: %d.\n", m->jcodelength);
1838 be = DNEW(bc_escape_analysis_t);
1839 bc_escape_analysis_init(be, m, verbose, depth);
1841 m->flags |= ACC_METHOD_EA;
1843 bc_escape_analysis_analyze(be);
1845 #if BC_ESCAPE_VERBOSE
1849 "%s/%s: Non-escaping params: %d\n",
1850 m->clazz->name->text,
1852 be->non_escaping_adr_params
1857 m->flags &= ~ACC_METHOD_EA;
1860 void bc_escape_analysis_perform(methodinfo *m) {
1861 bc_escape_analysis_perform_intern(m, 0);
1867 * These are local overrides for various environment variables in Emacs.
1868 * Please do not remove this and leave it at the end of the file, where
1869 * Emacs will automagically detect them.
1870 * ---------------------------------------------------------------------
1873 * indent-tabs-mode: t
1877 * vim:noexpandtab:sw=4:ts=4: