* configure.ac: Define ENABLE_TLH if ENABLE_SSA
authorPeter Molnar <pm@complang.tuwien.ac.at>
Sun, 22 Jun 2008 18:49:18 +0000 (20:49 +0200)
committerPeter Molnar <pm@complang.tuwien.ac.at>
Sun, 22 Jun 2008 18:49:18 +0000 (20:49 +0200)
* src/threads/posix/thread-posix.c [ENABLE_TLH] (threads_impl_thread_init, threads_impl_thread_reuse): Experimental TLH (thread local heap) support.
* src/threads/posix/thread-posix.h [ENABLE_TLH] (threadobject): Likewise.
* src/vm/jit/optimizing/bytecode_escape.c,
 src/vm/jit/optimizing/escape.c,
 src/vm/jit/optimizing/escape.h: Changed a lot.

configure.ac
src/threads/posix/thread-posix.c
src/threads/posix/thread-posix.h
src/vm/jit/optimizing/bytecode_escape.c
src/vm/jit/optimizing/escape.c
src/vm/jit/optimizing/escape.h

index 6797d5b098c22ae0463105b960332306f1d113ff..441263b2b5410c52430c5ef97822f1f79a666a33 100644 (file)
@@ -673,6 +673,7 @@ if test x"${ENABLE_SSA}" = "xyes"; then
     AC_DEFINE([ENABLE_SSA], 1, [enable lsra with ssa])
     AC_DEFINE([ENABLE_ESCAPE], 1, [enable escape analysis with ssa])
     AC_DEFINE([ENABLE_ESCAPE_CHECK], 1, [enable generating code to validate escape analysis results])
+    AC_DEFINE([ENABLE_TLH], 1, [enable thread local heap])
     ENABLE_LSRA="no"
 fi
 
index af5e43c05461b101d03a431b3a975696c1c80b5e..b7d83c289f6efec76b9b92e990daafe6f33cd294 100644 (file)
@@ -686,6 +686,10 @@ void threads_impl_thread_init(threadobject *t)
        result = pthread_cond_init(&(t->suspendcond), NULL);
        if (result != 0)
                vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
+
+#if defined(ENABLE_TLH)
+       tlh_init(t);
+#endif
 }
 
 /* threads_impl_thread_clear ***************************************************
@@ -775,6 +779,10 @@ void threads_impl_thread_reuse(threadobject *t)
 
 /*     not really needed */
        t->flc_object = NULL;
+
+#if defined(ENABLE_TLH)
+       tlh_reset(t);
+#endif
 }
 
 
index 58f7d845c755808d73318481742cd8c8f80e1a76..87df756dde8760b893f5e97567776c5a4582c867 100644 (file)
@@ -171,6 +171,12 @@ struct threadobject {
        u4                    tracejavacallcount;
 #endif
 
+#if defined(ENABLE_TLH)
+       uint8_t              *tlhstart;
+       uint8_t              *tlhtop;
+       uint8_t              *tlhbase;
+#endif
+
        listnode_t            linkage;      /* threads-list                       */
        listnode_t            linkage_free; /* free-list                          */
 };
index 22fb1f2810f7ec0d9abbef087a5d153d69564849..326f65f08015460cafe41aac7424c7c05fab5d82 100644 (file)
@@ -118,15 +118,10 @@ typedef struct {
        op_stack_slot_t *ptr;
        op_stack_slot_t *bottom;
        unsigned max;
+       bool *perror_flag;
 } op_stack_t;
 
