Merged.
[cacao.git] / src / vm / jit / optimizing / escape.c
index 5cd77dce96a83cc91d5fe94c561a32115cca9ad9..329ba02f066e6bd6f8b1971c0771483a9d3c950a 100644 (file)
@@ -1,4 +1,4 @@
-/* srcontainsc/vm/optimizing/escape.c
+/* src/vm/jit/optimizing/escape.c
 
    Copyright (C) 2008
    CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
+
 */
 
-#include "vm/jit/jit.h"
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
+
+#include "config.h"
+
+#include "vm/class.hpp"
+#include "vm/classcache.hpp"
+
+#include "vm/jit/jit.hpp"
 #include "vm/jit/optimizing/escape.h"
 
+#include <stdarg.h>
+
+#if defined(ENABLE_ESCAPE_REASON)
+#define ENABLE_REASON
+#endif
+
+#if defined(ENABLE_REASON)
+#define I2(why, tov, es) escape_analysis_record_reason(e, why, iptr, tov, es);
+#else
+#define I2(why, tov, es)
+#endif
+#define I(why, to, from) I2(why, instruction_ ## to (iptr), escape_analysis_get_state(e, instruction_ ## from (iptr)))
+#define E2(why, var) I2(why, var, ESCAPE_GLOBAL)
+#define E(why, which) E2(why, instruction_ ## which (iptr))
+
+typedef enum {
+       RED = 31,
+       GREEN,
+       YELLOW,
+       BLUE,
+       MAGENTA,
+       CYAN,
+       WHITE,
+       COLOR_END
+} color_t;
+
+#define ENABLE_COLOR
+
+static void color_start(color_t color) {
+#if defined(ENABLE_COLOR)
+       if (RED <= color && color < COLOR_END) {
+               printf("\033[%dm", color);
+       }
+#endif
+}
+
+static void color_end() {
+#if defined(ENABLE_COLOR)
+       printf("\033[m");
+       fflush(stdout);
+#endif
+}
+
+static void color_printf(color_t color, const char *fmt, ...) {
+       va_list ap;
+       color_start(color);
+       va_start(ap, fmt);
+       vprintf(fmt, ap);
+       va_end(ap);
+       color_end();
+}
+
+
 /*** escape_state *************************************************************/
 
 const char *escape_state_to_string(escape_state_t escape_state) {
@@ -277,6 +335,14 @@ void dependenCy_list_import(dependency_list_t *dl, dependency_list_t *other) {
 
 /*** var_extra ***************************************************************/
 
+#if defined(ENABLE_REASON)
+typedef struct reason {
+       const char *why;
+       instruction *iptr;
+       struct reason *next;
+} reason_t;
+#endif
+
 typedef struct var_extra {
        instruction *allocation;
        escape_state_t escape_state;
@@ -285,6 +351,9 @@ typedef struct var_extra {
        unsigned contains_arg:1;
        unsigned contains_only_args:1;
        /*signed adr_arg_num:30;*/
+#if defined(ENABLE_REASON)
+       reason_t *reasons;
+#endif
 } var_extra_t;
 
 static void var_extra_init(var_extra_t *ve) {
@@ -295,6 +364,9 @@ static void var_extra_init(var_extra_t *ve) {
        ve->contains_arg = false;
        ve->contains_only_args = false;
        /*ve->adr_arg_num = -1;*/
+#if defined(ENABLE_REASON)
+       ve->reasons = NULL;
+#endif
 }
 
 static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
@@ -389,12 +461,29 @@ static void escape_analysis_init(escape_analysis_t *e, jitdata *jd) {
 
        e->adr_args_count = 0;
 
-       e->verbose = (
-               strcmp(e->jd->m->clazz->name->text, "gnu/java/util/regex/RESyntax") == 0 
-               && strcmp(e->jd->m->name->text, "<clinit>") == 0
-       );
        e->verbose = 1;
+       e->verbose = strcmp(jd->m->name->text, "<init>") == 0;
+       e->verbose = getenv("EV") != NULL;
+}
+
+#if defined(ENABLE_REASON)
+static void escape_analysis_record_reason(escape_analysis_t *e, const char *why, instruction *iptr, s4 var, escape_state_t es) {
+       var_extra_t *ve;
+       reason_t *re;
+       if (es == ESCAPE_GLOBAL || es == ESCAPE_METHOD_RETURN) {
+               var = var_extra_get_representant(e, var);
+               ve = var_extra_get(e, var);
+               re = NEW(reason_t);
+               re->why = why;
+               re->iptr= iptr;
+               re->next = ve->reasons;
+               ve->reasons = re;
+               if (e->verbose) {
+                       printf("%d escapes because %s\n", var, why);
+               }
+       }
 }
+#endif
 
 static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr) {
        var_extra_get(e, var)->allocation = iptr;
@@ -410,18 +499,22 @@ static instruction *escape_analysis_get_allocation(const escape_analysis_t *e, s
 }
 
 static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var) {
+       var = var_extra_get_representant(e, var);
        var_extra_get(e, var)->contains_arg = true;
 }
 
 static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var) {
+       var = var_extra_get_representant(e, var);
        return var_extra_get(e, var)->contains_arg;
 }
 
 static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var) {
+       var = var_extra_get_representant(e, var);
        var_extra_get(e, var)->contains_only_args = true;
 }
 
 static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var) {
+       var = var_extra_get_representant(e, var);
        return var_extra_get(e, var)->contains_only_args;
 }
 
