* Merged gc7-branch to default.
[cacao.git] / src / vm / jit / optimizing / bytecode_escape.c
1 #include "mm/dumpmemory.h"
2 #include "mm/memory.h"
3
4 #include "toolbox/bitvector.h"
5
6 #include "vm/global.h"
7 #include "vm/jit/ir/bytecode.h"
8 #include "vm/jit/optimizing/escape.h"
9 #include "vm/resolve.h"
10
11 #include "vmcore/class.h"
12 #include "vmcore/descriptor.h"
13 #include "vmcore/references.h"
14
15 #include <assert.h>
16 #include <stdarg.h>
17
18 #define BC_ESCAPE_VERBOSE !defined(NDEBUG)
19
20 /*** dprintf *****************************************************************/
21
22 #if BC_ESCAPE_VERBOSE && 0
23 void dprintf(int depth, const char *fmt, ...) {
24         va_list ap;
25
26         while (depth-- > 0) {
27                 printf("    ");
28         }
29         printf("| ");
30
31         va_start(ap, fmt);
32         vprintf(fmt, ap);
33         va_end(ap);
34 }
35 #endif
36
37 #define dprintf(x, ...) printf(__VA_ARGS__)
38
39 /*** op_stack_slot  **********************************************************/
40
41 typedef enum {
42         OP_STACK_SLOT_TYPE_PARAM = 0,
43         OP_STACK_SLOT_TYPE_UNKNOWN = 1
44 } op_stack_slot_type_t;
45
46 typedef struct {
47         unsigned type:1;
48         unsigned index:31;
49 } op_stack_slot_t;
50
51 const op_stack_slot_t OP_STACK_SLOT_UNKNOWN = { 
52         OP_STACK_SLOT_TYPE_UNKNOWN,
53         0
54 };
55
56 static inline op_stack_slot_t op_stack_slot_create_param(s4 index) {
57         op_stack_slot_t res;
58         res.type = OP_STACK_SLOT_TYPE_PARAM;
59         res.index = index;
60         return res;
61 }
62
63 static inline bool op_stack_slot_is_unknown(const op_stack_slot_t slot) {
64         return slot.type == OP_STACK_SLOT_TYPE_UNKNOWN;
65 }
66
67 static inline bool op_stack_slot_is_param(const op_stack_slot_t slot) {
68         return slot.type == OP_STACK_SLOT_TYPE_PARAM;
69 }
70
71 /*** op_stack *****************************************************************/
72
73 /*
74
75 +---+---+---+---+  push 1
76         ^
77
78 +---+---+-1-+---+  push 2
79             ^
80
81 +---+---+-1-+-2-+  pop 2
82                 ^
83
84 +---+---+-1-+---+  pop 1
85             ^        
86
87 +---+---+---+---+  
88         ^
89 */
90
91 typedef struct {
92         op_stack_slot_t *elements;
93         op_stack_slot_t *start;
94         op_stack_slot_t *end;
95         op_stack_slot_t *ptr;
96         op_stack_slot_t *bottom;
97         unsigned max;
98 } op_stack_t;
99
100 #define stack_assert_position(stack, pos) \
101         do { \
102                 assert((stack)->elements <= (pos)); \
103                 assert((pos) < (stack)->end); \
104         } while (0)
105
106 static void op_stack_init(op_stack_t *stack, unsigned max) {
107         op_stack_slot_t *it;
108
109         stack->elements = DMNEW(op_stack_slot_t, max * 2);
110         stack->max = max;
111         stack->start = stack->elements + max;
112         stack->end = stack->elements + max + max;
113
114         for (it = stack->elements; it != stack->start; ++it) {
115                 *it = OP_STACK_SLOT_UNKNOWN;
116         }
117
118         stack->ptr = stack->start;
119         stack->bottom = stack->start;
120 }
121
122 static void op_stack_reset(op_stack_t *stack) {
123         op_stack_slot_t *it;
124
125         /* Clear bottom half. */
126
127         for (it = stack->bottom; it != stack->elements + stack->max; ++it) {
128                 *it = OP_STACK_SLOT_UNKNOWN;
129         }
130
131         /* Reset pointers. */
132
133         stack->ptr = stack->start;
134         stack->bottom = stack->start;
135 }
136
137 static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
138         op_stack_slot_t ret;
139         stack->ptr -= 1;
140         stack_assert_position(stack, stack->ptr);
141         ret = *(stack->ptr);
142         if (stack->ptr < stack->bottom) {
143                 stack->bottom = stack->ptr;
144         }
145         return ret;
146 }
147
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;
151         stack->ptr += 1;
152 }
153
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);
157 }
158
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;
162 }
163
164 static inline void op_stack_push_unknown(op_stack_t *stack) {
165         op_stack_push(stack, OP_STACK_SLOT_UNKNOWN);
166 }
167
168 static void op_stack_print(const op_stack_t *stack, FILE *f) {
169         op_stack_slot_t *it;
170         char sep;
171         
172         for (it = stack->bottom; it < stack->ptr; ++it) {
173                 if (it == stack->start) {
174                         sep = '!';
175                 } else {
176                         sep = '|';
177                 }
178                 if (op_stack_slot_is_unknown(*it)) {
179                         fprintf(f, "%c----", sep);
180                 } else {
181                         fprintf(f, "%cP%3d", sep, it->index);
182                 }
183         }
184
185         fprintf(f, "|");
186 }
187
188 static bool op_stack_is_empty(const op_stack_t *stack) {
189         return !(stack->bottom < stack->ptr);
190 }
191
192 static s4 op_stack_element_count(const op_stack_t *stack) {
193         return (stack->ptr - stack->bottom);
194 }
195
196 /*** bit_vector **************************************************************/
197
198 typedef struct {
199         bitvector bv;
200         s4 size;
201 } bit_vector_t;
202
203 static void bit_vector_init(bit_vector_t *bv, s4 size) {
204         bv->bv = bv_new(size);
205         bv->size = size;
206 }
207
208 static s4 bit_vector_size(const bit_vector_t *bv) {
209         return bv->size;
210 }
211
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);
215 }
216
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);
220 }
221
222 /*** basicblock_work_list ***********************************************/
223
224 typedef struct basicblock_work_item {
225         s4 bytecode_index;
226         struct basicblock_work_item *next;
227 } basicblock_work_item_t;
228
229 typedef struct {
230         basicblock_work_item_t *first;
231         basicblock_work_item_t *last;
232 } basicblock_work_list_t;
233
234 void basicblock_work_list_init(basicblock_work_list_t *lst) {
235         lst->first = NULL;
236         lst->last = NULL;
237 }
238
239 #define FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) \
240         for ((it) = (lst)->first; (it); (it) = (it)->next)
241
242 void basicblock_work_list_insert(basicblock_work_list_t *lst, s4 bytecode_index) {
243         basicblock_work_item_t *it, *item;
244
245         /* If the destination is already present in the list, do nothing. */
246
247         FOR_EACH_BASICBLOCK_WORK_LIST(lst, it) {
248                 if (it->bytecode_index == bytecode_index) {
249                         return;
250                 }
251         }
252
253         item = DNEW(basicblock_work_item_t);
254         item->bytecode_index = bytecode_index;
255         item->next = NULL;
256
257         if (lst->first == NULL) {
258                 lst->first = item;
259                 lst->last = item;
260         } else {
261                 lst->last->next = item;
262                 lst->last = item;
263         }
264 }
265
266 /*** value_category *****************************************************/
267
268 typedef enum {
269         VALUE_CATEGORY_1,
270         VALUE_CATEGORY_2
271 } value_category_t;
272
273 /*** jcode **************************************************************/
274
275 typedef struct {
276         u1 *start;
277         u1 *end;
278         u1 *pos;
279         u1 *instruction_start;
280         s4 offset;
281 } jcode_t;
282
283 static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset) {
284         jc->start = start;
285         jc->end = jc->start + length;
286         jc->pos = jc->start;
287         jc->offset = offset;
288 }
289
290 static void jcode_move_to_index(jcode_t *jc, s4 index) {
291         jc->pos = jc->start + (index - jc->offset);
292 }
293
294 static bool jcode_end(const jcode_t *jc) {
295         return (jc->pos >= jc->end);
296 }
297
298 static void jcode_record_instruction_start(jcode_t *jc) {
299         jc->instruction_start = jc->pos;
300 }
301
302 static void jcode_rewind_instruction(jcode_t *jc) {
303         jc->pos = jc->instruction_start;
304 }
305
306 static s4 jcode_get_instruction_length(const jcode_t *jc) {
307         return (jc->pos - jc->instruction_start);
308 }
309
310 static void jcode_align_bytecode_index(jcode_t *jc, s4 align) {
311         s4 idx, aidx;
312
313         idx = jc->offset + (jc->pos - jc->start);
314         aidx = MEMORY_ALIGN(idx, align);
315
316         jc->pos += (aidx - idx);
317 }
318
319 static void jcode_forward_instruction_relative(jcode_t *jc, s4 n) {
320         jc->pos = jc->instruction_start + n;
321 }
322
323 static s4 jcode_get_index(const jcode_t *jc) {
324         return jc->offset + (jc->pos - jc->start);
325 }
326
327 #define jcode_assert_has_bytes(jc, n) \
328         assert((jc->pos + n) <= jc->end)
329
330 static u1 jcode_get_u1(jcode_t *jc) {
331         u1 ret;
332         jcode_assert_has_bytes(jc, 1);
333         ret = jc->pos[0];
334         jc->pos += 1;
335         return ret;
336 }
337
338 static s2 jcode_get_s2(jcode_t *jc) {
339         s2 ret;
340         jcode_assert_has_bytes(jc, 2);
341         ret = (jc->pos[0] << 8) | (jc->pos[1]);
342         jc->pos += 2;
343         return ret;
344 }
345
346 static u2 jcode_get_u2(jcode_t *jc) {
347         u2 ret;
348         jcode_assert_has_bytes(jc, 2);
349         ret = (jc->pos[0] << 8) | (jc->pos[1]);
350         jc->pos += 2;
351         return ret;
352 }
353
354 static s4 jcode_get_s4(jcode_t *jc) {
355         s4 ret;
356         jcode_assert_has_bytes(jc, 4);
357         ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
358         jc->pos += 4;
359         return ret;
360 }
361
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;
365 }
366
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;
370 }
371
372 static s4 jcode_get_fall_through_target(jcode_t *jc) {
373         int length = bytecode[*jc->instruction_start].length;
374         assert(length > 0);
375         return jc->offset + (jc->instruction_start - jc->start) + length;
376 }
377
378 /*** bc_escape_analysis *************************************************/
379
380 typedef struct {
381         methodinfo *method;
382         op_stack_t *stack;
383         basicblock_work_list_t *basicblocks;
384
385         op_stack_slot_t *local_to_adr_param;
386         s4 local_to_adr_param_size;
387
388         u1 *param_escape;
389         s4 param_escape_size;
390
391         bit_vector_t *adr_param_dirty;
392         bit_vector_t *adr_param_returned;
393
394         s4 non_escaping_adr_params;
395
396 #if BC_ESCAPE_VERBOSE
397         bool verbose;
398 #endif
399         int depth;
400 } bc_escape_analysis_t;
401
402 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth);
403
404 static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, bool verbose, int depth) {
405         u2 p;
406         int l;
407         int a;
408         u1 *ite;
409         u1 t;
410         int ret_adr;
411         unsigned n;
412
413         be->method = m;
414
415         be->stack = DNEW(op_stack_t);
416         op_stack_init(be->stack, m->maxstack);
417
418         be->basicblocks = DNEW(basicblock_work_list_t);
419         basicblock_work_list_init(be->basicblocks);
420
421         be->local_to_adr_param_size = m->parseddesc->paramslots;
422         be->local_to_adr_param = DMNEW(op_stack_slot_t, m->parseddesc->paramslots);
423
424         /* Count number of address parameters a. */
425
426         for (p = 0, l = 0, a = 0; p < m->parseddesc->paramcount; ++p) {
427                 t = m->parseddesc->paramtypes[p].type;
428                 if (t == TYPE_ADR) {
429                         be->local_to_adr_param[l] = op_stack_slot_create_param(a);
430                         a += 1;
431                         l += 1;
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;
435                         l += 2;
436                 } else {
437                         be->local_to_adr_param[l] = OP_STACK_SLOT_UNKNOWN;
438                         l += 1;
439                 }
440         }
441
442         assert(l == be->local_to_adr_param_size);
443
444         /* Determine whether return type is address */
445
446         ret_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
447
448         /* Allocate param_escape on heap. */
449
450         be->param_escape_size = a;
451         n = a + ret_adr;
452
453         if (n == 0) {
454                 /* Use some non-NULL value. */
455                 be->param_escape = (u1 *)1;
456         } else {
457                 be->param_escape = MNEW(u1, n);
458         }
459
460         for (ite = be->param_escape; ite != be->param_escape + n; ++ite) {
461                 *ite = (u1)ESCAPE_NONE;
462         }
463
464         be->param_escape += ret_adr;
465
466         be->adr_param_dirty = DNEW(bit_vector_t);
467         bit_vector_init(be->adr_param_dirty, a);
468
469         be->adr_param_returned= DNEW(bit_vector_t);
470         bit_vector_init(be->adr_param_returned, a);
471
472         be->non_escaping_adr_params = be->param_escape_size;
473
474 #if BC_ESCAPE_VERBOSE
475         be->verbose = verbose;
476 #endif
477
478         be->depth = depth;
479 }
480
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);
483 }
484
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
489 ) {
490         escape_state_t old;
491
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) {
496
497                                 /* Adjust escape state. */
498                                 be->param_escape[adr_param.index] = (u1)escape_state;
499
500                                 /* If the parameter has just escaped, decrement number of non-escaping
501                                    parameters. */
502
503                                 if (
504                                         old < ESCAPE_GLOBAL_THROUGH_METHOD && 
505                                         escape_state >= ESCAPE_GLOBAL_THROUGH_METHOD
506                                 ) {
507                                         be->non_escaping_adr_params -= 1;
508                                 }
509                         }
510                 }
511         }
512 }
513
514 static void bc_escape_analysis_dirty(bc_escape_analysis_t *be, s4 local) {
515         op_stack_slot_t adr_param;
516
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);
521                 }
522         }
523 }
524
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);
528 }
529
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;
539                 }
540         }
541 }
542
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];
546         } else {
547                 return OP_STACK_SLOT_UNKNOWN;
548         }
549 }
550
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);
554
555         if (fmi == NULL) {
556                 /* TODO */
557                 assert(0);
558         }
559
560         switch (fmi->parseddesc.fd->type) {
561                 case TYPE_LNG:
562                 case TYPE_DBL:
563                         return VALUE_CATEGORY_2;
564                 default:
565                         return VALUE_CATEGORY_1;
566         }
567 }
568
569 static void bc_escape_analysis_adjust_invoke_parameters(
570         bc_escape_analysis_t *be,
571         methodinfo *mi
572 ) {
573         int i;
574         methoddesc *md = mi->parseddesc;
575         u1 *paramescape = mi->paramescape;
576         s4 stack_depth = md->paramslots;
577
578         /* Process parameters. 
579          * The first parameter is at the highest depth on the stack.
580          */
581
582         for (i = 0; i < md->paramcount; ++i) {
583                 switch (md->paramtypes[i].type) {
584                         case TYPE_ADR:
585                                 bc_escape_analysis_adjust_state(
586                                         be,
587                                         op_stack_get(be->stack, stack_depth),
588                                         (escape_state_t)*(paramescape++)
589                                 );
590                                 stack_depth -= 1;
591                                 break;
592                         case TYPE_LNG:
593                         case TYPE_DBL:
594                                 stack_depth -= 2;
595                                 break;
596                         default:
597                                 stack_depth -= 1;
598                                 break;
599                 }
600         }
601
602         /* Pop all parameters. */
603
604         for (i = 0; i < md->paramslots; ++i) {
605                 op_stack_pop(be->stack);
606         }
607
608 }
609
610 static void bc_escape_analysis_escape_invoke_parameters(
611         bc_escape_analysis_t *be,
612         methoddesc *md
613 ) {
614         s4 i;
615         for (i = 0; i < md->paramslots; ++i) {
616                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
617         }
618 }
619
620 static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *jc) {
621         constant_FMIref *fmi;
622         methoddesc *md;
623         u1 opc;
624         u2 cp_index;
625         s2 i;
626         resolve_result_t result;
627         methodinfo *mi;
628
629         opc = jcode_get_u1(jc);
630         cp_index = jcode_get_u2(jc);
631
632         /* Get method reference */
633
634         if (opc == BC_invokeinterface) {
635                 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_InterfaceMethodref);
636         } else {
637                 fmi = class_getconstant(be->method->clazz, cp_index, CONSTANT_Methodref);
638         }
639
640         if (fmi == NULL) {
641                 /* TODO */
642                 assert(0);
643         }
644
645         md = fmi->parseddesc.md;
646
647         assert(md != NULL);
648
649         /* Parse parameters if not done yet. */
650
651         if (md->params == NULL) {
652                 if (! descriptor_params_from_paramtypes(md, opc == BC_invokestatic ? ACC_STATIC : 0)) {
653                         /* TODO */
654                         assert(0);
655                 }
656         }
657
658         /* Try to lazyly resolve method. */
659
660         result = resolve_method_lazy(be->method, fmi, opc == BC_invokespecial);
661
662         if (result == resolveSucceeded) {
663                 mi = fmi->p.method;
664
665 #if BC_ESCAPE_VERBOSE
666                 if (be->verbose) {
667                         dprintf(
668                                 be->depth,
669                                 "Succefully resolved callee %s/%s. Recursing.\n",
670                                 mi->clazz->name->text,
671                                 mi->name->text
672                         );
673                 }
674 #endif
675         } else {
676                 mi = NULL;
677 #if BC_ESCAPE_VERBOSE
678                 if (be->verbose) {
679                         dprintf(
680                                 be->depth,
681                                 "Failed to resolve callee %s/%s.\n", 
682                                 (IS_FMIREF_RESOLVED(fmi) ? "ERR" : fmi->p.classref->name->text),
683                                 fmi->name->text
684                         );
685                 }
686 #endif
687         }
688
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. */
692
693         if (mi != NULL) {
694
695                 if (mi->paramescape == NULL) {
696                         bc_escape_analysis_perform_intern(mi, be->depth + 1);
697                 }
698
699                 if (mi->paramescape == NULL) {
700                         /* No escape information. */
701                         bc_escape_analysis_escape_invoke_parameters(be, md);
702                 } else {
703                         /* Adjust escape state of parameters. */
704                         bc_escape_analysis_adjust_invoke_parameters(be, mi);
705                 }
706
707         } else {
708                 bc_escape_analysis_escape_invoke_parameters(be, md);
709         }
710
711         switch (md->returntype.type) {
712                 case TYPE_LNG:
713                 case TYPE_DBL:
714                         op_stack_push_unknown(be->stack);
715                         op_stack_push_unknown(be->stack);
716                         break;
717                 case TYPE_VOID:
718                         /* Do nothing */
719                         break;
720                 default:
721                         op_stack_push_unknown(be->stack);
722                         break;
723         }
724 }
725
726 static void bc_escape_analysis_parse_tableswitch(
727         bc_escape_analysis_t *be, 
728         jcode_t *jc
729 ) {
730         s4 high, low, def;
731         s4 i;
732
733         jcode_get_u1(jc); /* opcode */
734
735         jcode_align_bytecode_index(jc, 4);
736
737         def = jcode_get_s4(jc);
738         low = jcode_get_s4(jc);
739         high = jcode_get_s4(jc);
740
741         if (low <= high) {
742                 for (i = 0; i < (high - low + 1); ++i) {
743                         bc_escape_analysis_branch_target(
744                                 be,
745                                 jcode_get_branch_target_wide(jc)
746                         );
747                 }
748         }
749
750 }
751
752 static void bc_escape_analysis_parse_lookupswitch(
753         bc_escape_analysis_t *be, 
754         jcode_t *jc
755 ) {
756         s4 npairs;
757         s4 i;
758
759         jcode_get_u1(jc); /* opcode */
760
761         jcode_align_bytecode_index(jc, 4);
762
763         /* default */
764
765         bc_escape_analysis_branch_target(
766                 be,
767                 jcode_get_branch_target_wide(jc)
768         );
769
770         /* npairs */
771
772         npairs = jcode_get_s4(jc);
773
774         for (i = 0; i < npairs; ++i) {
775                 /* Match */
776                 jcode_get_s4(jc);
777
778                 /* Offset */
779                 bc_escape_analysis_branch_target(
780                         be,
781                         jcode_get_branch_target_wide(jc)
782                 );
783         }
784
785 }
786
787 static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcode_t *jc) {
788         u1 opc;
789         op_stack_slot_t value1, value2, value3, value4;
790         u1 dim;
791         int length;
792         bool bb_end = false;
793
794 #if BC_ESCAPE_VERBOSE
795         if (be->verbose) {
796                 dprintf(be->depth, "Processing basicblock at offset %d.\n", jcode_get_index(jc));
797         }
798 #endif
799
800         op_stack_reset(be->stack);
801
802         /* TODO end if all parameters escape */
803         /* TODO move code into process_instruction or the like */
804
805         while ((! jcode_end(jc)) && (! bb_end)) {
806
807                 jcode_record_instruction_start(jc);
808
809                 opc = jcode_get_u1(jc);
810
811                 length = bytecode[opc].length;
812
813 #if BC_ESCAPE_VERBOSE   
814                 if (be->verbose) {
815                         dprintf(be->depth, "* %s, ", bytecode[opc].mnemonic);
816                         op_stack_print(be->stack, stdout);
817                         printf(" => ");
818                 }
819 #endif
820
821                 switch (opc) {
822                         case BC_nop:
823                                 break;
824
825                         case BC_aconst_null:
826                         case BC_iconst_m1:
827                         case BC_iconst_0:
828                         case BC_iconst_1:
829                         case BC_iconst_2:
830                         case BC_iconst_3:
831                         case BC_iconst_4:
832                         case BC_iconst_5:
833                         case BC_fconst_0:
834                         case BC_fconst_1:
835                         case BC_fconst_2:
836                                 op_stack_push_unknown(be->stack);
837                                 break;
838
839                         case BC_dconst_0:
840                         case BC_dconst_1:
841                         case BC_lconst_0:
842                         case BC_lconst_1:
843                                 op_stack_push_unknown(be->stack);
844                                 op_stack_push_unknown(be->stack);
845                                 break;
846
847                         case BC_bipush:
848                         case BC_sipush:
849                                 op_stack_push_unknown(be->stack);
850                                 break;
851
852                         case BC_ldc1:
853                         case BC_ldc2:
854                                 op_stack_push_unknown(be->stack);
855                                 break;
856
857                         case BC_ldc2w:
858                                 op_stack_push_unknown(be->stack);
859                                 op_stack_push_unknown(be->stack);
860                                 break;
861
862                         case BC_iload:
863                         case BC_fload:
864                         case BC_iload_0:
865                         case BC_iload_1:
866                         case BC_iload_2:
867                         case BC_iload_3:
868                         case BC_fload_0:
869                         case BC_fload_1:
870                         case BC_fload_2:
871                         case BC_fload_3:
872                                 op_stack_push_unknown(be->stack);
873                                 break;
874
875                         case BC_dload:
876                         case BC_lload:
877                         case BC_lload_0:
878                         case BC_lload_1:
879                         case BC_lload_2:
880                         case BC_lload_3:
881                         case BC_dload_0:
882                         case BC_dload_1:
883                         case BC_dload_2:
884                         case BC_dload_3:
885                                 op_stack_push_unknown(be->stack);
886                                 op_stack_push_unknown(be->stack);
887                                 break;
888
889                         case BC_aload:
890                                 op_stack_push(be->stack, bc_escape_analysis_address_local(be, jcode_get_u1(jc)));
891                                 break;
892
893                         case BC_aload_0:
894                                 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 0));
895                                 break;
896
897                         case BC_aload_1:
898                                 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 1));
899                                 break;
900
901                         case BC_aload_2:
902                                 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 2));
903                                 break;
904
905                         case BC_aload_3:
906                                 op_stack_push(be->stack, bc_escape_analysis_address_local(be, 3));
907                                 break;
908
909                         case BC_iaload:
910                         case BC_faload:
911                         case BC_baload:
912                         case BC_caload:
913                         case BC_saload:
914                                 op_stack_pop(be->stack);
915                                 op_stack_pop(be->stack);
916                                 op_stack_push_unknown(be->stack);
917                                 break;
918
919                         case BC_laload:
920                         case BC_daload:
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);
925                                 break;
926
927                         case BC_aaload:
928                                 op_stack_pop(be->stack);
929                                 op_stack_pop(be->stack);
930                                 op_stack_push_unknown(be->stack);
931                                 break;
932
933                         case BC_istore:
934                         case BC_fstore:
935                                 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
936                                 op_stack_pop(be->stack);
937                                 break;
938
939                         case BC_istore_0:
940                         case BC_fstore_0:
941                                 bc_escape_analysis_dirty(be, 0);
942                                 op_stack_pop(be->stack);
943                                 break;
944
945                         case BC_istore_1:
946                         case BC_fstore_1:
947                                 bc_escape_analysis_dirty(be, 1);
948                                 op_stack_pop(be->stack);
949                                 break;
950
951                         case BC_istore_2:
952                         case BC_fstore_2:
953                                 bc_escape_analysis_dirty(be, 2);
954                                 op_stack_pop(be->stack);
955                                 break;
956
957                         case BC_istore_3:
958                         case BC_fstore_3:
959                                 bc_escape_analysis_dirty(be, 3);
960                                 op_stack_pop(be->stack);
961                                 break;
962
963                         case BC_lstore:
964                         case BC_dstore:
965                                 bc_escape_analysis_dirty_2(be, jcode_get_u1(jc));
966                                 op_stack_pop(be->stack);
967                                 op_stack_pop(be->stack);
968                                 break;
969
970                         case BC_lstore_0:
971                         case BC_dstore_0:
972                                 bc_escape_analysis_dirty_2(be, 0);
973                                 op_stack_pop(be->stack);
974                                 op_stack_pop(be->stack);
975                                 break;
976
977                         case BC_lstore_1:
978                         case BC_dstore_1:
979                                 bc_escape_analysis_dirty_2(be, 1);
980                                 op_stack_pop(be->stack);
981                                 op_stack_pop(be->stack);
982                                 break;
983
984                         case BC_lstore_2:
985                         case BC_dstore_2:
986                                 bc_escape_analysis_dirty_2(be, 2);
987                                 op_stack_pop(be->stack);
988                                 op_stack_pop(be->stack);
989                                 break;
990
991                         case BC_lstore_3:
992                         case BC_dstore_3:
993                                 bc_escape_analysis_dirty_2(be, 3);
994                                 op_stack_pop(be->stack);
995                                 op_stack_pop(be->stack);
996                                 break;
997
998                         case BC_astore:
999                                 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1000                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1001                                 break;
1002
1003                         case BC_astore_0:
1004                                 bc_escape_analysis_dirty(be, 0);
1005                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1006                                 break;
1007
1008                         case BC_astore_1:
1009                                 bc_escape_analysis_dirty(be, 1);
1010                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1011                                 break;
1012
1013                         case BC_astore_2:
1014                                 bc_escape_analysis_dirty(be, 2);
1015                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1016                                 break;
1017
1018                         case BC_astore_3:
1019                                 bc_escape_analysis_dirty(be, 3);
1020                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1021                                 break;
1022
1023                         case BC_iastore:
1024                         case BC_fastore:
1025                         case BC_bastore:
1026                         case BC_castore:
1027                         case BC_sastore:
1028                                 op_stack_pop(be->stack);
1029                                 op_stack_pop(be->stack);
1030                                 op_stack_pop(be->stack);
1031                                 break;
1032
1033                         case BC_lastore:
1034                         case BC_dastore:
1035                                 op_stack_pop(be->stack);
1036                                 op_stack_pop(be->stack);
1037                                 op_stack_pop(be->stack);
1038                                 op_stack_pop(be->stack);
1039                                 break;
1040
1041                         case BC_aastore:
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);
1045                                 break;
1046
1047                         case BC_pop:
1048                                 op_stack_pop(be->stack);
1049                                 break;
1050
1051                         case BC_pop2:
1052                                 op_stack_pop(be->stack);
1053                                 op_stack_pop(be->stack);
1054                                 break;
1055
1056                         case BC_dup:
1057                                 value1 = op_stack_get(be->stack, 1);
1058                                 op_stack_push(be->stack, value1);
1059                                 break;
1060
1061                         case BC_dup_x1:
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);
1067                                 break;
1068
1069                         case BC_dup_x2:
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);
1077                                 break;
1078                                 
1079                         case BC_dup2:
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);
1084                                 break;
1085
1086                         case BC_dup2_x1:
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);
1095                                 break;
1096
1097                         case BC_dup2_x2:
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);
1108                                 break;
1109
1110                         case BC_swap:
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);
1115                                 break;
1116
1117                         case BC_iadd:
1118                         case BC_fadd:
1119
1120                         case BC_isub:
1121                         case BC_fsub:
1122
1123                         case BC_imul:
1124                         case BC_fmul:
1125
1126                         case BC_idiv:
1127                         case BC_fdiv:
1128
1129                         case BC_irem:
1130                         case BC_frem:
1131
1132                                 op_stack_pop(be->stack);
1133                                 op_stack_pop(be->stack);
1134                                 op_stack_push_unknown(be->stack);
1135                                 break;
1136
1137                         case BC_ladd:
1138                         case BC_dadd:
1139
1140                         case BC_lsub:
1141                         case BC_dsub:
1142
1143                         case BC_ldiv:
1144                         case BC_ddiv:
1145
1146                         case BC_lmul:
1147                         case BC_dmul:
1148
1149                         case BC_lrem:
1150                         case BC_drem:
1151
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);
1158                                 break;
1159
1160                         case BC_ineg:
1161                         case BC_lneg:
1162                         case BC_fneg:
1163                         case BC_dneg:
1164
1165                                 /* Nothing */
1166                                 break;
1167
1168                         case BC_ishl:
1169                         case BC_ishr:
1170                         case BC_iushr:
1171                                 op_stack_pop(be->stack);
1172                                 op_stack_pop(be->stack);
1173                                 op_stack_push_unknown(be->stack);
1174                                 break;
1175
1176                         case BC_lshl:
1177                         case BC_lshr:
1178                         case BC_lushr:
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);
1185                                 break;
1186
1187                         case BC_iand:
1188                         case BC_ior:
1189                         case BC_ixor:
1190                                 op_stack_pop(be->stack);
1191                                 op_stack_pop(be->stack);
1192                                 op_stack_push_unknown(be->stack);
1193                                 break;
1194
1195                         case BC_land:
1196                         case BC_lor:
1197                         case BC_lxor:
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);
1204                                 break;
1205
1206                         case BC_iinc:
1207                                 /* Not stack operation. */
1208                                 bc_escape_analysis_dirty(be, jcode_get_u1(jc));
1209                                 break;
1210
1211                         case BC_i2l:
1212                         case BC_i2d:
1213                                 op_stack_pop(be->stack);
1214                                 op_stack_push_unknown(be->stack);
1215                                 op_stack_push_unknown(be->stack);
1216                                 break;
1217
1218                         case BC_i2f:
1219                                 op_stack_pop(be->stack);
1220                                 op_stack_push_unknown(be->stack);
1221                                 break;
1222
1223                         case BC_l2i:
1224                         case BC_l2f:
1225                                 op_stack_pop(be->stack);
1226                                 op_stack_pop(be->stack);
1227                                 op_stack_push_unknown(be->stack);
1228                                 break;
1229
1230                         case BC_l2d:
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);
1235                                 break;
1236
1237                         case BC_f2i:
1238                                 op_stack_pop(be->stack);
1239                                 op_stack_push_unknown(be->stack);
1240                                 break;
1241                                 
1242                         case BC_f2l:
1243                         case BC_f2d:
1244                                 op_stack_pop(be->stack);
1245                                 op_stack_push_unknown(be->stack);
1246                                 op_stack_push_unknown(be->stack);
1247                                 break;
1248
1249                         case BC_d2i:
1250                         case BC_d2f:
1251                                 op_stack_pop(be->stack);
1252                                 op_stack_pop(be->stack);
1253                                 op_stack_push_unknown(be->stack);
1254                                 break;
1255
1256                         case BC_d2l:
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);
1261                                 break;
1262
1263                         case BC_int2byte:
1264                         case BC_int2char:
1265                         case BC_int2short:
1266                                 op_stack_pop(be->stack);
1267                                 op_stack_push_unknown(be->stack);
1268                                 break;
1269
1270                         case BC_fcmpl:
1271                         case BC_fcmpg:
1272                                 op_stack_pop(be->stack);
1273                                 op_stack_pop(be->stack);
1274                                 op_stack_push_unknown(be->stack);
1275                                 break;
1276
1277                         case BC_lcmp:
1278                         case BC_dcmpl:
1279                         case BC_dcmpg:
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);
1285                                 break;
1286
1287                         case BC_ifeq:
1288                         case BC_ifne:
1289                         case BC_iflt:
1290                         case BC_ifge:
1291                         case BC_ifgt:
1292                         case BC_ifle:
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));
1296                                 bb_end = true;
1297                                 break;
1298
1299                         case BC_if_icmpeq:
1300                         case BC_if_icmpne:
1301                         case BC_if_icmplt:
1302                         case BC_if_icmpge:
1303                         case BC_if_icmpgt:
1304                         case BC_if_icmple:
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));
1309                                 bb_end = true;
1310                                 break;
1311
1312                         case BC_if_acmpeq:
1313                         case BC_if_acmpne:
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));
1318                                 bb_end = true;
1319                                 break;
1320
1321                         case BC_goto:
1322                                 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1323                                 bb_end = true;
1324                                 break;
1325
1326                         case BC_jsr:
1327                                 op_stack_push_unknown(be->stack);
1328                                 bc_escape_analysis_branch_target(be, jcode_get_branch_target(jc));
1329                                 bb_end = true;
1330                                 break;
1331
1332                         case BC_ret:
1333                                 break;
1334
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);
1340                                 bb_end = 1;
1341                                 break;
1342
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);
1348                                 bb_end = 1;
1349                                 break;
1350
1351                         case BC_return:
1352                                 bb_end = true;
1353                                 break;
1354
1355                         case BC_ireturn:
1356                         case BC_freturn:
1357                                 op_stack_pop(be->stack);
1358                                 bb_end = true;
1359                                 break;
1360
1361                         case BC_lreturn:
1362                         case BC_dreturn:
1363                                 op_stack_pop(be->stack);
1364                                 op_stack_pop(be->stack);
1365                                 bb_end = true;
1366                                 break;
1367
1368                         case BC_areturn:
1369                                 /* FIXME */
1370                                 bc_escape_analyisis_returned(be, op_stack_pop(be->stack));
1371                                 bb_end = true;
1372                                 break;
1373
1374                         case BC_getfield:
1375                                 op_stack_pop(be->stack);
1376                                 /* Fall through. */
1377
1378                         case BC_getstatic:
1379                                 if (
1380                                         bc_escape_analysis_value_category(be, jcode_get_s2(jc)) == 
1381                                         VALUE_CATEGORY_2
1382                                 ) {
1383                                         op_stack_push_unknown(be->stack);
1384                                 }
1385                                 op_stack_push_unknown(be->stack);
1386                                 break;
1387
1388                         
1389                         case BC_putfield:
1390                                 if (
1391                                         bc_escape_analysis_value_category(be, jcode_get_u2(jc)) == 
1392                                         VALUE_CATEGORY_2
1393                                 ) {
1394                                         op_stack_pop(be->stack);
1395
1396                                         op_stack_pop(be->stack);
1397                                         op_stack_pop(be->stack);
1398                                 } else {
1399                                         value2 = op_stack_pop(be->stack);
1400                                         value1 = op_stack_pop(be->stack);
1401                                         bc_escape_analysis_adjust_state(be, value2, ESCAPE_GLOBAL);
1402                                 }
1403                                 break;
1404
1405                         case BC_putstatic:
1406                                 if (
1407                                         bc_escape_analysis_value_category(be, jcode_get_u2(jc)) == 
1408                                         VALUE_CATEGORY_2
1409                                 ) {
1410                                         op_stack_pop(be->stack);
1411                                         op_stack_pop(be->stack);
1412                                 } else {
1413                                         value1 = op_stack_pop(be->stack);
1414                                         bc_escape_analysis_adjust_state(be, value1, ESCAPE_GLOBAL);
1415                                 }
1416                                 break;
1417
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);
1424                                 break;
1425
1426                         case BC_new:
1427                                 op_stack_push_unknown(be->stack);
1428                                 break;
1429
1430                         case BC_newarray:
1431                         case BC_anewarray:
1432                                 op_stack_pop(be->stack);
1433                                 op_stack_push_unknown(be->stack);
1434                                 break;
1435
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);
1439                                 break;
1440
1441                         case BC_athrow:
1442                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1443                                 bb_end = true;
1444                                 break;
1445
1446                         case BC_checkcast:
1447                                 value1 = op_stack_get(be->stack, 1);
1448                                 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1449                                 break;
1450
1451                         case BC_instanceof:
1452                                 value1 = op_stack_pop(be->stack);
1453                                 bc_escape_analysis_adjust_state(be, value1, ESCAPE_METHOD);
1454                                 op_stack_push_unknown(be->stack);
1455                                 break;
1456
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);
1461                                 break;
1462
1463                         case BC_wide:
1464
1465                                 /* All except iinc have a length of 4. */
1466                                 length = 4;
1467
1468                                 switch (jcode_get_u1(jc)) {
1469                                         case BC_iload:
1470                                         case BC_fload:
1471                                                 op_stack_push_unknown(be->stack);
1472                                                 break;
1473
1474                                         case BC_lload:
1475                                         case BC_dload:
1476                                                 op_stack_push_unknown(be->stack);
1477                                                 op_stack_push_unknown(be->stack);
1478                                                 break;
1479
1480                                         case BC_aload:
1481                                                 op_stack_push(
1482                                                         be->stack, 
1483                                                         bc_escape_analysis_address_local(
1484                                                                 be, 
1485                                                                 jcode_get_u1(jc)
1486                                                         )
1487                                                 );
1488                                                 break;
1489
1490                                         case BC_istore:
1491                                         case BC_fstore:
1492                                                 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1493                                                 op_stack_pop(be->stack);
1494                                                 break;
1495
1496                                         case BC_lstore:
1497                                         case BC_dstore:
1498                                                 bc_escape_analysis_dirty_2(be, jcode_get_u2(jc));
1499                                                 op_stack_pop(be->stack);
1500                                                 op_stack_pop(be->stack);
1501                                                 break;
1502
1503                                         case BC_astore:
1504                                                 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1505                                                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1506                                                 break;
1507                                                 
1508                                         case BC_ret:
1509                                                 /* Do nothing. */
1510                                                 break;
1511
1512                                         case BC_iinc:
1513                                                 bc_escape_analysis_dirty(be, jcode_get_u2(jc));
1514                                                 length = 6;
1515                                                 /* Do nothing. */
1516                                                 break;
1517                                 }
1518                                 break;
1519
1520                         case BC_multianewarray:
1521                                 jcode_get_u2(jc);
1522                                 dim = jcode_get_u1(jc);
1523                                 while (dim-- > 0) {
1524                                         op_stack_pop(be->stack);
1525                                 }
1526                                 op_stack_push_unknown(be->stack);
1527                                 break;
1528
1529                         case BC_ifnull:
1530                         case BC_ifnonnull:
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));
1535                                 bb_end = true;
1536                                 break;
1537
1538                         case BC_goto_w:
1539                                 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1540                                 bb_end = true;
1541                                 break;
1542
1543                         case BC_jsr_w:
1544                                 bc_escape_analysis_branch_target(be, jcode_get_branch_target_wide(jc));
1545                                 bb_end = true;
1546                                 break;
1547
1548                         case BC_breakpoint:
1549                         case BC_impdep1:
1550                         case BC_impdep2:
1551                                 break;
1552
1553                         default:
1554                                 break;
1555                 }
1556                 assert(length > 0);
1557                 jcode_forward_instruction_relative(jc, length);
1558
1559 #if BC_ESCAPE_VERBOSE
1560                 if (be->verbose) {
1561                         op_stack_print(be->stack, stdout);
1562                         printf("\n");
1563                 }
1564 #endif
1565         }
1566
1567 #if BC_ESCAPE_VERBOSE
1568         if (be->verbose) {
1569                 dprintf(be->depth, "Elements left on stack: %d\n", op_stack_element_count(be->stack));
1570         }
1571 #endif
1572
1573         while (! op_stack_is_empty(be->stack)) {
1574 #if BC_ESCAPE_VERBOSE
1575                 if (be->verbose) {
1576                         dprintf(be->depth, "Stack element: ");
1577                         op_stack_print(be->stack, stdout);
1578                         printf(" => ");
1579                 }
1580 #endif
1581                 bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
1582 #if BC_ESCAPE_VERBOSE
1583                 if (be->verbose) {
1584                         op_stack_print(be->stack, stdout);
1585                         printf("\n");
1586                 }
1587 #endif
1588         }
1589 }
1590
1591 static void     bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
1592         escape_state_t e, pe;
1593         int i;
1594
1595         /* Only calculate, if return value is of type address. */
1596
1597         if (be->method->parseddesc->returntype.type != TYPE_ADR) {
1598                 return ;
1599         }
1600
1601         /* Get current escape state of return value. */
1602
1603         e = (escape_state_t)be->param_escape[-1];
1604
1605         /* If a parameter can be returned, adjust to its escape state. */
1606
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];
1610                         if (pe > e) {
1611                                 e = pe;
1612                         }
1613                 }
1614         }
1615
1616         be->param_escape[-1] = (u1)e;
1617 }
1618
1619 static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
1620         raw_exception_entry *itee;
1621         basicblock_work_item_t *bb;
1622         jcode_t jc;
1623
1624         /* Add root as basic block. */
1625
1626         bc_escape_analysis_branch_target(be, 0);
1627
1628         /* Add each exception handler as basic block. */
1629
1630         for (
1631                 itee = be->method->rawexceptiontable;
1632                 itee != be->method->rawexceptiontable + be->method->rawexceptiontablelength;
1633                 ++itee
1634         ) {
1635                 bc_escape_analysis_branch_target(be, itee->handlerpc);
1636         }
1637
1638         /* Init jcode parser. */
1639
1640         jcode_init(
1641                 &jc,
1642                 be->method->jcode,
1643                 be->method->jcodelength,
1644                 0
1645         );
1646
1647         /* Process basicblock by basicblock. */
1648
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(
1652                         be,
1653                         &jc
1654                 );
1655         }
1656
1657         /* Calculate escape of return value. */
1658
1659         bc_escape_analysis_adjust_return_value(be);
1660
1661         /* Export escape of parameters. */
1662
1663         be->method->paramescape = be->param_escape;
1664 }
1665
1666 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
1667         bc_escape_analysis_t *be;
1668         bool verbose = false;
1669
1670 #if BC_ESCAPE_VERBOSE
1671         if (verbose) {
1672                 dprintf(
1673                         depth,
1674                         "=== BC escape analysis of %s/%s at depth %d ===\n",
1675                         m->clazz->name->text,
1676                         m->name->text,
1677                         depth
1678                 );
1679         }
1680 #endif
1681
1682         if (m->paramescape != NULL) {
1683 #if BC_ESCAPE_VERBOSE
1684                 if (verbose) {  
1685                         dprintf(depth, "Escape info for method already available.\n");
1686                 }
1687 #endif
1688                 return;
1689         }
1690
1691         if ((m->flags & ACC_METHOD_EA) != 0) {
1692 #if BC_ESCAPE_VERBOSE
1693                 if (verbose) {  
1694                         dprintf(depth, "Detected recursion, aborting.\n");
1695                 }
1696 #endif
1697                 return;
1698         }
1699
1700         if (m->jcode == NULL) {
1701 #if BC_ESCAPE_VERBOSE
1702                 if (verbose) {
1703                         dprintf(depth, "No bytecode for callee.\n");
1704                 }
1705 #endif
1706                 return;
1707         }
1708
1709         /* TODO threshold */
1710
1711         be = DNEW(bc_escape_analysis_t);
1712         bc_escape_analysis_init(be, m, verbose, depth);
1713
1714         m->flags |= ACC_METHOD_EA;
1715
1716         bc_escape_analysis_analyze(be);
1717
1718 #if BC_ESCAPE_VERBOSE
1719         if (be->verbose) {
1720                 dprintf(
1721                         depth,
1722                         "%s/%s: Non-escaping params: %d\n", 
1723                         m->clazz->name->text,
1724                         m->name->text,
1725                         be->non_escaping_adr_params
1726                 );
1727         }
1728 #endif
1729
1730         m->flags &= ~ACC_METHOD_EA;
1731 }
1732
1733 void bc_escape_analysis_perform(methodinfo *m) {
1734         bc_escape_analysis_perform_intern(m, 0);
1735 }
1736
1737