-#define stack_assert_position(stack, pos) \
-       do { \
-               assert((stack)->elements <= (pos)); \
-               assert((pos) < (stack)->end); \
-       } while (0)
-
-static void op_stack_init(op_stack_t *stack, unsigned max) {
+static void op_stack_init(op_stack_t *stack, unsigned max, bool *perror_flag) {
        op_stack_slot_t *it;
 
        stack->elements = DMNEW(op_stack_slot_t, max * 2);
@@ -140,6 +135,27 @@ static void op_stack_init(op_stack_t *stack, unsigned max) {
 
        stack->ptr = stack->start;
        stack->bottom = stack->start;
+
+       stack->perror_flag = perror_flag;
+}
+
+static void op_stack_set_error(op_stack_t *stack) {
+       *(stack->perror_flag) = true;
+#if BC_ESCAPE_VERBOSE
+       printf("%s: error.\n", __FUNCTION__);
+#endif
+}
+
+static bool op_stack_test_position(op_stack_t *stack, op_stack_slot_t *pos) {
+       if (!(stack->elements <= pos)) {
+               op_stack_set_error(stack);
+               return false;
+       } else if (!(pos < stack->end)) {
+               op_stack_set_error(stack);
+               return false;
+       } else {
+               return true;
+       }
 }
 
 static void op_stack_reset(op_stack_t *stack) {
@@ -160,7 +176,9 @@ static void op_stack_reset(op_stack_t *stack) {
 static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
        op_stack_slot_t ret;
        stack->ptr -= 1;
-       stack_assert_position(stack, stack->ptr);
+       if (! op_stack_test_position(stack, stack->ptr)) {
+               return OP_STACK_SLOT_UNKNOWN;
+       }
        ret = *(stack->ptr);
        if (stack->ptr < stack->bottom) {
                stack->bottom = stack->ptr;
@@ -169,19 +187,24 @@ static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
 }
 
 static void op_stack_push(op_stack_t *stack, op_stack_slot_t element) {
-       stack_assert_position(stack, stack->ptr);
-       *(stack->ptr) = element;
-       stack->ptr += 1;
+       if (op_stack_test_position(stack, stack->ptr)) {
+               *(stack->ptr) = element;
+               stack->ptr += 1;
+       }
 }
 
 static op_stack_slot_t op_stack_get(const op_stack_t *stack, int offset) {
-       stack_assert_position(stack, stack->ptr - offset);
-       return *(stack->ptr - offset);
+       if (op_stack_test_position(stack, stack->ptr - offset)) {
+               return *(stack->ptr - offset);
+       } else {
+               return OP_STACK_SLOT_UNKNOWN;
+       }
 }
 
 static void op_stack_set(op_stack_t *stack, int offset, op_stack_slot_t value) {
-       stack_assert_position(stack, stack->ptr - offset);
-       *(stack->ptr - offset) = value;
+       if (op_stack_test_position(stack, stack->ptr - offset)) {
+               *(stack->ptr - offset) = value;
+       }
 }
 
 static inline void op_stack_push_unknown(op_stack_t *stack) {
@@ -301,13 +324,22 @@ typedef struct {
        u1 *pos;
        u1 *instruction_start;
        s4 offset;
+       bool *perror_flag;
 } jcode_t;
 
-static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset) {
+static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset, bool *perror_flag) {
        jc->start = start;
        jc->end = jc->start + length;
        jc->pos = jc->start;
        jc->offset = offset;
+       jc->perror_flag = perror_flag;
+}
+
+static void jcode_set_error(jcode_t *jc) {
+       *(jc->perror_flag) = true;
+#if BC_ESCAPE_VERBOSE
+       printf("%s: error.\n", __FUNCTION__);
+#endif
 }
 
 static void jcode_move_to_index(jcode_t *jc, s4 index) {
@@ -347,38 +379,56 @@ static s4 jcode_get_index(const jcode_t *jc) {
        return jc->offset + (jc->pos - jc->start);
 }
 
-#define jcode_assert_has_bytes(jc, n) \
-       assert((jc->pos + n) <= jc->end)
+bool jcode_test_has_bytes(jcode_t *jc, s4 n) {
+       if ((jc->pos + n) <= jc->end) {
+               return true;
+       } else {
+               jcode_set_error(jc);
+               return false;
+       }
+}
 
 static u1 jcode_get_u1(jcode_t *jc) {
        u1 ret;
-       jcode_assert_has_bytes(jc, 1);
-       ret = jc->pos[0];
-       jc->pos += 1;
+       if (jcode_test_has_bytes(jc, 1)) {
+               ret = jc->pos[0];
+               jc->pos += 1;
+       } else {
+               ret = 0;
+       }
        return ret;
 }
 
 static s2 jcode_get_s2(jcode_t *jc) {
        s2 ret;
-       jcode_assert_has_bytes(jc, 2);
-       ret = (jc->pos[0] << 8) | (jc->pos[1]);
-       jc->pos += 2;
+       if (jcode_test_has_bytes(jc, 2)) {
+               ret = (jc->pos[0] << 8) | (jc->pos[1]);
+               jc->pos += 2;
+       } else {
+               ret = 0;
+       }
        return ret;
 }
 
 static u2 jcode_get_u2(jcode_t *jc) {
        u2 ret;
-       jcode_assert_has_bytes(jc, 2);
-       ret = (jc->pos[0] << 8) | (jc->pos[1]);
-       jc->pos += 2;
+       if (jcode_test_has_bytes(jc, 2)) {
+               ret = (jc->pos[0] << 8) | (jc->pos[1]);
+               jc->pos += 2;
+       } else {
+               ret = 0;
+       }
        return ret;
 }
 
 static s4 jcode_get_s4(jcode_t *jc) {
        s4 ret;
-       jcode_assert_has_bytes(jc, 4);
-       ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
-       jc->pos += 4;
+       if (jcode_test_has_bytes(jc, 4)) {
+               ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
+               jc->pos += 4;
+       } else {
+               ret = 0;
+       }
        return ret;
 }
 
@@ -394,7 +444,9 @@ static s4 jcode_get_branch_target_wide(jcode_t *jc) {
 
 static s4 jcode_get_fall_through_target(jcode_t *jc) {
        int length = bytecode[*jc->instruction_start].length;
-       assert(length > 0);
+       if (length <= 0) {
+               jcode_set_error(jc);
+       }
        return jc->offset + (jc->instruction_start - jc->start) + length;
 }
 
@@ -420,6 +472,8 @@ typedef struct {
        bool verbose;
 #endif
        int depth;
+
+       bool fatal_error;
 } bc_escape_analysis_t;
 
 static void bc_escape_analysis_perform_intern(methodinfo *m, int depth);
@@ -430,13 +484,13 @@ static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, boo
        int a;
        u1 *ite;
        u1 t;
-       int ret_adr;
        unsigned n;
+       int ret_val_is_adr;
 
        be->method = m;
 
        be->stack = DNEW(op_stack_t);
-       op_stack_init(be->stack, m->maxstack);
+       op_stack_init(be->stack, m->maxstack, &(be->fatal_error));
 
        be->basicblocks = DNEW(basicblock_work_list_t);
        basicblock_work_list_init(be->basicblocks);
@@ -464,27 +518,28 @@ static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, boo
 
        assert(l == be->local_to_adr_param_size);
 
-       /* Determine whether return type is address */
-
-       ret_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
+       ret_val_is_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
 
        /* Allocate param_escape on heap. */
 
        be->param_escape_size = a;
-       n = a + ret_adr;
+       n = a + ret_val_is_adr;
 
        if (n == 0) {
                /* Use some non-NULL value. */
                be->param_escape = (u1 *)1;
        } else {
                be->param_escape = MNEW(u1, n);
+               be->param_escape += ret_val_is_adr;
        }
 
        for (ite = be->param_escape; ite != be->param_escape + n; ++ite) {
-               *ite = (u1)ESCAPE_NONE;
+               *ite = escape_state_to_u1(ESCAPE_NONE);
        }
 
-       be->param_escape += ret_adr;
+       if (ret_val_is_adr) {
+               be->param_escape[-1] = escape_state_to_u1(ESCAPE_NONE);
+       }
 
        be->adr_param_dirty = DNEW(bit_vector_t);
        bit_vector_init(be->adr_param_dirty, a);
@@ -499,6 +554,8 @@ static void bc_escape_analysis_init(bc_escape_analysis_t *be, methodinfo *m, boo
 #endif
 
        be->depth = depth;
+
+       be->fatal_error = false;
 }
 
 static void bc_escape_analysis_branch_target(bc_escape_analysis_t *be, s4 branch_target) {
@@ -524,8 +581,8 @@ static void bc_escape_analysis_adjust_state(
                                   parameters. */
 
                                if (
-                                       old < ESCAPE_GLOBAL_THROUGH_METHOD && 
-                                       escape_state >= ESCAPE_GLOBAL_THROUGH_METHOD
+                                       old < ESCAPE_GLOBAL && 
+                                       escape_state >= ESCAPE_GLOBAL
                                ) {
                                        be->non_escaping_adr_params -= 1;
                                }
@@ -550,16 +607,17 @@ static void bc_escape_analysis_dirty_2(bc_escape_analysis_t *be, s4 local) {
        bc_escape_analysis_dirty(be, local + 1);
 }
 
-static void bc_escape_analyisis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
+static void bc_escape_analysis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
        if (op_stack_slot_is_param(value)) {
                /* A parameter is returned, mark it as being returned. */
                bit_vector_set(be->adr_param_returned, value.index);
-       } else if (op_stack_slot_is_unknown(value)) {
-               /* An untracked value is returned.
-                  Conservatively asume a globally escaping value is returned. */
+               /* The escape state of the return value will be adjusted later. */
+       } else {
+               /* Adjust escape state of return value. */
                if (be->method->parseddesc->returntype.type == TYPE_ADR) {
-                       be->param_escape[-1] = (u1)ESCAPE_GLOBAL;
+                       be->param_escape[-1] = escape_state_to_u1(ESCAPE_GLOBAL);
                }
+               bc_escape_analysis_adjust_state(be, value, ESCAPE_GLOBAL);
        }
 }
 
@@ -589,6 +647,25 @@ value_category_t bc_escape_analysis_value_category(bc_escape_analysis_t *be, s4
        }
 }
 
+static void bc_escape_analysis_push_return_value(
+       bc_escape_analysis_t *be,
+       methoddesc *md
+) {
+       switch (md->returntype.type) {
+               case TYPE_LNG:
+               case TYPE_DBL:
+                       op_stack_push_unknown(be->stack);
+                       op_stack_push_unknown(be->stack);
+                       break;
+               case TYPE_VOID:
+                       /* Do nothing */
+                       break;
+               default:
+                       op_stack_push_unknown(be->stack);
+                       break;
+       }
+}
+
 static void bc_escape_analysis_adjust_invoke_parameters(
        bc_escape_analysis_t *be,
        methodinfo *mi
@@ -597,6 +674,8 @@ static void bc_escape_analysis_adjust_invoke_parameters(
        methoddesc *md = mi->parseddesc;
        u1 *paramescape = mi->paramescape;
        s4 stack_depth = md->paramslots;
+       unsigned num_params_returned = 0;
+       op_stack_slot_t param_returned;
 
        /* Process parameters. 
         * The first parameter is at the highest depth on the stack.
@@ -605,10 +684,14 @@ static void bc_escape_analysis_adjust_invoke_parameters(
        for (i = 0; i < md->paramcount; ++i) {
                switch (md->paramtypes[i].type) {
                        case TYPE_ADR:
+                               if (*paramescape & 0x80) {
+                                       num_params_returned += 1;
+                                       param_returned = op_stack_get(be->stack, stack_depth);
+                               }
                                bc_escape_analysis_adjust_state(
                                        be,
                                        op_stack_get(be->stack, stack_depth),
-                                       (escape_state_t)*(paramescape++)
+                                       escape_state_from_u1(*paramescape++)
                                );
                                stack_depth -= 1;
                                break;
@@ -627,7 +710,20 @@ static void bc_escape_analysis_adjust_invoke_parameters(
        for (i = 0; i < md->paramslots; ++i) {
                op_stack_pop(be->stack);
        }
+       
+       /* Push return value. */
 
+       if (md->returntype.type == TYPE_ADR) {
+               if ((num_params_returned == 1) && (mi->paramescape[-1] < ESCAPE_GLOBAL)) {
+                       /* Only a single argument can be returned by the method,
+                          and the retun value does not escape otherwise. */
+                       op_stack_push(be->stack, param_returned);
+               } else {
+                       op_stack_push_unknown(be->stack);
+               }
+       } else {
+               bc_escape_analysis_push_return_value(be, md);
+       }
 }
 
 static void bc_escape_analysis_escape_invoke_parameters(
@@ -638,6 +734,8 @@ static void bc_escape_analysis_escape_invoke_parameters(
        for (i = 0; i < md->paramslots; ++i) {
                bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
        }
+
+       bc_escape_analysis_push_return_value(be, md);
 }
 
 static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *jc) {
@@ -713,7 +811,7 @@ static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *j
           or recurse into callee. 
           Otherwise we must assume, that all parameters escape. */
 
-       if (mi != NULL) {
+       if (mi != NULL && method_profile_is_monomorphic(mi)) {
 
                if (mi->paramescape == NULL) {
                        bc_escape_analysis_perform_intern(mi, be->depth + 1);
@@ -730,20 +828,6 @@ static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *j
        } else {
                bc_escape_analysis_escape_invoke_parameters(be, md);
        }
-
-       switch (md->returntype.type) {
-               case TYPE_LNG:
-               case TYPE_DBL:
-                       op_stack_push_unknown(be->stack);
-                       op_stack_push_unknown(be->stack);
-                       break;
-               case TYPE_VOID:
-                       /* Do nothing */
-                       break;
-               default:
-                       op_stack_push_unknown(be->stack);
-                       break;
-       }
 }
 
 static void bc_escape_analysis_parse_tableswitch(
@@ -825,7 +909,7 @@ static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcod
        /* TODO end if all parameters escape */
        /* TODO move code into process_instruction or the like */
 
-       while ((! jcode_end(jc)) && (! bb_end)) {
+       while ((! jcode_end(jc)) && (! bb_end) && (! be->fatal_error)) {
 
                jcode_record_instruction_start(jc);
 
@@ -1390,7 +1474,7 @@ static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcod
 
                        case BC_areturn:
                                /* FIXME */
-                               bc_escape_analyisis_returned(be, op_stack_pop(be->stack));
+                               bc_escape_analysis_returned(be, op_stack_pop(be->stack));
                                bb_end = true;
                                break;
 
@@ -1593,7 +1677,7 @@ static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcod
        }
 #endif
 
-       while (! op_stack_is_empty(be->stack)) {
+       while ((! op_stack_is_empty(be->stack)) && (! be->fatal_error)) {
 #if BC_ESCAPE_VERBOSE
                if (be->verbose) {
                        dprintf(be->depth, "Stack element: ");
@@ -1609,10 +1693,19 @@ static void bc_escape_analysis_process_basicblock(bc_escape_analysis_t *be, jcod
                }
 #endif
        }
+
+       if (be->fatal_error) {
+#if BC_ESCAPE_VERBOSE
+               if (be->verbose) {
+                       printf("Fatal error while processing basic block. Aborting.\n");
+               }
+#endif
+               assert(0);
+       }
 }
 
 static void    bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
-       escape_state_t e, pe;
+       escape_state_t re, pe;
        int i;
 
        /* Only calculate, if return value is of type address. */
@@ -1621,22 +1714,20 @@ static void     bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
                return ;
        }
 
-       /* Get current escape state of return value. */
-
-       e = (escape_state_t)be->param_escape[-1];
-
        /* If a parameter can be returned, adjust to its escape state. */
 
        for (i = 0; i < be->param_escape_size; ++i) {
                if (bit_vector_get(be->adr_param_returned, i)) {
-                       pe = (escape_state_t)be->param_escape[i];
-                       if (pe > e) {
-                               e = pe;
+                       be->param_escape[i] |= 0x80;
+
+                       pe = escape_state_from_u1(be->param_escape[i]);
+                       re = escape_state_from_u1(be->param_escape[-1]);
+                       
+                       if (pe > re) {
+                               be->param_escape[-1] = escape_state_to_u1(pe);
                        }
                }
        }
-
-       be->param_escape[-1] = (u1)e;
 }
 
 static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
@@ -1664,7 +1755,8 @@ static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
                &jc,
                be->method->jcode,
                be->method->jcodelength,
-               0
+               0,
+               &(be->fatal_error)
        );
 
        /* Process basicblock by basicblock. */
index b1c0679d584720036e7d81704fc7d160c5d62cfd..03b03b4af2bb853274b76958ae0320ea7e775f3c 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/optimizing/escape.c
+/* srcontainsc/vm/optimizing/escape.c
 
    Copyright (C) 2008
    CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
@@ -23,6 +23,7 @@
 
 #include "vm/jit/jit.h"
 #include "vmcore/class.h"
+#include "vmcore/classcache.h"
 #include "vm/jit/optimizing/escape.h"
 
 /*** escape_state *************************************************************/
@@ -33,7 +34,7 @@ const char *escape_state_to_string(escape_state_t escape_state) {
                str(ESCAPE_UNKNOWN)
                str(ESCAPE_NONE)
                str(ESCAPE_METHOD)
-               str(ESCAPE_GLOBAL_THROUGH_METHOD)
+               str(ESCAPE_METHOD_RETURN)
                str(ESCAPE_GLOBAL)
                default: return "???";
        }
@@ -150,6 +151,8 @@ typedef struct {
 
        instruction_list_t *allocations;
        instruction_list_t *getfields;
+       instruction_list_t *monitors;
+       instruction_list_t *returns;
 
        struct var_extra **var;
 
@@ -279,7 +282,9 @@ typedef struct var_extra {
        escape_state_t escape_state;
        s4 representant;
        dependency_list_t *dependency_list;
-       bool is_arg; /* TODO optimize */
+       unsigned contains_arg:1;
+       unsigned contains_only_args:1;
+       /*signed adr_arg_num:30;*/
 } var_extra_t;
 
 static void var_extra_init(var_extra_t *ve) {
@@ -287,7 +292,9 @@ static void var_extra_init(var_extra_t *ve) {
        ve->escape_state = ESCAPE_NONE;
        ve->representant = -1;
        ve->dependency_list = NULL;
-       ve->is_arg = false;
+       ve->contains_arg = false;
+       ve->contains_only_args = false;
+       /*ve->adr_arg_num = -1;*/
 }
 
 static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
@@ -371,6 +378,12 @@ static void escape_analysis_init(escape_analysis_t *e, jitdata *jd) {
        e->getfields = DNEW(instruction_list_t);
        instruction_list_init(e->getfields);
 
+       e->monitors = DNEW(instruction_list_t);
+       instruction_list_init(e->monitors);
+
+       e->returns = DNEW(instruction_list_t);
+       instruction_list_init(e->returns);
+
        e->var = DMNEW(var_extra_t *, jd->vartop);
        MZERO(e->var, var_extra_t *, jd->vartop);
 
@@ -396,12 +409,34 @@ static instruction *escape_analysis_get_allocation(const escape_analysis_t *e, s
        return ve->allocation;
 }
 
-static void escape_analysis_set_is_argument(escape_analysis_t *e, s4 var) {
-       var_extra_get(e, var)->is_arg = true;
+static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var) {
+       var_extra_get(e, var)->contains_arg = true;
+}
+
+static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var) {
+       return var_extra_get(e, var)->contains_arg;
+}
+
+static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var) {
+       var_extra_get(e, var)->contains_only_args = true;
+}
+
+static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var) {
+       return var_extra_get(e, var)->contains_only_args;
 }
 
-static bool escape_analysis_get_is_argument(escape_analysis_t *e, s4 var) {
-       return var_extra_get(e, var)->is_arg;
+/*
+static void escape_analysis_set_adr_arg_num(escape_analysis_t *e, s4 var, s4 num) {
+       var_extra_get(e, var)->adr_arg_num = num;
+}
+
+static s4 escape_analysis_get_adr_arg_num(escape_analysis_t *e, s4 var) {
+       return var_extra_get(e, var)->adr_arg_num;
+}
+*/
+
+static bool escape_analysis_in_same_set(escape_analysis_t *e, s4 var1, s4 var2) {
+       return var_extra_get_representant(e, var1) == var_extra_get_representant(e, var2);
 }
 
 static void escape_analysis_ensure_state(escape_analysis_t *e, s4 var, escape_state_t escape_state) {
@@ -441,12 +476,6 @@ static escape_state_t escape_analysis_get_state(escape_analysis_t *e, s4 var) {
        return var_extra_get_escape_state(e, var);
 }
 
-#define escape_analysis_assert_has_escape(e, var) \
-       assert( \
-               var_extra_get_no_alloc(e, var) && \
-               (var_extra_get_no_alloc(e, var)->escape_state > ESCAPE_UNKNOWN) \
-       )
-
 static classinfo *escape_analysis_classinfo_in_var(escape_analysis_t *e, s4 var) {
        instruction *iptr = escape_analysis_get_allocation(e, var);
 
@@ -496,10 +525,10 @@ static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
 
        ve2->representant = var1;
 
-       /* Adjust is_argument to logical or. */
+       /* Adjust is_arg to logical or. */
        
-       has_become_arg = ve1->is_arg != ve2->is_arg;
-       ve1->is_arg = ve1->is_arg || ve2->is_arg;
+       has_become_arg = ve1->contains_arg != ve2->contains_arg;
+       ve1->contains_arg = ve1->contains_arg || ve2->contains_arg;
 
        if (e->verbose && has_become_arg) printf("(%d,%d) has become arg.\n", var1, var2);
 
@@ -523,6 +552,18 @@ static void escape_analysis_merge(escape_analysis_t *e, s4 var1, s4 var2) {
                        );
                }
        }
+
+       /* Adjust contains_only_args to logical and. */
+
+       ve1->contains_only_args = ve1->contains_only_args && ve2->contains_only_args;
+
+       /* Adjust address argument number contained in this var. */
+
+       /*
+       if (ve1->adr_arg_num != ve2->adr_arg_num) {
+               ve1->adr_arg_num = -1;
+       }
+       */
 }
 
 static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
@@ -545,9 +586,8 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
        u1 *paramescape;
        unsigned i;
        instruction **iarg;
-       constant_FMIref *fmi;
        methodinfo *mi;
-       resolve_result_t result;
+       escape_state_t es;
 
        if (e->verbose) {
                printf("processing %s@%d\n", icmd_table[iptr->opc].name, iptr->line);
@@ -568,19 +608,23 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                        if (c == NULL) {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
-                               if (e->verbose) printf("1\n");
                        } else if (c->finalizer != NULL) {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
-                               if (e->verbose) printf("3\n");
                        } else {
                                escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
-                               if (e->verbose) printf("2\n");
                        }
 
                        instruction_list_add(e->allocations, iptr);
 
                        break;
 
+               case ICMD_MONITORENTER:
+               case ICMD_MONITOREXIT:
+               
+                       instruction_list_add(e->monitors, iptr);
+
+                       break;
+
                case ICMD_NEWARRAY:
                case ICMD_ANEWARRAY:
                        
@@ -592,21 +636,17 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                case ICMD_PUTSTATIC:
                        if (instruction_field_type(iptr) == TYPE_ADR) {
-                               /*
-                               escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                               */
                                escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
                        }
                        break;
 
                case ICMD_PUTFIELD:
                        if (instruction_field_type(iptr) == TYPE_ADR) {
-                               /*
-                               escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                               escape_analysis_assert_has_escape(e, instruction_s2(iptr));
-                               */
-                               if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+                               if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
                                        escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_GLOBAL);
+                                       /* 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. */
                                } else {
                                        escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
                                        escape_analysis_add_dependency(e, iptr);
@@ -615,11 +655,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        break;
 
                case ICMD_AASTORE:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       escape_analysis_assert_has_escape(e, instruction_s3(iptr));
-                       */
-                       if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+                       if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
                                escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
                        } else {
                                escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
@@ -636,11 +672,8 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                case ICMD_GETFIELD:
                        if (instruction_field_type(iptr) == TYPE_ADR) {
-                               /*
-                               escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                               */
 
-                               if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+                               if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
                                        /* Fields loaded from arguments escape globally.
                                           x = arg.foo;
                                           x.bar = y;
@@ -657,17 +690,12 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                        break;
 
                case ICMD_ARRAYLENGTH:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
+                       /* TODO */
                        break;
 
                case ICMD_AALOAD:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
 
-                       if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+                       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);
                        } else {
@@ -681,10 +709,6 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                case ICMD_IF_ACMPEQ:
                case ICMD_IF_ACMPNE:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       escape_analysis_assert_has_escape(e, instruction_s2(iptr));
-                       */
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
                        escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_METHOD);
                        break;
@@ -692,25 +716,16 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                case ICMD_IFNULL:
                case ICMD_IFNONNULL:
                case ICMD_CHECKNULL:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
                        break;
 
                case ICMD_CHECKCAST:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
                        escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
                        escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
                        break;
 
                case ICMD_INSTANCEOF:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
                        break;
 
@@ -728,7 +743,7 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
 
                                if (paramescape == NULL) {
                                        if (e->verbose) {
-                                               printf("BC escape analyzing callee.\n");
+                                               printf("BC escape analyzing callee %s/%s.\n", mi->clazz->name->text, mi->name->text);
                                        }
                                        bc_escape_analysis_perform(mi);
                                        paramescape = mi->paramescape;
@@ -739,24 +754,51 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                }
                        }
 
+                       if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
+                               if (mi != NULL && !method_profile_is_monomorphic(mi)) {
+                                       paramescape = NULL;
+                               }
+                       }
+
+                       /* Set the escape state of the return value.
+                          This is: global if we down have information of the callee, or the callee
+                          supplied escape state. */
+
+                       if (instruction_return_type(iptr) == TYPE_ADR) {
+                               if (paramescape == NULL) {
+                                       escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+                               } else {
+                                       es = escape_state_from_u1(paramescape[-1]);
+                                       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) {
 
-                                       /*
-                                       escape_analysis_assert_has_escape(e, instruction_arg(iptr, i));
-                                       */
                                        if (paramescape == NULL) {
                                                escape_analysis_ensure_state(
                                                        e, 
                                                        instruction_arg(iptr, i), 
-                                                       instruction_local_methodinfo(iptr) && instruction_local_methodinfo(iptr)->jcode ?
-                                                               ESCAPE_GLOBAL_THROUGH_METHOD :
-                                                               ESCAPE_GLOBAL
+                                                       ESCAPE_GLOBAL
                                                );
-                                       } else if ((escape_state_t)*paramescape < ESCAPE_METHOD) {
-                                               escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_METHOD);
-                                       } else {
-                                               escape_analysis_ensure_state(e, instruction_arg(iptr, i), (escape_state_t)*paramescape);
+                                       } else if (escape_state_from_u1(*paramescape) < ESCAPE_METHOD) {
+                                               es = escape_state_from_u1(*paramescape);
+
+                                               if (es < ESCAPE_METHOD) {
+                                                       es = ESCAPE_METHOD;
+                                               }
+
+                                               escape_analysis_ensure_state(e, instruction_arg(iptr, i), es);
+
+                                               if (*paramescape & 0x80) {
+                                                       /* Parameter can be returned from method.
+                                                          This creates an alias to the retur value.
+                                                          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));
+                                               }
                                        }
 
                                        if (paramescape != NULL) {
@@ -765,25 +807,18 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                                }
                        }
 
-                       if (instruction_return_type(iptr) == TYPE_ADR) {
-                               escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
-                               escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
-                       }
-
                        break;
 
                case ICMD_ATHROW:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
                        escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
                        break;
 
                case ICMD_ARETURN:
-                       /*
-                       escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                       */
-                       escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+                       /* If we return only arguments, the return value escapes only the method.
+                          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);
+                       instruction_list_add(e->returns, iptr);
                        break;
 
                case ICMD_ALOAD:
@@ -791,9 +826,6 @@ static void escape_analysis_process_instruction(escape_analysis_t *e, instructio
                case ICMD_MOVE:
                case ICMD_COPY:
                        if (instruction_dst_type(iptr, jd) == TYPE_ADR) {
-                               /*
-                               escape_analysis_assert_has_escape(e, instruction_s1(iptr));
-                               */
                                escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
                                escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
                        }
@@ -832,6 +864,19 @@ static void escape_analysis_process_instructions(escape_analysis_t *e) {
        }
 }
 
+static void escape_analysis_post_process_returns(escape_analysis_t *e) {
+       instruction_list_item_t *iti;
+       instruction *iptr;
+
+       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);
+               }
+       }
+}
+
 static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
        instruction_list_item_t *iti;
        dependency_list_item_t *itd;
@@ -867,6 +912,20 @@ static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
        }
 }
 
+static void escape_analysis_mark_monitors(escape_analysis_t *e) {
+       instruction_list_item_t *iti;
+       instruction *iptr;
+
+       FOR_EACH_INSTRUCTION_LIST(e->monitors, iti) {
+               iptr = iti->instr;
+
+               /* 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;
@@ -922,7 +981,9 @@ static void escape_analysis_process_arguments(escape_analysis_t *e) {
                if (t == TYPE_ADR) {
                        if (varindex != UNUSED) {
                                escape_analysis_ensure_state(e, varindex, ESCAPE_NONE);
-                               escape_analysis_set_is_argument(e, varindex);
+                               escape_analysis_set_contains_argument(e, varindex);
+                               escape_analysis_set_contains_only_arguments(e, varindex);
+                               /*escape_analysis_set_adr_arg_num(e, varindex, e->adr_args_count);*/
                        }
                        e->adr_args_count += 1;
                }
@@ -937,11 +998,18 @@ static void escape_analysis_export_arguments(escape_analysis_t *e) {
        s4 varindex;
        methoddesc *md;
        u1 *paramescape;
+       instruction_list_item_t *iti;
+       instruction *iptr;
+       escape_state_t es, re;
+       int ret_val_is_adr;
        
        md = e->jd->m->parseddesc;
 
-       paramescape = MNEW(u1, e->adr_args_count);
-       e->jd->m->paramescape = paramescape;
+       ret_val_is_adr = (md->returntype.type == TYPE_ADR) ? 1 : 0;
+
+       paramescape = MNEW(u1, e->adr_args_count + ret_val_is_adr);
+
+       e->jd->m->paramescape = paramescape + ret_val_is_adr;
 
        for (p = 0, l = 0; p < md->paramcount; ++p) {
                t = md->paramtypes[p].type;
@@ -950,15 +1018,40 @@ static void escape_analysis_export_arguments(escape_analysis_t *e) {
                        if (varindex == UNUSED) {
                                *paramescape = (u1)ESCAPE_NONE;
                        } else {
-                               *paramescape = (u1)escape_analysis_get_state(e, varindex);
-                       }
-                       if (e->verbose) {
-                               printf("adr parameter %d: %s\n", p, escape_state_to_string((escape_state_t)*paramescape));
+                               es = escape_analysis_get_state(e, varindex);
+
+                               if (es == ESCAPE_METHOD_RETURN) {
+                                       *paramescape = escape_state_to_u1(ESCAPE_METHOD) | 0x80;
+                                       if (e->verbose) {
+                                               printf("non-escaping adr parameter returned: %d\n", p);
+                                       }
+                               } else {
+                                       *paramescape = escape_state_to_u1(es);
+                               }
+
                        }
                        paramescape += 1;
                }
                l += IS_2_WORD_TYPE(t) ? 2 : 1;
        }
+
+       if (ret_val_is_adr) {
+               /* Calculate escape state of return value as maximum escape state of all
+                  values returned. */
+
+               re = ESCAPE_NONE;
+
+               FOR_EACH_INSTRUCTION_LIST(e->returns, iti) {
+                       iptr = iti->instr;
+                       es = escape_analysis_get_state(e, instruction_s1(iptr));
+
+                       if (es > re) {
+                               re = es;
+                       }
+               }
+
+               e->jd->m->paramescape[-1] = escape_state_to_u1(re);
+       }
 }
 
 static void escape_analysis_display(escape_analysis_t *e) {
@@ -983,25 +1076,147 @@ void escape_analysis_perform(jitdata *jd) {
 
        jd->m->flags |= ACC_METHOD_EA;
 
-       /*bc_escape_analysis_perform(jd->m);*/
-
        e = DNEW(escape_analysis_t);
        escape_analysis_init(e, jd);
 
        if (e->verbose) 
                printf("==== %s/%s ====\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
                
-       /*fprintf(stderr, ".");*/
-
        escape_analysis_process_arguments(e);
        escape_analysis_process_instructions(e);
        escape_analysis_post_process_getfields(e);
+       escape_analysis_post_process_returns(e);
+
        escape_analysis_export_arguments(e);
        if (e->verbose) escape_analysis_display(e);
+
        escape_analysis_mark_allocations(e);
+       escape_analysis_mark_monitors(e);
 
        jd->m->flags &= ~ACC_METHOD_EA;
 }
 
 void escape_analysis_escape_check(void *vp) {
 }
+
+/*** monomorphic *************************************************************/
+
+monomorphic_t monomorphic_get(methodinfo *caller, methodinfo *callee) {
+       monomorphic_t res = { 0, 0 };
+}
+
+#if 0
+
+/*** HACK to store method monomorphy information upon shutdown ****************/
+
+#include <sqlite3.h>
+
+bool method_profile_is_monomorphic(methodinfo *m) {
+       static sqlite3 *db = NULL;
+       static sqlite3_stmt *stmt = NULL;
+       int ret;
+
+       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);
+               }
+       }
+}
+
+
+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);
+}
+
+void iterate_classes() {
+       return;
+       method_profile_store();
+
+}
+
+#endif
+
+#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);
+}
+
+bool tlh_sigsegv_handler(void *addr) {
+}
+
+#endif
index 2f427fa31b6c2faf245a3748704b98485e62e234..c9f86239df574071e635f926419eed95a0c9a98a 100644 (file)
@@ -31,14 +31,29 @@ typedef enum {
        ESCAPE_UNKNOWN,
        ESCAPE_NONE,
        ESCAPE_METHOD,
-       ESCAPE_GLOBAL_THROUGH_METHOD,
+       ESCAPE_METHOD_RETURN,
        ESCAPE_GLOBAL
 } escape_state_t;
 
+static inline escape_state_t escape_state_from_u1(u1 x) {
+       return (escape_state_t)(x & ~0x80);
+}
+
+static inline u1 escape_state_to_u1(escape_state_t x) {
+       return (u1)x;
+}
+
 void escape_analysis_perform(jitdata *jd);
 
 void escape_analysis_escape_check(void *vp);
 
 void bc_escape_analysis_perform(methodinfo *m);
 
+typedef struct {
+       unsigned monomorphic:1;
+       unsigned speculative:1;
+} monomorphic_t;
+
+bool method_profile_is_monomorphic(methodinfo *m);
+
 #endif