* src/mm/tlh.c (tlh_alloc): Correctly zero memory.
authorPeter Molnar <pm@complang.tuwien.ac.at>
Wed, 9 Jul 2008 17:54:26 +0000 (19:54 +0200)
committerPeter Molnar <pm@complang.tuwien.ac.at>
Wed, 9 Jul 2008 17:54:26 +0000 (19:54 +0200)
* src/mm/tlh.h: Added include guardians.
* src/threads/posix/thread-posix.c [ENABLE_TLH] (threads_tlh_add_frame, threads_tlh_remove_frame): New symbols.
* src/threads/posix/thread-posix.h: Likewise, [ENABLE_ESCAPE_REASON] (threadobject): New field escape_reasons for passing escape reasons to builtin_escape_reasons_new.
* src/vm/builtin.c [ENABLE_TLH] (builtin_tlh_new): new symbol, [ENABLE_ESCAPE_REASON] (builtin_escape_reason_new): new symbol.
* src/vm/builtin.h: Likewise.
* src/vm/builtintable.inc: [ENABLE_TLH] added builtin_tlh_new builtintable entry, [ENABLE_ESCAPE_REASON] added builtin_escape_reasons_new builtintable entry.
* src/vm/global.h (ACC_METHOD_MONOMORPHY_USED, ACC_METHOD_PARENT_MONOMORPHY_USED): New symbols.
* src/vm/jit/code.h (CODE_FLAG_TLH): New symbol.
* src/vm/jit/i386/codegen.c [ENABLE_ESCAPE_REASON] (codegen_emit): Pass escape reasons to BUILTIN_escape_reason_new.
* src/vm/jit/jit.c (jit_compile_intern): move fix_exception_handlers and cfg_build after inline pass, as inline modifies the cfg.
* src/vm/jit/jit.h [ENABLE_ESCAPE_REASON] (struct instruction): added escape_reasons field. This wastes space, but it does not matter, as ENABLE_ESCAPE_REASON has never to be used in a producetion environment.
* src/vm/jit/optimizing/bytecode_escape.c,
src/vm/jit/optimizing/escape.c,
src/vm/jit/optimizing/escape.h,
src/vm/jit/optimizing/ssa3.c: Changed a lot.
* src/vm/jit/replace.c [__I386__] (md_push_stackframe): destroying stackslot 0, so it does not contain a garbage argument 0, that would break patching the virtual function table later (as argument registers are not restored during replacement), (replace_me_wrapper): added rt timing,
* src/vm/jit/show.c (show_basicblock) [ENABLE_SSA]: display phi functions, (show_icmd) [ENABLE_SSA]: display phi functions.
* src/vmcore/linker.c [ENABLE_TLH] (linker_overwrite_method) set ACC_METHOD_PARENT_MONOMORPHY_USED method flag, if a method overwrites some monomorphic method, who's monomorphy information has already been used.
* src/vmcore/method.c [ENABLE_TLH] (method_break_assumption_monomorphic): Hack.
* src/vmcore/rt-timing.c,
src/vmcore/rt-timing.h: (RT_TIMING_REPLACE): timing for replacement,  (RT_TIMING_1, ..., RT_TIMING_4): 4 new timers for ad-hoc timing.

22 files changed:
src/mm/tlh.c
src/mm/tlh.h
src/threads/posix/thread-posix.c
src/threads/posix/thread-posix.h
src/vm/builtin.c
src/vm/builtin.h
src/vm/builtintable.inc
src/vm/global.h
src/vm/jit/code.h
src/vm/jit/i386/codegen.c
src/vm/jit/jit.c
src/vm/jit/jit.h
src/vm/jit/optimizing/bytecode_escape.c
src/vm/jit/optimizing/escape.c
src/vm/jit/optimizing/escape.h
src/vm/jit/optimizing/ssa3.c
src/vm/jit/replace.c
src/vm/jit/show.c
src/vmcore/linker.c
src/vmcore/method.c
src/vmcore/rt-timing.c
src/vmcore/rt-timing.h

index 5db19b88d6e87d4df3cbdae9854752d431c352b4..e46cf87602be1397271c68a2f4751c08337d6bac 100644 (file)
@@ -23,7 +23,9 @@
 
 #include "config.h"
 
+#include "mm/memory.h"
 #include "mm/tlh.h"
+
 #include "vm/global.h"
 
 #include <assert.h>
