* Moved all files from vmcore/ to vm/.
[cacao.git] / src / vm / jit / replace.c
index 0770c6bb876ca771256489690a82ba6da7881629..dea13b1ed821ff41bddc65c387ed80f5c7dfbfeb 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/replace.c - on-stack replacement of methods
 
-   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
@@ -32,6 +30,7 @@
 #include <stdlib.h>
 
 #include "arch.h"
+#include "md.h"
 
 #if defined(ENABLE_GC_CACAO)
 # include "mm/cacao-gc/gc.h"
 
 #include "mm/memory.h"
 
-#include "threads/threads-common.h"
+#include "threads/thread.hpp"
 
 #include "toolbox/logging.h"
 
-#include "vm/stringlocal.h"
+#include "vm/classcache.h"
+#include "vm/globals.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+#if defined(ENABLE_RT_TIMING)
+# include "vm/rt-timing.h"
+#endif
 
 #include "vm/jit/abi.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/disass.h"
+#include "vm/jit/executionstate.h"
 #include "vm/jit/jit.h"
-#include "vm/jit/md.h"
 #include "vm/jit/methodheader.h"
 #include "vm/jit/replace.h"
 #include "vm/jit/show.h"
 #include "vm/jit/stack.h"
 
-#include "vmcore/options.h"
-#include "vmcore/classcache.h"
-
 
 #define REPLACE_PATCH_DYNAMIC_CALL
 /*#define REPLACE_PATCH_ALL*/
@@ -73,7 +76,6 @@
 #undef REPLACE_RA_TOP_OF_FRAME
 #undef REPLACE_RA_LINKAGE_AREA
 #undef REPLACE_LEAFMETHODS_RA_REGISTER
-#undef REPLACE_REG_RA
 
 /* i386, x86_64 and m68k */
 #if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
 #elif defined(__ALPHA__)
 #define REPLACE_RA_TOP_OF_FRAME
 #define REPLACE_LEAFMETHODS_RA_REGISTER
-#define REPLACE_REG_RA REG_RA
 /* powerpc */
 #elif defined(__POWERPC__)
 #define REPLACE_RA_LINKAGE_AREA
 #define REPLACE_LEAFMETHODS_RA_REGISTER
-#define REPLACE_REG_RA REG_ITMP3 /* the execution state has the LR in itmp3 */
 /* s390 */
 #elif defined(__S390__)
 #define REPLACE_RA_TOP_OF_FRAME
-#define REPLACE_REG_RA REG_ITMP3
 #endif
 
 
@@ -114,7 +113,7 @@ typedef u8 stackslot_t;
 
 #if !defined(NDEBUG)
 static void java_value_print(s4 type, replace_val_t value);
-static void replace_stackframeinfo_println(stackframeinfo *sfi);
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
 #endif
 
 #if !defined(NDEBUG)
@@ -429,11 +428,6 @@ bool replace_create_replacement_points(jitdata *jd)
 
        m = code->m;
 
-       /* set codeinfo flags */
-
-       if (jd->isleafmethod)
-               CODE_SETFLAG_LEAFMETHOD(code);
-
        /* in instance methods, we may need a rplpoint at the method entry */
 
 #if defined(REPLACE_PATCH_DYNAMIC_CALL)
@@ -1238,6 +1232,12 @@ static void replace_read_executionstate(rplpoint *rp,
                replace_read_value(es, &instra, &(frame->instance));
 #endif
        }
+#if defined(__I386__)
+       else if (!(rp->method->flags & ACC_STATIC)) {
+               /* On i386 we always pass the first argument on stack. */
+               frame->instance.a = *(java_object_t **)(basesp + 1);
+       } 
+#endif
 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
 
        /* read stack slots */
@@ -1469,6 +1469,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);
@@ -1489,81 +1495,72 @@ static void replace_write_executionstate(rplpoint *rp,
 }
 
 
-/* replace_pop_activation_record ***********************************************
+/* md_pop_stackframe ***********************************************************
+
+   Restore callee-saved registers (including the RA register),
+   set the stack pointer to the next stackframe,
+   set the PC to the return address of the popped frame.
 
-   Peel a stack frame from the execution state.
-   
    *** This function imitates the effects of the method epilog ***
    *** and returning from the method call.                     ***
 
    IN:
-          es...............execution state
-          frame............source frame, receives synchronization slots
+       es...............execution state
 
    OUT:
        *es..............the execution state after popping the stack frame
-  
+                        NOTE: es->code and es->pv are NOT updated.
+
 *******************************************************************************/
 
