b1c0679d584720036e7d81704fc7d160c5d62cfd
[cacao.git] / src / vm / jit / optimizing / escape.c
1 /* src/vm/optimizing/escape.c
2
3    Copyright (C) 2008
4    CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 */
23
24 #include "vm/jit/jit.h"
25 #include "vmcore/class.h"
26 #include "vm/jit/optimizing/escape.h"
27
28 /*** escape_state *************************************************************/
29
30 const char *escape_state_to_string(escape_state_t escape_state) {
31 #       define str(x) case x: return #x;
32         switch (escape_state) {
33                 str(ESCAPE_UNKNOWN)
34                 str(ESCAPE_NONE)
35                 str(ESCAPE_METHOD)
36                 str(ESCAPE_GLOBAL_THROUGH_METHOD)
37                 str(ESCAPE_GLOBAL)
38                 default: return "???";
39         }
40 #       undef str
41 }
42
43 /*** instruction **************************************************************/
44
45 static inline s2 instruction_get_opcode(const instruction *iptr) {
46         if (iptr->opc == ICMD_BUILTIN) {
47                 return iptr->sx.s23.s3.bte->opcode;
48         } else {
49                 return iptr->opc;
50         }
51 }
52
53 static inline bool instruction_is_unresolved(const instruction *iptr) {
54         return iptr->flags.bits & INS_FLAG_UNRESOLVED;
55 }
56
57 static inline s4 instruction_field_type(const instruction *iptr) {
58         if (instruction_is_unresolved(iptr)) {
59                 return iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type;
60         } else {
61                 return iptr->sx.s23.s3.fmiref->p.field->type;
62         }
63 }
64
65 static inline s4 instruction_s1(const instruction *iptr) {
66         return iptr->s1.varindex;
67 }
68
69 static inline s4 instruction_s2(const instruction *iptr) {
70         return iptr->sx.s23.s2.varindex;
71 }
72
73 static inline s4 instruction_s3(const instruction *iptr) {
74         return iptr->sx.s23.s3.varindex;
75 }
76
77 static inline s4 instruction_dst(const instruction *iptr) {
78         return iptr->dst.varindex;
79 }
80
81 static inline s4 instruction_arg(const instruction *iptr, int arg) {
82         return iptr->sx.s23.s2.args[arg];
83 }
84
85 static inline bool instruction_is_class_constant(const instruction *iptr) {
86         return iptr->flags.bits & INS_FLAG_CLASS;
87 }
88
89 static inline classinfo *instruction_classinfo(const instruction *iptr) {
90         return iptr->sx.val.c.cls;
91 }
92
93 static inline methodinfo *instruction_local_methodinfo(const instruction *iptr) {
94         if (instruction_is_unresolved(iptr)) {
95                 return NULL;
96         } else {
97                 return iptr->sx.s23.s3.fmiref->p.method;
98         }
99 }
100
101 static inline int instruction_dst_type(const instruction *iptr, jitdata *jd) {
102         return VAROP(iptr->dst)->type;
103 }
104
105 static inline int instruction_return_type(const instruction *iptr) {
106         return instruction_call_site(iptr)->returntype.type;
107 }
108
109 static inline s4 instruction_arg_type(const instruction *iptr, int arg) {
110         methoddesc *md = instruction_call_site(iptr);
111         assert(0 <= arg && arg < md->paramcount);
112         return md->paramtypes[arg].type;
113 }
114
115 static inline int instruction_arg_count(const instruction *iptr) {
116         return instruction_call_site(iptr)->paramcount;
117 }
118
119 /*** instruction_list ********************************************************/
120
121 typedef struct instruction_list_item {
122         instruction *instr;
123         struct instruction_list_item *next;
124 } instruction_list_item_t;
125
126 typedef struct {
127         instruction_list_item_t *first;
128 } instruction_list_t;
129
130 void instruction_list_init(instruction_list_t *list) {
131         list->first = NULL;
132 }
133
134 void instruction_list_add(instruction_list_t *list, instruction *instr) {
135         instruction_list_item_t *item = DNEW(instruction_list_item_t);
136         item->instr = instr;
137         item->next = list->first;
138         list->first = item;
139 }
140
141 #define FOR_EACH_INSTRUCTION_LIST(list, it) \
142         for ((it) = (list)->first; (it) != NULL; (it) = (it)->next)
143
144 /*** escape_analysis *********************************************************/
145
146 struct var_extra;
147
148 typedef struct {
149         jitdata *jd;
150
151         instruction_list_t *allocations;
152         instruction_list_t *getfields;
153
154         struct var_extra **var;
155
156         unsigned adr_args_count;
157
158         bool verbose;
159
160 } escape_analysis_t;
161
162 /*** dependency_list_item ****************************************************/
163
164 typedef struct dependency_list_item {
165         instruction *store;
166         struct dependency_list_item *next;
167 } dependency_list_item_t;
168
169 bool dependency_list_item_compare(const dependency_list_item_t *item, const instruction *load) {
170
171         instruction *store = item->store;
172         utf *storen;
173         const utf *loadn;
174
175         if (load->opc == ICMD_AALOAD) {
176
177                 if (store->opc != ICMD_AASTORE) {
178                         return false;
179                 }
180
181                 return true;
182
183         } else {
184
185                 if (store->opc != ICMD_PUTFIELD) {
186                         return false;
187                 }
188
189                 if (
190                         instruction_is_unresolved(store) !=
191                         instruction_is_unresolved(load)
192                 ) {
193                         return false;
194                 }
195
196                 if (instruction_is_unresolved(store)) {
197                         storen = store->sx.s23.s3.uf->fieldref->name;
198                         loadn = load->sx.s23.s3.uf->fieldref->name;
199                 } else {
200                         storen = store->sx.s23.s3.fmiref->name;
201                         loadn = load->sx.s23.s3.fmiref->name;
202                 }
203
204                 /* TODO pointer equality ? */   
205
206                 if (storen->blength != loadn->blength) {
207                         return false;
208                 }
209
210                 return (strcmp(storen->text, loadn->text) == 0);
211         }
212 }
213
214 /* TODO rename */
215 s4 dependency_list_item_get_dependency(const dependency_list_item_t *item) {
216         switch (item->store->opc) {
217                 case ICMD_AASTORE:
218                         return instruction_s3(item->store);
219                 case ICMD_PUTFIELD:
220                         return instruction_s2(item->store);
221                 default:
222                         assert(0);
223                         return 0;
224         }
225 }
226
227 /*** dependency_list *********************************************************/
228
229 typedef struct {
230         dependency_list_item_t *first;
231         dependency_list_item_t *last;
232 } dependency_list_t;
233
234 void dependency_list_init(dependency_list_t *dl) {
235         dl->first = NULL;
236         dl->last = NULL;
237 }
238
239 void dependency_list_add(dependency_list_t *dl, instruction *store) {
240         dependency_list_item_t *item = DNEW(dependency_list_item_t);
241
242         item->store = store;
243         item->next = NULL;
244         
245         if (dl->first == NULL) {
246                 dl->first = item;
247                 dl->last = item;
248         } else {
249                 dl->last->next = item;
250                 dl->last = item;
251         }
252 }
253
254 void dependenCy_list_import(dependency_list_t *dl, dependency_list_t *other) {
255
256         if (other == NULL) {
257                 return;
258         }
259
260         if (dl->first == NULL) {
261                 *dl = *other;
262         } else {
263                 dl->last->next = other->first;
264                 dl->last = other->last;
265         }
266
267         other->first = NULL;
268         other->last = NULL;
269         
270 }
271
272 #define FOR_EACH_DEPENDENCY_LIST(dl, it) \
273         for ((it) = (dl)->first; (it) != NULL; (it) = (it)->next)
274
275 /*** var_extra ***************************************************************/
276
277 typedef struct var_extra {
278         instruction *allocation;
279         escape_state_t escape_state;
280         s4 representant;
281         dependency_list_t *dependency_list;
282         bool is_arg; /* TODO optimize */
283 } var_extra_t;
284
285 static void var_extra_init(var_extra_t *ve) {
286         ve->allocation = NULL;
287         ve->escape_state = ESCAPE_NONE;
288         ve->representant = -1;
289         ve->dependency_list = NULL;
290         ve->is_arg = false;
291 }
292
293 static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
294         return e->var[var];
295 }
296
297 static var_extra_t* var_extra_get(escape_analysis_t *e, s4 var) {
298         var_extra_t *ve;
299
300         assert(0 <= var && var <= e->jd->vartop);
301
302         ve = var_extra_get_no_alloc(e, var);
303
304         if (ve == NULL) {
305                 ve = DNEW(var_extra_t);
306                 var_extra_init(ve);
307                 e->var[var] = ve;
308         }
309
310         return ve;
311 }
312
313 static s4 var_extra_get_representant(escape_analysis_t *e, s4 var) {
314         var_extra_t *ve;
315 #if !defined(NDEBUG)
316         int ctr = 0;
317 #endif
318
319         ve = var_extra_get(e, var);
320
321         while (ve->representant != -1) {
322                 assert(ctr++ < 10000);
323                 var = ve->representant;
324                 ve = var_extra_get_no_alloc(e, var);
325                 assert(ve);
326         }
327
328         return var;
329 }
330
331 static escape_state_t var_extra_get_escape_state(escape_analysis_t *e, s4 var) {
332         var_extra_t *ve;
333         
334         var = var_extra_get_representant(e, var);
335         ve = var_extra_get(e, var);
336
337         return ve->escape_state;
338 }
339
340 static void var_extra_set_escape_state(escape_analysis_t *e, s4 var, escape_state_t escape_state) {
341         var_extra_t *ve;
342         
343         var = var_extra_get_representant(e, var);
344         ve = var_extra_get(e, var);
345
346         ve->escape_state = escape_state;
347 }
348
349 static dependency_list_t *var_extra_get_dependency_list(escape_analysis_t *e, s4 var) {
350         var_extra_t *ve;
351         
352         var = var_extra_get_representant(e, var);
353         ve = var_extra_get(e, var);
354
355         if (ve->dependency_list == NULL) {
356                 ve->dependency_list = DNEW(dependency_list_t);
357                 dependency_list_init(ve->dependency_list);
358         }
359
360         return ve->dependency_list;
361 }
362
363 /*** escape_analysis *********************************************************/
364
365 static void escape_analysis_init(escape_analysis_t *e, jitdata *jd) {
366         e->jd = jd;
367
368         e->allocations = DNEW(instruction_list_t);
369         instruction_list_init(e->allocations);
370
371         e->getfields = DNEW(instruction_list_t);
372         instruction_list_init(e->getfields);
373
374         e->var = DMNEW(var_extra_t *, jd->vartop);
375         MZERO(e->var, var_extra_t *, jd->vartop);
376
377         e->adr_args_count = 0;
378
379         e->verbose = (
380                 strcmp(e->jd->m->clazz->name->text, "gnu/java/util/regex/RESyntax") == 0 
381                 && strcmp(e->jd->m->name->text, "<clinit>") == 0
382         );
383         e->verbose = 1;
384 }
385
386 static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr) {
387         var_extra_get(e, var)->allocation = iptr;
388 }
389
390 static instruction *escape_analysis_get_allocation(const escape_analysis_t *e, s4 var) {
391         var_extra_t *ve = var_extra_get_no_alloc(e, var);
392
393         assert(ve != NULL);
394         assert(ve->allocation != NULL);
395
396         return ve->allocation;
397 }
398
399 static void escape_analysis_set_is_argument(escape_analysis_t *e, s4 var) {
400         var_extra_get(e, var)->is_arg = true;
401 }
402
403 static bool escape_analysis_get_is_argument(escape_analysis_t *e, s4 var) {
404         return var_extra_get(e, var)->is_arg;
405 }
406
407 static void escape_analysis_ensure_state(escape_analysis_t *e, s4 var, escape_state_t escape_state) {
408         
409         var_extra_t *ve;
410         dependency_list_item_t *it;
411
412         var = var_extra_get_representant(e, var);
413         ve = var_extra_get(e, var);
414
415         if (ve->escape_state < escape_state) {
416                 if (e->verbose) {
417                         printf(
418                                 "escape state of %d %s => %s\n", 
419                                 var, 
420                                 escape_state_to_string(ve->escape_state), 
421                                 escape_state_to_string(escape_state)
422                         );
423                 }
424                 ve->escape_state = escape_state;
425                 if (ve->dependency_list != NULL) {
426                         FOR_EACH_DEPENDENCY_LIST(ve->dependency_list, it) {
427                                 if (e->verbose) {
428                                         printf("propagating to %s@%d\n", icmd_table[it->store->opc].name, it->store->line);
429                                 }
430                                 escape_analysis_ensure_state(
431                                         e, 
432                                         dependency_list_item_get_dependency(it),
433                                         escape_state
434                                 );
435                         }
436                 }
437         }
438 }
439
440 static escape_state_t escape_analysis_get_state(escape_analysis_t *e, s4 var) {
441         return var_extra_get_escape_state(e, var);
442 }
443
444 #define escape_analysis_assert_has_escape(e, var) \
445         assert( \
446                 var_extra_get_no_alloc(e, var) && \
447                 (var_extra_get_no_alloc(e, var)->escape_state > ESCAPE_UNKNOWN) \
448         )
449
450 static classinfo *escape_analysis_classinfo_in_var(escape_analysis_t *e, s4 var) {
451         instruction *iptr = escape_analysis_get_allocation(e, var);
452
453         if (iptr == NULL) {
454                 return NULL;
455         }
456
457         if (! instruction_is_class_constant(iptr)) {
458                 return NULL;
459         }
460
461         if (instruction_dst(iptr) != var) {
462                 return NULL;
463         }
464
465         if (instruction_is_unresolved(iptr)) {
466                 return NULL;
467         }
468
469         return instruction_classinfo(iptr);
470 }
471
472 static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
473
474         var_extra_t *ve1, *ve2;
475         dependency_list_item_t *itd;
476         bool has_become_arg;
477
478         var1 = var_extra_get_representant(e, var1);
479         var2 = var_extra_get_representant(e, var2);
480
481         /* Don't merge the same escape sets. */
482
483         if (var1 == var2) {
484                 return;
485         }
486
487         ve1 = var_extra_get(e, var1);
488         ve2 = var_extra_get(e, var2);
489
490         /* Adjust escape state to maximal escape state. */
491
492         escape_analysis_ensure_state(e, var1, ve2->escape_state);
493         escape_analysis_ensure_state(e, var2, ve1->escape_state);
494
495         /* Representant of var1 becomes the representant of var2. */
496
497         ve2->representant = var1;
498
499         /* Adjust is_argument to logical or. */
500         
501         has_become_arg = ve1->is_arg != ve2->is_arg;
502         ve1->is_arg = ve1->is_arg || ve2->is_arg;
503
504         if (e->verbose && has_become_arg) printf("(%d,%d) has become arg.\n", var1, var2);
505
506         /* Merge list of dependencies. */
507
508         if (ve1->dependency_list == NULL) {
509                 ve1->dependency_list = ve2->dependency_list;
510         } else {
511                 dependenCy_list_import(ve1->dependency_list, ve2->dependency_list);
512         }
513
514         /* If one of the merged values is an argument but the other not,
515            all dependencies of the newly created value escape globally. */
516
517         if (has_become_arg && ve1->dependency_list != NULL) {
518                 FOR_EACH_DEPENDENCY_LIST(ve1->dependency_list, itd) {
519                         escape_analysis_ensure_state(
520                                 e,
521                                 dependency_list_item_get_dependency(itd),
522                                 ESCAPE_GLOBAL
523                         );
524                 }
525         }
526 }
527
528 static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
529         s4 obj = instruction_s1(store);
530         dependency_list_t *dl = var_extra_get_dependency_list(e, obj);
531
532         assert(store->opc == ICMD_PUTFIELD || store->opc == ICMD_AASTORE);
533
534         dependency_list_add(dl, store);
535
536         if (e->verbose) {
537                 printf("dependency_list_add\n");
538         }
539 }
540
541 static void escape_analysis_process_instruction(escape_analysis_t *e, instruction *iptr) {
542         jitdata *jd = e->jd;
543         classinfo *c;
544         s4 count;
545         u1 *paramescape;
546         unsigned i;
547         instruction **iarg;
548         constant_FMIref *fmi;
549         methodinfo *mi;
550         resolve_result_t result;
551
552         if (e->verbose) {
553                 printf("processing %s@%d\n", icmd_table[iptr->opc].name, iptr->line);
554         }
555
556         switch (instruction_get_opcode(iptr)) {
557                 case ICMD_ACONST:
558
559                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
560                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
561
562                         break;
563
564                 case ICMD_NEW:
565                         c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
566
567                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
568
569                         if (c == NULL) {
570                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
571                                 if (e->verbose) printf("1\n");
572                         } else if (c->finalizer != NULL) {
573                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
574                                 if (e->verbose) printf("3\n");
575                         } else {
576                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
577                                 if (e->verbose) printf("2\n");
578                         }
579
580                         instruction_list_add(e->allocations, iptr);
581
582                         break;
583
584                 case ICMD_NEWARRAY:
585                 case ICMD_ANEWARRAY:
586                         
587                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
588                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
589                         instruction_list_add(e->allocations, iptr);
590
591                         break;
592
593                 case ICMD_PUTSTATIC:
594                         if (instruction_field_type(iptr) == TYPE_ADR) {
595                                 /*
596                                 escape_analysis_assert_has_escape(e, instruction_s1(iptr));
597                                 */
598                                 escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
599                         }
600                         break;
601
602                 case ICMD_PUTFIELD:
603                         if (instruction_field_type(iptr) == TYPE_ADR) {
604                                 /*
605                                 escape_analysis_assert_has_escape(e, instruction_s1(iptr));
606                                 escape_analysis_assert_has_escape(e, instruction_s2(iptr));
607                                 */
608                                 if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
609                                         escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_GLOBAL);
610                                 } else {
611                                         escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
612                                         escape_analysis_add_dependency(e, iptr);
613                                 }
614                         }
615                         break;
616
617                 case ICMD_AASTORE:
618                         /*
619                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
620                         escape_analysis_assert_has_escape(e, instruction_s3(iptr));
621                         */
622                         if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
623                                 escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
624                         } else {
625                                 escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
626                                 escape_analysis_add_dependency(e, iptr);
627                         }
628                         break;
629
630                 case ICMD_GETSTATIC:
631                         if (instruction_field_type(iptr) == TYPE_ADR) {
632                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
633                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
634                         }
635                         break;
636
637                 case ICMD_GETFIELD:
638                         if (instruction_field_type(iptr) == TYPE_ADR) {
639                                 /*
640                                 escape_analysis_assert_has_escape(e, instruction_s1(iptr));
641                                 */
642
643                                 if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
644                                         /* Fields loaded from arguments escape globally.
645                                            x = arg.foo;
646                                            x.bar = y;
647                                            => y escapes globally. */
648                                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
649                                 } else {
650                                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
651                                 }
652
653                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
654
655                                 instruction_list_add(e->getfields, iptr);
656                         }
657                         break;
658
659                 case ICMD_ARRAYLENGTH:
660                         /*
661                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
662                         */
663                         break;
664
665                 case ICMD_AALOAD:
666                         /*
667                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
668                         */
669
670                         if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
671                                 /* If store into argument, escapes globally. See ICMD_GETFIELD. */
672                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
673                         } else {
674                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
675                         }
676
677                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
678
679                         instruction_list_add(e->getfields, iptr);
680                         break;
681
682                 case ICMD_IF_ACMPEQ:
683                 case ICMD_IF_ACMPNE:
684                         /*
685                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
686                         escape_analysis_assert_has_escape(e, instruction_s2(iptr));
687                         */
688                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
689                         escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_METHOD);
690                         break;
691
692                 case ICMD_IFNULL:
693                 case ICMD_IFNONNULL:
694                 case ICMD_CHECKNULL:
695                         /*
696                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
697                         */
698                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
699                         break;
700
701                 case ICMD_CHECKCAST:
702                         /*
703                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
704                         */
705                         escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
706                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
707                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
708                         break;
709
710                 case ICMD_INSTANCEOF:
711                         /*
712                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
713                         */
714                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
715                         break;
716
717                 case ICMD_INVOKESPECIAL:
718                 case ICMD_INVOKEVIRTUAL:
719                 case ICMD_INVOKEINTERFACE:
720                 case ICMD_INVOKESTATIC:
721                         count = instruction_arg_count(iptr);
722                         mi = instruction_local_methodinfo(iptr);
723                         paramescape = NULL;
724
725                         if (mi != NULL) {
726                                 /* If the method could be resolved, it already is. */
727                                 paramescape = mi->paramescape;
728
729                                 if (paramescape == NULL) {
730                                         if (e->verbose) {
731                                                 printf("BC escape analyzing callee.\n");
732                                         }
733                                         bc_escape_analysis_perform(mi);
734                                         paramescape = mi->paramescape;
735                                 }
736                         } else {
737                                 if (e->verbose) {
738                                         printf("Unresolved callee.\n");
739                                 }
740                         }
741
742                         for (i = 0; i < count; ++i) {
743                                 if (instruction_arg_type(iptr, i) == TYPE_ADR) {
744
745                                         /*
746                                         escape_analysis_assert_has_escape(e, instruction_arg(iptr, i));
747                                         */
748                                         if (paramescape == NULL) {
749                                                 escape_analysis_ensure_state(
750                                                         e, 
751                                                         instruction_arg(iptr, i), 
752                                                         instruction_local_methodinfo(iptr) && instruction_local_methodinfo(iptr)->jcode ?
753                                                                 ESCAPE_GLOBAL_THROUGH_METHOD :
754                                                                 ESCAPE_GLOBAL
755                                                 );
756                                         } else if ((escape_state_t)*paramescape < ESCAPE_METHOD) {
757                                                 escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_METHOD);
758                                         } else {
759                                                 escape_analysis_ensure_state(e, instruction_arg(iptr, i), (escape_state_t)*paramescape);
760                                         }
761
762                                         if (paramescape != NULL) {
763                                                 ++paramescape;
764                                         }
765                                 }
766                         }
767
768                         if (instruction_return_type(iptr) == TYPE_ADR) {
769                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
770                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
771                         }
772
773                         break;
774
775                 case ICMD_ATHROW:
776                         /*
777                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
778                         */
779                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
780                         break;
781
782                 case ICMD_ARETURN:
783                         /*
784                         escape_analysis_assert_has_escape(e, instruction_s1(iptr));
785                         */
786                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
787                         break;
788
789                 case ICMD_ALOAD:
790                 case ICMD_ASTORE:
791                 case ICMD_MOVE:
792                 case ICMD_COPY:
793                         if (instruction_dst_type(iptr, jd) == TYPE_ADR) {
794                                 /*
795                                 escape_analysis_assert_has_escape(e, instruction_s1(iptr));
796                                 */
797                                 escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
798                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
799                         }
800                         break;
801
802                 case ICMD_PHI:
803                         for (
804                                 iarg = iptr->sx.s23.s2.iargs;
805                                 iarg != iptr->sx.s23.s2.iargs + iptr->s1.argcount;
806                                 ++iarg
807                         ) {
808                                 escape_analysis_merge(e, instruction_dst(iptr), instruction_dst(*iarg));
809                         }
810                         break;
811
812                 case ICMD_GETEXCEPTION:
813                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
814                         break;
815         }
816 }
817
818 static void escape_analysis_process_instructions(escape_analysis_t *e) {
819         basicblock *bptr;
820         instruction *iptr;
821
822         FOR_EACH_BASICBLOCK(e->jd, bptr) {
823
824                 for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
825                         escape_analysis_process_instruction(e, iptr);
826                 }
827
828                 FOR_EACH_INSTRUCTION(bptr, iptr) {
829                         escape_analysis_process_instruction(e, iptr);
830                 }
831
832         }
833 }
834
835 static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
836         instruction_list_item_t *iti;
837         dependency_list_item_t *itd;
838         instruction *iptr;
839         dependency_list_t *dl;
840
841         FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
842
843                 iptr = iti->instr;
844
845                 /* Get the object the field/element is loaded from. */
846
847                 dl = var_extra_get_dependency_list(e, instruction_s1(iptr));
848
849                 /* Adjust escape state of all objects in the dependency list,
850                    referenced via the field of this getfield/arraystore. */
851
852                 if (dl != NULL) {
853                         FOR_EACH_DEPENDENCY_LIST(dl, itd) {
854                                 if (dependency_list_item_compare(itd, iptr)) {
855
856                                         /* Fields match. Adjust escape state. */
857
858                                         escape_analysis_ensure_state(
859                                                 e, 
860                                                 dependency_list_item_get_dependency(itd),
861                                                 escape_analysis_get_state(e, instruction_dst(iptr))
862                                         );
863                                 }
864                         }
865                 }
866
867         }
868 }
869
870 static void display_allocation(escape_analysis_t *e, const char *prefix, const instruction *iptr, escape_state_t es) {
871         const char *cl = "WTF";
872         classinfo *c;
873
874         if (instruction_get_opcode(iptr) == ICMD_NEW) {
875                 c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
876                 if (c) {
877                         cl = c->name->text;
878                 }
879         }
880         
881
882         printf(
883                 " %s %s %s: %s %s @%d %s\n", 
884                 prefix,
885                 e->jd->m->clazz->name->text,
886                 e->jd->m->name->text,
887                 icmd_table[iptr->opc].name,
888                 cl,
889                 iptr->line,
890                 escape_state_to_string(es)
891         );
892 }
893
894 static void escape_analysis_mark_allocations(escape_analysis_t *e) {
895         instruction_list_item_t *iti;
896         escape_state_t es;
897 /*
898         FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
899                 es = escape_analysis_get_state(e, instruction_dst(iti->instr));
900                 if (es < ESCAPE_GLOBAL_THROUGH_METHOD) {
901                         display_allocation(e, "****", iti->instr, es);
902                 }
903                 if (es == ESCAPE_GLOBAL_THROUGH_METHOD) {
904                         display_allocation(e, "!!!!", iti->instr, es);
905                 }
906         }
907 */
908 }
909
910 static void escape_analysis_process_arguments(escape_analysis_t *e) {
911         s4 p;
912         s4 t;
913         s4 l;
914         s4 varindex;
915         methoddesc *md;
916         
917         md = e->jd->m->parseddesc;
918
919         for (p = 0, l = 0; p < md->paramcount; ++p) {
920                 t = md->paramtypes[p].type;
921                 varindex = e->jd->local_map[l * 5 + t];
922                 if (t == TYPE_ADR) {
923                         if (varindex != UNUSED) {
924                                 escape_analysis_ensure_state(e, varindex, ESCAPE_NONE);
925                                 escape_analysis_set_is_argument(e, varindex);
926                         }
927                         e->adr_args_count += 1;
928                 }
929                 l += IS_2_WORD_TYPE(t) ? 2 : 1;
930         }
931 }
932
933 static void escape_analysis_export_arguments(escape_analysis_t *e) {
934         s4 p;
935         s4 t;
936         s4 l;
937         s4 varindex;
938         methoddesc *md;
939         u1 *paramescape;
940         
941         md = e->jd->m->parseddesc;
942
943         paramescape = MNEW(u1, e->adr_args_count);
944         e->jd->m->paramescape = paramescape;
945
946         for (p = 0, l = 0; p < md->paramcount; ++p) {
947                 t = md->paramtypes[p].type;
948                 varindex = e->jd->local_map[l * 5 + t];
949                 if (t == TYPE_ADR) {
950                         if (varindex == UNUSED) {
951                                 *paramescape = (u1)ESCAPE_NONE;
952                         } else {
953                                 *paramescape = (u1)escape_analysis_get_state(e, varindex);
954                         }
955                         if (e->verbose) {
956                                 printf("adr parameter %d: %s\n", p, escape_state_to_string((escape_state_t)*paramescape));
957                         }
958                         paramescape += 1;
959                 }
960                 l += IS_2_WORD_TYPE(t) ? 2 : 1;
961         }
962 }
963
964 static void escape_analysis_display(escape_analysis_t *e) {
965         instruction_list_item_t *iti;
966         var_extra_t *ve;
967         instruction *iptr;
968
969         FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
970                 iptr = iti->instr;
971                 ve = var_extra_get(e, instruction_dst(iptr));
972                 printf(
973                         "%s@%d: %s\n", 
974                         icmd_table[iptr->opc].name, 
975                         iptr->line, 
976                         escape_state_to_string(ve->escape_state)
977                 );
978         }
979 }
980
981 void escape_analysis_perform(jitdata *jd) {
982         escape_analysis_t *e;
983
984         jd->m->flags |= ACC_METHOD_EA;
985
986         /*bc_escape_analysis_perform(jd->m);*/
987
988         e = DNEW(escape_analysis_t);
989         escape_analysis_init(e, jd);
990
991         if (e->verbose) 
992                 printf("==== %s/%s ====\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
993                 
994         /*fprintf(stderr, ".");*/
995
996         escape_analysis_process_arguments(e);
997         escape_analysis_process_instructions(e);
998         escape_analysis_post_process_getfields(e);
999         escape_analysis_export_arguments(e);
1000         if (e->verbose) escape_analysis_display(e);
1001         escape_analysis_mark_allocations(e);
1002
1003         jd->m->flags &= ~ACC_METHOD_EA;
1004 }
1005
1006 void escape_analysis_escape_check(void *vp) {
1007 }