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
28 #include "mm/dumpmemory.h"
29 #include "mm/memory.h"
31 #include "toolbox/bitvector.h"
34 #include "vm/descriptor.h"
35 #include "vm/global.h"
36 #include "vm/references.h"
37 #include "vm/resolve.h"
39 #include "vm/jit/ir/bytecode.h"
40 #include "vm/jit/optimizing/escape.h"
45 #define BC_ESCAPE_VERBOSE !defined(NDEBUG)
47 /*** dprintf *****************************************************************/
49 #if BC_ESCAPE_VERBOSE && 0
50 void dprintf(int depth, const char *fmt, ...) {
64 #define dprintf(x, ...) printf(__VA_ARGS__)
66 /*** op_stack_slot **********************************************************/
69 OP_STACK_SLOT_TYPE_PARAM = 0,
70 OP_STACK_SLOT_TYPE_UNKNOWN = 1
71 } op_stack_slot_type_t;
78 const op_stack_slot_t OP_STACK_SLOT_UNKNOWN = {
79 OP_STACK_SLOT_TYPE_UNKNOWN,
83 static inline op_stack_slot_t op_stack_slot_create_param(s4 index) {
85 res.type = OP_STACK_SLOT_TYPE_PARAM;
90 static inline bool op_stack_slot_is_unknown(const op_stack_slot_t slot) {
91 return slot.type == OP_STACK_SLOT_TYPE_UNKNOWN;
94 static inline bool op_stack_slot_is_param(const op_stack_slot_t slot) {
95 return slot.type == OP_STACK_SLOT_TYPE_PARAM;
98 /*** op_stack *****************************************************************/
102 +---+---+---+---+ push 1
105 +---+---+-1-+---+ push 2
108 +---+---+-1-+-2-+ pop 2
111 +---+---+-1-+---+ pop 1
119 op_stack_slot_t *elements;
120 op_stack_slot_t *start;
121 op_stack_slot_t *end;
122 op_stack_slot_t *ptr;
123 op_stack_slot_t *bottom;
128 static void op_stack_init(op_stack_t *stack, unsigned max, bool *perror_flag) {
131 stack->elements = DMNEW(op_stack_slot_t, max * 2);
133 stack->start = stack->elements + max;
134 stack->end = stack->elements + max + max;
136 for (it = stack->elements; it != stack->start; ++it) {
137 *it = OP_STACK_SLOT_UNKNOWN;
140 stack->ptr = stack->start;
141 stack->bottom = stack->start;
143 stack->perror_flag = perror_flag;
146 static void op_stack_set_error(op_stack_t *stack) {
147 *(stack->perror_flag) = true;
148 #if BC_ESCAPE_VERBOSE
149 printf("%s: error.\n", __FUNCTION__);
153 static bool op_stack_test_position(op_stack_t *stack, op_stack_slot_t *pos) {
154 if (!(stack->elements <= pos)) {
155 op_stack_set_error(stack);
157 } else if (!(pos < stack->end)) {
158 op_stack_set_error(stack);
165 static void op_stack_reset(op_stack_t *stack) {
168 /* Clear bottom half. */
170 for (it = stack->bottom; it != stack->elements + stack->max; ++it) {
171 *it = OP_STACK_SLOT_UNKNOWN;
174 /* Reset pointers. */
176 stack->ptr = stack->start;
177 stack->bottom = stack->start;
180 static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
183 if (! op_stack_test_position(stack, stack->ptr)) {
184 return OP_STACK_SLOT_UNKNOWN;
187 if (stack->ptr < stack->bottom) {
188 stack->bottom = stack->ptr;
193 static void op_stack_push(op_stack_t *stack, op_stack_slot_t element) {
194 if (op_stack_test_position(stack, stack->ptr)) {
195 *(stack->ptr) = element;
200 static op_stack_slot_t op_stack_get(const op_stack_t *stack, int offset) {
201 if (op_stack_test_position(stack, stack->ptr - offset)) {
202 return *(stack->ptr - offset);
204 return OP_STACK_SLOT_UNKNOWN;
208 static void op_stack_set(op_stack_t *stack, int offset, op_stack_slot_t value) {
209 if (op_stack_test_position(stack, stack->ptr - offset)) {
210 *(stack->ptr - offset) = value;
214 static inline void op_stack_push_unknown(op_stack_t *stack) {
215 op_stack_push(stack, OP_STACK_SLOT_UNKNOWN);
218 static void op_stack_print(const op_stack_t *stack, FILE *f) {
222 for (it = stack->bottom; it < stack->ptr; ++it) {
223 if (it == stack->start) {
228 if (op_stack_slot_is_unknown(*it)) {
229 fprintf(f, "%c----", sep);
231 fprintf(f, "%cP%3d", sep, it->index);
238 static bool op_stack_is_empty(const op_stack_t *stack) {
239 return !(stack->bottom < stack->ptr);
242 static s4 op_stack_element_count(const op_stack_t *stack) {
243 return (stack->ptr - stack->bottom);
246 /*** bit_vector **************************************************************/
253 static void bit_vector_init(bit_vector_t *bv, s4 size) {
254 bv->bv = bv_new(size);
258 static s4 bit_vector_size(const bit_vector_t *bv) {
262 static void bit_vector_set(bit_vector_t *bv, s4 bit) {
263 assert(0 <= bit && bit < bv->size);
264 bv_set_bit(bv->bv, bit);
267 static bool bit_vector_get(const bit_vector_t *bv, s4 bit) {
268 assert(0 <= bit && bit < bv->size);
269 return bv_get_bit(bv->bv, bit);
272 /*** basicblock_work_list ***********************************************/
274 typedef struct basicblock_work_item {
276 struct basicblock_work_item *next;
277 } basicblock_work_item_t;
280 basicblock_work_item_t *first;
281 basicblock_work_item_t *last;
282 } basicblock_work_list_t;
284 void basicblock_work_list_init(basicblock_work_list_t *lst) {
289 #define FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) \
290 for ((it) = (lst)->first; (it); (it) = (it)->next)
292 void basicblock_work_list_insert(basicblock_work_list_t *lst, s4 bytecode_index) {
293 basicblock_work_item_t *it, *item;
295 /* If the destination is already present in the list, do nothing. */
297 FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) {
298 if (it->bytecode_index == bytecode_index) {
303 item = DNEW(basicblock_work_item_t);
304 item->bytecode_index = bytecode_index;
307 if (lst->first == NULL) {
311 lst->last->next = item;
316 /*** value_category *****************************************************/
323 /*** jcode **************************************************************/
329 u1 *instruction_start;
334 static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset, bool *perror_flag) {
336 jc->end = jc->start + length;
339 jc->perror_flag = perror_flag;
342 static void jcode_set_error(jcode_t *jc) {
343 *(jc->perror_flag) = true;
344 #if BC_ESCAPE_VERBOSE
345 printf("%s: error.\n", __FUNCTION__);
349 static void jcode_move_to_index(jcode_t *jc, s4 index) {
350 jc->pos = jc->start + (index - jc->offset);
353 static bool jcode_end(const jcode_t *jc) {
354 return (jc->pos >= jc->end);
357 static void jcode_record_instruction_start(jcode_t *jc) {
358 jc->instruction_start = jc->pos;
361 static void jcode_rewind_instruction(jcode_t *jc) {
362 jc->pos = jc->instruction_start;
365 static s4 jcode_get_instruction_length(const jcode_t *jc) {
366 return (jc->pos - jc->instruction_start);
369 static void jcode_align_bytecode_index(jcode_t *jc, s4 align) {
372 idx = jc->offset + (jc->pos - jc->start);
373 aidx = MEMORY_ALIGN(idx, align);
375 jc->pos += (aidx - idx);
378 static void jcode_forward_instruction_relative(jcode_t *jc, s4 n) {
379 jc->pos = jc->instruction_start + n;
382 static s4 jcode_get_index(const jcode_t *jc) {
383 return jc->offset + (jc->pos - jc->start);
386 bool jcode_test_has_bytes(jcode_t *jc, s4 n) {
387 if ((jc->pos + n) <= jc->end) {
395 static u1 jcode_get_u1(jcode_t *jc) {
397 if (jcode_test_has_bytes(jc, 1)) {
406 static s2 jcode_get_s2(jcode_t *jc) {
408 if (jcode_test_has_bytes(jc, 2)) {
409 ret = (jc->pos[0] << 8) | (jc->pos[1]);
417 static u2 jcode_get_u2(jcode_t *jc) {
419 if (jcode_test_has_bytes(jc, 2)) {
420 ret = (jc->pos[0] << 8) | (jc->pos[1]);
428 static s4 jcode_get_s4(jcode_t *jc) {
430 if (jcode_test_has_bytes(jc, 4)) {
431 ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
439 static s4 jcode_get_branch_target(jcode_t *jc) {
440 s2 off = jcode_get_s2(jc);
441 return jc->offset + (jc->instruction_start - jc->start) + off;
444 static s4 jcode_get_branch_target_wide(jcode_t *jc) {
445 s4 off = jcode_get_s4(jc);
446 return jc->offset + (jc->instruction_start - jc->start) + off;
449 static s4 jcode_get_fall_through_target(jcode_t *jc) {
450 int length = bytecode[*jc->instruction_start].length;
454 return jc->offset + (jc->instruction_start - jc->start) + length;
457 /*** bc_escape_analysis *************************************************/
462 basicblock_work_list_t *basicblocks;
464 op_stack_slot_t *local_to_adr_param;
465 s4 local_to_adr_param_size;
468 s4 param_escape_size;
470 bit_vector_t *adr_param_dirty;
471 bit_vector_t *adr_param_returned;
473 s4 non_escaping_adr_params;
475 #if BC_ESCAPE_VERBOSE
481 } bc_escape_analysis_t;
483 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth);
485 static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, bool verbose, int depth) {
496 be->stack = DNEW(op_stack_t);
497 op_stack_init(be->stack, m->maxstack, &(be->fatal_error));
499 be->basicblocks = DNEW(basicblock_work_list_t);
500 basicblock_work_list_init(be->basicblocks);
502 be->local_to_adr_param_size = m->parseddesc->paramslots;
503 be->local_to_adr_param = DMNEW(op_stack_slot_t, m->parseddesc->paramslots);
505 /* Count number of address parameters a. */
507 for (p = 0, l = 0, a = 0; p < m->parseddesc->paramcount; ++p) {
508 t = m->parseddesc->paramtypes[p].type;
510 be->local_to_adr_param[l] = op_stack_slot_create_param(a);
513 } else if (IS_2_WORD_TYPE(t)) {
514 be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
515 be->local_to_adr_param[l + 1] = OP_STACK_SLOT_UNKNOWN;
518 be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
523 assert(l == be->local_to_adr_param_size);
525 ret_val_is_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
527 /* Allocate param_escape on heap. */
529 be->param_escape_size = a;
530 n = a + ret_val_is_adr;
533 /* Use some non-NULL value. */
534 be->param_escape = (u1 *)1;
536 be->param_escape = MNEW(u1, n);
537 be->param_escape += ret_val_is_adr;
540 for (ite = be->param_escape; ite != be->param_escape + n; ++ite) {
541 *ite = escape_state_to_u1(ESCAPE_NONE);
544 if (ret_val_is_adr) {
545 be->param_escape[-1] = escape_state_to_u1(ESCAPE_NONE);
548 be->adr_param_dirty = DNEW(bit_vector_t);
549 bit_vector_init(be->adr_param_dirty, a);
551 be->adr_param_returned= DNEW(bit_vector_t);
552 bit_vector_init(be->adr_param_returned, a);
554 be->non_escaping_adr_params = be->param_escape_size;
556 #if BC_ESCAPE_VERBOSE
557 be->verbose = verbose;
562 be->fatal_error = false;
565 static void bc_escape_analysis_branch_target(bc_escape_analysis_t *be, s4 branch_target) {
566 basicblock_work_list_insert(be->basicblocks, branch_target);
569 static void bc_escape_analysis_adjust_state(
570 bc_escape_analysis_t *be,
571 op_stack_slot_t adr_param,
572 escape_state_t escape_state
576 if (op_stack_slot_is_param(adr_param)) {
577 if (0 <= adr_param.index && adr_param.index < be->param_escape_size) {
578 old = (escape_state_t)be->param_escape[adr_param.index];
579 if (old < escape_state) {
581 /* Adjust escape state. */
582 be->param_escape[adr_param.index] = (u1)escape_state;
584 /* If the parameter has just escaped, decrement number of non-escaping
588 old < ESCAPE_GLOBAL &&
589 escape_state >= ESCAPE_GLOBAL
591 be->non_escaping_adr_params -= 1;
598 static void bc_escape_analysis_dirty(bc_escape_analysis_t *be, s4 local) {
599 op_stack_slot_t adr_param;
601 if (0 <= local && local < be->local_to_adr_param_size) {
602 adr_param = be->local_to_adr_param[local];
603 if (op_stack_slot_is_param(adr_param)) {
604 bit_vector_set(be->adr_param_dirty, adr_param.index);
609 static void bc_escape_analysis_dirty_2(bc_escape_analysis_t *be, s4 local) {
610 bc_escape_analysis_dirty(be, local);
611 bc_escape_analysis_dirty(be, local + 1);
614 static void bc_escape_analysis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
615 if (op_stack_slot_is_param(value)) {
616 /* A parameter is returned, mark it as being returned. */
617 bit_vector_set(be->adr_param_returned, value.index);
618 /* The escape state of the return value will be adjusted later. */
620 /* Adjust escape state of return value. */
621 if (be->method->parseddesc->returntype.type == TYPE_ADR) {
622 be->param_escape[-1] = escape_state_to_u1(ESCAPE_GLOBAL);
624 bc_escape_analysis_adjust_state(be, value, ESCAPE_GLOBAL);
628 op_stack_slot_t bc_escape_analysis_address_local(bc_escape_analysis_t *be, s4 local) {
629 if (0 <= local && local < be->local_to_adr_param_size) {
630 return be->local_to_adr_param[local];
632 return OP_STACK_SLOT_UNKNOWN;
636 value_category_t bc_escape_analysis_value_category(bc_escape_analysis_t *be, s4 index) {
637 constant_FMIref *fmi;
638 fmi = class_getconstant(be->method->clazz, index, CONSTANT_Fieldref);
645 switch (fmi->parseddesc.fd->type) {
648 return VALUE_CATEGORY_2;
650 return VALUE_CATEGORY_1;
654 static void bc_escape_analysis_push_return_value(
655 bc_escape_analysis_t *be,
658 switch (md->returntype.type) {
661 op_stack_push_unknown(be->stack);
662 op_stack_push_unknown(be->stack);
668 op_stack_push_unknown(be->stack);
673 static void bc_escape_analysis_adjust_invoke_parameters(
674 bc_escape_analysis_t *be,
678 methoddesc *md = mi->parseddesc;
679 u1 *paramescape = mi->paramescape;
680 s4 stack_depth = md->paramslots;
681 unsigned num_params_returned = 0;
682 op_stack_slot_t param_returned;
684 /* Process parameters.
685 * The first parameter is at the highest depth on the stack.
688 for (i = 0; i < md->paramcount; ++i) {
689 switch (md->paramtypes[i].type) {
691 if (*paramescape & 0x80) {
692 num_params_returned += 1;
693 param_returned = op_stack_get(be->stack, stack_depth);
695 bc_escape_analysis_adjust_state(
697 op_stack_get(be->stack, stack_depth),
698 escape_state_from_u1(*paramescape++)
712 /* Pop all parameters. */
714 for (i = 0; i < md->paramslots; ++i) {
715 op_stack_pop(be->stack);
718 /* Push return value. */
720 if (md->returntype.type == TYPE_ADR) {
721 if ((num_params_returned == 1) && (mi->paramescape[-1] < ESCAPE_GLOBAL)) {
722 /* Only a single argument can be returned by the method,
723 and the retun value does not escape otherwise. */
724 op_stack_push(be->stack, param_returned);
726 op_stack_push_unknown(be->stack);
729 bc_escape_analysis_push_return_value(be, md);
733 static void bc_escape_analysis_escape_invoke_parameters(
734 bc_escape_analysis_t *be,
738 for (i = 0; i < md->paramslots; ++i) {
739 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
742 bc_escape_analysis_push_return_value(be, md);
745 static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *jc) {
746 constant_FMIref *fmi;
751 resolve_result_t result;
754 opc = jcode_get_u1(jc);
755 cp_index = jcode_get_u2(jc);
757 /* Get method reference */
759 if (opc == BC_invokeinterface) {
760 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_InterfaceMethodref);
762 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_Methodref);
770 md = fmi->parseddesc.md;
774 /* Parse parameters if not done yet. */
776 if (md->params == NULL) {
777 if (! descriptor_params_from_paramtypes(md, opc == BC_invokestatic ? ACC_STATIC : 0)) {
783 /* Try to lazyly resolve method. */
785 result = resolve_method_lazy(be->method, fmi, opc == BC_invokespecial);
787 if (result == resolveSucceeded) {
790 #if BC_ESCAPE_VERBOSE
794 "Succefully resolved callee %s/%s. Recursing.\n",
795 mi->clazz->name->text,
802 #if BC_ESCAPE_VERBOSE
806 "Failed to resolve callee %s/%s.\n",
807 (IS_FMIREF_RESOLVED(fmi) ? "ERR" : fmi->p.classref->name->text),
814 /* If we could resolve the method, either reuse available escape inormation
815 or recurse into callee.
816 Otherwise we must assume, that all parameters escape. */
818 if (mi != NULL && escape_is_monomorphic(be->method, mi)) {
820 if (mi->paramescape == NULL) {
821 bc_escape_analysis_perform_intern(mi, be->depth + 1);
824 if (mi->paramescape == NULL) {
825 /* No escape information. */
826 bc_escape_analysis_escape_invoke_parameters(be, md);
828 /* Adjust escape state of parameters. */
829 bc_escape_analysis_adjust_invoke_parameters(be, mi);
833 bc_escape_analysis_escape_invoke_parameters(be, md);
837 static void bc_escape_analysis_parse_tableswitch(
838 bc_escape_analysis_t *be,
844 jcode_get_u1(jc); /* opcode */
846 jcode_align_bytecode_index(jc, 4);
848 def = jcode_get_s4(jc);
849 low = jcode_get_s4(jc);
850 high = jcode_get_s4(jc);
853 for (i = 0; i < (high - low + 1); ++i) {
854 bc_escape_analysis_branch_target(
856 jcode_get_branch_target_wide(jc)
863 static void bc_escape_analysis_parse_lookupswitch(
864 bc_escape_analysis_t *be,
870 jcode_get_u1(jc); /* opcode */
872 jcode_align_bytecode_index(jc, 4);
876 bc_escape_analysis_branch_target(
878 jcode_get_branch_target_wide(jc)
883 npairs = jcode_get_s4(jc);
885 for (i = 0; i < npairs; ++i) {
890 bc_escape_analysis_branch_target(
892 jcode_get_branch_target_wide(jc)
898 static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcode_t *jc) {
900 op_stack_slot_t value1, value2, value3, value4;
905 #if BC_ESCAPE_VERBOSE
907 dprintf(be->depth, "Processing basicblock at offset %d.\n", jcode_get_index(jc));
911 op_stack_reset(be->stack);
913 /* TODO end if all parameters escape */
914 /* TODO move code into process_instruction or the like */
916 while ((! jcode_end(jc)) && (! bb_end) && (! be->fatal_error)) {
918 jcode_record_instruction_start(jc);
920 opc = jcode_get_u1(jc);
922 length = bytecode[opc].length;
924 #if BC_ESCAPE_VERBOSE
926 dprintf(be->depth, "* %s, ", bytecode[opc].mnemonic);
927 op_stack_print(be->stack, stdout);
947 op_stack_push_unknown(be->stack);
954 op_stack_push_unknown(be->stack);
955 op_stack_push_unknown(be->stack);
960 op_stack_push_unknown(be->stack);
965 op_stack_push_unknown(be->stack);
969 op_stack_push_unknown(be->stack);
970 op_stack_push_unknown(be->stack);
983 op_stack_push_unknown(be->stack);
996 op_stack_push_unknown(be->stack);
997 op_stack_push_unknown(be->stack);
1001 op_stack_push(be->stack, bc_escape_analysis_address_local(be, jcode_get_u1(jc)));
1005 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 0));
1009 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 1));
1013 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 2));
1017 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 3));
1025 op_stack_pop(be->stack);
1026 op_stack_pop(be->stack);
1027 op_stack_push_unknown(be->stack);
1032 op_stack_pop(be->stack);
1033 op_stack_pop(be->stack);
1034 op_stack_push_unknown(be->stack);
1035 op_stack_push_unknown(be->stack);
1039 op_stack_pop(be->stack);
1040 op_stack_pop(be->stack);
1041 op_stack_push_unknown(be->stack);
1046 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1047 op_stack_pop(be->stack);
1052 bc_escape_analysis_dirty(be, 0);
1053 op_stack_pop(be->stack);
1058 bc_escape_analysis_dirty(be, 1);
1059 op_stack_pop(be->stack);
1064 bc_escape_analysis_dirty(be, 2);
1065 op_stack_pop(be->stack);
1070 bc_escape_analysis_dirty(be, 3);
1071 op_stack_pop(be->stack);
1076 bc_escape_analysis_dirty_2(be, jcode_get_u1(jc));
1077 op_stack_pop(be->stack);
1078 op_stack_pop(be->stack);
1083 bc_escape_analysis_dirty_2(be, 0);
1084 op_stack_pop(be->stack);
1085 op_stack_pop(be->stack);
1090 bc_escape_analysis_dirty_2(be, 1);
1091 op_stack_pop(be->stack);
1092 op_stack_pop(be->stack);
1097 bc_escape_analysis_dirty_2(be, 2);
1098 op_stack_pop(be->stack);
1099 op_stack_pop(be->stack);
1104 bc_escape_analysis_dirty_2(be, 3);
1105 op_stack_pop(be->stack);
1106 op_stack_pop(be->stack);
1110 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1111 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1115 bc_escape_analysis_dirty(be, 0);
1116 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1120 bc_escape_analysis_dirty(be, 1);
1121 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1125 bc_escape_analysis_dirty(be, 2);
1126 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1130 bc_escape_analysis_dirty(be, 3);
1131 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1139 op_stack_pop(be->stack);
1140 op_stack_pop(be->stack);
1141 op_stack_pop(be->stack);
1146 op_stack_pop(be->stack);
1147 op_stack_pop(be->stack);
1148 op_stack_pop(be->stack);
1149 op_stack_pop(be->stack);
1153 op_stack_pop(be->stack);
1154 op_stack_pop(be->stack);
1155 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1159 op_stack_pop(be->stack);
1163 op_stack_pop(be->stack);
1164 op_stack_pop(be->stack);
1168 value1 = op_stack_get(be->stack, 1);
1169 op_stack_push(be->stack, value1);
1173 value1 = op_stack_pop(be->stack);
1174 value2 = op_stack_pop(be->stack);
1175 op_stack_push(be->stack, value1);
1176 op_stack_push(be->stack, value2);
1177 op_stack_push(be->stack, value1);
1181 value1 = op_stack_pop(be->stack);
1182 value2 = op_stack_pop(be->stack);
1183 value3 = op_stack_pop(be->stack);
1184 op_stack_push(be->stack, value1);
1185 op_stack_push(be->stack, value3);
1186 op_stack_push(be->stack, value2);
1187 op_stack_push(be->stack, value1);
1191 value1 = op_stack_get(be->stack, 1);
1192 value2 = op_stack_get(be->stack, 2);
1193 op_stack_push(be->stack, value2);
1194 op_stack_push(be->stack, value1);
1198 value1 = op_stack_pop(be->stack);
1199 value2 = op_stack_pop(be->stack);
1200 value3 = op_stack_pop(be->stack);
1201 op_stack_push(be->stack, value2);
1202 op_stack_push(be->stack, value1);
1203 op_stack_push(be->stack, value3);
1204 op_stack_push(be->stack, value2);
1205 op_stack_push(be->stack, value1);
1209 value1 = op_stack_pop(be->stack);
1210 value2 = op_stack_pop(be->stack);
1211 value3 = op_stack_pop(be->stack);
1212 value4 = op_stack_pop(be->stack);
1213 op_stack_push(be->stack, value2);
1214 op_stack_push(be->stack, value1);
1215 op_stack_push(be->stack, value4);
1216 op_stack_push(be->stack, value3);
1217 op_stack_push(be->stack, value2);
1218 op_stack_push(be->stack, value1);
1222 value1 = op_stack_get(be->stack, 1);
1223 value2 = op_stack_get(be->stack, 2);
1224 op_stack_set(be->stack, 1, value2);
1225 op_stack_set(be->stack, 2, value1);
1243 op_stack_pop(be->stack);
1244 op_stack_pop(be->stack);
1245 op_stack_push_unknown(be->stack);
1263 op_stack_pop(be->stack);
1264 op_stack_pop(be->stack);
1265 op_stack_pop(be->stack);
1266 op_stack_pop(be->stack);
1267 op_stack_push_unknown(be->stack);
1268 op_stack_push_unknown(be->stack);
1282 op_stack_pop(be->stack);
1283 op_stack_pop(be->stack);
1284 op_stack_push_unknown(be->stack);
1290 op_stack_pop(be->stack);
1291 op_stack_pop(be->stack);
1292 /* Second operand is int. */
1293 op_stack_pop(be->stack);
1294 op_stack_push_unknown(be->stack);
1295 op_stack_push_unknown(be->stack);
1301 op_stack_pop(be->stack);
1302 op_stack_pop(be->stack);
1303 op_stack_push_unknown(be->stack);
1309 op_stack_pop(be->stack);
1310 op_stack_pop(be->stack);
1311 op_stack_pop(be->stack);
1312 op_stack_pop(be->stack);
1313 op_stack_push_unknown(be->stack);
1314 op_stack_push_unknown(be->stack);
1318 /* Not stack operation. */
1319 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1324 op_stack_pop(be->stack);
1325 op_stack_push_unknown(be->stack);
1326 op_stack_push_unknown(be->stack);
1330 op_stack_pop(be->stack);
1331 op_stack_push_unknown(be->stack);
1336 op_stack_pop(be->stack);
1337 op_stack_pop(be->stack);
1338 op_stack_push_unknown(be->stack);
1342 op_stack_pop(be->stack);
1343 op_stack_pop(be->stack);
1344 op_stack_push_unknown(be->stack);
1345 op_stack_push_unknown(be->stack);
1349 op_stack_pop(be->stack);
1350 op_stack_push_unknown(be->stack);
1355 op_stack_pop(be->stack);
1356 op_stack_push_unknown(be->stack);
1357 op_stack_push_unknown(be->stack);
1362 op_stack_pop(be->stack);
1363 op_stack_pop(be->stack);
1364 op_stack_push_unknown(be->stack);
1368 op_stack_pop(be->stack);
1369 op_stack_pop(be->stack);
1370 op_stack_push_unknown(be->stack);
1371 op_stack_push_unknown(be->stack);
1377 op_stack_pop(be->stack);
1378 op_stack_push_unknown(be->stack);
1383 op_stack_pop(be->stack);
1384 op_stack_pop(be->stack);
1385 op_stack_push_unknown(be->stack);
1391 op_stack_pop(be->stack);
1392 op_stack_pop(be->stack);
1393 op_stack_pop(be->stack);
1394 op_stack_pop(be->stack);
1395 op_stack_push_unknown(be->stack);
1404 op_stack_pop(be->stack);
1405 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1406 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1416 op_stack_pop(be->stack);
1417 op_stack_pop(be->stack);
1418 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1419 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1425 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1426 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1427 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1428 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1433 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1438 op_stack_push_unknown(be->stack);
1439 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1446 case BC_tableswitch:
1447 op_stack_pop(be->stack);
1448 jcode_rewind_instruction(jc);
1449 bc_escape_analysis_parse_tableswitch(be, jc);
1450 length = jcode_get_instruction_length(jc);
1454 case BC_lookupswitch:
1455 op_stack_pop(be->stack);
1456 jcode_rewind_instruction(jc);
1457 bc_escape_analysis_parse_lookupswitch(be, jc);
1458 length = jcode_get_instruction_length(jc);
1468 op_stack_pop(be->stack);
1474 op_stack_pop(be->stack);
1475 op_stack_pop(be->stack);
1481 bc_escape_analysis_returned(be, op_stack_pop(be->stack));
1486 op_stack_pop(be->stack);
1491 bc_escape_analysis_value_category(be, jcode_get_s2(jc)) ==
1494 op_stack_push_unknown(be->stack);
1496 op_stack_push_unknown(be->stack);
1502 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1505 op_stack_pop(be->stack);
1507 op_stack_pop(be->stack);
1508 op_stack_pop(be->stack);
1510 value2 = op_stack_pop(be->stack);
1511 value1 = op_stack_pop(be->stack);
1512 bc_escape_analysis_adjust_state(be, value2, ESCAPE_GLOBAL);
1518 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1521 op_stack_pop(be->stack);
1522 op_stack_pop(be->stack);
1524 value1 = op_stack_pop(be->stack);
1525 bc_escape_analysis_adjust_state(be, value1, ESCAPE_GLOBAL);
1529 case BC_invokevirtual:
1530 case BC_invokespecial:
1531 case BC_invokestatic:
1532 case BC_invokeinterface:
1533 jcode_rewind_instruction(jc);
1534 bc_escape_analysis_parse_invoke(be, jc);
1538 op_stack_push_unknown(be->stack);
1543 op_stack_pop(be->stack);
1544 op_stack_push_unknown(be->stack);
1547 case BC_arraylength:
1548 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1549 op_stack_push_unknown(be->stack);
1553 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1558 value1 = op_stack_get(be->stack, 1);
1559 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1563 value1 = op_stack_pop(be->stack);
1564 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1565 op_stack_push_unknown(be->stack);
1568 case BC_monitorenter:
1569 case BC_monitorexit:
1570 value1 = op_stack_pop(be->stack);
1571 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1576 /* All except iinc have a length of 4. */
1579 switch (jcode_get_u1(jc)) {
1582 op_stack_push_unknown(be->stack);
1587 op_stack_push_unknown(be->stack);
1588 op_stack_push_unknown(be->stack);
1594 bc_escape_analysis_address_local(
1603 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1604 op_stack_pop(be->stack);
1609 bc_escape_analysis_dirty_2(be, jcode_get_u2(jc));
1610 op_stack_pop(be->stack);
1611 op_stack_pop(be->stack);
1615 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1616 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1624 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1631 case BC_multianewarray:
1633 dim = jcode_get_u1(jc);
1635 op_stack_pop(be->stack);
1637 op_stack_push_unknown(be->stack);
1642 value1 = op_stack_pop(be->stack);
1643 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1644 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1645 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1650 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1655 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1668 jcode_forward_instruction_relative(jc, length);
1670 #if BC_ESCAPE_VERBOSE
1672 op_stack_print(be->stack, stdout);
1678 #if BC_ESCAPE_VERBOSE
1680 dprintf(be->depth, "Elements left on stack: %d\n", op_stack_element_count(be->stack));
1684 while ((! op_stack_is_empty(be->stack)) && (! be->fatal_error)) {
1685 #if BC_ESCAPE_VERBOSE
1687 dprintf(be->depth, "Stack element: ");
1688 op_stack_print(be->stack, stdout);
1692 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1693 #if BC_ESCAPE_VERBOSE
1695 op_stack_print(be->stack, stdout);
1701 if (be->fatal_error) {
1702 #if BC_ESCAPE_VERBOSE
1704 printf("Fatal error while processing basic block. Aborting.\n");
1711 static void bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
1712 escape_state_t re, pe;
1715 /* Only calculate, if return value is of type address. */
1717 if (be->method->parseddesc->returntype.type != TYPE_ADR) {
1721 /* If a parameter can be returned, adjust to its escape state. */
1723 for (i = 0; i < be->param_escape_size; ++i) {
1724 if (bit_vector_get(be->adr_param_returned, i)) {
1725 be->param_escape[i] |= 0x80;
1727 pe = escape_state_from_u1(be->param_escape[i]);
1728 re = escape_state_from_u1(be->param_escape[-1]);
1731 be->param_escape[-1] = escape_state_to_u1(pe);
1737 static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
1738 raw_exception_entry *itee;
1739 basicblock_work_item_t *bb;
1742 /* Add root as basic block. */
1744 bc_escape_analysis_branch_target(be, 0);
1746 /* Add each exception handler as basic block. */
1749 itee = be->method->rawexceptiontable;
1750 itee != be->method->rawexceptiontable + be->method->rawexceptiontablelength;
1753 bc_escape_analysis_branch_target(be, itee->handlerpc);
1756 /* Init jcode parser. */
1761 be->method->jcodelength,
1766 /* Process basicblock by basicblock. */
1768 for (bb = be->basicblocks->first; bb; bb = bb->next) {
1769 jcode_move_to_index(&jc, bb->bytecode_index);
1770 bc_escape_analysis_process_basicblock(
1776 /* Calculate escape of return value. */
1778 bc_escape_analysis_adjust_return_value(be);
1780 /* Export escape of parameters. */
1782 be->method->paramescape = be->param_escape;
1785 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
1786 bc_escape_analysis_t *be;
1787 bool verbose = false;
1789 #if BC_ESCAPE_VERBOSE
1793 "=== BC escape analysis of %s/%s at depth %d ===\n",
1794 m->clazz->name->text,
1805 if (m->paramescape != NULL) {
1806 #if BC_ESCAPE_VERBOSE
1808 dprintf(depth, "Escape info for method already available.\n");
1814 if ((m->flags & ACC_METHOD_EA) != 0) {
1815 #if BC_ESCAPE_VERBOSE
1817 dprintf(depth, "Detected recursion, aborting.\n");
1823 if (m->jcode == NULL) {
1824 #if BC_ESCAPE_VERBOSE
1826 dprintf(depth, "No bytecode for callee.\n");
1832 if (m->jcodelength > 250) {
1833 #if BC_ESCAPE_VERBOSE
1835 dprintf(depth, "Bytecode too long: %d.\n", m->jcodelength);
1841 be = DNEW(bc_escape_analysis_t);
1842 bc_escape_analysis_init(be, m, verbose, depth);
1844 m->flags |= ACC_METHOD_EA;
1846 bc_escape_analysis_analyze(be);
1848 #if BC_ESCAPE_VERBOSE
1852 "%s/%s: Non-escaping params: %d\n",
1853 m->clazz->name->text,
1855 be->non_escaping_adr_params
1860 m->flags &= ~ACC_METHOD_EA;
1863 void bc_escape_analysis_perform(methodinfo *m) {
1864 bc_escape_analysis_perform_intern(m, 0);