1 #include "mm/dumpmemory.h"
4 #include "toolbox/bitvector.h"
7 #include "vm/jit/ir/bytecode.h"
8 #include "vm/jit/optimizing/escape.h"
9 #include "vm/resolve.h"
11 #include "vmcore/class.h"
12 #include "vmcore/descriptor.h"
13 #include "vmcore/references.h"
18 #define BC_ESCAPE_VERBOSE !defined(NDEBUG)
20 /*** dprintf *****************************************************************/
22 #if BC_ESCAPE_VERBOSE && 0
23 void dprintf(int depth, const char *fmt, ...) {
37 #define dprintf(x, ...) printf(__VA_ARGS__)
39 /*** op_stack_slot **********************************************************/
42 OP_STACK_SLOT_TYPE_PARAM = 0,
43 OP_STACK_SLOT_TYPE_UNKNOWN = 1
44 } op_stack_slot_type_t;
51 const op_stack_slot_t OP_STACK_SLOT_UNKNOWN = {
52 OP_STACK_SLOT_TYPE_UNKNOWN,
56 static inline op_stack_slot_t op_stack_slot_create_param(s4 index) {
58 res.type = OP_STACK_SLOT_TYPE_PARAM;
63 static inline bool op_stack_slot_is_unknown(const op_stack_slot_t slot) {
64 return slot.type == OP_STACK_SLOT_TYPE_UNKNOWN;
67 static inline bool op_stack_slot_is_param(const op_stack_slot_t slot) {
68 return slot.type == OP_STACK_SLOT_TYPE_PARAM;
71 /*** op_stack *****************************************************************/
75 +---+---+---+---+ push 1
78 +---+---+-1-+---+ push 2
81 +---+---+-1-+-2-+ pop 2
84 +---+---+-1-+---+ pop 1
92 op_stack_slot_t *elements;
93 op_stack_slot_t *start;
96 op_stack_slot_t *bottom;
100 #define stack_assert_position(stack, pos) \
102 assert((stack)->elements <= (pos)); \
103 assert((pos) < (stack)->end); \
106 static void op_stack_init(op_stack_t *stack, unsigned max) {
109 stack->elements = DMNEW(op_stack_slot_t, max * 2);
111 stack->start = stack->elements + max;
112 stack->end = stack->elements + max + max;
114 for (it = stack->elements; it != stack->start; ++it) {
115 *it = OP_STACK_SLOT_UNKNOWN;
118 stack->ptr = stack->start;
119 stack->bottom = stack->start;
122 static void op_stack_reset(op_stack_t *stack) {
125 /* Clear bottom half. */
127 for (it = stack->bottom; it != stack->elements + stack->max; ++it) {
128 *it = OP_STACK_SLOT_UNKNOWN;
131 /* Reset pointers. */
133 stack->ptr = stack->start;
134 stack->bottom = stack->start;
137 static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
140 stack_assert_position(stack, stack->ptr);
142 if (stack->ptr < stack->bottom) {
143 stack->bottom = stack->ptr;
148 static void op_stack_push(op_stack_t *stack, op_stack_slot_t element) {
149 stack_assert_position(stack, stack->ptr);
150 *(stack->ptr) = element;
154 static op_stack_slot_t op_stack_get(const op_stack_t *stack, int offset) {
155 stack_assert_position(stack, stack->ptr - offset);
156 return *(stack->ptr - offset);
159 static void op_stack_set(op_stack_t *stack, int offset, op_stack_slot_t value) {
160 stack_assert_position(stack, stack->ptr - offset);
161 *(stack->ptr - offset) = value;
164 static inline void op_stack_push_unknown(op_stack_t *stack) {
165 op_stack_push(stack, OP_STACK_SLOT_UNKNOWN);
168 static void op_stack_print(const op_stack_t *stack, FILE *f) {
172 for (it = stack->bottom; it < stack->ptr; ++it) {
173 if (it == stack->start) {
178 if (op_stack_slot_is_unknown(*it)) {
179 fprintf(f, "%c----", sep);
181 fprintf(f, "%cP%3d", sep, it->index);
188 static bool op_stack_is_empty(const op_stack_t *stack) {
189 return !(stack->bottom < stack->ptr);
192 static s4 op_stack_element_count(const op_stack_t *stack) {
193 return (stack->ptr - stack->bottom);
196 /*** bit_vector **************************************************************/
203 static void bit_vector_init(bit_vector_t *bv, s4 size) {
204 bv->bv = bv_new(size);
208 static s4 bit_vector_size(const bit_vector_t *bv) {
212 static void bit_vector_set(bit_vector_t *bv, s4 bit) {
213 assert(0 <= bit && bit < bv->size);
214 bv_set_bit(bv->bv, bit);
217 static bool bit_vector_get(const bit_vector_t *bv, s4 bit) {
218 assert(0 <= bit && bit < bv->size);
219 return bv_get_bit(bv->bv, bit);
222 /*** basicblock_work_list ***********************************************/
224 typedef struct basicblock_work_item {
226 struct basicblock_work_item *next;
227 } basicblock_work_item_t;
230 basicblock_work_item_t *first;
231 basicblock_work_item_t *last;
232 } basicblock_work_list_t;
234 void basicblock_work_list_init(basicblock_work_list_t *lst) {
239 #define FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) \
240 for ((it) = (lst)->first; (it); (it) = (it)->next)
242 void basicblock_work_list_insert(basicblock_work_list_t *lst, s4 bytecode_index) {
243 basicblock_work_item_t *it, *item;
245 /* If the destination is already present in the list, do nothing. */
247 FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) {
248 if (it->bytecode_index == bytecode_index) {
253 item = DNEW(basicblock_work_item_t);
254 item->bytecode_index = bytecode_index;
257 if (lst->first == NULL) {
261 lst->last->next = item;
266 /*** value_category *****************************************************/
273 /*** jcode **************************************************************/
279 u1 *instruction_start;
283 static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset) {
285 jc->end = jc->start + length;
290 static void jcode_move_to_index(jcode_t *jc, s4 index) {
291 jc->pos = jc->start + (index - jc->offset);
294 static bool jcode_end(const jcode_t *jc) {
295 return (jc->pos >= jc->end);
298 static void jcode_record_instruction_start(jcode_t *jc) {
299 jc->instruction_start = jc->pos;
302 static void jcode_rewind_instruction(jcode_t *jc) {
303 jc->pos = jc->instruction_start;
306 static s4 jcode_get_instruction_length(const jcode_t *jc) {
307 return (jc->pos - jc->instruction_start);
310 static void jcode_align_bytecode_index(jcode_t *jc, s4 align) {
313 idx = jc->offset + (jc->pos - jc->start);
314 aidx = MEMORY_ALIGN(idx, align);
316 jc->pos += (aidx - idx);
319 static void jcode_forward_instruction_relative(jcode_t *jc, s4 n) {
320 jc->pos = jc->instruction_start + n;
323 static s4 jcode_get_index(const jcode_t *jc) {
324 return jc->offset + (jc->pos - jc->start);
327 #define jcode_assert_has_bytes(jc, n) \
328 assert((jc->pos + n) <= jc->end)
330 static u1 jcode_get_u1(jcode_t *jc) {
332 jcode_assert_has_bytes(jc, 1);
338 static s2 jcode_get_s2(jcode_t *jc) {
340 jcode_assert_has_bytes(jc, 2);
341 ret = (jc->pos[0] << 8) | (jc->pos[1]);
346 static u2 jcode_get_u2(jcode_t *jc) {
348 jcode_assert_has_bytes(jc, 2);
349 ret = (jc->pos[0] << 8) | (jc->pos[1]);
354 static s4 jcode_get_s4(jcode_t *jc) {
356 jcode_assert_has_bytes(jc, 4);
357 ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
362 static s4 jcode_get_branch_target(jcode_t *jc) {
363 s2 off = jcode_get_s2(jc);
364 return jc->offset + (jc->instruction_start - jc->start) + off;
367 static s4 jcode_get_branch_target_wide(jcode_t *jc) {
368 s4 off = jcode_get_s4(jc);
369 return jc->offset + (jc->instruction_start - jc->start) + off;
372 static s4 jcode_get_fall_through_target(jcode_t *jc) {
373 int length = bytecode[*jc->instruction_start].length;
375 return jc->offset + (jc->instruction_start - jc->start) + length;
378 /*** bc_escape_analysis *************************************************/
383 basicblock_work_list_t *basicblocks;
385 op_stack_slot_t *local_to_adr_param;
386 s4 local_to_adr_param_size;
389 s4 param_escape_size;
391 bit_vector_t *adr_param_dirty;
392 bit_vector_t *adr_param_returned;
394 s4 non_escaping_adr_params;
396 #if BC_ESCAPE_VERBOSE
400 } bc_escape_analysis_t;
402 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth);
404 static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, bool verbose, int depth) {
415 be->stack = DNEW(op_stack_t);
416 op_stack_init(be->stack, m->maxstack);
418 be->basicblocks = DNEW(basicblock_work_list_t);
419 basicblock_work_list_init(be->basicblocks);
421 be->local_to_adr_param_size = m->parseddesc->paramslots;
422 be->local_to_adr_param = DMNEW(op_stack_slot_t, m->parseddesc->paramslots);
424 /* Count number of address parameters a. */
426 for (p = 0, l = 0, a = 0; p < m->parseddesc->paramcount; ++p) {
427 t = m->parseddesc->paramtypes[p].type;
429 be->local_to_adr_param[l] = op_stack_slot_create_param(a);
432 } else if (IS_2_WORD_TYPE(t)) {
433 be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
434 be->local_to_adr_param[l + 1] = OP_STACK_SLOT_UNKNOWN;
437 be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
442 assert(l == be->local_to_adr_param_size);
444 /* Determine whether return type is address */
446 ret_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
448 /* Allocate param_escape on heap. */
450 be->param_escape_size = a;
454 /* Use some non-NULL value. */
455 be->param_escape = (u1 *)1;
457 be->param_escape = MNEW(u1, n);
460 for (ite = be->param_escape; ite != be->param_escape + n; ++ite) {
461 *ite = (u1)ESCAPE_NONE;
464 be->param_escape += ret_adr;
466 be->adr_param_dirty = DNEW(bit_vector_t);
467 bit_vector_init(be->adr_param_dirty, a);
469 be->adr_param_returned= DNEW(bit_vector_t);
470 bit_vector_init(be->adr_param_returned, a);
472 be->non_escaping_adr_params = be->param_escape_size;
474 #if BC_ESCAPE_VERBOSE
475 be->verbose = verbose;
481 static void bc_escape_analysis_branch_target(bc_escape_analysis_t *be, s4 branch_target) {
482 basicblock_work_list_insert(be->basicblocks, branch_target);
485 static void bc_escape_analysis_adjust_state(
486 bc_escape_analysis_t *be,
487 op_stack_slot_t adr_param,
488 escape_state_t escape_state
492 if (op_stack_slot_is_param(adr_param)) {
493 if (0 <= adr_param.index && adr_param.index < be->param_escape_size) {
494 old = (escape_state_t)be->param_escape[adr_param.index];
495 if (old < escape_state) {
497 /* Adjust escape state. */
498 be->param_escape[adr_param.index] = (u1)escape_state;
500 /* If the parameter has just escaped, decrement number of non-escaping
504 old < ESCAPE_GLOBAL_THROUGH_METHOD &&
505 escape_state >= ESCAPE_GLOBAL_THROUGH_METHOD
507 be->non_escaping_adr_params -= 1;
514 static void bc_escape_analysis_dirty(bc_escape_analysis_t *be, s4 local) {
515 op_stack_slot_t adr_param;
517 if (0 <= local && local < be->local_to_adr_param_size) {
518 adr_param = be->local_to_adr_param[local];
519 if (op_stack_slot_is_param(adr_param)) {
520 bit_vector_set(be->adr_param_dirty, adr_param.index);
525 static void bc_escape_analysis_dirty_2(bc_escape_analysis_t *be, s4 local) {
526 bc_escape_analysis_dirty(be, local);
527 bc_escape_analysis_dirty(be, local + 1);
530 static void bc_escape_analyisis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
531 if (op_stack_slot_is_param(value)) {
532 /* A parameter is returned, mark it as being returned. */
533 bit_vector_set(be->adr_param_returned, value.index);
534 } else if (op_stack_slot_is_unknown(value)) {
535 /* An untracked value is returned.
536 Conservatively asume a globally escaping value is returned. */
537 if (be->method->parseddesc->returntype.type == TYPE_ADR) {
538 be->param_escape[-1] = (u1)ESCAPE_GLOBAL;
543 op_stack_slot_t bc_escape_analysis_address_local(bc_escape_analysis_t *be, s4 local) {
544 if (0 <= local && local < be->local_to_adr_param_size) {
545 return be->local_to_adr_param[local];
547 return OP_STACK_SLOT_UNKNOWN;
551 value_category_t bc_escape_analysis_value_category(bc_escape_analysis_t *be, s4 index) {
552 constant_FMIref *fmi;
553 fmi = class_getconstant(be->method->clazz, index, CONSTANT_Fieldref);
560 switch (fmi->parseddesc.fd->type) {
563 return VALUE_CATEGORY_2;
565 return VALUE_CATEGORY_1;
569 static void bc_escape_analysis_adjust_invoke_parameters(
570 bc_escape_analysis_t *be,
574 methoddesc *md = mi->parseddesc;
575 u1 *paramescape = mi->paramescape;
576 s4 stack_depth = md->paramslots;
578 /* Process parameters.
579 * The first parameter is at the highest depth on the stack.
582 for (i = 0; i < md->paramcount; ++i) {
583 switch (md->paramtypes[i].type) {
585 bc_escape_analysis_adjust_state(
587 op_stack_get(be->stack, stack_depth),
588 (escape_state_t)*(paramescape++)
602 /* Pop all parameters. */
604 for (i = 0; i < md->paramslots; ++i) {
605 op_stack_pop(be->stack);
610 static void bc_escape_analysis_escape_invoke_parameters(
611 bc_escape_analysis_t *be,
615 for (i = 0; i < md->paramslots; ++i) {
616 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
620 static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *jc) {
621 constant_FMIref *fmi;
626 resolve_result_t result;
629 opc = jcode_get_u1(jc);
630 cp_index = jcode_get_u2(jc);
632 /* Get method reference */
634 if (opc == BC_invokeinterface) {
635 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_InterfaceMethodref);
637 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_Methodref);
645 md = fmi->parseddesc.md;
649 /* Parse parameters if not done yet. */
651 if (md->params == NULL) {
652 if (! descriptor_params_from_paramtypes(md, opc == BC_invokestatic ? ACC_STATIC : 0)) {
658 /* Try to lazyly resolve method. */
660 result = resolve_method_lazy(be->method, fmi, opc == BC_invokespecial);
662 if (result == resolveSucceeded) {
665 #if BC_ESCAPE_VERBOSE
669 "Succefully resolved callee %s/%s. Recursing.\n",
670 mi->clazz->name->text,
677 #if BC_ESCAPE_VERBOSE
681 "Failed to resolve callee %s/%s.\n",
682 (IS_FMIREF_RESOLVED(fmi) ? "ERR" : fmi->p.classref->name->text),
689 /* If we could resolve the method, either reuse available escape inormation
690 or recurse into callee.
691 Otherwise we must assume, that all parameters escape. */
695 if (mi->paramescape == NULL) {
696 bc_escape_analysis_perform_intern(mi, be->depth + 1);
699 if (mi->paramescape == NULL) {
700 /* No escape information. */
701 bc_escape_analysis_escape_invoke_parameters(be, md);
703 /* Adjust escape state of parameters. */
704 bc_escape_analysis_adjust_invoke_parameters(be, mi);
708 bc_escape_analysis_escape_invoke_parameters(be, md);
711 switch (md->returntype.type) {
714 op_stack_push_unknown(be->stack);
715 op_stack_push_unknown(be->stack);
721 op_stack_push_unknown(be->stack);
726 static void bc_escape_analysis_parse_tableswitch(
727 bc_escape_analysis_t *be,
733 jcode_get_u1(jc); /* opcode */
735 jcode_align_bytecode_index(jc, 4);
737 def = jcode_get_s4(jc);
738 low = jcode_get_s4(jc);
739 high = jcode_get_s4(jc);
742 for (i = 0; i < (high - low + 1); ++i) {
743 bc_escape_analysis_branch_target(
745 jcode_get_branch_target_wide(jc)
752 static void bc_escape_analysis_parse_lookupswitch(
753 bc_escape_analysis_t *be,
759 jcode_get_u1(jc); /* opcode */
761 jcode_align_bytecode_index(jc, 4);
765 bc_escape_analysis_branch_target(
767 jcode_get_branch_target_wide(jc)
772 npairs = jcode_get_s4(jc);
774 for (i = 0; i < npairs; ++i) {
779 bc_escape_analysis_branch_target(
781 jcode_get_branch_target_wide(jc)
787 static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcode_t *jc) {
789 op_stack_slot_t value1, value2, value3, value4;
794 #if BC_ESCAPE_VERBOSE
796 dprintf(be->depth, "Processing basicblock at offset %d.\n", jcode_get_index(jc));
800 op_stack_reset(be->stack);
802 /* TODO end if all parameters escape */
803 /* TODO move code into process_instruction or the like */
805 while ((! jcode_end(jc)) && (! bb_end)) {
807 jcode_record_instruction_start(jc);
809 opc = jcode_get_u1(jc);
811 length = bytecode[opc].length;
813 #if BC_ESCAPE_VERBOSE
815 dprintf(be->depth, "* %s, ", bytecode[opc].mnemonic);
816 op_stack_print(be->stack, stdout);
836 op_stack_push_unknown(be->stack);
843 op_stack_push_unknown(be->stack);
844 op_stack_push_unknown(be->stack);
849 op_stack_push_unknown(be->stack);
854 op_stack_push_unknown(be->stack);
858 op_stack_push_unknown(be->stack);
859 op_stack_push_unknown(be->stack);
872 op_stack_push_unknown(be->stack);
885 op_stack_push_unknown(be->stack);
886 op_stack_push_unknown(be->stack);
890 op_stack_push(be->stack, bc_escape_analysis_address_local(be, jcode_get_u1(jc)));
894 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 0));
898 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 1));
902 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 2));
906 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 3));
914 op_stack_pop(be->stack);
915 op_stack_pop(be->stack);
916 op_stack_push_unknown(be->stack);
921 op_stack_pop(be->stack);
922 op_stack_pop(be->stack);
923 op_stack_push_unknown(be->stack);
924 op_stack_push_unknown(be->stack);
928 op_stack_pop(be->stack);
929 op_stack_pop(be->stack);
930 op_stack_push_unknown(be->stack);
935 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
936 op_stack_pop(be->stack);
941 bc_escape_analysis_dirty(be, 0);
942 op_stack_pop(be->stack);
947 bc_escape_analysis_dirty(be, 1);
948 op_stack_pop(be->stack);
953 bc_escape_analysis_dirty(be, 2);
954 op_stack_pop(be->stack);
959 bc_escape_analysis_dirty(be, 3);
960 op_stack_pop(be->stack);
965 bc_escape_analysis_dirty_2(be, jcode_get_u1(jc));
966 op_stack_pop(be->stack);
967 op_stack_pop(be->stack);
972 bc_escape_analysis_dirty_2(be, 0);
973 op_stack_pop(be->stack);
974 op_stack_pop(be->stack);
979 bc_escape_analysis_dirty_2(be, 1);
980 op_stack_pop(be->stack);
981 op_stack_pop(be->stack);
986 bc_escape_analysis_dirty_2(be, 2);
987 op_stack_pop(be->stack);
988 op_stack_pop(be->stack);
993 bc_escape_analysis_dirty_2(be, 3);
994 op_stack_pop(be->stack);
995 op_stack_pop(be->stack);
999 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1000 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1004 bc_escape_analysis_dirty(be, 0);
1005 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1009 bc_escape_analysis_dirty(be, 1);
1010 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1014 bc_escape_analysis_dirty(be, 2);
1015 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1019 bc_escape_analysis_dirty(be, 3);
1020 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1028 op_stack_pop(be->stack);
1029 op_stack_pop(be->stack);
1030 op_stack_pop(be->stack);
1035 op_stack_pop(be->stack);
1036 op_stack_pop(be->stack);
1037 op_stack_pop(be->stack);
1038 op_stack_pop(be->stack);
1042 op_stack_pop(be->stack);
1043 op_stack_pop(be->stack);
1044 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1048 op_stack_pop(be->stack);
1052 op_stack_pop(be->stack);
1053 op_stack_pop(be->stack);
1057 value1 = op_stack_get(be->stack, 1);
1058 op_stack_push(be->stack, value1);
1062 value1 = op_stack_pop(be->stack);
1063 value2 = op_stack_pop(be->stack);
1064 op_stack_push(be->stack, value1);
1065 op_stack_push(be->stack, value2);
1066 op_stack_push(be->stack, value1);
1070 value1 = op_stack_pop(be->stack);
1071 value2 = op_stack_pop(be->stack);
1072 value3 = op_stack_pop(be->stack);
1073 op_stack_push(be->stack, value1);
1074 op_stack_push(be->stack, value3);
1075 op_stack_push(be->stack, value2);
1076 op_stack_push(be->stack, value1);
1080 value1 = op_stack_get(be->stack, 1);
1081 value2 = op_stack_get(be->stack, 2);
1082 op_stack_push(be->stack, value2);
1083 op_stack_push(be->stack, value1);
1087 value1 = op_stack_pop(be->stack);
1088 value2 = op_stack_pop(be->stack);
1089 value3 = op_stack_pop(be->stack);
1090 op_stack_push(be->stack, value2);
1091 op_stack_push(be->stack, value1);
1092 op_stack_push(be->stack, value3);
1093 op_stack_push(be->stack, value2);
1094 op_stack_push(be->stack, value1);
1098 value1 = op_stack_pop(be->stack);
1099 value2 = op_stack_pop(be->stack);
1100 value3 = op_stack_pop(be->stack);
1101 value4 = op_stack_pop(be->stack);
1102 op_stack_push(be->stack, value2);
1103 op_stack_push(be->stack, value1);
1104 op_stack_push(be->stack, value4);
1105 op_stack_push(be->stack, value3);
1106 op_stack_push(be->stack, value2);
1107 op_stack_push(be->stack, value1);
1111 value1 = op_stack_get(be->stack, 1);
1112 value2 = op_stack_get(be->stack, 2);
1113 op_stack_set(be->stack, 1, value2);
1114 op_stack_set(be->stack, 2, value1);
1132 op_stack_pop(be->stack);
1133 op_stack_pop(be->stack);
1134 op_stack_push_unknown(be->stack);
1152 op_stack_pop(be->stack);
1153 op_stack_pop(be->stack);
1154 op_stack_pop(be->stack);
1155 op_stack_pop(be->stack);
1156 op_stack_push_unknown(be->stack);
1157 op_stack_push_unknown(be->stack);
1171 op_stack_pop(be->stack);
1172 op_stack_pop(be->stack);
1173 op_stack_push_unknown(be->stack);
1179 op_stack_pop(be->stack);
1180 op_stack_pop(be->stack);
1181 /* Second operand is int. */
1182 op_stack_pop(be->stack);
1183 op_stack_push_unknown(be->stack);
1184 op_stack_push_unknown(be->stack);
1190 op_stack_pop(be->stack);
1191 op_stack_pop(be->stack);
1192 op_stack_push_unknown(be->stack);
1198 op_stack_pop(be->stack);
1199 op_stack_pop(be->stack);
1200 op_stack_pop(be->stack);
1201 op_stack_pop(be->stack);
1202 op_stack_push_unknown(be->stack);
1203 op_stack_push_unknown(be->stack);
1207 /* Not stack operation. */
1208 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1213 op_stack_pop(be->stack);
1214 op_stack_push_unknown(be->stack);
1215 op_stack_push_unknown(be->stack);
1219 op_stack_pop(be->stack);
1220 op_stack_push_unknown(be->stack);
1225 op_stack_pop(be->stack);
1226 op_stack_pop(be->stack);
1227 op_stack_push_unknown(be->stack);
1231 op_stack_pop(be->stack);
1232 op_stack_pop(be->stack);
1233 op_stack_push_unknown(be->stack);
1234 op_stack_push_unknown(be->stack);
1238 op_stack_pop(be->stack);
1239 op_stack_push_unknown(be->stack);
1244 op_stack_pop(be->stack);
1245 op_stack_push_unknown(be->stack);
1246 op_stack_push_unknown(be->stack);
1251 op_stack_pop(be->stack);
1252 op_stack_pop(be->stack);
1253 op_stack_push_unknown(be->stack);
1257 op_stack_pop(be->stack);
1258 op_stack_pop(be->stack);
1259 op_stack_push_unknown(be->stack);
1260 op_stack_push_unknown(be->stack);
1266 op_stack_pop(be->stack);
1267 op_stack_push_unknown(be->stack);
1272 op_stack_pop(be->stack);
1273 op_stack_pop(be->stack);
1274 op_stack_push_unknown(be->stack);
1280 op_stack_pop(be->stack);
1281 op_stack_pop(be->stack);
1282 op_stack_pop(be->stack);
1283 op_stack_pop(be->stack);
1284 op_stack_push_unknown(be->stack);
1293 op_stack_pop(be->stack);
1294 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1295 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1305 op_stack_pop(be->stack);
1306 op_stack_pop(be->stack);
1307 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1308 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1314 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1315 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1316 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1317 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1322 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1327 op_stack_push_unknown(be->stack);
1328 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1335 case BC_tableswitch:
1336 op_stack_pop(be->stack);
1337 jcode_rewind_instruction(jc);
1338 bc_escape_analysis_parse_tableswitch(be, jc);
1339 length = jcode_get_instruction_length(jc);
1343 case BC_lookupswitch:
1344 op_stack_pop(be->stack);
1345 jcode_rewind_instruction(jc);
1346 bc_escape_analysis_parse_lookupswitch(be, jc);
1347 length = jcode_get_instruction_length(jc);
1357 op_stack_pop(be->stack);
1363 op_stack_pop(be->stack);
1364 op_stack_pop(be->stack);
1370 bc_escape_analyisis_returned(be, op_stack_pop(be->stack));
1375 op_stack_pop(be->stack);
1380 bc_escape_analysis_value_category(be, jcode_get_s2(jc)) ==
1383 op_stack_push_unknown(be->stack);
1385 op_stack_push_unknown(be->stack);
1391 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1394 op_stack_pop(be->stack);
1396 op_stack_pop(be->stack);
1397 op_stack_pop(be->stack);
1399 value2 = op_stack_pop(be->stack);
1400 value1 = op_stack_pop(be->stack);
1401 bc_escape_analysis_adjust_state(be, value2, ESCAPE_GLOBAL);
1407 bc_escape_analysis_value_category(be, jcode_get_u2(jc)) ==
1410 op_stack_pop(be->stack);
1411 op_stack_pop(be->stack);
1413 value1 = op_stack_pop(be->stack);
1414 bc_escape_analysis_adjust_state(be, value1, ESCAPE_GLOBAL);
1418 case BC_invokevirtual:
1419 case BC_invokespecial:
1420 case BC_invokestatic:
1421 case BC_invokeinterface:
1422 jcode_rewind_instruction(jc);
1423 bc_escape_analysis_parse_invoke(be, jc);
1427 op_stack_push_unknown(be->stack);
1432 op_stack_pop(be->stack);
1433 op_stack_push_unknown(be->stack);
1436 case BC_arraylength:
1437 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_METHOD);
1438 op_stack_push_unknown(be->stack);
1442 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1447 value1 = op_stack_get(be->stack, 1);
1448 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1452 value1 = op_stack_pop(be->stack);
1453 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1454 op_stack_push_unknown(be->stack);
1457 case BC_monitorenter:
1458 case BC_monitorexit:
1459 value1 = op_stack_pop(be->stack);
1460 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1465 /* All except iinc have a length of 4. */
1468 switch (jcode_get_u1(jc)) {
1471 op_stack_push_unknown(be->stack);
1476 op_stack_push_unknown(be->stack);
1477 op_stack_push_unknown(be->stack);
1483 bc_escape_analysis_address_local(
1492 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1493 op_stack_pop(be->stack);
1498 bc_escape_analysis_dirty_2(be, jcode_get_u2(jc));
1499 op_stack_pop(be->stack);
1500 op_stack_pop(be->stack);
1504 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1505 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1513 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1520 case BC_multianewarray:
1522 dim = jcode_get_u1(jc);
1524 op_stack_pop(be->stack);
1526 op_stack_push_unknown(be->stack);
1531 value1 = op_stack_pop(be->stack);
1532 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1533 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1534 bc_escape_analysis_branch_target(be, jcode_get_fall_through_target(jc));
1539 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1544 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1557 jcode_forward_instruction_relative(jc, length);
1559 #if BC_ESCAPE_VERBOSE
1561 op_stack_print(be->stack, stdout);
1567 #if BC_ESCAPE_VERBOSE
1569 dprintf(be->depth, "Elements left on stack: %d\n", op_stack_element_count(be->stack));
1573 while (! op_stack_is_empty(be->stack)) {
1574 #if BC_ESCAPE_VERBOSE
1576 dprintf(be->depth, "Stack element: ");
1577 op_stack_print(be->stack, stdout);
1581 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1582 #if BC_ESCAPE_VERBOSE
1584 op_stack_print(be->stack, stdout);
1591 static void bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
1592 escape_state_t e, pe;
1595 /* Only calculate, if return value is of type address. */
1597 if (be->method->parseddesc->returntype.type != TYPE_ADR) {
1601 /* Get current escape state of return value. */
1603 e = (escape_state_t)be->param_escape[-1];
1605 /* If a parameter can be returned, adjust to its escape state. */
1607 for (i = 0; i < be->param_escape_size; ++i) {
1608 if (bit_vector_get(be->adr_param_returned, i)) {
1609 pe = (escape_state_t)be->param_escape[i];
1616 be->param_escape[-1] = (u1)e;
1619 static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
1620 raw_exception_entry *itee;
1621 basicblock_work_item_t *bb;
1624 /* Add root as basic block. */
1626 bc_escape_analysis_branch_target(be, 0);
1628 /* Add each exception handler as basic block. */
1631 itee = be->method->rawexceptiontable;
1632 itee != be->method->rawexceptiontable + be->method->rawexceptiontablelength;
1635 bc_escape_analysis_branch_target(be, itee->handlerpc);
1638 /* Init jcode parser. */
1643 be->method->jcodelength,
1647 /* Process basicblock by basicblock. */
1649 for (bb = be->basicblocks->first; bb; bb = bb->next) {
1650 jcode_move_to_index(&jc, bb->bytecode_index);
1651 bc_escape_analysis_process_basicblock(
1657 /* Calculate escape of return value. */
1659 bc_escape_analysis_adjust_return_value(be);
1661 /* Export escape of parameters. */
1663 be->method->paramescape = be->param_escape;
1666 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
1667 bc_escape_analysis_t *be;
1668 bool verbose = false;
1670 #if BC_ESCAPE_VERBOSE
1674 "=== BC escape analysis of %s/%s at depth %d ===\n",
1675 m->clazz->name->text,
1682 if (m->paramescape != NULL) {
1683 #if BC_ESCAPE_VERBOSE
1685 dprintf(depth, "Escape info for method already available.\n");
1691 if ((m->flags & ACC_METHOD_EA) != 0) {
1692 #if BC_ESCAPE_VERBOSE
1694 dprintf(depth, "Detected recursion, aborting.\n");
1700 if (m->jcode == NULL) {
1701 #if BC_ESCAPE_VERBOSE
1703 dprintf(depth, "No bytecode for callee.\n");
1709 /* TODO threshold */
1711 be = DNEW(bc_escape_analysis_t);
1712 bc_escape_analysis_init(be, m, verbose, depth);
1714 m->flags |= ACC_METHOD_EA;
1716 bc_escape_analysis_analyze(be);
1718 #if BC_ESCAPE_VERBOSE
1722 "%s/%s: Non-escaping params: %d\n",
1723 m->clazz->name->text,
1725 be->non_escaping_adr_params
1730 m->flags &= ~ACC_METHOD_EA;
1733 void bc_escape_analysis_perform(methodinfo *m) {
1734 bc_escape_analysis_perform_intern(m, 0);