-u1* replace_pop_activation_record(executionstate_t *es,
-                                                                 sourceframe_t *frame)
+void md_pop_stackframe(executionstate_t *es)
 {
        u1 *ra;
-       u1 *pv;
+       s4 ra_align_off;
        s4 reg;
        s4 i;
-       s4 count;
-       codeinfo *code;
        stackslot_t *basesp;
        stackslot_t *sp;
 
        assert(es->code);
-       assert(frame);
+
+       /* alignment offset of RA */
+
+       ra_align_off = 0;
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+    if (es->code->stackframesize)
+               ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
+#endif
 
        /* read the return address */
 
 #if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (CODE_IS_LEAFMETHOD(es->code))
-               ra = (u1*) (ptrint) es->intregs[REPLACE_REG_RA];
+       if (code_is_leafmethod(es->code))
+               ra = es->ra;
        else
 #endif
                ra = md_stacktrace_get_returnaddress(es->sp,
-                               SIZE_OF_STACKSLOT * es->code->stackframesize);
-
-       DOLOG( printf("return address: %p\n", (void*)ra); );
-
-       assert(ra);
+                          SIZE_OF_STACKSLOT * es->code->stackframesize + ra_align_off);
 
        /* calculate the base of the stack frame */
 
        sp = (stackslot_t *) es->sp;
        basesp = sp + es->code->stackframesize;
 
-       /* read slots used for synchronization */
-
-       assert(frame->syncslotcount == 0);
-       assert(frame->syncslots == NULL);
-       count = code_get_sync_slot_count(es->code);
-       frame->syncslotcount = count;
-       frame->syncslots = DMNEW(replace_val_t, count);
-       for (i=0; i<count; ++i) {
-               frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX */
-       }
-
        /* restore return address, if part of frame */
 
 #if defined(REPLACE_RA_TOP_OF_FRAME)
 #if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!CODE_IS_LEAFMETHOD(es->code))
+       if (!code_is_leafmethod(es->code))
 #endif
-               es->intregs[REPLACE_REG_RA] = *--basesp;
+               es->ra = (u1*) (ptrint) *--basesp;
 #endif /* REPLACE_RA_TOP_OF_FRAME */
 
 #if defined(REPLACE_RA_LINKAGE_AREA)
 #if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!CODE_IS_LEAFMETHOD(es->code))
+       if (!code_is_leafmethod(es->code))
 #endif
-               es->intregs[REPLACE_REG_RA] = basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
+               es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
 #endif /* REPLACE_RA_LINKAGE_AREA */
 
        /* restore saved int registers */