@@ -467,6 +560,10 @@ static void escape_analysis_ensure_state(escape_analysis_t *e, s4 var, escape_st
                                        dependency_list_item_get_dependency(it),
                                        escape_state
                                );
+                               {
+                               instruction *iptr = NULL;
+                               I2("propagated by dependency", dependency_list_item_get_dependency(it), escape_state);
+                               }
                        }
                }
        }
@@ -513,6 +610,8 @@ static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
                return;
        }
 
+       if (e->verbose) printf("Merging (%d,%d)\n", var1, var2);
+
        ve1 = var_extra_get(e, var1);
        ve2 = var_extra_get(e, var2);
 
@@ -550,6 +649,10 @@ static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
                                dependency_list_item_get_dependency(itd),
                                ESCAPE_GLOBAL
                        );
+                       {
+                       instruction *iptr = NULL;
+                       E2("has become arg", dependency_list_item_get_dependency(itd));
+                       }
                }
        }
 
@@ -564,6 +667,17 @@ static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
                ve1->adr_arg_num = -1;
        }
        */
+#if defined(ENABLE_REASON)
+       if (ve1->reasons) {
+               reason_t *re = ve1->reasons;
+               while (re->next != NULL) {
+                       re = re->next;
+               }
+               re->next = ve2->reasons;
+       } else {
+               ve1->reasons = ve2->reasons;
+       }
+#endif
 }
 
 static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
@@ -575,7 +689,9 @@ static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *st
        dependency_list_add(dl, store);
 
        if (e->verbose) {
-               printf("dependency_list_add\n");
+               printf("dependency_list_add: %d.dependency_list.add( { ", obj);
+               show_icmd(e->jd, store, 0, 3);
+               printf(" } )\n"); 
        }
 }
 
@@ -588,9 +704,14 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
        instruction **iarg;
        methodinfo *mi;
        escape_state_t es;
+       const char *why;
 
        if (e->verbose) {
-               printf("processing %s@%d\n", icmd_table[iptr->opc].name, iptr->line);
+               color_start(CYAN);
+               printf("%d: ", iptr->line);
+               show_icmd(e->jd, iptr, 0, 3);
+               color_end();
+               printf("\n");
        }
 
        switch (instruction_get_opcode(iptr)) {
@@ -608,8 +729,10 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                        if (c == NULL) {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                               E("unresolved class", dst)
                        } else if (c->finalizer != NULL) {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                               E("finalizer", dst)
                        } else {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
                        }
@@ -631,12 +754,13 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
                        escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
                        instruction_list_add(e->allocations, iptr);
-
+                       E("untracked array", dst)
                        break;
 
                case ICMD_PUTSTATIC:
                        if (instruction_field_type(iptr) == TYPE_ADR) {
                                escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+                               E("putstatic", s1)
                        }
                        break;
 
@@ -647,7 +771,9 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                        /* If s1 is currently not an argument, but can contain one later because
                                           of a phi function, the merge function takes care to make all
                                           dependencies escape globally. */
+                                       E("putfield into argument", s2)
                                } else {
+                                       I("putfield inherit", s2, s1);
                                        escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
                                        escape_analysis_add_dependency(e, iptr);
                                }
@@ -656,8 +782,12 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                case ICMD_AASTORE:
                        if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
+                               if (e->verbose) printf("Contains argument.\n");
                                escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
