* configure.ac: New switch for disabling -O2 (--disable-optimizations).
[cacao.git] / src / vm / jit / optimizing / escape.c
1 /* src/vm/jit/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
25
26 #include "config.h"
27
28 #include "vm/class.hpp"
29 #include "vm/classcache.hpp"
30
31 #include "vm/jit/jit.hpp"
32 #include "vm/jit/optimizing/escape.h"
33
34 #include <stdarg.h>
35
36 #if defined(ENABLE_ESCAPE_REASON)
37 #define ENABLE_REASON
38 #endif
39
40 #if defined(ENABLE_REASON)
41 #define I2(why, tov, es) escape_analysis_record_reason(e, why, iptr, tov, es);
42 #else
43 #define I2(why, tov, es)
44 #endif
45 #define I(why, to, from) I2(why, instruction_ ## to (iptr), escape_analysis_get_state(e, instruction_ ## from (iptr)))
46 #define E2(why, var) I2(why, var, ESCAPE_GLOBAL)
47 #define E(why, which) E2(why, instruction_ ## which (iptr))
48
49 typedef enum {
50         RED = 31,
51         GREEN,
52         YELLOW,
53         BLUE,
54         MAGENTA,
55         CYAN,
56         WHITE,
57         COLOR_END
58 } color_t;
59
60 #define ENABLE_COLOR
61
62 static void color_start(color_t color) {
63 #if defined(ENABLE_COLOR)
64         if (RED <= color && color < COLOR_END) {
65                 printf("\033[%dm", color);
66         }
67 #endif
68 }
69
70 static void color_end() {
71 #if defined(ENABLE_COLOR)
72         printf("\033[m");
73         fflush(stdout);
74 #endif
75 }
76
77 static void color_printf(color_t color, const char *fmt, ...) {
78         va_list ap;
79         color_start(color);
80         va_start(ap, fmt);
81         vprintf(fmt, ap);
82         va_end(ap);
83         color_end();
84 }
85
86
87 /*** escape_state *************************************************************/
88
89 const char *escape_state_to_string(escape_state_t escape_state) {
90 #       define str(x) case x: return #x;
91         switch (escape_state) {
92                 str(ESCAPE_UNKNOWN)
93                 str(ESCAPE_NONE)
94                 str(ESCAPE_METHOD)
95                 str(ESCAPE_METHOD_RETURN)
96                 str(ESCAPE_GLOBAL)
97                 default: return "???";
98         }
99 #       undef str
100 }
101
102 /*** instruction **************************************************************/
103
104 static inline s2 instruction_get_opcode(const instruction *iptr) {
105         if (iptr->opc == ICMD_BUILTIN) {
106                 return iptr->sx.s23.s3.bte->opcode;
107         } else {
108                 return iptr->opc;
109         }
110 }
111
112 static inline bool instruction_is_unresolved(const instruction *iptr) {
113         return iptr->flags.bits & INS_FLAG_UNRESOLVED;
114 }
115
116 static inline s4 instruction_field_type(const instruction *iptr) {
117         if (instruction_is_unresolved(iptr)) {
118                 return iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type;
119         } else {
120                 return iptr->sx.s23.s3.fmiref->p.field->type;
121         }
122 }
123
124 static inline s4 instruction_s1(const instruction *iptr) {
125         return iptr->s1.varindex;
126 }
127
128 static inline s4 instruction_s2(const instruction *iptr) {
129         return iptr->sx.s23.s2.varindex;
130 }
131
132 static inline s4 instruction_s3(const instruction *iptr) {
133         return iptr->sx.s23.s3.varindex;
134 }
135
136 static inline s4 instruction_dst(const instruction *iptr) {
137         return iptr->dst.varindex;
138 }
139
140 static inline s4 instruction_arg(const instruction *iptr, int arg) {
141         return iptr->sx.s23.s2.args[arg];
142 }
143
144 static inline bool instruction_is_class_constant(const instruction *iptr) {
145         return iptr->flags.bits & INS_FLAG_CLASS;
146 }
147
148 static inline classinfo *instruction_classinfo(const instruction *iptr) {
149         return iptr->sx.val.c.cls;
150 }
151
152 static inline methodinfo *instruction_local_methodinfo(const instruction *iptr) {
153         if (instruction_is_unresolved(iptr)) {
154                 return NULL;
155         } else {
156                 return iptr->sx.s23.s3.fmiref->p.method;
157         }
158 }
159
160 static inline int instruction_dst_type(const instruction *iptr, jitdata *jd) {
161         return VAROP(iptr->dst)->type;
162 }
163
164 static inline int instruction_return_type(const instruction *iptr) {
165         return instruction_call_site(iptr)->returntype.type;
166 }
167
168 static inline s4 instruction_arg_type(const instruction *iptr, int arg) {
169         methoddesc *md = instruction_call_site(iptr);
170         assert(0 <= arg && arg < md->paramcount);
171         return md->paramtypes[arg].type;
172 }
173
174 static inline int instruction_arg_count(const instruction *iptr) {
175         return instruction_call_site(iptr)->paramcount;
176 }
177
178 /*** instruction_list ********************************************************/
179
180 typedef struct instruction_list_item {
181         instruction *instr;
182         struct instruction_list_item *next;
183 } instruction_list_item_t;
184
185 typedef struct {
186         instruction_list_item_t *first;
187 } instruction_list_t;
188
189 void instruction_list_init(instruction_list_t *list) {
190         list->first = NULL;
191 }
192
193 void instruction_list_add(instruction_list_t *list, instruction *instr) {
194         instruction_list_item_t *item = DNEW(instruction_list_item_t);
195         item->instr = instr;
196         item->next = list->first;
197         list->first = item;
198 }
199
200 #define FOR_EACH_INSTRUCTION_LIST(list, it) \
201         for ((it) = (list)->first; (it) != NULL; (it) = (it)->next)
202
203 /*** escape_analysis *********************************************************/
204
205 struct var_extra;
206
207 typedef struct {
208         jitdata *jd;
209
210         instruction_list_t *allocations;
211         instruction_list_t *getfields;
212         instruction_list_t *monitors;
213         instruction_list_t *returns;
214
215         struct var_extra **var;
216
217         unsigned adr_args_count;
218
219         bool verbose;
220
221 } escape_analysis_t;
222
223 /*** dependency_list_item ****************************************************/
224
225 typedef struct dependency_list_item {
226         instruction *store;
227         struct dependency_list_item *next;
228 } dependency_list_item_t;
229
230 bool dependency_list_item_compare(const dependency_list_item_t *item, const instruction *load) {
231
232         instruction *store = item->store;
233         utf *storen;
234         const utf *loadn;
235
236         if (load->opc == ICMD_AALOAD) {
237
238                 if (store->opc != ICMD_AASTORE) {
239                         return false;
240                 }
241
242                 return true;
243
244         } else {
245
246                 if (store->opc != ICMD_PUTFIELD) {
247                         return false;
248                 }
249
250                 if (
251                         instruction_is_unresolved(store) !=
252                         instruction_is_unresolved(load)
253                 ) {
254                         return false;
255                 }
256
257                 if (instruction_is_unresolved(store)) {
258                         storen = store->sx.s23.s3.uf->fieldref->name;
259                         loadn = load->sx.s23.s3.uf->fieldref->name;
260                 } else {
261                         storen = store->sx.s23.s3.fmiref->name;
262                         loadn = load->sx.s23.s3.fmiref->name;
263                 }
264
265                 /* TODO pointer equality ? */   
266
267                 if (storen->blength != loadn->blength) {
268                         return false;
269                 }
270
271                 return (strcmp(storen->text, loadn->text) == 0);
272         }
273 }
274
275 /* TODO rename */
276 s4 dependency_list_item_get_dependency(const dependency_list_item_t *item) {
277         switch (item->store->opc) {
278                 case ICMD_AASTORE:
279                         return instruction_s3(item->store);
280                 case ICMD_PUTFIELD:
281                         return instruction_s2(item->store);
282                 default:
283                         assert(0);
284                         return 0;
285         }
286 }
287
288 /*** dependency_list *********************************************************/
289
290 typedef struct {
291         dependency_list_item_t *first;
292         dependency_list_item_t *last;
293 } dependency_list_t;
294
295 void dependency_list_init(dependency_list_t *dl) {
296         dl->first = NULL;
297         dl->last = NULL;
298 }
299
300 void dependency_list_add(dependency_list_t *dl, instruction *store) {
301         dependency_list_item_t *item = DNEW(dependency_list_item_t);
302
303         item->store = store;
304         item->next = NULL;
305         
306         if (dl->first == NULL) {
307                 dl->first = item;
308                 dl->last = item;
309         } else {
310                 dl->last->next = item;
311                 dl->last = item;
312         }
313 }
314
315 void dependenCy_list_import(dependency_list_t *dl, dependency_list_t *other) {
316
317         if (other == NULL) {
318                 return;
319         }
320
321         if (dl->first == NULL) {
322                 *dl = *other;
323         } else {
324                 dl->last->next = other->first;
325                 dl->last = other->last;
326         }
327
328         other->first = NULL;
329         other->last = NULL;
330         
331 }
332
333 #define FOR_EACH_DEPENDENCY_LIST(dl, it) \
334         for ((it) = (dl)->first; (it) != NULL; (it) = (it)->next)
335
336 /*** var_extra ***************************************************************/
337
338 #if defined(ENABLE_REASON)
339 typedef struct reason {
340         const char *why;
341         instruction *iptr;
342         struct reason *next;
343 } reason_t;
344 #endif
345
346 typedef struct var_extra {
347         instruction *allocation;
348         escape_state_t escape_state;
349         s4 representant;
350         dependency_list_t *dependency_list;
351         unsigned contains_arg:1;
352         unsigned contains_only_args:1;
353         /*signed adr_arg_num:30;*/
354 #if defined(ENABLE_REASON)
355         reason_t *reasons;
356 #endif
357 } var_extra_t;
358
359 static void var_extra_init(var_extra_t *ve) {
360         ve->allocation = NULL;
361         ve->escape_state = ESCAPE_NONE;
362         ve->representant = -1;
363         ve->dependency_list = NULL;
364         ve->contains_arg = false;
365         ve->contains_only_args = false;
366         /*ve->adr_arg_num = -1;*/
367 #if defined(ENABLE_REASON)
368         ve->reasons = NULL;
369 #endif
370 }
371
372 static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
373         return e->var[var];
374 }
375
376 static var_extra_t* var_extra_get(escape_analysis_t *e, s4 var) {
377         var_extra_t *ve;
378
379         assert(0 <= var && var <= e->jd->vartop);
380
381         ve = var_extra_get_no_alloc(e, var);
382
383         if (ve == NULL) {
384                 ve = DNEW(var_extra_t);
385                 var_extra_init(ve);
386                 e->var[var] = ve;
387         }
388
389         return ve;
390 }
391
392 static s4 var_extra_get_representant(escape_analysis_t *e, s4 var) {
393         var_extra_t *ve;
394 #if !defined(NDEBUG)
395         int ctr = 0;
396 #endif
397
398         ve = var_extra_get(e, var);
399
400         while (ve->representant != -1) {
401                 assert(ctr++ < 10000);
402                 var = ve->representant;
403                 ve = var_extra_get_no_alloc(e, var);
404                 assert(ve);
405         }
406
407         return var;
408 }
409
410 static escape_state_t var_extra_get_escape_state(escape_analysis_t *e, s4 var) {
411         var_extra_t *ve;
412         
413         var = var_extra_get_representant(e, var);
414         ve = var_extra_get(e, var);
415
416         return ve->escape_state;
417 }
418
419 static void var_extra_set_escape_state(escape_analysis_t *e, s4 var, escape_state_t escape_state) {
420         var_extra_t *ve;
421         
422         var = var_extra_get_representant(e, var);
423         ve = var_extra_get(e, var);
424
425         ve->escape_state = escape_state;
426 }
427
428 static dependency_list_t *var_extra_get_dependency_list(escape_analysis_t *e, s4 var) {
429         var_extra_t *ve;
430         
431         var = var_extra_get_representant(e, var);
432         ve = var_extra_get(e, var);
433
434         if (ve->dependency_list == NULL) {
435                 ve->dependency_list = DNEW(dependency_list_t);
436                 dependency_list_init(ve->dependency_list);
437         }
438
439         return ve->dependency_list;
440 }
441
442 /*** escape_analysis *********************************************************/
443
444 static void escape_analysis_init(escape_analysis_t *e, jitdata *jd) {
445         e->jd = jd;
446
447         e->allocations = DNEW(instruction_list_t);
448         instruction_list_init(e->allocations);
449
450         e->getfields = DNEW(instruction_list_t);
451         instruction_list_init(e->getfields);
452
453         e->monitors = DNEW(instruction_list_t);
454         instruction_list_init(e->monitors);
455
456         e->returns = DNEW(instruction_list_t);
457         instruction_list_init(e->returns);
458
459         e->var = DMNEW(var_extra_t *, jd->vartop);
460         MZERO(e->var, var_extra_t *, jd->vartop);
461
462         e->adr_args_count = 0;
463
464         e->verbose = 1;
465         e->verbose = strcmp(jd->m->name->text, "<init>") == 0;
466         e->verbose = getenv("EV") != NULL;
467 }
468
469 #if defined(ENABLE_REASON)
470 static void escape_analysis_record_reason(escape_analysis_t *e, const char *why, instruction *iptr, s4 var, escape_state_t es) {
471         var_extra_t *ve;
472         reason_t *re;
473         if (es == ESCAPE_GLOBAL || es == ESCAPE_METHOD_RETURN) {
474                 var = var_extra_get_representant(e, var);
475                 ve = var_extra_get(e, var);
476                 re = NEW(reason_t);
477                 re->why = why;
478                 re->iptr= iptr;
479                 re->next = ve->reasons;
480                 ve->reasons = re;
481                 if (e->verbose) {
482                         printf("%d escapes because %s\n", var, why);
483                 }
484         }
485 }
486 #endif
487
488 static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr) {
489         var_extra_get(e, var)->allocation = iptr;
490 }
491
492 static instruction *escape_analysis_get_allocation(const escape_analysis_t *e, s4 var) {
493         var_extra_t *ve = var_extra_get_no_alloc(e, var);
494
495         assert(ve != NULL);
496         assert(ve->allocation != NULL);
497
498         return ve->allocation;
499 }
500
501 static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var) {
502         var = var_extra_get_representant(e, var);
503         var_extra_get(e, var)->contains_arg = true;
504 }
505
506 static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var) {
507         var = var_extra_get_representant(e, var);
508         return var_extra_get(e, var)->contains_arg;
509 }
510
511 static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var) {
512         var = var_extra_get_representant(e, var);
513         var_extra_get(e, var)->contains_only_args = true;
514 }
515
516 static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var) {
517         var = var_extra_get_representant(e, var);
518         return var_extra_get(e, var)->contains_only_args;
519 }
520
521 /*
522 static void escape_analysis_set_adr_arg_num(escape_analysis_t *e, s4 var, s4 num) {
523         var_extra_get(e, var)->adr_arg_num = num;
524 }
525
526 static s4 escape_analysis_get_adr_arg_num(escape_analysis_t *e, s4 var) {
527         return var_extra_get(e, var)->adr_arg_num;
528 }
529 */
530
531 static bool escape_analysis_in_same_set(escape_analysis_t *e, s4 var1, s4 var2) {
532         return var_extra_get_representant(e, var1) == var_extra_get_representant(e, var2);
533 }
534
535 static void escape_analysis_ensure_state(escape_analysis_t *e, s4 var, escape_state_t escape_state) {
536         
537         var_extra_t *ve;
538         dependency_list_item_t *it;
539
540         var = var_extra_get_representant(e, var);
541         ve = var_extra_get(e, var);
542
543         if (ve->escape_state < escape_state) {
544                 if (e->verbose) {
545                         printf(
546                                 "escape state of %d %s => %s\n", 
547                                 var, 
548                                 escape_state_to_string(ve->escape_state), 
549                                 escape_state_to_string(escape_state)
550                         );
551                 }
552                 ve->escape_state = escape_state;
553                 if (ve->dependency_list != NULL) {
554                         FOR_EACH_DEPENDENCY_LIST(ve->dependency_list, it) {
555                                 if (e->verbose) {
556                                         printf("propagating to %s@%d\n", icmd_table[it->store->opc].name, it->store->line);
557                                 }
558                                 escape_analysis_ensure_state(
559                                         e, 
560                                         dependency_list_item_get_dependency(it),
561                                         escape_state
562                                 );
563                                 {
564                                 instruction *iptr = NULL;
565                                 I2("propagated by dependency", dependency_list_item_get_dependency(it), escape_state);
566                                 }
567                         }
568                 }
569         }
570 }
571
572 static escape_state_t escape_analysis_get_state(escape_analysis_t *e, s4 var) {
573         return var_extra_get_escape_state(e, var);
574 }
575
576 static classinfo *escape_analysis_classinfo_in_var(escape_analysis_t *e, s4 var) {
577         instruction *iptr = escape_analysis_get_allocation(e, var);
578
579         if (iptr == NULL) {
580                 return NULL;
581         }
582
583         if (! instruction_is_class_constant(iptr)) {
584                 return NULL;
585         }
586
587         if (instruction_dst(iptr) != var) {
588                 return NULL;
589         }
590
591         if (instruction_is_unresolved(iptr)) {
592                 return NULL;
593         }
594
595         return instruction_classinfo(iptr);
596 }
597
598 static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
599
600         var_extra_t *ve1, *ve2;
601         dependency_list_item_t *itd;
602         bool has_become_arg;
603
604         var1 = var_extra_get_representant(e, var1);
605         var2 = var_extra_get_representant(e, var2);
606
607         /* Don't merge the same escape sets. */
608
609         if (var1 == var2) {
610                 return;
611         }
612
613         if (e->verbose) printf("Merging (%d,%d)\n", var1, var2);
614
615         ve1 = var_extra_get(e, var1);
616         ve2 = var_extra_get(e, var2);
617
618         /* Adjust escape state to maximal escape state. */
619
620         escape_analysis_ensure_state(e, var1, ve2->escape_state);
621         escape_analysis_ensure_state(e, var2, ve1->escape_state);
622
623         /* Representant of var1 becomes the representant of var2. */
624
625         ve2->representant = var1;
626
627         /* Adjust is_arg to logical or. */
628         
629         has_become_arg = ve1->contains_arg != ve2->contains_arg;
630         ve1->contains_arg = ve1->contains_arg || ve2->contains_arg;
631
632         if (e->verbose && has_become_arg) printf("(%d,%d) has become arg.\n", var1, var2);
633
634         /* Merge list of dependencies. */
635
636         if (ve1->dependency_list == NULL) {
637                 ve1->dependency_list = ve2->dependency_list;
638         } else {
639                 dependenCy_list_import(ve1->dependency_list, ve2->dependency_list);
640         }
641
642         /* If one of the merged values is an argument but the other not,
643            all dependencies of the newly created value escape globally. */
644
645         if (has_become_arg && ve1->dependency_list != NULL) {
646                 FOR_EACH_DEPENDENCY_LIST(ve1->dependency_list, itd) {
647                         escape_analysis_ensure_state(
648                                 e,
649                                 dependency_list_item_get_dependency(itd),
650                                 ESCAPE_GLOBAL
651                         );
652                         {
653                         instruction *iptr = NULL;
654                         E2("has become arg", dependency_list_item_get_dependency(itd));
655                         }
656                 }
657         }
658
659         /* Adjust contains_only_args to logical and. */
660
661         ve1->contains_only_args = ve1->contains_only_args && ve2->contains_only_args;
662
663         /* Adjust address argument number contained in this var. */
664
665         /*
666         if (ve1->adr_arg_num != ve2->adr_arg_num) {
667                 ve1->adr_arg_num = -1;
668         }
669         */
670 #if defined(ENABLE_REASON)
671         if (ve1->reasons) {
672                 reason_t *re = ve1->reasons;
673                 while (re->next != NULL) {
674                         re = re->next;
675                 }
676                 re->next = ve2->reasons;
677         } else {
678                 ve1->reasons = ve2->reasons;
679         }
680 #endif
681 }
682
683 static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
684         s4 obj = instruction_s1(store);
685         dependency_list_t *dl = var_extra_get_dependency_list(e, obj);
686
687         assert(store->opc == ICMD_PUTFIELD || store->opc == ICMD_AASTORE);
688
689         dependency_list_add(dl, store);
690
691         if (e->verbose) {
692                 printf("dependency_list_add: %d.dependency_list.add( { ", obj);
693                 show_icmd(e->jd, store, 0, 3);
694                 printf(" } )\n"); 
695         }
696 }
697
698 static void escape_analysis_process_instruction(escape_analysis_t *e, instruction *iptr) {
699         jitdata *jd = e->jd;
700         classinfo *c;
701         s4 count;
702         u1 *paramescape;
703         unsigned i;
704         instruction **iarg;
705         methodinfo *mi;
706         escape_state_t es;
707         const char *why;
708
709         if (e->verbose) {
710                 color_start(CYAN);
711                 printf("%d: ", iptr->line);
712                 show_icmd(e->jd, iptr, 0, 3);
713                 color_end();
714                 printf("\n");
715         }
716
717         switch (instruction_get_opcode(iptr)) {
718                 case ICMD_ACONST:
719
720                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
721                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
722
723                         break;
724
725                 case ICMD_NEW:
726                         c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
727
728                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
729
730                         if (c == NULL) {
731                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
732                                 E("unresolved class", dst)
733                         } else if (c->finalizer != NULL) {
734                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
735                                 E("finalizer", dst)
736                         } else {
737                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
738                         }
739
740                         instruction_list_add(e->allocations, iptr);
741
742                         break;
743
744                 case ICMD_MONITORENTER:
745                 case ICMD_MONITOREXIT:
746                 
747                         instruction_list_add(e->monitors, iptr);
748
749                         break;
750
751                 case ICMD_NEWARRAY:
752                 case ICMD_ANEWARRAY:
753                         
754                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
755                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
756                         instruction_list_add(e->allocations, iptr);
757                         E("untracked array", dst)
758                         break;
759
760                 case ICMD_PUTSTATIC:
761                         if (instruction_field_type(iptr) == TYPE_ADR) {
762                                 escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
763                                 E("putstatic", s1)
764                         }
765                         break;
766
767                 case ICMD_PUTFIELD:
768                         if (instruction_field_type(iptr) == TYPE_ADR) {
769                                 if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
770                                         escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_GLOBAL);
771                                         /* If s1 is currently not an argument, but can contain one later because
772                                            of a phi function, the merge function takes care to make all
773                                            dependencies escape globally. */
774                                         E("putfield into argument", s2)
775                                 } else {
776                                         I("putfield inherit", s2, s1);
777                                         escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
778                                         escape_analysis_add_dependency(e, iptr);
779                                 }
780                         }
781                         break;
782
783                 case ICMD_AASTORE:
784                         if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
785                                 if (e->verbose) printf("Contains argument.\n");
786                                 escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
787                                 E("aastore into argument", s3)
788                         } else {
789                                 if (e->verbose) printf("Contains no argument.\n");
790                                 I("aastore", s3, s1)
791                                 escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
792                                 escape_analysis_add_dependency(e, iptr);
793                         }
794                         break;
795
796                 case ICMD_GETSTATIC:
797                         if (instruction_field_type(iptr) == TYPE_ADR) {
798                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
799                                 E("loaded from static var", dst)
800                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
801                         }
802                         break;
803
804                 case ICMD_GETFIELD:
805                         if (instruction_field_type(iptr) == TYPE_ADR) {
806
807                                 if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
808                                         /* Fields loaded from arguments escape globally.
809                                            x = arg.foo;
810                                            x.bar = y;
811                                            => y escapes globally. */
812                                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
813                                         E("loaded from arg", dst)
814                                 } else {
815                                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
816                                 }
817
818                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
819
820                                 instruction_list_add(e->getfields, iptr);
821                         }
822                         break;
823
824                 case ICMD_ARRAYLENGTH:
825                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
826                         break;
827
828                 case ICMD_AALOAD:
829
830                         if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
831                                 /* If store into argument, escapes globally. See ICMD_GETFIELD. */
832                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
833                                 E("aaload from argument", dst)
834                         } else {
835                                 escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
836                         }
837
838                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
839
840                         instruction_list_add(e->getfields, iptr);
841                         break;
842
843                 case ICMD_IF_ACMPEQ:
844                 case ICMD_IF_ACMPNE:
845                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
846                         escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_METHOD);
847                         break;
848
849                 case ICMD_IFNULL:
850                 case ICMD_IFNONNULL:
851                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
852                         break;
853
854                 case ICMD_CHECKNULL:
855                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
856                         escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
857                         break;
858
859                 case ICMD_CHECKCAST:
860                         escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
861                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
862                         escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
863                         break;
864
865                 case ICMD_INSTANCEOF:
866                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
867                         break;
868
869                 case ICMD_INVOKESPECIAL:
870                 case ICMD_INVOKEVIRTUAL:
871                 case ICMD_INVOKEINTERFACE:
872                 case ICMD_INVOKESTATIC:
873                         count = instruction_arg_count(iptr);
874                         mi = instruction_local_methodinfo(iptr);
875                         paramescape = NULL;
876                         why = "???";
877
878                         if (mi != NULL) {
879                                 /* If the method could be resolved, it already is. */
880                                 paramescape = mi->paramescape;
881
882                                 if (e->verbose) {
883                                         if (paramescape) {
884                                                 printf("Paramescape for callee available.\n");
885                                         }
886                                 }
887
888                                 if (paramescape) why = "Available param escape";
889
890                                 if (paramescape == NULL) {
891                                         if (e->verbose) {
892                                                 printf("BC escape analyzing callee.\n");
893                                         }
894                                         why = "BC param escape";
895                                         bc_escape_analysis_perform(mi);
896                                         paramescape = mi->paramescape;
897                                 }
898                         } else {
899                                 if (e->verbose) {
900                                         printf("Unresolved callee.\n");
901                                 }
902                                 why = "Unresolved callee";
903                         }
904
905                         if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
906                                 if (mi != NULL && !escape_is_monomorphic(e->jd->m, mi)) {
907                                         if (e->verbose) {
908                                                 printf("Not monomorphic.\n");
909                                         }
910                                         why = "Polymorphic";
911                                         paramescape = NULL;
912                                 }
913                         }
914
915                         /* Set the escape state of the return value.
916                            This is: global if we down have information of the callee, or the callee
917                            supplied escape state. */
918
919                         if (instruction_return_type(iptr) == TYPE_ADR) {
920                                 if (paramescape == NULL) {
921                                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
922                                         E(why, dst);
923                                 } else {
924                                         es = escape_state_from_u1(paramescape[-1]);
925                                         I2(why, instruction_dst(iptr), es)
926                                         escape_analysis_ensure_state(e, instruction_dst(iptr), es);
927                                 }
928                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
929                         }
930                         
931                         for (i = 0; i < count; ++i) {
932                                 if (instruction_arg_type(iptr, i) == TYPE_ADR) {
933
934                                         if (paramescape == NULL) {
935                                                 escape_analysis_ensure_state(
936                                                         e, 
937                                                         instruction_arg(iptr, i), 
938                                                         ESCAPE_GLOBAL
939                                                 );
940                                                 E2(why, instruction_arg(iptr, i));
941                                         } else if (escape_state_from_u1(*paramescape) <= ESCAPE_METHOD) {
942                                                 es = escape_state_from_u1(*paramescape);
943
944                                                 if (es < ESCAPE_METHOD) {
945                                                         es = ESCAPE_METHOD;
946                                                 }
947
948                                                 I2(why, instruction_arg(iptr, i), es);
949                                                 escape_analysis_ensure_state(e, instruction_arg(iptr, i), es);
950
951                                                 if (*paramescape & 0x80) {
952                                                         /* Parameter can be returned from method.
953                                                            This creates an alias to the retur value.
954                                                            If the return value escapes, the ES of the parameter needs 
955                                                            to be adjusted. */
956                                                         escape_analysis_merge(e, instruction_arg(iptr, i), instruction_dst(iptr));
957                                                         I2("return alias", instruction_arg(iptr, i), instruction_dst(iptr));
958                                                 }
959                                         } else {
960                                                 escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_GLOBAL);
961                                                 E2(why, instruction_arg(iptr, i));
962                                         }
963
964                                         if (paramescape != NULL) {
965                                                 ++paramescape;
966                                         }
967                                 }
968                         }
969
970                         break;
971
972                 case ICMD_ATHROW:
973                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
974                         E("throw", s1)
975                         break;
976
977                 case ICMD_ARETURN:
978                         /* If we return only arguments, the return value escapes only the method.
979                            ESCAPE_METHOD for now, and check later, if a different value than an
980                            argument is possibly returned. */
981                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD_RETURN);
982                         E("return", s1)
983                         instruction_list_add(e->returns, iptr);
984                         break;
985
986                 case ICMD_ALOAD:
987                 case ICMD_ASTORE:
988                 case ICMD_MOVE:
989                 case ICMD_COPY:
990                         if (instruction_dst_type(iptr, jd) == TYPE_ADR) {
991                                 escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
992                                 escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
993                         }
994                         break;
995
996                 case ICMD_PHI:
997                         for (
998                                 iarg = iptr->sx.s23.s2.iargs;
999                                 iarg != iptr->sx.s23.s2.iargs + iptr->s1.argcount;
1000                                 ++iarg
1001                         ) {
1002                                 escape_analysis_merge(e, instruction_dst(iptr), instruction_dst(*iarg));
1003                         }
1004                         break;
1005
1006                 case ICMD_GETEXCEPTION:
1007                         escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
1008                         break;
1009         }
1010 }
1011
1012 static void escape_analysis_process_instructions(escape_analysis_t *e) {
1013         basicblock *bptr;
1014         instruction *iptr;
1015
1016         FOR_EACH_BASICBLOCK(e->jd, bptr) {
1017
1018                 if (e->verbose) {
1019                         color_printf(CYAN, "=== BB %d ===\n", bptr->nr);        
1020                 }
1021
1022                 for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
1023                         escape_analysis_process_instruction(e, iptr);
1024                 }
1025
1026                 FOR_EACH_INSTRUCTION(bptr, iptr) {
1027                         escape_analysis_process_instruction(e, iptr);
1028                 }
1029
1030         }
1031 }
1032
1033 static void escape_analysis_post_process_returns(escape_analysis_t *e) {
1034         instruction_list_item_t *iti;
1035         instruction *iptr;
1036
1037         if (e->verbose) printf("Post processing returns:\n");
1038
1039         FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
1040                 iptr = iti->instr;
1041
1042                 if (! escape_analysis_get_contains_only_arguments(e, instruction_s1(iptr))) {
1043                         escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
1044                         E("return of not argument", s1)
1045                 }
1046         }
1047 }
1048
1049 static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
1050         instruction_list_item_t *iti;
1051         dependency_list_item_t *itd;
1052         instruction *iptr;
1053         dependency_list_t *dl;
1054
1055         if (e->verbose) printf("Post processing getfields:\n");
1056
1057         FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
1058
1059                 iptr = iti->instr;
1060
1061                 /* Get the object the field/element is loaded from. */
1062
1063                 dl = var_extra_get_dependency_list(e, instruction_s1(iptr));
1064
1065                 /* Adjust escape state of all objects in the dependency list,
1066                    referenced via the field of this getfield/arraystore. */
1067
1068                 if (dl != NULL) {
1069                         FOR_EACH_DEPENDENCY_LIST(dl, itd) {
1070                                 if (dependency_list_item_compare(itd, iptr)) {
1071
1072                                         /* Fields match. Adjust escape state. */
1073
1074                                         escape_analysis_ensure_state(
1075                                                 e, 
1076                                                 dependency_list_item_get_dependency(itd),
1077                                                 escape_analysis_get_state(e, instruction_dst(iptr))
1078                                         );
1079                                         I2("post process getfield", dependency_list_item_get_dependency(itd), escape_analysis_get_state(e, instruction_dst(iptr)));
1080                                 }
1081                         }
1082                 }
1083
1084         }
1085 }
1086
1087 static void escape_analysis_mark_monitors(escape_analysis_t *e) {
1088         instruction_list_item_t *iti;
1089         instruction *iptr;
1090
1091         FOR_EACH_INSTRUCTION_LIST(e->monitors, iti) {
1092                 iptr = iti->instr;
1093
1094                 /* TODO if argument does not escape, mark. */
1095                 if (escape_analysis_get_state(e, instruction_arg(iptr, 0)) != ESCAPE_GLOBAL) {
1096                         if (e->verbose) {
1097                                 printf("Monitor on thread local object!\n");
1098                         }
1099                 }
1100         }
1101 }
1102
1103 static void escape_analysis_mark_allocations(escape_analysis_t *e) {
1104         instruction_list_item_t *iti;
1105         instruction *iptr;
1106         escape_state_t es;
1107         FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
1108                 iptr = iti->instr;
1109                 es = escape_analysis_get_state(e, instruction_dst(iptr));
1110
1111 #if defined(ENABLE_REASON)
1112                 if (instruction_get_opcode(iptr) == ICMD_NEW) {
1113                         var_extra_t *ve;
1114                         iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_escape_reason_new);
1115                         ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
1116                         iptr->escape_reasons = ve->reasons;
1117                         if (es < ESCAPE_METHOD_RETURN) {
1118                                 assert(!ve->reasons);
1119                                 reason_t *r = NEW(reason_t);
1120                                 r->why = "No escape\n";
1121                                 r->iptr = NULL;
1122                                 r->next = NULL;
1123                                 iptr->escape_reasons = r;
1124                         } else {
1125                                 assert(iptr->escape_reasons);
1126                         }
1127                 }
1128 #endif
1129
1130 /*
1131                 if (instruction_get_opcode(iptr) == ICMD_NEW) {
1132                         es = escape_analysis_get_state(e, instruction_dst(iptr));
1133                         if (es < ESCAPE_METHOD_RETURN) {
1134                                 iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_tlh_new);
1135                                 e->jd->code->flags |= CODE_FLAG_TLH;
1136                         }
1137                 }
1138 */
1139         }
1140 }
1141
1142 static void escape_analysis_process_arguments(escape_analysis_t *e) {
1143         s4 p;
1144         s4 t;
1145         s4 l;
1146         s4 varindex;
1147         methoddesc *md;
1148         
1149         md = e->jd->m->parseddesc;
1150
1151         for (p = 0, l = 0; p < md->paramcount; ++p) {
1152                 t = md->paramtypes[p].type;
1153                 varindex = e->jd->local_map[l * 5 + t];
1154                 if (t == TYPE_ADR) {
1155                         if (varindex != UNUSED) {
1156                                 escape_analysis_ensure_state(e, varindex, ESCAPE_NONE);
1157                                 escape_analysis_set_contains_argument(e, varindex);
1158                                 escape_analysis_set_contains_only_arguments(e, varindex);
1159                                 /*escape_analysis_set_adr_arg_num(e, varindex, e->adr_args_count);*/
1160                         }
1161                         e->adr_args_count += 1;
1162                 }
1163                 l += IS_2_WORD_TYPE(t) ? 2 : 1;
1164         }
1165 }
1166
1167 static void escape_analysis_export_arguments(escape_analysis_t *e) {
1168         s4 p;
1169         s4 t;
1170         s4 l;
1171         s4 varindex;
1172         methoddesc *md;
1173         u1 *paramescape;
1174         instruction_list_item_t *iti;
1175         instruction *iptr;
1176         escape_state_t es, re;
1177         int ret_val_is_adr;
1178         
1179         md = e->jd->m->parseddesc;
1180
1181         ret_val_is_adr = (md->returntype.type == TYPE_ADR) ? 1 : 0;
1182
1183         paramescape = MNEW(u1, e->adr_args_count + ret_val_is_adr);
1184
1185         e->jd->m->paramescape = paramescape + ret_val_is_adr;
1186
1187         for (p = 0, l = 0; p < md->paramcount; ++p) {
1188                 t = md->paramtypes[p].type;
1189                 varindex = e->jd->local_map[l * 5 + t];
1190                 if (t == TYPE_ADR) {
1191                         if (varindex == UNUSED) {
1192                                 *paramescape = (u1)ESCAPE_NONE;
1193                         } else {
1194                                 es = escape_analysis_get_state(e, varindex);
1195
1196                                 if (es == ESCAPE_METHOD_RETURN) {
1197                                         *paramescape = escape_state_to_u1(ESCAPE_METHOD) | 0x80;
1198                                         if (e->verbose) {
1199                                                 printf("non-escaping adr parameter returned: %d\n", p);
1200                                         }
1201                                 } else {
1202                                         *paramescape = escape_state_to_u1(es);
1203                                 }
1204
1205                         }
1206                         paramescape += 1;
1207                 }
1208                 l += IS_2_WORD_TYPE(t) ? 2 : 1;
1209         }
1210
1211         if (ret_val_is_adr) {
1212                 /* Calculate escape state of return value as maximum escape state of all
1213                    values returned. */
1214
1215                 re = ESCAPE_NONE;
1216
1217                 FOR_EACH_INSTRUCTION_LIST(e->returns, iti) {
1218                         iptr = iti->instr;
1219                         es = escape_analysis_get_state(e, instruction_s1(iptr));
1220
1221                         if (es > re) {
1222                                 re = es;
1223                         }
1224                 }
1225
1226                 e->jd->m->paramescape[-1] = escape_state_to_u1(re);
1227         }
1228 }
1229
1230 #if defined(ENABLE_REASON)
1231 void print_escape_reasons() {
1232         reason_t *re = THREADOBJECT->escape_reasons;
1233
1234         fprintf(stderr, "DYN_REASON");
1235         
1236         for (; re; re = re->next) {
1237                 fprintf(stderr,":%s", re->why);
1238         }
1239
1240         fprintf(stderr, "\n");
1241 }
1242
1243 void set_escape_reasons(void *vp) {
1244         THREADOBJECT->escape_reasons = vp;
1245 }
1246 #endif
1247
1248 static void escape_analysis_display(escape_analysis_t *e) {
1249         instruction_list_item_t *iti;
1250         var_extra_t *ve;
1251         instruction *iptr;
1252
1253         FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
1254                 iptr = iti->instr;
1255                 ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
1256                 show_icmd(e->jd, iptr-1, 0, 3);
1257                 printf("\n");
1258                 show_icmd(e->jd, iptr, 0, 3);
1259                 printf("\n");
1260                 printf(
1261                         "%s@%d: --%s-- %d\n\n", 
1262                         icmd_table[iptr->opc].name, 
1263                         iptr->line, 
1264                         escape_state_to_string(ve->escape_state),
1265                         ve->representant
1266                 );
1267 #if defined(ENABLE_REASON)
1268                 {
1269                         reason_t *re;
1270                         for (re = ve->reasons; re; re = re->next) {
1271                                 printf("ESCAPE_REASON: %s\n", re->why);
1272                         }
1273                 }
1274 #endif
1275         }
1276 }
1277
1278 void escape_analysis_perform(jitdata *jd) {
1279         escape_analysis_t *e;
1280
1281         jd->m->flags |= ACC_METHOD_EA;
1282
1283         e = DNEW(escape_analysis_t);
1284         escape_analysis_init(e, jd);
1285
1286         if (e->verbose) 
1287                 color_printf(RED, "\n\n==== %s/%s ====\n\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
1288                 
1289         escape_analysis_process_arguments(e);
1290         escape_analysis_process_instructions(e);
1291         escape_analysis_post_process_getfields(e);
1292         escape_analysis_post_process_returns(e);
1293
1294         escape_analysis_export_arguments(e);
1295         if (e->verbose) escape_analysis_display(e);
1296
1297         if (e->verbose) {
1298                 int i, j, r;
1299                 for (i = 0; i < jd->vartop; ++i) {
1300                         r = var_extra_get_representant(e, i);
1301                         if (i == r) {
1302                                 printf("EES of %d: ", i);
1303                                 for (j = 0; j < jd->vartop; ++j) {
1304                                         if (var_extra_get_representant(e, j) == r) {
1305                                                 printf("%d, ", j);
1306                                         }
1307                                 }
1308                                 printf("\n");
1309                         }
1310                 }
1311                 printf("\n");
1312         }
1313
1314         escape_analysis_mark_allocations(e);
1315         escape_analysis_mark_monitors(e);
1316
1317         jd->m->flags &= ~ACC_METHOD_EA;
1318 }
1319
1320 void escape_analysis_escape_check(void *vp) {
1321 }
1322
1323 /*** monomorphic *************************************************************/
1324
1325 bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee) {
1326
1327         /* Non-speculative case */
1328
1329         if (callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
1330                 return true;
1331         }
1332
1333         if (
1334                 (callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED| ACC_ABSTRACT))
1335                 == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)
1336         ) {
1337
1338                 /* Mark that we have used the information about monomorphy. */
1339
1340                 callee->flags |= ACC_METHOD_MONOMORPHY_USED;
1341
1342                 /* We assume the callee is monomorphic. */
1343
1344                 method_add_assumption_monomorphic(caller, callee);
1345
1346                 return true;
1347         }
1348
1349         return false;
1350 }
1351