@@ -1602,42 +1599,19 @@ u1* replace_pop_activation_record(executionstate_t *es,
        es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
 
 #if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp += SIZE_OF_STACKSLOT; /* skip return address */
+       es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
 #endif
 
-       /* Set the new pc. Subtract one so we do not hit the replacement point */
-       /* of the instruction following the call, if there is one.             */
-
-       es->pc = ra - 1;
+       /* set the program counter to the return address */
 
-       /* find the new codeinfo */
-
-       pv = md_codegen_get_pv_from_pc(ra);
-
-       DOLOG( printf("PV = %p\n", (void*) pv); );
-
-       if (pv == NULL) /* XXX can this really happen? */
-               return NULL;
-
-       code = *(codeinfo **)(pv + CodeinfoPointer);
-
-       DOLOG( printf("CODE = %p\n", (void*) code); );
-
-       /* return NULL if we reached native code */
-
-       es->pv = pv;
-       es->code = code;
+       es->pc = ra;
 
        /* in debugging mode clobber non-saved registers */
 
 #if !defined(NDEBUG)
        /* for debugging */
        for (i=0; i<INT_REG_CNT; ++i)
-               if ((nregdescint[i] != REG_SAV)
-#if defined(REG_RA)
-                               && (i != REPLACE_REG_RA)
-#endif
-                       )
+               if (nregdescint[i] != REG_SAV)
                        es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
        for (i=0; i<FLT_REG_CNT; ++i)
                if (nregdescfloat[i] != REG_SAV)
@@ -1648,6 +1622,211 @@ u1* replace_pop_activation_record(executionstate_t *es,
                        es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
 # endif
 #endif /* !defined(NDEBUG) */
+}
+
+
+/* md_push_stackframe **********************************************************
+
+   Save the given return address, build the new stackframe,
+   and store callee-saved registers.
+
+   *** This function imitates the effects of a call and the ***
+   *** method prolog of the callee.                         ***
+
+   IN:
+       es...............execution state
+       calleecode.......the code we are "calling"
+       ra...............the return address to save
+
+   OUT:
+       *es..............the execution state after pushing the stack frame
+                        NOTE: es->pc, es->code, and es->pv are NOT updated.
+
+*******************************************************************************/
+
+void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
+{
+       s4           reg;
+       s4           i;
+       stackslot_t *basesp;
+       stackslot_t *sp;
+
+       assert(es);
+       assert(calleecode);
+
+       /* write the return address */
+
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp -= SIZEOF_VOID_P;
+       *((void **)es->sp) = (void *) ra;
+       if (calleecode->stackframesize)
+               es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
+#endif /* REPLACE_RA_BETWEEN_FRAMES */
+
+       es->ra = (u1*) (ptrint) ra;
+
+       /* build the stackframe */
+
+       DOLOG( printf("building stackframe of %d words at %p\n",
+                                 calleecode->stackframesize, (void*)es->sp); );
+
+       sp = (stackslot_t *) es->sp;
+       basesp = sp;
+
+       sp -= calleecode->stackframesize;
+       es->sp = (u1*) sp;
+
+       /* 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 < 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)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (!code_is_leafmethod(calleecode))
+#endif
+               *--basesp = (ptrint) ra;
+#endif /* REPLACE_RA_TOP_OF_FRAME */
+
+#if defined(REPLACE_RA_LINKAGE_AREA)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+       if (!code_is_leafmethod(calleecode))
+#endif
+               basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
+#endif /* REPLACE_RA_LINKAGE_AREA */
+
+       /* save int registers */
+
+       reg = INT_REG_CNT;
+       for (i=0; i<calleecode->savedintcount; ++i) {
+               while (nregdescint[--reg] != REG_SAV)
+                       ;
+               *--basesp = es->intregs[reg];
+
+               /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+               es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
+#endif
+       }
+
+       /* save flt registers */
+
+       /* XXX align? */
+       reg = FLT_REG_CNT;
+       for (i=0; i<calleecode->savedfltcount; ++i) {
+               while (nregdescfloat[--reg] != REG_SAV)
+                       ;
+               basesp -= STACK_SLOTS_PER_FLOAT;
+               *(double*)basesp = es->fltregs[reg];
+
+               /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+               *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
+#endif
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       /* save adr registers */
+
+       reg = ADR_REG_CNT;
+       for (i=0; i<calleecode->savedadrcount; ++i) {
+               while (nregdescadr[--reg] != REG_SAV)
+                       ;
+               *--basesp = es->adrregs[reg];
+
+               /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+               es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL;
+#endif
+       }
+#endif
+}
+
+
+/* replace_pop_activation_record ***********************************************
+
+   Peel a stack frame from the execution state.
+
+   *** This function imitates the effects of the method epilog ***
+   *** and returning from the method call.                     ***
+
+   IN:
+       es...............execution state
+       frame............source frame, receives synchronization slots
+
+   OUT:
+       *es..............the execution state after popping the stack frame
+
+   RETURN VALUE:
+       the return address of the poped activation record
+
+*******************************************************************************/
+
+u1* replace_pop_activation_record(executionstate_t *es,
+                                                                 sourceframe_t *frame)
+{
+       u1 *ra;
+       u1 *pv;
+       s4 i;
+       s4 count;
+       codeinfo *code;
+       stackslot_t *sp;
+
+       assert(es->code);
+       assert(frame);
+
+       /* calculate the base of the stack frame */
+
+       sp = (stackslot_t *) es->sp;
+       assert(frame->syncslotcount == 0);
+       assert(frame->syncslots == NULL);
+       count = code_get_sync_slot_count(es->code);
+       frame->syncslotcount = count;
+       frame->syncslots = DMNEW(replace_val_t, count);
+       for (i=0; i<count; ++i) {
+               frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX md_ function */
+       }
+
+       /* pop the stackframe */
+
+       md_pop_stackframe(es);
+
+       ra = es->pc;
+
+       DOLOG( printf("RA = %p\n", (void*)ra); );
+
+       /* Subtract one from the PC so we do not hit the replacement point */
+       /* of the instruction following the call, if there is one.         */
+
+       es->pc--;
+
+       /* find the new codeinfo */
+
+       pv = md_codegen_get_pv_from_pc(ra);
+       DOLOG( printf("PV = %p\n", (void*) pv); );
+
+       code = code_get_codeinfo_for_pv(pv);
+       DOLOG( printf("CODE = %p\n", (void*) code); );
+
+       /* return NULL if we reached native code */
+
+       es->pv = pv;
+       es->code = code;
 
        return (code) ? ra : NULL;
 }
@@ -1678,8 +1857,8 @@ static void replace_patch_method_pointer(methodptr *mpp,
                                  (void*) *mpp, (void*)entrypoint); );
 
 #if !defined(NDEBUG)
-       oldcode = *(codeinfo **)((u1*)(*mpp) + CodeinfoPointer);
-       newcode = *(codeinfo **)((u1*)(entrypoint) + CodeinfoPointer);
+       oldcode = code_get_codeinfo_for_pv(*mpp);
+       newcode = code_get_codeinfo_for_pv(entrypoint);
 
        DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
                                 method_println(oldcode->m);
@@ -1754,12 +1933,6 @@ struct replace_patch_data_t {
        u1         *entrypoint;
 };
 
-#define CODEINFO_OF_CODE(entrypoint) \
-       (*(codeinfo **)((u1*)(entrypoint) + CodeinfoPointer))
-
-#define METHOD_OF_CODE(entrypoint) \
-       (CODEINFO_OF_CODE(entrypoint)->m)
-
 void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
 {
        vftbl_t *vftbl = c->vftbl;
@@ -1767,7 +1940,7 @@ void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
        if (vftbl != NULL
                && vftbl->vftbllength > pd->m->vftblindex
                && vftbl->table[pd->m->vftblindex] != &asm_abstractmethoderror
-               && METHOD_OF_CODE(vftbl->table[pd->m->vftblindex]) == pd->m)
+               && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
        {
                replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
        }
@@ -1808,15 +1981,15 @@ void replace_patch_future_calls(u1 *ra,
                                                                sourceframe_t *callerframe,
                                                                sourceframe_t *calleeframe)
 {
-       u1             *patchpos;
-       methodptr       entrypoint;
-       methodptr       oldentrypoint;
-       bool            atentry;
-       stackframeinfo  sfi;
-       codeinfo       *calleecode;
-       methodinfo     *calleem;
-       java_object_t  *obj;
-       vftbl_t        *vftbl;
+       u1            *patchpos;
+       methodptr      entrypoint;
+       methodptr      oldentrypoint;
+       bool           atentry;
+       void          *pv;
+       codeinfo      *calleecode;
+       methodinfo    *calleem;
+       java_object_t *obj;
+       vftbl_t       *vftbl;
 
        assert(ra);
        assert(callerframe->down == calleeframe);
@@ -1839,16 +2012,19 @@ void replace_patch_future_calls(u1 *ra,
 
        /* get the position to patch, in case it was a statically bound call   */
 
-       sfi.pv = callerframe->fromcode->entrypoint;
-       patchpos = md_get_method_patch_address(ra, &sfi, NULL);
+       pv = callerframe->fromcode->entrypoint;
+       patchpos = md_jit_method_patch_address(pv, ra, NULL);
 
        if (patchpos == NULL) {
                /* the call was dispatched dynamically */
 
                /* we can only patch such calls if we are at the entry point */
 
+#if !defined(__I386__)
+               /* On i386 we always know the instance argument. */
                if (!atentry)
                        return;
+#endif
 
                assert((calleem->flags & ACC_STATIC) == 0);
 
@@ -1867,15 +2043,20 @@ void replace_patch_future_calls(u1 *ra,
                obj = calleeframe->instance.a;
                vftbl = obj->vftbl;
 
-               assert(vftbl->class->vftbl == vftbl);
+               assert(vftbl->clazz->vftbl == vftbl);
 
-               DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->class); );
+               DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
 
                replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
        }
        else {
                /* the call was statically bound */
 
+#if defined(__I386__)
+               /* It happens that there is a patcher trap. (pm) */
+               if (*(u2 *)(patchpos - 1) == 0x0b0f) {
+               } else
+#endif
                replace_patch_method_pointer((methodptr *) patchpos, entrypoint, "static   ");
        }
 }
@@ -1905,10 +2086,8 @@ void replace_push_activation_record(executionstate_t *es,
                                                                        sourceframe_t *callerframe,
                                                                        sourceframe_t *calleeframe)
 {
-       s4           reg;
        s4           i;
        s4           count;
-       stackslot_t *basesp;
        stackslot_t *sp;
        u1          *ra;
        codeinfo    *calleecode;
@@ -1932,120 +2111,25 @@ void replace_push_activation_record(executionstate_t *es,
        else
                ra = es->pc + 1 /* XXX this is ugly */;
 
-       /* write the return address */
+       /* push the stackframe */
 
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
-       es->sp -= SIZE_OF_STACKSLOT;
+       md_push_stackframe(es, calleecode, ra);
 
-       *((stackslot_t *)es->sp) = (stackslot_t) ra;
-#endif /* REPLACE_RA_BETWEEN_FRAMES */
-
-#if defined(REPLACE_REG_RA)
-       es->intregs[REPLACE_REG_RA] = (ptrint) ra;
-#endif
-
-       /* we move into a new code unit */
+       /* we move into a new code unit, set code, PC, PV */
 
        es->code = calleecode;
-
-       /* set the new pc XXX not needed? */
-
-       es->pc = calleecode->entrypoint;
-
-       /* build the stackframe */
-
-       DOLOG( printf("building stackframe of %d words at %p\n",
-                                 calleecode->stackframesize, (void*)es->sp); );
-
-       sp = (stackslot_t *) es->sp;
-       basesp = sp;
-
-       sp -= calleecode->stackframesize;
-       es->sp = (u1*) sp;
-
-       /* 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) {
-               sp[i] = 0xdeaddeadU;
-       }
-#endif
-
-       /* save the return address register */
-
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!CODE_IS_LEAFMETHOD(calleecode))
-#endif
-               *--basesp = (ptrint) ra;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!CODE_IS_LEAFMETHOD(calleecode))
-#endif
-               basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
-       /* save int registers */
-
-       reg = INT_REG_CNT;
-       for (i=0; i<calleecode->savedintcount; ++i) {
-               while (nregdescint[--reg] != REG_SAV)
-                       ;
-               *--basesp = es->intregs[reg];
-
-               /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
-               es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
-#endif
-       }
-
-       /* save flt registers */
-
-       /* XXX align? */
-       reg = FLT_REG_CNT;
-       for (i=0; i<calleecode->savedfltcount; ++i) {
-               while (nregdescfloat[--reg] != REG_SAV)
-                       ;
-               basesp -= STACK_SLOTS_PER_FLOAT;
-               *(double*)basesp = es->fltregs[reg];
-
-               /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
-               *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
-#endif
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       /* save adr registers */
-
-       reg = ADR_REG_CNT;
-       for (i=0; i<calleecode->savedadrcount; ++i) {
-               while (nregdescadr[--reg] != REG_SAV)
-                       ;
-               *--basesp = es->adrregs[reg];
-
-               /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
-               es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL;
-#endif
-       }
-#endif
+       es->pc = calleecode->entrypoint; /* XXX not needed? */
+       es->pv = calleecode->entrypoint;
 
        /* write slots used for synchronization */
 
+       sp = (stackslot_t *) es->sp;
        count = code_get_sync_slot_count(calleecode);
        assert(count == calleeframe->syncslotcount);
        for (i=0; i<count; ++i) {
                sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
        }
 
-       /* set the PV */
-
-       es->pv = calleecode->entrypoint;
-
        /* redirect future invocations */
 
        if (callerframe && rpcall) {
@@ -2161,7 +2245,7 @@ no_match:
 
 *******************************************************************************/
 
-rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc)
+rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
 {
        rplpoint *found;
        rplpoint *rp;
@@ -2175,14 +2259,20 @@ rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc)
        rp = code->rplpoints;
        for (i=0; i<code->rplpointcount; ++i, ++rp) {
                DOLOG( replace_replacement_point_println(rp, 2); );
-               if (rp->pc <= pc && rp->pc + rp->callsize >= pc)
-                       found = rp;
+               if (rp->pc <= pc && rp->pc + rp->callsize >= pc) {
+                       if (desired_flags) {
+                               if (rp->flags & desired_flags) {
+                                       found = rp;
+                               }
+                       } else {
+                               found = rp;
+                       }
+               }
        }
 
        return found;
 }
 
-
 /* replace_pop_native_frame ****************************************************
 
    Unroll a native frame in the execution state and create a source frame
@@ -2201,7 +2291,7 @@ rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc)
 
 static void replace_pop_native_frame(executionstate_t *es,
                                                                         sourcestate_t *ss,
-                                                                        stackframeinfo *sfi)
+                                                                        stackframeinfo_t *sfi)
 {
        sourceframe_t *frame;
        codeinfo      *code;
@@ -2216,7 +2306,7 @@ static void replace_pop_native_frame(executionstate_t *es,
        /* remember pc and size of native frame */
 
        frame->nativepc = es->pc;
-       frame->nativeframesize = (es->sp != 0) ? (sfi->sp - es->sp) : 0;
+       frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
        assert(frame->nativeframesize >= 0);
 
        /* remember values of saved registers */
@@ -2280,29 +2370,21 @@ static void replace_pop_native_frame(executionstate_t *es,
 # endif
 #endif
 
-       /* restore pv, pc, and sp */
-
-       if (sfi->pv == NULL) {
-               /* frame of a native function call */
-               es->pv = md_codegen_get_pv_from_pc(sfi->ra);
-       }
-       else {
-               es->pv = sfi->pv;
-       }
-       es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1;
-       es->sp = sfi->sp;
-
-       /* find the new codeinfo */
+       /* restore codeinfo of the native stub */
 
-       DOLOG( printf("PV = %p\n", (void*) es->pv); );
+       code = code_get_codeinfo_for_pv(sfi->pv);
 
-       assert(es->pv != NULL);
+       /* restore sp, pv, pc and codeinfo of the parent method */
 
-       code = *(codeinfo **)(es->pv + CodeinfoPointer);
-
-       DOLOG( printf("CODE = %p\n", (void*) code); );
-
-       es->code = code;
+       /* XXX michi: use this instead:
+       es->sp = sfi->sp + code->stackframesize; */
+       es->sp   = (void*) (((uintptr_t) sfi->sp) + (*(s4 *) (((uintptr_t) sfi->pv) + FrameSize)));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp  += SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+       es->pv   = md_codegen_get_pv_from_pc(sfi->ra);
+       es->pc   = (void*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
+       es->code = code_get_codeinfo_for_pv(es->pv);
 }
 
 
@@ -2343,6 +2425,13 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
 
        ss->frames = frame->down;
 
+       /* skip sp for the native stub */
+
+       es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+       es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+
        /* assert that the native frame has not moved */
 
        assert(es->sp == frame->sfi->sp);
@@ -2414,7 +2503,7 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
 *******************************************************************************/
 
 sourcestate_t *replace_recover_source_state(rplpoint *rp,
-                                                                                       stackframeinfo *sfi,
+                                                                                       stackframeinfo_t *sfi,
                                                                                    executionstate_t *es)
 {
        sourcestate_t *ss;
@@ -2436,7 +2525,7 @@ sourcestate_t *replace_recover_source_state(rplpoint *rp,
 
        while (rp || sfi) {
 
-               DOLOG( replace_executionstate_println(es); );
+               DOLOG( executionstate_println(es); );
 
                /* if we are not at a replacement point, it is a native frame */
 
@@ -2510,7 +2599,7 @@ sourcestate_t *replace_recover_source_state(rplpoint *rp,
                        /* find the replacement point at the call site */
 
 after_machine_frame:
-                       rp = replace_find_replacement_point_for_pc(es->code, es->pc);
+                       rp = replace_find_replacement_point_for_pc(es->code, es->pc, 0);
 
                        if (rp == NULL)
                                vm_abort("could not find replacement point while unrolling call");
@@ -2719,7 +2808,7 @@ static void replace_build_execution_state(sourcestate_t *ss,
 
                        replace_push_activation_record(es, rp, prevframe, ss->frames);
 
-                       DOLOG( replace_executionstate_println(es); );
+                       DOLOG( executionstate_println(es); );
                }
 
                rp = ss->frames->torp;
@@ -2739,7 +2828,7 @@ static void replace_build_execution_state(sourcestate_t *ss,
 
                replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
 
-               DOLOG( replace_executionstate_println(es); );
+               DOLOG( executionstate_println(es); );
 
                if (rp->type == RPLPOINT_TYPE_CALL) {
                        parent = NULL;
@@ -2768,19 +2857,25 @@ static void replace_build_execution_state(sourcestate_t *ss,
 
 static void replace_me(rplpoint *rp, executionstate_t *es)
 {
-       stackframeinfo      *sfi;
+       stackframeinfo_t    *sfi;
        sourcestate_t       *ss;
        sourceframe_t       *frame;
-       s4                   dumpsize;
        codeinfo            *origcode;
        rplpoint            *origrp;
 #if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
        threadobject        *thread;
 #endif
+       int32_t              dumpmarker;
 
        origcode = es->code;
        origrp   = rp;
 
+#if defined(ENABLE_TLH)
+       /*printf("Replacing in %s/%s\n", rp->method->clazz->name->text, rp->method->name->text);*/
+#endif
+
+       /*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);
@@ -2792,11 +2887,11 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
 
        /* mark start of dump memory area */
 
-       dumpsize = dump_size();
+       DMARKER;
 
-       /* get the stackframeinfo for the current thread */
+       /* Get the stackframeinfo for the current thread. */
 
-       sfi = STACKFRAMEINFO;
+       sfi = threads_get_current_stackframeinfo();
 
        /* recover source state */
 
@@ -2875,7 +2970,7 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
 
        /* release dump area */
 
-       dump_release(dumpsize);
+       DRELEASE;
 }
 
 
@@ -2906,6 +3001,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 */
 
@@ -2914,11 +3012,18 @@ bool replace_me_wrapper(u1 *pc, void *context)
 
        /* search for a replacement point at the given PC */
 
-       rp = replace_find_replacement_point_for_pc(code, pc);
+       rp = replace_find_replacement_point_for_pc(code, pc, (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN));
 
        /* check if the replacement point belongs to given PC and is active */
 
-       if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
+       if ((rp != NULL) && (rp->pc == pc)
+           && (rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))) {
+
+               DOLOG( printf("valid replacement point\n"); );
+
+#if !defined(NDEBUG)
+               executionstate_sanity_check(context);
+#endif
 
                /* set codeinfo pointer in execution state */
 
@@ -2926,21 +3031,30 @@ bool replace_me_wrapper(u1 *pc, void *context)
 
                /* read execution state from current context */
 
-               md_replace_executionstate_read(&es, context);
+               md_executionstate_read(&es, context);
 
                DOLOG( printf("REPLACEMENT READ: ");
-                          replace_executionstate_println(&es); );
+                          executionstate_println(&es); );
 
                /* 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_replace_executionstate_write(&es, context);
+               md_executionstate_write(&es, context);
 
                DOLOG( printf("REPLACEMENT WRITE: ");
-                          replace_executionstate_println(&es); );
+                          executionstate_println(&es); );
 
                /* new code is entered after returning */
 
@@ -2959,13 +3073,15 @@ bool replace_me_wrapper(u1 *pc, void *context)
 #if defined(ENABLE_GC_CACAO)
 void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
 {
-       stackframeinfo   *sfi;
+       stackframeinfo_t *sfi;
        executionstate_t *es;
        sourcestate_t    *ss;
 
-       /* get the stackframeinfo of this thread */
+       /* Get the stackframeinfo of this thread. */
+
        assert(thread == THREADOBJECT);
-       sfi = STACKFRAMEINFO;
+
+       sfi = threads_get_current_stackframeinfo();
 
        /* create the execution state */
        es = DNEW(executionstate_t);
@@ -3239,108 +3355,6 @@ void replace_show_replacement_points(codeinfo *code)
 #endif
 
 
-/* replace_executionstate_println **********************************************
-   Print execution state
-  
-   IN:
-       es...............the execution state to print
-  
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_executionstate_println(executionstate_t *es)
-{
-       int i;
-       int slots;
-       stackslot_t *sp;
-       int extraslots;
-
-       if (!es) {
-               printf("(executionstate_t *)NULL\n");
-               return;
-       }
-
-       printf("executionstate_t:\n");
-       printf("\tpc = %p",(void*)es->pc);
-       printf("  sp = %p",(void*)es->sp);
-       printf("  pv = %p\n",(void*)es->pv);
-#if defined(ENABLE_DISASSEMBLER)
-       for (i=0; i<INT_REG_CNT; ++i) {
-               if (i%4 == 0)
-                       printf("\t");
-               else
-                       printf(" ");
-#if SIZEOF_VOID_P == 8
-               printf("%-3s = %016llx",abi_registers_integer_name[i],(unsigned long long)es->intregs[i]);
-#else
-               printf("%-3s = %08lx",abi_registers_integer_name[i],(unsigned long)es->intregs[i]);
-#endif
-               if (i%4 == 3)
-                       printf("\n");
-       }
-       for (i=0; i<FLT_REG_CNT; ++i) {
-               if (i%4 == 0)
-                       printf("\t");
-               else
-                       printf(" ");
-               printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
-               if (i%4 == 3)
-                       printf("\n");
-       }
-# if defined(HAS_ADDRESS_REGISTER_FILE)
-       for (i=0; i<ADR_REG_CNT; ++i) {
-               if (i%4 == 0)
-                       printf("\t");
-               else
-                       printf(" ");
-               printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
-               if (i%4 == 3)
-                       printf("\n");
-       }
-# endif
-#endif
-
-       sp = (stackslot_t *) es->sp;
-
-       extraslots = 2;
-
-       if (es->code) {
-               methoddesc *md = es->code->m->parseddesc;
-               slots = es->code->stackframesize;
-               extraslots = 1 + md->memuse;
-       }
-       else
-               slots = 0;
-
-
-       if (slots) {
-               printf("\tstack slots(+%d) at sp:", extraslots);
-               for (i=0; i<slots+extraslots; ++i) {
-                       if (i%4 == 0)
-                               printf("\n\t\t");
-                       printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
-#ifdef HAS_4BYTE_STACKSLOT
-                       printf("%08lx",(unsigned long)*sp++);
-#else
-                       printf("%016llx",(unsigned long long)*sp++);
-#endif
-                       printf("%c", (i >= slots) ? ')' : ' ');
-               }
-               printf("\n");
-       }
-
-       printf("\tcode: %p", (void*)es->code);
-       if (es->code != NULL) {
-               printf(" stackframesize=%d ", es->code->stackframesize);
-               method_print(es->code->m);
-       }
-       printf("\n");
-
-       printf("\n");
-}
-#endif
-
 #if !defined(NDEBUG)
 static void java_value_print(s4 type, replace_val_t value)
 {
@@ -3357,9 +3371,9 @@ static void java_value_print(s4 type, replace_val_t value)
        if (type == TYPE_ADR && value.a != NULL) {
                obj = value.a;
                putchar(' ');
-               utf_display_printable_ascii_classname(obj->vftbl->class->name);
+               utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
 
-               if (obj->vftbl->class == class_java_lang_String) {
+               if (obj->vftbl->clazz == class_java_lang_String) {
                        printf(" \"");
                        u = javastring_toutf(obj, false);
                        utf_display_printable_ascii(u);
@@ -3539,7 +3553,7 @@ void replace_sourcestate_println_short(sourcestate_t *ss)
 
                if (REPLACE_IS_NATIVE_FRAME(frame)) {
                        printf("NATIVE (pc %p size %d) ",
-                                       (void*)frame->nativepc, frame->nativeframesize);
+                                  (void*)frame->nativepc, frame->nativeframesize);
                        replace_stackframeinfo_println(frame->sfi);
                        continue;
                }
@@ -3566,19 +3580,20 @@ void replace_sourcestate_println_short(sourcestate_t *ss)
 #endif
 
 #if !defined(NDEBUG)
-static void replace_stackframeinfo_println(stackframeinfo *sfi)
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
 {
        printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
                        (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
                        (void*)sfi->ra, (void*)sfi->xpc);
 
-       if (sfi->method)
-               method_println(sfi->method);
+       if (sfi->code)
+               method_println(sfi->code->m);
        else
                printf("(nil)\n");
 }
 #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