+                               E("aastore into argument", s3)
                        } else {
+                               if (e->verbose) printf("Contains no argument.\n");
+                               I("aastore", s3, s1)
                                escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
                                escape_analysis_add_dependency(e, iptr);
                        }
@@ -666,6 +796,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                case ICMD_GETSTATIC:
                        if (instruction_field_type(iptr) == TYPE_ADR) {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                               E("loaded from static var", dst)
                                escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
                        }
                        break;
@@ -679,6 +810,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                           x.bar = y;
                                           => y escapes globally. */
                                        escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                                       E("loaded from arg", dst)
                                } else {
                                        escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
                                }
@@ -690,7 +822,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        break;
 
                case ICMD_ARRAYLENGTH:
-                       /* TODO */
+                       escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
                        break;
 
                case ICMD_AALOAD:
@@ -698,6 +830,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
                                /* If store into argument, escapes globally. See ICMD_GETFIELD. */
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                               E("aaload from argument", dst)
                        } else {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
                        }
@@ -715,8 +848,12 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                case ICMD_IFNULL:
                case ICMD_IFNONNULL:
+                       escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+                       break;
+
                case ICMD_CHECKNULL:
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+                       escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
                        break;
 
                case ICMD_CHECKCAST:
@@ -736,15 +873,25 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        count = instruction_arg_count(iptr);
                        mi = instruction_local_methodinfo(iptr);
                        paramescape = NULL;
+                       why = "???";
 
                        if (mi != NULL) {
                                /* If the method could be resolved, it already is. */
                                paramescape = mi->paramescape;
 
+                               if (e->verbose) {
+                                       if (paramescape) {
+                                               printf("Paramescape for callee available.\n");
+                                       }
+                               }
+
+                               if (paramescape) why = "Available param escape";
+
                                if (paramescape == NULL) {
                                        if (e->verbose) {
-                                               printf("BC escape analyzing callee %s/%s.\n", mi->clazz->name->text, mi->name->text);
+                                               printf("BC escape analyzing callee.\n");
                                        }
+                                       why = "BC param escape";
                                        bc_escape_analysis_perform(mi);
                                        paramescape = mi->paramescape;
                                }
@@ -752,10 +899,15 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                if (e->verbose) {
                                        printf("Unresolved callee.\n");
                                }
+                               why = "Unresolved callee";
                        }
 
                        if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
-                               if (mi != NULL && !method_profile_is_monomorphic(mi)) {
+                               if (mi != NULL && !escape_is_monomorphic(e->jd->m, mi)) {
+                                       if (e->verbose) {
+                                               printf("Not monomorphic.\n");
+                                       }
+                                       why = "Polymorphic";
                                        paramescape = NULL;
                                }
                        }
@@ -767,13 +919,15 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        if (instruction_return_type(iptr) == TYPE_ADR) {
                                if (paramescape == NULL) {
                                        escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                                       E(why, dst);
                                } else {
                                        es = escape_state_from_u1(paramescape[-1]);
+                                       I2(why, instruction_dst(iptr), es)
                                        escape_analysis_ensure_state(e, instruction_dst(iptr), es);
                                }
                                escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
                        }
-
+                       
                        for (i = 0; i < count; ++i) {
                                if (instruction_arg_type(iptr, i) == TYPE_ADR) {
 
@@ -783,13 +937,15 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                                        instruction_arg(iptr, i), 
                                                        ESCAPE_GLOBAL
                                                );
-                                       } else if (escape_state_from_u1(*paramescape) < ESCAPE_METHOD) {
+                                               E2(why, instruction_arg(iptr, i));
+                                       } else if (escape_state_from_u1(*paramescape) <= ESCAPE_METHOD) {
                                                es = escape_state_from_u1(*paramescape);
 
                                                if (es < ESCAPE_METHOD) {
                                                        es = ESCAPE_METHOD;
                                                }
 
+                                               I2(why, instruction_arg(iptr, i), es);
                                                escape_analysis_ensure_state(e, instruction_arg(iptr, i), es);
 
                                                if (*paramescape & 0x80) {
@@ -798,7 +954,11 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                                           If the return value escapes, the ES of the parameter needs 
                                                           to be adjusted. */
                                                        escape_analysis_merge(e, instruction_arg(iptr, i), instruction_dst(iptr));
+                                                       I2("return alias", instruction_arg(iptr, i), instruction_dst(iptr));
                                                }
+                                       } else {
+                                               escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_GLOBAL);
+                                               E2(why, instruction_arg(iptr, i));
                                        }
 
                                        if (paramescape != NULL) {
@@ -811,6 +971,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                case ICMD_ATHROW:
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+                       E("throw", s1)
                        break;
 
                case ICMD_ARETURN:
@@ -818,6 +979,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                           ESCAPE_METHOD for now, and check later, if a different value than an
                           argument is possibly returned. */
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD_RETURN);
+                       E("return", s1)
                        instruction_list_add(e->returns, iptr);
                        break;
 