@@ -104,6 +106,7 @@ void *tlh_alloc(tlh_t *tlh, size_t size) {
        if (tlh_avail(tlh, size)) {
                ret = tlh->top;
                tlh->top += size;
+               MZERO(ret, char, size);
        } else {
                ret = NULL;
        }
index 884d16eb73656830b8aaa92f7f2b1c8e4fada46f..48b40e307257225d88478007651bd12946923c47 100644 (file)
@@ -21,6 +21,9 @@
    02110-1301, USA.
 */
 
+#ifndef _MM_TLH_H
+#define _MM_TLH_H
+
 #include <stddef.h>
 #include <stdint.h>
 
@@ -42,6 +45,8 @@ void tlh_remove_frame(tlh_t *tlh);
 
 void *tlh_alloc(tlh_t *tlh, size_t size);
 
+#endif
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
index f5c6c3148ce89c85d70bf2effa5fa04ce745e661..3c2c2b237b2f21289c3e3469027ae21de78e5a44 100644 (file)
@@ -1811,6 +1811,17 @@ void threads_yield(void)
        sched_yield();
 }
 
+#if defined(ENABLE_TLH)
+
+void threads_tlh_add_frame() {
+       tlh_add_frame(&(THREADOBJECT->tlh));
+}
+
+void threads_tlh_remove_frame() {
+       tlh_remove_frame(&(THREADOBJECT->tlh));
+}
+
+#endif
 
 /*
  * These are local overrides for various environment variables in Emacs.
index 069d0f5daa9b82eabc56b92bd536bd212c7f11da..349b5c33248f26e231778bd6d947db17615b7b63 100644 (file)
@@ -180,6 +180,10 @@ struct threadobject {
        tlh_t                 tlh;
 #endif
 
+#if defined(ENABLE_ESCAPE_REASON)
+       void *escape_reasons;
+#endif
+
        listnode_t            linkage;      /* threads-list                       */
        listnode_t            linkage_free; /* free-list                          */
 };
@@ -296,6 +300,11 @@ void threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
 
 void threads_thread_interrupt(threadobject *thread);
 
+#if defined(ENABLE_TLH)
+void threads_tlh_add_frame();
+void threads_tlh_remove_frame();
+#endif
+
 #endif /* _THREAD_POSIX_H */
 
 
index 86ba2e5469a3e06713fa99320f4d0261b315ce6e..52c5c10de24442bc8b8a6392e2373e7f5f872530 100644 (file)
@@ -904,6 +904,90 @@ java_handle_t *builtin_new(classinfo *c)
        return o;
 }
 
+#if defined(ENABLE_ESCAPE_REASON)
+java_handle_t *builtin_escape_reason_new(classinfo *c) {
+       print_escape_reasons();
+       return builtin_java_new(c);
+}
+#endif
+
+#if defined(ENABLE_TLH)
+java_handle_t *builtin_tlh_new(classinfo *c)
+{
+       java_handle_t *o;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
+#if defined(ENABLE_CYCLES_STATS)
+       u8 cycles_start, cycles_end;
+#endif
+
+       RT_TIMING_GET_TIME(time_start);
+       CYCLES_STATS_GET(cycles_start);
+
+       /* is the class loaded */
+
+       assert(c->state & CLASS_LOADED);
+
+       /* check if we can instantiate this class */
+
+       if (c->flags & ACC_ABSTRACT) {
+               exceptions_throw_instantiationerror(c);
+               return NULL;
+       }
+
+       /* is the class linked */
+
+       if (!(c->state & CLASS_LINKED))
+               if (!link_class(c))
+                       return NULL;
+
+       if (!(c->state & CLASS_INITIALIZED)) {
+#if !defined(NDEBUG)
+               if (initverbose)
+                       log_message_class("Initialize class (from builtin_new): ", c);
+#endif
+
+               if (!initialize_class(c))
+                       return NULL;
+       }
+
+       /*
+       o = tlh_alloc(&(THREADOBJECT->tlh), c->instancesize);
+       */
+       o = NULL;
+
+       if (o == NULL) {
+               o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+                                          c->finalizer, true);
+       }
+
+       if (!o)
+               return NULL;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+       /* XXX this is only a dirty hack to make Boehm work with handles */
+
+       o = LLNI_WRAP((java_object_t *) o);
+#endif
+
+       LLNI_vftbl_direct(o) = c->vftbl;
+
+#if defined(ENABLE_THREADS)
+       lock_init_object_lock(LLNI_DIRECT(o));
+#endif
+
+       CYCLES_STATS_GET(cycles_end);
+       RT_TIMING_GET_TIME(time_end);
+
+/*
+       CYCLES_STATS_COUNT(builtin_new,cycles_end - cycles_start);
+       RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_OBJECT);
+*/
+
+       return o;
+#endif
+}
 
 /* builtin_java_new ************************************************************
 
index af6fd824aeabf0d1af65c85853413f502e1e9733..757467271d431cb981afda2a5dfc7342792bd334 100644 (file)
@@ -145,6 +145,17 @@ java_handle_t *builtin_new(classinfo *c);
 /* NOT AN OP */
 java_handle_t *builtin_java_new(java_handle_t *c);
 #define BUILTIN_new (functionptr) builtin_java_new
