1 /* src/vm/optimizing/bytecode_escape.c
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.h"
33 #include "toolbox/bitvector.h"
36 #include "vm/descriptor.h"
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 if (md->params == NULL) {
779 if (! descriptor_params_from_paramtypes(md, opc == BC_invokestatic ? ACC_STATIC : 0)) {
785 /* Try to lazyly resolve method. */
787 result = resolve_method_lazy(be->method, fmi, opc == BC_invokespecial);
789 if (result == resolveSucceeded) {
792 #if BC_ESCAPE_VERBOSE
796 "Succefully resolved callee %s/%s. Recursing.\n",
797 mi->clazz->name->text,
804 #if BC_ESCAPE_VERBOSE
808 "Failed to resolve callee %s/%s.\n",
809 (IS_FMIREF_RESOLVED(fmi) ? "ERR" : fmi->p.classref->name->text),
816 /* If we could resolve the method, either reuse available escape inormation
817 or recurse into callee.
818 Otherwise we must assume, that all parameters escape. */
820 if (mi != NULL && escape_is_monomorphic(be->method, mi)) {
822 if (mi->paramescape == NULL) {
823 bc_escape_analysis_perform_intern(mi, be->depth + 1);
826 if (mi->paramescape == NULL) {
827 /* No escape information. */
828 bc_escape_analysis_escape_invoke_parameters(be, md);
830 /* Adjust escape state of parameters. */
831 bc_escape_analysis_adjust_invoke_parameters(be, mi);
835 bc_escape_analysis_escape_invoke_parameters(be, md);
839 static void bc_escape_analysis_parse_tableswitch(
840 bc_escape_analysis_t *be,
846 jcode_get_u1(jc); /* opcode */
848 jcode_align_bytecode_index(jc, 4);
850 def = jcode_get_s4(jc);
851 low = jcode_get_s4(jc);
852 high = jcode_get_s4(jc);
855 for (i = 0; i < (high - low + 1); ++i) {
856 bc_escape_analysis_branch_target(
858 jcode_get_branch_target_wide(jc)
865 static void bc_escape_analysis_parse_lookupswitch(
866 bc_escape_analysis_t *be,
872 jcode_get_u1(jc); /* opcode */
874 jcode_align_bytecode_index(jc, 4);
878 bc_escape_analysis_branch_target(
880 jcode_get_branch_target_wide(jc)
885 npairs = jcode_get_s4(jc);
887 for (i = 0; i < npairs; ++i) {
892 bc_escape_analysis_branch_target(
894 jcode_get_branch_target_wide(jc)
900 static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcode_t *jc) {
902 op_stack_slot_t value1, value2, value3, value4;
907 #if BC_ESCAPE_VERBOSE
909 dprintf(be->depth, "Processing basicblock at offset %d.\n", jcode_get_index(jc));
913 op_stack_reset(be->stack);
915 /* TODO end if all parameters escape */
916 /* TODO move code into process_instruction or the like */
918 while ((! jcode_end(jc)) && (! bb_end) && (! be->fatal_error)) {
920 jcode_record_instruction_start(jc);
922 opc = jcode_get_u1(jc);
924 length = bytecode[opc].length;
926 #if BC_ESCAPE_VERBOSE
928 dprintf(be->depth, "* %s, ", bytecode[opc].mnemonic);
929 op_stack_print(be->stack, stdout);
949 op_stack_push_unknown(be->stack);
956 op_stack_push_unknown(be->stack);
957 op_stack_push_unknown(be->stack);
962 op_stack_push_unknown(be->stack);
967 op_stack_push_unknown(be->stack);
971 op_stack_push_unknown(be->stack);
972 op_stack_push_unknown(be->stack);
985 op_stack_push_unknown(be->stack);
998 op_stack_push_unknown(be->stack);
999 op_stack_push_unknown(be->stack);
1003 op_stack_push(be->stack, bc_escape_analysis_address_local(be, jcode_get_u1(jc)));
1007 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 0));
1011 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 1));
1015 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 2));
1019 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 3));
1027 op_stack_pop(be->stack);
1028 op_stack_pop(be->stack);
1029 op_stack_push_unknown(be->stack);
1034 op_stack_pop(be->stack);
1035 op_stack_pop(be->stack);
1036 op_stack_push_unknown(be->stack);
1037 op_stack_push_unknown(be->stack);
1041 op_stack_pop(be->stack);
1042 op_stack_pop(be->stack);
1043 op_stack_push_unknown(be->stack);
1048 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1049 op_stack_pop(be->stack);
1054 bc_escape_analysis_dirty(be, 0);
1055 op_stack_pop(be->stack);
1060 bc_escape_analysis_dirty(be, 1);
1061 op_stack_pop(be->stack);
1066 bc_escape_analysis_dirty(be, 2);
1067 op_stack_pop(be->stack);
1072 bc_escape_analysis_dirty(be, 3);
1073 op_stack_pop(be->stack);
1078 bc_escape_analysis_dirty_2(be, jcode_get_u1(jc));
1079 op_stack_pop(be->stack);
1080 op_stack_pop(be->stack);
1085 bc_escape_analysis_dirty_2(be, 0);
1086 op_stack_pop(be->stack);
1087 op_stack_pop(be->stack);
1092 bc_escape_analysis_dirty_2(be, 1);
1093 op_stack_pop(be->stack);
1094 op_stack_pop(be->stack);
1099 bc_escape_analysis_dirty_2(be, 2);
1100 op_stack_pop(be->stack);
1101 op_stack_pop(be->stack);
1106 bc_escape_analysis_dirty_2(be, 3);
1107 op_stack_pop(be->stack);
1108 op_stack_pop(be->stack);
1112 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1113 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1117 bc_escape_analysis_dirty(be, 0);
1118 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1122 bc_escape_analysis_dirty(be, 1);
1123 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1127 bc_escape_analysis_dirty(be, 2);
1128 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1132 bc_escape_analysis_dirty(be, 3);
1133 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1141 op_stack_pop(be->stack);
1142 op_stack_pop(be->stack);
1143 op_stack_pop(be->stack);
1148 op_stack_pop(be->stack);
1149 op_stack_pop(be->stack);
1150 op_stack_pop(be->stack);
1151 op_stack_pop(be->stack);
1155 op_stack_pop(be->stack);
1156 op_stack_pop(be->stack);
1157 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1161 op_stack_pop(be->stack);
1165 op_stack_pop(be->stack);
1166 op_stack_pop(be->stack);
1170 value1 = op_stack_get(be->stack, 1);
1171 op_stack_push(be->stack, value1);
1175 value1 = op_stack_pop(be->stack);
1176 value2 = op_stack_pop(be->stack);
1177 op_stack_push(be->stack, value1);
1178 op_stack_push(be->stack, value2);
1179 op_stack_push(be->stack, value1);
1183 value1 = op_stack_pop(be->stack);
1184 value2 = op_stack_pop(be->stack);
1185 value3 = op_stack_pop(be->stack);
1186 op_stack_push(be->stack, value1);
1187 op_stack_push(be->stack, value3);
1188 op_stack_push(be->stack, value2);
1189 op_stack_push(be->stack, value1);
1193 value1 = op_stack_get(be->stack, 1);
1194 value2 = op_stack_get(be->stack, 2);
1195 op_stack_push(be->stack, value2);
1196 op_stack_push(be->stack, value1);
1200 value1 = op_stack_pop(be->stack);
1201 value2 = op_stack_pop(be->stack);
1202 value3 = op_stack_pop(be->stack);
1203 op_stack_push(be->stack, value2);
1204 op_stack_push(be->stack, value1);
1205 op_stack_push(be->stack, value3);
1206 op_stack_push(be->stack, value2);
1207 op_stack_push(be->stack, value1);
1211 value1 = op_stack_pop(be->stack);
1212 value2 = op_stack_pop(be->stack);
1213 value3 = op_stack_pop(be->stack);
1214 value4 = op_stack_pop(be->stack);
1215 op_stack_push(be->stack, value2);
1216 op_stack_push(be->stack, value1);
1217 op_stack_push(be->stack, value4);
1218 op_stack_push(be->stack, value3);
1219 op_stack_push(be->stack, value2);
1220 op_stack_push(be->stack, value1);
1224 value1 = op_stack_get(be->stack, 1);
1225 value2 = op_stack_get(be->stack, 2);
1226 op_stack_set(be->stack, 1, value2);
1227 op_stack_set(be->stack, 2, value1);
1245 op_stack_pop(be->stack);
1246 op_stack_pop(be->stack);
1247 op_stack_push_unknown(be->stack);
1265 op_stack_pop(be->stack);
1266 op_stack_pop(be->stack);
1267 op_stack_pop(be->stack);
1268 op_stack_pop(be->stack);
1269 op_stack_push_unknown(be->stack);
1270 op_stack_push_unknown(be->stack);
1284 op_stack_pop(be->stack);
1285 op_stack_pop(be->stack);
1286 op_stack_push_unknown(be->stack);
1292 op_stack_pop(be->stack);
1293 op_stack_pop(be->stack);
1294 /* Second operand is int. */
1295 op_stack_pop(be->stack);
1296 op_stack_push_unknown(be->stack);
1297 op_stack_push_unknown(be->stack);
1303 op_stack_pop(be->stack);
1304 op_stack_pop(be->stack);
1305 op_stack_push_unknown(be->stack);
1311 op_stack_pop(be->stack);
1312 op_stack_pop(be->stack);
1313 op_stack_pop(be->stack);
1314 op_stack_pop(be->stack);
1315 op_stack_push_unknown(be->stack);
1316 op_stack_push_unknown(be->stack);
1320 /* Not stack operation. */
1321 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1326 op_stack_pop(be->stack);
1327 op_stack_push_unknown(be->stack);
1328 op_stack_push_unknown(be->stack);
1332 op_stack_pop(be->stack);
1333 op_stack_push_unknown(be->stack);
1338 op_stack_pop(be->stack);
1339 op_stack_pop(be->stack);
1340 op_stack_push_unknown(be->stack);
1344 op_stack_pop(be->stack);
1345 op_stack_pop(be->stack);
1346 op_stack_push_unknown(be->stack);
1347 op_stack_push_unknown(be->stack);
1351 op_stack_pop(be->stack);
1352 op_stack_push_unknown(be->stack);
1357 op_stack_pop(be->stack);
1358 op_stack_push_unknown(be->stack);
1359 op_stack_push_unknown(be->stack);
1364 op_stack_pop(be->stack);
1365 op_stack_pop(be->stack);
1366 op_stack_push_unknown(be->stack);
1370 op_stack_pop(be->stack);
1371 op_stack_pop(be->stack);
1372 op_stack_push_unknown(be->stack);
1373 op_stack_push_unknown(be->stack);
1379 op_stack_pop(be->stack);
1380 op_stack_push_unknown(be->stack);
1385 op_stack_pop(be->stack);
1386 op_stack_pop(be->stack);
1387 op_stack_push_unknown(be->stack);
1393 op_stack_pop(be->stack);
1394 op_stack_pop(be->stack);
1395 op_stack_pop(be->stack);
1396 op_stack_pop(be->stack);
1397 op_stack_push_unknown(be->stack);
1406 op_stack_pop(be->stack);
1407 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1408 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1418 op_stack_pop(be->stack);
1419 op_stack_pop(be->stack);
1420 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1421 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1427 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1428 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1429 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1430 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1435 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1440 op_stack_push_unknown(be->stack);
1441 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1448 case BC_tableswitch:
1449 op_stack_pop(be->stack);
1450 jcode_rewind_instruction(jc);
1451 bc_escape_analysis_parse_tableswitch(be, jc);
1452 length = jcode_get_instruction_length(jc);
1456 case BC_lookupswitch:
1457 op_stack_pop(be->stack);
1458 jcode_rewind_instruction(jc);
1459 bc_escape_analysis_parse_lookupswitch(be, jc);
1460 length = jcode_get_instruction_length(jc);
1470 op_stack_pop(be->stack);
1476 op_stack_pop(be->stack);
1477 op_stack_pop(be->stack);
1483 bc_escape_analysis_returned(be, op_stack_pop(be->stack));
1488 op_stack_pop(be->stack);
1493 bc_escape_analysis_value_category(be, jcode_get_s2(jc)) ==
1496 op_stack_push_unknown(be->stack);
1498 op_stack_push_unknown(be->stack);
1504 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1507 op_stack_pop(be->stack);
1509 op_stack_pop(be->stack);
1510 op_stack_pop(be->stack);
1512 value2 = op_stack_pop(be->stack);
1513 value1 = op_stack_pop(be->stack);
1514 bc_escape_analysis_adjust_state(be, value2, ESCAPE_GLOBAL);
1520 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1523 op_stack_pop(be->stack);
1524 op_stack_pop(be->stack);
1526 value1 = op_stack_pop(be->stack);
1527 bc_escape_analysis_adjust_state(be, value1, ESCAPE_GLOBAL);
1531 case BC_invokevirtual:
1532 case BC_invokespecial:
1533 case BC_invokestatic:
1534 case BC_invokeinterface:
1535 jcode_rewind_instruction(jc);
1536 bc_escape_analysis_parse_invoke(be, jc);
1540 op_stack_push_unknown(be->stack);
1545 op_stack_pop(be->stack);
1546 op_stack_push_unknown(be->stack);
1549 case BC_arraylength:
1550 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1551 op_stack_push_unknown(be->stack);
1555 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1560 value1 = op_stack_get(be->stack, 1);
1561 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1565 value1 = op_stack_pop(be->stack);
1566 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1567 op_stack_push_unknown(be->stack);
1570 case BC_monitorenter:
1571 case BC_monitorexit:
1572 value1 = op_stack_pop(be->stack);
1573 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1578 /* All except iinc have a length of 4. */
1581 switch (jcode_get_u1(jc)) {
1584 op_stack_push_unknown(be->stack);
1589 op_stack_push_unknown(be->stack);
1590 op_stack_push_unknown(be->stack);
1596 bc_escape_analysis_address_local(
1605 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1606 op_stack_pop(be->stack);
1611 bc_escape_analysis_dirty_2(be, jcode_get_u2(jc));
1612 op_stack_pop(be->stack);
1613 op_stack_pop(be->stack);
1617 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1618 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1626 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1633 case BC_multianewarray:
1635 dim = jcode_get_u1(jc);
1637 op_stack_pop(be->stack);
1639 op_stack_push_unknown(be->stack);
1644 value1 = op_stack_pop(be->stack);
1645 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1646 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1647 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1652 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1657 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1670 jcode_forward_instruction_relative(jc, length);
1672 #if BC_ESCAPE_VERBOSE
1674 op_stack_print(be->stack, stdout);
1680 #if BC_ESCAPE_VERBOSE
1682 dprintf(be->depth, "Elements left on stack: %d\n", op_stack_element_count(be->stack));
1686 while ((! op_stack_is_empty(be->stack)) && (! be->fatal_error)) {
1687 #if BC_ESCAPE_VERBOSE
1689 dprintf(be->depth, "Stack element: ");
1690 op_stack_print(be->stack, stdout);
1694 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1695 #if BC_ESCAPE_VERBOSE
1697 op_stack_print(be->stack, stdout);
1703 if (be->fatal_error) {
1704 #if BC_ESCAPE_VERBOSE
1706 printf("Fatal error while processing basic block. Aborting.\n");
1713 static void bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
1714 escape_state_t re, pe;
1717 /* Only calculate, if return value is of type address. */
1719 if (be->method->parseddesc->returntype.type != TYPE_ADR) {
1723 /* If a parameter can be returned, adjust to its escape state. */
1725 for (i = 0; i < be->param_escape_size; ++i) {
1726 if (bit_vector_get(be->adr_param_returned, i)) {
1727 be->param_escape[i] |= 0x80;
1729 pe = escape_state_from_u1(be->param_escape[i]);
1730 re = escape_state_from_u1(be->param_escape[-1]);
1733 be->param_escape[-1] = escape_state_to_u1(pe);
1739 static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
1740 raw_exception_entry *itee;
1741 basicblock_work_item_t *bb;
1744 /* Add root as basic block. */
1746 bc_escape_analysis_branch_target(be, 0);
1748 /* Add each exception handler as basic block. */
1751 itee = be->method->rawexceptiontable;
1752 itee != be->method->rawexceptiontable + be->method->rawexceptiontablelength;
1755 bc_escape_analysis_branch_target(be, itee->handlerpc);
1758 /* Init jcode parser. */
1763 be->method->jcodelength,
1768 /* Process basicblock by basicblock. */
1770 for (bb = be->basicblocks->first; bb; bb = bb->next) {
1771 jcode_move_to_index(&jc, bb->bytecode_index);
1772 bc_escape_analysis_process_basicblock(
1778 /* Calculate escape of return value. */
1780 bc_escape_analysis_adjust_return_value(be);
1782 /* Export escape of parameters. */
1784 be->method->paramescape = be->param_escape;
1787 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
1788 bc_escape_analysis_t *be;
1789 bool verbose = false;
1791 #if BC_ESCAPE_VERBOSE
1795 "=== BC escape analysis of %s/%s at depth %d ===\n",
1796 m->clazz->name->text,
1807 if (m->paramescape != NULL) {
1808 #if BC_ESCAPE_VERBOSE
1810 dprintf(depth, "Escape info for method already available.\n");
1816 if ((m->flags & ACC_METHOD_EA) != 0) {
1817 #if BC_ESCAPE_VERBOSE
1819 dprintf(depth, "Detected recursion, aborting.\n");
1825 if (m->jcode == NULL) {
1826 #if BC_ESCAPE_VERBOSE
1828 dprintf(depth, "No bytecode for callee.\n");
1834 if (m->jcodelength > 250) {
1835 #if BC_ESCAPE_VERBOSE
1837 dprintf(depth, "Bytecode too long: %d.\n", m->jcodelength);
1843 be = DNEW(bc_escape_analysis_t);
1844 bc_escape_analysis_init(be, m, verbose, depth);
1846 m->flags |= ACC_METHOD_EA;
1848 bc_escape_analysis_analyze(be);
1850 #if BC_ESCAPE_VERBOSE
1854 "%s/%s: Non-escaping params: %d\n",
1855 m->clazz->name->text,
1857 be->non_escaping_adr_params
1862 m->flags &= ~ACC_METHOD_EA;
1865 void bc_escape_analysis_perform(methodinfo *m) {
1866 bc_escape_analysis_perform_intern(m, 0);