@@ -853,6 +1015,10 @@ static void escape_analysis_process_instructions(escape_analysis_t *e) {
 
        FOR_EACH_BASICBLOCK(e->jd, bptr) {
 
+               if (e->verbose) {
+                       color_printf(CYAN, "=== BB %d ===\n", bptr->nr);        
+               }
+
                for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
                        escape_analysis_process_instruction(e, iptr);
                }
@@ -868,11 +1034,14 @@ static void escape_analysis_post_process_returns(escape_analysis_t *e) {
        instruction_list_item_t *iti;
        instruction *iptr;
 
+       if (e->verbose) printf("Post processing returns:\n");
+
        FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
                iptr = iti->instr;
 
                if (! escape_analysis_get_contains_only_arguments(e, instruction_s1(iptr))) {
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+                       E("return of not argument", s1)
                }
        }
 }
@@ -883,6 +1052,8 @@ static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
        instruction *iptr;
        dependency_list_t *dl;
 
+       if (e->verbose) printf("Post processing getfields:\n");
+
        FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
 
                iptr = iti->instr;
@@ -905,6 +1076,7 @@ static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
                                                dependency_list_item_get_dependency(itd),
                                                escape_analysis_get_state(e, instruction_dst(iptr))
                                        );
+                                       I2("post process getfield", dependency_list_item_get_dependency(itd), escape_analysis_get_state(e, instruction_dst(iptr)));
                                }
                        }
                }
@@ -921,49 +1093,50 @@ static void escape_analysis_mark_monitors(escape_analysis_t *e) {
 
                /* TODO if argument does not escape, mark. */
                if (escape_analysis_get_state(e, instruction_arg(iptr, 0)) != ESCAPE_GLOBAL) {
-                       printf("Monitor on thread local object!\n");
-               }
-       }
-}
-
-static void display_allocation(escape_analysis_t *e, const char *prefix, const instruction *iptr, escape_state_t es) {
-       const char *cl = "WTF";
-       classinfo *c;
-
-       if (instruction_get_opcode(iptr) == ICMD_NEW) {
-               c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
-               if (c) {
-                       cl = c->name->text;
+                       if (e->verbose) {
+                               printf("Monitor on thread local object!\n");
+                       }
                }
        }
-       
-
-       printf(
-               " %s %s %s: %s %s @%d %s\n", 
-               prefix,
-               e->jd->m->clazz->name->text,
-               e->jd->m->name->text,
-               icmd_table[iptr->opc].name,
-               cl,
-               iptr->line,
-               escape_state_to_string(es)
-       );
 }
 
 static void escape_analysis_mark_allocations(escape_analysis_t *e) {
        instruction_list_item_t *iti;
+       instruction *iptr;
        escape_state_t es;
-/*
        FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
-               es = escape_analysis_get_state(e, instruction_dst(iti->instr));
-               if (es < ESCAPE_GLOBAL_THROUGH_METHOD) {
-                       display_allocation(e, "****", iti->instr, es);
+               iptr = iti->instr;
+               es = escape_analysis_get_state(e, instruction_dst(iptr));
+
+#if defined(ENABLE_REASON)
+               if (instruction_get_opcode(iptr) == ICMD_NEW) {
+                       var_extra_t *ve;
+                       iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_escape_reason_new);
+                       ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+                       iptr->escape_reasons = ve->reasons;
+                       if (es < ESCAPE_METHOD_RETURN) {
+                               assert(!ve->reasons);
+                               reason_t *r = NEW(reason_t);
+                               r->why = "No escape\n";
+                               r->iptr = NULL;
+                               r->next = NULL;
+                               iptr->escape_reasons = r;
+                       } else {
+                               assert(iptr->escape_reasons);
+                       }
                }
-               if (es == ESCAPE_GLOBAL_THROUGH_METHOD) {
-                       display_allocation(e, "!!!!", iti->instr, es);
+#endif
+
+/*
+               if (instruction_get_opcode(iptr) == ICMD_NEW) {
+                       es = escape_analysis_get_state(e, instruction_dst(iptr));
+                       if (es < ESCAPE_METHOD_RETURN) {
+                               iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_tlh_new);
+                               e->jd->code->flags |= CODE_FLAG_TLH;
+                       }
                }
-       }
 */
+       }
 }
 
 static void escape_analysis_process_arguments(escape_analysis_t *e) {
@@ -1054,6 +1227,24 @@ static void escape_analysis_export_arguments(escape_analysis_t *e) {
        }
 }
 