+
+#if defined(ENABLE_TLH)
+#define BUILTIN_tlh_new (functionptr) builtin_tlh_new
+java_handle_t *builtin_tlh_new(classinfo *c);
+#endif
+
+#if defined(ENABLE_ESCAPE_REASON)
+#define BUILTIN_escape_reason_new (functionptr)builtin_escape_reason_new
+java_handle_t *builtin_escape_reason_new(classinfo *c);
+#endif
+
 java_object_t *builtin_fast_new(classinfo *c);
 #define BUILTIN_FAST_new (functionptr) builtin_fast_new
 
index 735c1de70776c296d1113670634222df52a2526e..3f5781fe261a27bff1c1cd70173e64ea41011157 100644 (file)
@@ -194,6 +194,39 @@ static builtintable_entry builtintable_internal[] = {
                NULL,
                NULL
        },
+
+#if defined(ENABLE_TLH)
+       {
+               ICMD_NEW,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_tlh_new,
+               NULL,
+               NULL,
+               "tlh_new",
+               "(Ljava/lang/Class;)Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
+#if defined(ENABLE_ESCAPE_REASON)
+       {
+               ICMD_NEW,
+               BUILTINTABLE_FLAG_STUB,
+               BUILTIN_escape_reason_new,
+               NULL,
+               NULL,
+               "escape_reason_new",
+               "(Ljava/lang/Class;)Ljava/lang/Object;",
+               NULL,
+               NULL,
+               NULL,
+               NULL
+       },
+#endif
+
        {
                ICMD_NEW,
                0,
index 125eb3ff1096ff8e76fb1cdd82886dbfe1a21811..f08ba31aaa2ecca797c2e57b48153f2587c5afdd 100644 (file)
@@ -211,6 +211,10 @@ typedef struct java_objectarray_t java_objectarray_t;
 #define ACC_METHOD_IMPLEMENTED 0x00020000     /* there is an implementation   */
 #define ACC_METHOD_MONOMORPHIC 0x00040000     /* currently monomorphic method */
 #define ACC_METHOD_EA          0x00080000     /* method being escape analyzed */
+#define ACC_METHOD_MONOMORPHY_USED \
+                               0x00100000
+#define ACC_METHOD_PARENT_MONOMORPHY_USED \
+                               0x00200000
 
 
 /* data structures of the runtime system **************************************/
index adff257fe0262c85398d156effa7bb900144a240..375379725984bfcec636ae7f6c9d29591a1a7de4 100644 (file)
@@ -50,6 +50,7 @@
 #define CODE_FLAG_INVALID         0x0001
 #define CODE_FLAG_LEAFMETHOD      0x0002
 #define CODE_FLAG_SYNCHRONIZED    0x0004
+#define CODE_FLAG_TLH             0x0008
 
 
 /* codeinfo *******************************************************************
index 9c02d23ba5d282b7c72564296a0b3828e33888dd..cfed36af9c3405652c268b5600129b86c72319a3 100644 (file)
@@ -2222,7 +2222,7 @@ bool codegen_emit(jitdata *jd)
                        break;
 
                case ICMD_PUTSTATIC:  /* ..., value  ==> ...                          */
-
+                       
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                uf        = iptr->sx.s23.s3.uf;
                                fieldtype = uf->fieldref->parseddesc.fd->type;
@@ -2888,6 +2888,21 @@ nowperformreturn:
 
                        bte = iptr->sx.s23.s3.bte;
                        md = bte->md;
+
+#if defined(ENABLE_ESCAPE_REASON)
+                       if (bte->fp == BUILTIN_escape_reason_new) {
+                               void set_escape_reasons(void *);
+                               M_ASUB_IMM(8, REG_SP);
+                               M_MOV_IMM(iptr->escape_reasons, REG_ITMP1);
+                               M_AST(EDX, REG_SP, 4);
+                               M_AST(REG_ITMP1, REG_SP, 0);
+                               M_MOV_IMM(set_escape_reasons, REG_ITMP1);
+                               M_CALL(REG_ITMP1);
+                               M_ALD(EDX, REG_SP, 4);
+                               M_AADD_IMM(8, REG_SP);
+                       }
+#endif
+
                        goto gen_method;
 
                case ICMD_INVOKESTATIC: /* ..., [arg1, [arg2 ...]] ==> ...            */
index 45bea30c9d16df90e7e0878ac8f9a3c8a66db9b3..b93f8dacc05c2b35293dcd1006907f654851a4d0 100644 (file)
@@ -701,18 +701,6 @@ static u1 *jit_compile_intern(jitdata *jd)
 #endif
                RT_TIMING_GET_TIME(time_typecheck);
 
-#if defined(ENABLE_SSA)
-               if (opt_lsra) {
-                       fix_exception_handlers(jd);
-               }
-#endif
-
-               /* Build the CFG.  This has to be done after stack_analyse, as
-                  there happens the JSR elimination. */
-
-               if (!cfg_build(jd))
-                       return NULL;
-
 #if defined(ENABLE_LOOP)
                if (opt_loops) {
                        depthFirst(jd);
@@ -734,13 +722,25 @@ static u1 *jit_compile_intern(jitdata *jd)
 
                /* inlining */
 
-#if defined(ENABLE_INLINING) && !defined(ENABLE_ESCAPE)
+#if defined(ENABLE_INLINING) && !defined(ENABLE_ESCAPE) || 1
                if (JITDATA_HAS_FLAG_INLINE(jd)) {
                        if (!inline_inline(jd))
                                return NULL;
                }
 #endif
 
+#if defined(ENABLE_SSA)
+               if (opt_lsra) {
+                       fix_exception_handlers(jd);
+               }
+#endif
+
+               /* Build the CFG.  This has to be done after stack_analyse, as
+                  there happens the JSR elimination. */
+
+               if (!cfg_build(jd))
+                       return NULL;
+
 #if defined(ENABLE_PROFILING)
                /* Basic block reordering.  I think this should be done after
                   if-conversion, as we could lose the ability to do the
@@ -771,8 +771,9 @@ static u1 *jit_compile_intern(jitdata *jd)
 #if defined(ENABLE_SSA)
                /* allocate registers */
                if (
-                       (opt_lsra) 
-                       /*&& strncmp(jd->m->name->text, "banana", 6) == 0*/
+                       (opt_lsra &&
+                       jd->code->optlevel > 0) 
+                       /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
                        /*&& jd->exceptiontablelength == 0*/
                ) {
                        /*printf("=== %s ===\n", jd->m->name->text);*/
index 7fac7fd67d7a67b78b80e341257f44b48591f183..c447b1bd2db27018ba14c9e0eb2c7f3a6e3e4cc0 100644 (file)
@@ -383,6 +383,9 @@ struct instruction {
 #if SIZEOF_VOID_P == 4
     flags_operand_t         flags;  /* 4 bytes      */
 #endif
+#if defined(ENABLE_ESCAPE_REASON)
+       void *escape_reasons;
+#endif
 };
 
 
index 326f65f08015460cafe41aac7424c7c05fab5d82..82db44003bf577987776683cb87dbf8f39ad8577 100644 (file)
@@ -811,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 && method_profile_is_monomorphic(mi)) {
+       if (mi != NULL && escape_is_monomorphic(be->method, mi)) {
 
                if (mi->paramescape == NULL) {
                        bc_escape_analysis_perform_intern(mi, be->depth + 1);
@@ -1794,6 +1794,10 @@ static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
        }
 #endif
 
+       if (depth >= 3) {
+               return;
+       }
+
        if (m->paramescape != NULL) {
 #if BC_ESCAPE_VERBOSE
                if (verbose) {  
@@ -1821,7 +1825,14 @@ static void bc_escape_analysis_perform_intern(methodinfo *m, int depth) {
                return;
        }
 
-       /* TODO threshold */
+       if (m->jcodelength > 250) {
+#if BC_ESCAPE_VERBOSE
+               if (verbose) {
+                       dprintf(depth, "Bytecode too long: %d.\n", m->jcodelength);
+               }
+#endif
+               return;
+       }
 
        be = DNEW(bc_escape_analysis_t);
        bc_escape_analysis_init(be, m, verbose, depth);
index e05bf5cbe8071f4afc82c0eb52439833096b6dee..7642a5360d156f8fe7e061ba33bcda6486dd2cae 100644 (file)
@@ -1,4 +1,4 @@
-/* src/vm/optimizing/escape.c
+/* src/vm/optimizing/e&scape.c
 
    Copyright (C) 2008
    CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
 #include "vmcore/classcache.h"
 #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 +330,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 +346,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 +359,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,13 +456,30 @@ 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 +494,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 +555,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 +605,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 +644,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 +662,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 +684,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 +699,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 +724,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 +749,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 +766,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 +777,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 +791,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 +805,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);
                                }
@@ -698,6 +825,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 +843,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 +868,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 +894,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 +914,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 +932,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 +949,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 +966,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 +974,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 +1010,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 +1029,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 +1047,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 +1071,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 +1088,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 +1222,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 +1247,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 +1279,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 +1289,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,11 +1317,30 @@ void escape_analysis_escape_check(void *vp) {
 
 /*** monomorphic *************************************************************/
 
-monomorphic_t monomorphic_get(methodinfo *caller, methodinfo *callee) {
-       monomorphic_t res = { 0, 0 };
-}
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee) {
+
+       /* Non-speculative case */
+
+       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)
+       ) {
+
+               /* Mark that we have used the information about monomorphy. */
+
+               callee->flags |= ACC_METHOD_MONOMORPHY_USED;
+
+               /* We assume the callee is monomorphic. */
+
+               method_add_assumption_monomorphic(caller, callee);
+
+               return true;
+       }
 
-bool method_profile_is_monomorphic(methodinfo *m) {
-return 0;
+       return false;
 }
 
index c9f86239df574071e635f926419eed95a0c9a98a..5b5f7b6eeb7c377afbb76fc157cb3195f19df92c 100644 (file)
@@ -49,11 +49,6 @@ 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);
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee);
 
 #endif
index d522951997f37f6ec4860a145cd37b9069b51eec..29864f17f311bbeb8489fe0fb7d672a642ff6b2e 100644 (file)
@@ -345,8 +345,8 @@ static inline void instruction_set_uses(instruction *iptr, s4 *buf, s4 *uses, un
 
 /*** vars *******************************************************************/
 
-#define VARS_CATEGORY_SHIFT 29
-#define VARS_INDEX_MASK 0x1FFFFFFF
+#define VARS_CATEGORY_SHIFT 28
+#define VARS_INDEX_MASK 0x0FFFFFFF
 
 #define VARS_CATEGORY_LOCAL 0
 #define VARS_CATEGORY_STACK 1
@@ -538,13 +538,15 @@ FIXME() inline void phis_print(const phis_t *ps) {
 }
 #endif
 
-static inline void phis_copy_to(const phis_t *ps, instruction *dst) {
-       MCOPY(
-               dst,
-               ps->items,
-               instruction,
-               ps->count
-       );
+static inline unsigned phis_copy_to(const phis_t *ps, instruction *dst) {
+       instruction *it;
+       instruction *out = dst;
+
+       FOR_EACH_PHI_FUNCTION(ps, it) {
+               *(out++) = *it;
+       }
+
+       return (out - dst);
 }
 
 /*** state_array ************************************************************/
@@ -990,6 +992,8 @@ void fix_exception_handlers(jitdata *jd) {
        basicblock_chain_t chain;
        basicblock *last = NULL;
        basicblock *marker = NULL;
+       s4 vartop;
+       unsigned i;
 
        if (jd->exceptiontablelength == 0) {
                return;
@@ -997,22 +1001,38 @@ void fix_exception_handlers(jitdata *jd) {
 
        basicblock_chain_init(&chain);
 
-       /* We need to allocate new iovars */
+       /* Remember, where we started adding IO variables. */
 
-       avail_vars = (jd->varcount - jd->vartop);
-       add_vars = jd->exceptiontablelength;
-
-       if (add_vars > avail_vars) {
-               add_vars -= avail_vars;
-               jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
-               jd->varcount += add_vars;
-       }
+       vartop = jd->vartop;
 
        /* For each exception handler block, create one block with a prologue block */
 
        FOR_EACH_BASICBLOCK(jd, bptr) {
                if (bptr->type == BBTYPE_EXH) {
 
+                       /*
+             
+            +---- EXH (exh)-------+
+            |  in0 in1 in2 exc    |
+                       |  .....              |
+            +---------------------+
+
+            === TRANSFORMED TO ===>
+
+            +---- PROL (exh) -------+
+            |  in0 in1 in2          |
+            |  GETEXECEPTION => OU3 |
+            |  GOTO REAL_EXH        |
+            |  in0 in1 in2 OU3      |
+            +-----------------------+
+
+            +---- REAL_EXH (std) -+
+            |  in0 in1 in2 exc    |
+                       |  ......             |
+            +---------------------+
+
+                       */
+
                        bptr->type = BBTYPE_STD;
                        bptr->predecessorcount = 0; /* legacy */
 
@@ -1023,7 +1043,24 @@ void fix_exception_handlers(jitdata *jd) {
 
                        iptr = DMNEW(instruction, 2);
                        MZERO(iptr, instruction, 2);
+                       
+                       /* Create outvars */
+
+                       exh->outdepth = bptr->indepth;
+
+                       if (exh->outdepth > 0) {
+                               exh->outvars = DMNEW(s4, exh->outdepth);
+                               for (i = 0; i < exh->outdepth; ++i) {
+                                       exh->outvars[i] = vartop++;
+                               }
+                       }
+
+                       /* Create invars */
+
+                       exh->indepth = exh->outdepth - 1;
+                       exh->invars = exh->outvars;
 
+#if 0
                        /* Create new outvar */
 
                        assert(jd->vartop < jd->varcount);
@@ -1031,6 +1068,7 @@ void fix_exception_handlers(jitdata *jd) {
                        jd->vartop += 1;
                        jd->var[v].type = TYPE_ADR;
                        jd->var[v].flags = INOUT;
+#endif
 
                        exh->nr = jd->basicblockcount;
                        jd->basicblockcount += 1;
@@ -1038,9 +1076,11 @@ void fix_exception_handlers(jitdata *jd) {
                        exh->type = BBTYPE_EXH;
                        exh->icount = 2;
                        exh->iinstr = iptr;
+/*
                        exh->outdepth = 1;
                        exh->outvars = DNEW(s4);
                        exh->outvars[0] = v;
+*/
                        exh->predecessorcount = -1; /* legacy */
                        exh->flags = BBFINISHED;
                        exh->method = jd->m;
@@ -1050,7 +1090,7 @@ void fix_exception_handlers(jitdata *jd) {
                        /* Get exception */
 
                        iptr->opc = ICMD_GETEXCEPTION;
-                       iptr->dst.varindex = v;
+                       iptr->dst.varindex = exh->outvars[exh->outdepth - 1];
                        iptr += 1;
 
                        /* Goto real exception handler */
@@ -1069,6 +1109,19 @@ void fix_exception_handlers(jitdata *jd) {
                }
        }
 
+       /* We need to allocate the new iovars in the var array */
+
+       avail_vars = (jd->varcount - jd->vartop);
+       add_vars = (vartop - jd->vartop);
+
+       if (add_vars > avail_vars) {
+               add_vars -= avail_vars;
+               jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
+               jd->varcount += add_vars;
+       }
+
+       jd->vartop = vartop;
+
        /* Put the chain of exception handlers between just before the last
           basic block (end marker). */
 
@@ -1086,7 +1139,20 @@ void fix_exception_handlers(jitdata *jd) {
 
        for (ee = jd->exceptiontable; ee; ee = ee->down) {
                assert(ee->handler->vp);
-               ee->handler = ee->handler->vp;
+
+               bptr = ee->handler;
+               exh = (basicblock *)ee->handler->vp;
+
+               ee->handler = exh;
+
+               /* Set up IO variables in newly craeted exception handlers. */
+
+               for (i = 0; i < exh->outdepth; ++i) {
+                       v = exh->outvars[i];
+
+                       jd->var[v].flags = INOUT;
+                       jd->var[v].type = jd->var[ bptr->invars[i] ].type;
+               }
        }
 
 }
@@ -1248,6 +1314,10 @@ static void ssa_enter_verify_no_redundant_phis(ssa_info_t *ssa) {
        basicblock *bptr;
        basicblock_info_t *bbi;
        instruction *itph;
+
+       /* XXX */
+       return;
+
        FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
                if (basicblock_reached(bptr)) {
                        bbi = bb_info(bptr);
@@ -1370,6 +1440,14 @@ static void ssa_enter_process_pei(ssa_info *ssa, basicblock *bb, unsigned pei) {
                        basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
                        ssa->locals
                );
+
+               ssa_enter_merge(
+                       bbi->stack,
+                       succi->stack,
+                       *itsucc,
+                       basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
+                       ssa->stack
+               );
        }
 }
 
@@ -1378,6 +1456,9 @@ static FIXME(bool) ssa_enter_eliminate_redundant_phis(traversal_t *t, vars_t *vs
        instruction *itph;
        bool ret = false;
 
+       /* XXX */
+       return;
+
        FOR_EACH_PHI_FUNCTION(t->phis, itph) {
 
                phi_calculate_redundancy(itph);
@@ -1475,12 +1556,16 @@ static void ssa_enter_process_block(ssa_info *ssa, basicblock *bb) {
                state_array_allocate_items(bbi->stack->state_array);
        }
 
+#if 0
        /* Exception handlers have a clean stack. */
 
+       /* Not true with inlining. */
+
        if (bb->type == BBTYPE_EXH) {
                state_array_assert_no_items(bbi->stack->state_array);
                state_array_allocate_items(bbi->stack->state_array);
        }
+#endif
 
        /* Some in/out vars get marked as INOUT in simplereg,
           and are not marked at this point. 
@@ -1665,19 +1750,15 @@ static void ssa_enter_export_phis(ssa_info_t *ssa) {
        FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
                bbi = bb_info(bptr);
                if (bbi != NULL) {
-                       bptr->phicount = 
-                               bbi->locals->phis->count + 
-                               bbi->stack->phis->count;
-
-                       bptr->phis = DMNEW(instruction, bptr->phicount);
+                       bptr->phis = DMNEW(instruction, bbi->locals->phis->count + bbi->stack->phis->count);
 
                        dst = bptr->phis;
 
-                       phis_copy_to(bbi->locals->phis, dst);
+                       dst += phis_copy_to(bbi->locals->phis, dst);
 
-                       dst += bbi->locals->phis->count;
+                       dst += phis_copy_to(bbi->stack->phis, dst);
 
-                       phis_copy_to(bbi->stack->phis, dst);
+                       bptr->phicount = dst - bptr->phis;
                }
        }
 }
@@ -2269,6 +2350,7 @@ void ssa_simple_leave(ssa_info_t *ssa) {
                        }
                        instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
                }
+               bptr->phicount = 0;
        }
 
        unfix_exception_handlers(ssa->jd);
@@ -2282,11 +2364,17 @@ void ssa_simple_leave(ssa_info_t *ssa) {
        ssa->jd->localcount = ssa->original.localcount;
 }
 
+#include "vmcore/rt-timing.h"
+
 void yssa(jitdata *jd) {
        basicblock *it;
        basicblock_info_t *iti;
        ssa_info *ssa;
 
+       struct timespec bs, es, be, ee;
+
+       RT_TIMING_GET_TIME(bs);
+
 #ifdef SSA_VERBOSE
        bool verb = true;
        if (verb) {
@@ -2325,7 +2413,9 @@ void yssa(jitdata *jd) {
 
        /*ssa_enter_create_phi_graph(ssa);*/
 
-       /*escape_analysis_perform(ssa->jd);*/
+       RT_TIMING_GET_TIME(be);
+       escape_analysis_perform(ssa->jd);
+       RT_TIMING_GET_TIME(ee);
 
        /*
        ssa_leave_create_phi_moves(ssa);
@@ -2351,6 +2441,10 @@ void yssa(jitdata *jd) {
        }
 #endif
 
+       RT_TIMING_GET_TIME(es);
+
+       RT_TIMING_TIME_DIFF(bs, es, RT_TIMING_1);
+       RT_TIMING_TIME_DIFF(be, ee, RT_TIMING_2);
 }
 
 void eliminate_subbasicblocks(jitdata *jd) {
index 12d77508841b455e3bb7b0a10c097af70b3dfef7..c08d48d1ef6809d29d57f9f14837b5d9bec00490 100644 (file)
@@ -56,7 +56,9 @@
 
 #include "vmcore/options.h"
 #include "vmcore/classcache.h"
-
+#if defined(ENABLE_RT_TIMING)
+#include "vmcore/rt-timing.h"
+#endif
 
 #define REPLACE_PATCH_DYNAMIC_CALL
 /*#define REPLACE_PATCH_ALL*/
@@ -1465,6 +1467,12 @@ static void replace_write_executionstate(rplpoint *rp,
 
                if (!topframe && ra->index == RPLALLOC_PARAM) {
                        /* skip it */
+                       /*
+                       ra->index = RPLALLOC_PARAM;
+                       replace_val_t v;
+                       v.l = 0;
+                       replace_write_value(es,ra,&v);
+                       */
                }
                else {
                        assert(i < frame->javastackdepth);
@@ -1669,12 +1677,21 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
        /* in debug mode, invalidate stack frame first */
 
        /* XXX may not invalidate linkage area used by native code! */
+
 #if !defined(NDEBUG) && 0
-       for (i=0; i<(basesp - sp); ++i) {
+       for (i=0; i< (basesp - sp) && i < 1; ++i) {
                sp[i] = 0xdeaddeadU;
        }
 #endif
 
+#if defined(__I386__)
+       /* Stackslot 0 may contain the object instance for vftbl patching.
+          Destroy it, so there's no undefined value used. */
+       if ((basesp - sp) > 0) {
+               sp[0] = 0;
+       }
+#endif
+
        /* save the return address register */
 
 #if defined(REPLACE_RA_TOP_OF_FRAME)
@@ -2851,6 +2868,10 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
        origcode = es->code;
        origrp   = rp;
 
+       printf("Replacing in %s/%s\n", rp->method->clazz->name->text, rp->method->name->text);
+
+       /*if (strcmp(rp->method->clazz->name->text, "antlr/AlternativeElement") == 0 && strcmp(rp->method->name->text, "getAutoGenType") ==0) opt_TraceReplacement = 2; else opt_TraceReplacement = 0;*/
+
        DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
                                 stat_replacements, (void*)THREADOBJECT,
                                 rp->id, (void*)rp);
@@ -2976,6 +2997,9 @@ bool replace_me_wrapper(u1 *pc, void *context)
        codeinfo         *code;
        rplpoint         *rp;
        executionstate_t  es;
+#if defined(ENABLE_RT_TIMING)
+       struct timespec time_start, time_end;
+#endif
 
        /* search the codeinfo for the given PC */
 
@@ -3010,8 +3034,17 @@ bool replace_me_wrapper(u1 *pc, void *context)
 
                /* do the actual replacement */
 
+#if defined(ENABLE_RT_TIMING)
+               RT_TIMING_GET_TIME(time_start);
+#endif
+
                replace_me(rp, &es);
 
+#if defined(ENABLE_RT_TIMING)
+               RT_TIMING_GET_TIME(time_end);
+               RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_REPLACE);
+#endif
+
                /* write execution state to current context */
 
                md_executionstate_write(&es, context);
index 0b429ccadba6ef1cc03c43d1298c5e5c24aedfc8..7287f0968e56b600c981ef66ad0061dca47e385e 100644 (file)
@@ -549,6 +549,18 @@ void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
                }
 #endif /* defined(ENABLE_INLINING) */
 
+#if defined(ENABLE_SSA)
+       
+               iptr = bptr->phis;
+
+               for (i = 0; i < bptr->phicount; i++, iptr++) {
+                       printf("%4d:%4d:  ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
+
+                       show_icmd(jd, iptr, deadcode, irstage);
+                       printf("\n");
+               }
+#endif
+
                iptr = bptr->iinstr;
 
                for (i = 0; i < bptr->icount; i++, iptr++) {
@@ -1425,6 +1437,19 @@ void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
        case ICMD_GETEXCEPTION:
                SHOW_DST(iptr);
                break;
+#if defined(ENABLE_SSA)        
+       case ICMD_PHI:
+               printf("[ ");
+               for (i = 0; i < iptr->s1.argcount; ++i) {
+                       SHOW_VARIABLE(iptr->sx.s23.s2.iargs[i]->dst.varindex);
+               }
+               printf("] ");
+               SHOW_DST(iptr);
+               if (iptr->flags.bits & (1 << 0)) printf("used ");
+               if (iptr->flags.bits & (1 << 1)) printf("redundantAll ");
+               if (iptr->flags.bits & (1 << 2)) printf("redundantOne ");
+               break;
+#endif
        }
        fflush(stdout);
 }
index cee3866ee312c30c30532673bb8c05ce7f379e57..02d56b601ef347925547aaae263950ce92f31a18 100644 (file)
@@ -523,6 +523,15 @@ static bool linker_overwrite_method(methodinfo *mg,
 
        if ((ms->flags & ACC_METHOD_IMPLEMENTED) && ms->name != utf_init) {
                do {
+
+#if defined(ENABLE_TLH)
+                       if (mg->flags & ACC_METHOD_MONOMORPHY_USED) {
+                               printf("%s/%s is evil! the siner is %s/%s\n", mg->clazz->name->text, mg->name->text,
+                                       ms->clazz->name->text, ms->name->text);
+                               ms->flags |= ACC_METHOD_PARENT_MONOMORPHY_USED;                                 
+                       }
+#endif
+
                        if (mg->flags & ACC_METHOD_IMPLEMENTED) {
                                /* this adds another implementation */
 
index 393ad44728396b57ca6a1053e69340eb08874ed8..d1fb1b29611c7f325089fd54a22f5add8c516199 100644 (file)
@@ -1037,7 +1037,6 @@ void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
        m->assumptions = as;
 }
 
-
 /* method_break_assumption_monomorphic *****************************************
 
    Break the assumption that this method is monomorphic. All callers that
@@ -1064,10 +1063,21 @@ void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
                );
 
                method_add_to_worklist(as->context, wl);
+
+#if defined(ENABLE_TLH) && 0
+               /* XXX hack */
+               method_assumption *as2;
+               as2 = m->assumptions;
+               m->assumptions = NULL;
+               method_break_assumption_monomorphic(as->context, wl);
+               /*
+               assert(m->assumptions == NULL);
+               m->assumptions = as2;*/
+#endif
+
        }
 }
 
-
 /* method_printflags ***********************************************************
 
    Prints the flags of a method to stdout like.
index 7e535bef0fd4cd1f698ca7815b5d034014f73487..eb4a7533ba6799b2e7d71ba0b28f4108a1963bb6 100644 (file)
@@ -116,9 +116,20 @@ static struct rt_timing_stat rt_timing_stat_defs[] = {
        { RT_TIMING_GC_COMPACT      ,RT_TIMING_GC_TOTAL       , "gc: compaction phase" },
        { RT_TIMING_GC_ROOTSET2     ,RT_TIMING_GC_TOTAL       , "gc: rootset writeback" },
        { RT_TIMING_GC_TOTAL        ,-1                       , "total garbage collection time" },
+#endif
+       { -1                        ,-1                       , "" },
+
+#if defined(ENABLE_REPLACEMENT)
+       { RT_TIMING_REPLACE         ,-1                       , "replacement" },
        { -1                        ,-1                       , "" },
 #endif
 
+       { RT_TIMING_1               ,-1                       , "temporary timer 1" },
+       { RT_TIMING_2               ,-1                       , "temporary timer 2" },
+       { RT_TIMING_3               ,-1                       , "temporary timer 3" },
+       { RT_TIMING_4               ,-1                       , "temporary timer 4" },
+       { -1                        ,-1                       , "" },
+
     { 0                         ,-1                       , NULL }
 };
 
index d78e8c986420da1eaac8557c227e7ab86a1df4d7..01b3c80aaf1f219624a11ac0ec9d2b975c18bc07 100644 (file)
 #define RT_TIMING_GC_ROOTSET2      53
 #define RT_TIMING_GC_TOTAL         54
 
-#define RT_TIMING_N                55
+#define RT_TIMING_REPLACE          55
+
+#define RT_TIMING_1                56
+#define RT_TIMING_2                57
+#define RT_TIMING_3                58
+#define RT_TIMING_4                59
+
+#define RT_TIMING_N                60
 
 void rt_timing_gettime(struct timespec *ts);