+#if defined(ENABLE_REASON)
+void print_escape_reasons() {
+       reason_t *re = THREADOBJECT->escape_reasons;
+
+       fprintf(stderr, "DYN_REASON");
+       
+       for (; re; re = re->next) {
+               fprintf(stderr,":%s", re->why);
+       }
+
+       fprintf(stderr, "\n");
+}
+
+void set_escape_reasons(void *vp) {
+       THREADOBJECT->escape_reasons = vp;
+}
+#endif
+
 static void escape_analysis_display(escape_analysis_t *e) {
        instruction_list_item_t *iti;
        var_extra_t *ve;
@@ -1061,13 +1252,26 @@ static void escape_analysis_display(escape_analysis_t *e) {
 
        FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
                iptr = iti->instr;
-               ve = var_extra_get(e, instruction_dst(iptr));
+               ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+               show_icmd(e->jd, iptr-1, 0, 3);
+               printf("\n");
+               show_icmd(e->jd, iptr, 0, 3);
+               printf("\n");
                printf(
-                       "%s@%d: %s\n", 
+                       "%s@%d: --%s-- %d\n\n", 
                        icmd_table[iptr->opc].name, 
                        iptr->line, 
-                       escape_state_to_string(ve->escape_state)
+                       escape_state_to_string(ve->escape_state),
+                       ve->representant
                );
+#if defined(ENABLE_REASON)
+               {
+                       reason_t *re;
+                       for (re = ve->reasons; re; re = re->next) {
+                               printf("ESCAPE_REASON: %s\n", re->why);
+                       }
+               }
+#endif
        }
 }
 
@@ -1080,7 +1284,7 @@ void escape_analysis_perform(jitdata *jd) {
        escape_analysis_init(e, jd);
 
        if (e->verbose) 
-               printf("==== %s/%s ====\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
+               color_printf(RED, "\n\n==== %s/%s ====\n\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
                
        escape_analysis_process_arguments(e);
        escape_analysis_process_instructions(e);
@@ -1090,6 +1294,23 @@ void escape_analysis_perform(jitdata *jd) {
        escape_analysis_export_arguments(e);
        if (e->verbose) escape_analysis_display(e);
 
+       if (e->verbose) {
+               int i, j, r;
+               for (i = 0; i < jd->vartop; ++i) {
+                       r = var_extra_get_representant(e, i);
+                       if (i == r) {
+                               printf("EES of %d: ", i);
+                               for (j = 0; j < jd->vartop; ++j) {
+                                       if (var_extra_get_representant(e, j) == r) {
+                                               printf("%d, ", j);
+                                       }
+                               }
+                               printf("\n");
+                       }
+               }
+               printf("\n");
+       }
+
        escape_analysis_mark_allocations(e);
        escape_analysis_mark_monitors(e);
 
@@ -1101,126 +1322,30 @@ void escape_analysis_escape_check(void *vp) {
 
 /*** monomorphic *************************************************************/
 
-monomorphic_t monomorphic_get(methodinfo *caller, methodinfo *callee) {
-       monomorphic_t res = { 0, 0 };
-}
-
-bool method_profile_is_monomorphic(methodinfo *m) {
-return 0;
-}
-
-#if 0
-
-/*** HACK to store method monomorphy information upon shutdown ****************/
-
-#include <sqlite3.h>
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee) {
 
-bool method_profile_is_monomorphic(methodinfo *m) {
-       static sqlite3 *db = NULL;
-       static sqlite3_stmt *stmt = NULL;
-       int ret;
+       /* Non-speculative case */
 
-       if (db == NULL) {
-               assert(sqlite3_open("/home/peter/cacao-dev/profile.sqlite", &db) == SQLITE_OK);
-               assert(sqlite3_prepare(db, "SELECT count(*) FROM monomorphic where class=? and method=? and descriptor=?", -1, &stmt, 0) == SQLITE_OK);
-       }
-
-       assert(sqlite3_bind_text(stmt, 1, m->clazz->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
-       assert(sqlite3_bind_text(stmt, 2, m->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
-       assert(sqlite3_bind_text(stmt, 3, m->descriptor->text, -1, SQLITE_STATIC) == SQLITE_OK);
-                               
-       assert(sqlite3_step(stmt) == SQLITE_ROW);
-       ret = sqlite3_column_int(stmt, 0);
-       assert(sqlite3_reset(stmt) == SQLITE_OK);
-
-       return ret;
-}
-void func(classinfo *c, void *arg) {
-       methodinfo *it;
-       sqlite3_stmt *stmt = (sqlite3_stmt *)arg;
-       s4 flags;
-       for (it = c->methods; it != c->methods + c->methodscount; ++it) {
-               flags = it->flags;
-               if (flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
-                       continue;
-               }
-               if ((flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED | ACC_ABSTRACT)) ==
-                       (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)) {
-                               assert(sqlite3_bind_text(stmt, 1, c->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
-                               assert(sqlite3_bind_text(stmt, 2, it->name->text, -1, SQLITE_STATIC) == SQLITE_OK);
-                               assert(sqlite3_bind_text(stmt, 3, it->descriptor->text, -1, SQLITE_STATIC) == SQLITE_OK);
-                               
-                               assert(sqlite3_step(stmt) == SQLITE_DONE);
-                               assert(sqlite3_reset(stmt) == SQLITE_OK);
-               }
+       if (callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
+               return true;
        }
-}
 
+       if (
+               (callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED| ACC_ABSTRACT))
+               == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)
+       ) {
 
-void method_profile_store() {
-       sqlite3 *db = NULL;
-       sqlite3_stmt *stmt;
-       assert(sqlite3_open("/home/peter/cacao-dev/profile.sqlite", &db) == SQLITE_OK);
-       assert(sqlite3_exec(db, "DELETE FROM monomorphic", NULL, NULL, NULL) == SQLITE_OK);
-       assert(sqlite3_prepare(db, "INSERT INTO monomorphic (class, method, descriptor) VALUES (?,?,?)", -1, &stmt, 0) == SQLITE_OK);
-       classcache_foreach_loaded_class(func, stmt);
-       assert(sqlite3_finalize(stmt) == SQLITE_OK);
-       assert(sqlite3_close(db) == SQLITE_OK);
-}
+               /* Mark that we have used the information about monomorphy. */
 
-void iterate_classes() {
-       return;
-       method_profile_store();
+               callee->flags |= ACC_METHOD_MONOMORPHY_USED;
 
-}
+               /* We assume the callee is monomorphic. */
 
-#endif
+               method_add_assumption_monomorphic(caller, callee);
 
-#if defined(ENABLE_TLH)
-/*** TLH (Thread local heap) hack  ********************************************/
-
-#include <sys/mman.h>
-#include "threads/thread.h"
-
-#define TLH_MAX_SIZE (20 * 1024 * 1024)
-
-void tlh_init(threadobject *t) {
-       uint8_t *heap = (uint8_t *)mmap(
-               NULL, 
-               TLH_MAX_SIZE, 
-               PROT_READ|PROT_WRITE, 
-               MAP_ANONYMOUS|MAP_PRIVATE, 
-               -1, 
-               0
-       );
-       uint8_t *red = (uint8_t *)mmap(
-               heap + TLH_MAX_SIZE - getpagesize(), 
-               getpagesize(), 
-               PROT_NONE, 
-               MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED, 
-               -1, 
-               0
-       );
-       assert(heap);
-       assert(red);
-       t->tlhstart = heap;
-       t->tlhtop = heap;
-       t->tlhbase = heap;
-}
-
-void tlh_reset(threadobject *t) {
-       t->tlhtop = t->tlhstart;
-       t->tlhbase = t->tlhstart;
-}
-
-void tlh_destroy(threadobject *t) {
-       int res = munmap(t->tlhstart, TLH_MAX_SIZE - getpagesize());
-       int res2 = munmap(t->tlhstart + TLH_MAX_SIZE - getpagesize(), getpagesize());
-       assert(res);
-       assert(res2);
-}
+               return true;
+       }
 
-bool tlh_sigsegv_handler(void *addr) {
+       return false;
 }
 
-#endif