* configure.ac: Added tests for python.
[cacao.git] / src / vm / jit / replace.c
index b6d417e7e6ba6b2c790b81f700fc4b2abb859d65..c0c7ea52adb38d855d5dc5bed3cc6a20bdc92a68 100644 (file)
@@ -1,6 +1,6 @@
-/* vm/jit/replace.c - on-stack replacement of methods
+/* src/vm/jit/replace.c - on-stack replacement of methods
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Edwin Steiner
-
-   $Id$
-
 */
 
 #include "config.h"
 #include "vm/types.h"
 
 #include <assert.h>
+#include <stdint.h>
 #include <stdlib.h>
 
 #include "arch.h"
+#include "md.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "mm/cacao-gc/gc.h"
+#endif
 
 #include "mm/memory.h"
+
+#include "threads/threads-common.h"
+
 #include "toolbox/logging.h"
-#include "vm/options.h"
+
 #include "vm/stringlocal.h"
+
 #include "vm/jit/abi.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/stack.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/disass.h"
-#include "vm/jit/show.h"
+#include "vm/jit/jit.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"
 
-#include "native/include/java_lang_String.h"
 
 #define REPLACE_PATCH_DYNAMIC_CALL
 /*#define REPLACE_PATCH_ALL*/
 
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
 
 /*** architecture-dependent configuration *************************************/
 
@@ -66,8 +75,8 @@
 #undef REPLACE_LEAFMETHODS_RA_REGISTER
 #undef REPLACE_REG_RA
 
-/* i386 and x86_64 */
-#if defined(__I386__) || defined(__X86_64__)
+/* i386, x86_64 and m68k */
+#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
 #define REPLACE_RA_BETWEEN_FRAMES
 /* alpha */
 #elif defined(__ALPHA__)
 #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
 
 
@@ -99,17 +112,14 @@ typedef u8 stackslot_t;
 
 /*** debugging ****************************************************************/
 
-/*#define REPLACE_VERBOSE*/
-
 #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) && defined(REPLACE_VERBOSE)
-int replace_verbose = 0;
-#define DOLOG(code)        do{ if (replace_verbose > 1) { code; } } while(0)
-#define DOLOG_SHORT(code)  do{ if (replace_verbose > 0) { code; } } while(0)
+#if !defined(NDEBUG)
+#define DOLOG(code)        do{ if (opt_TraceReplacement > 1) { code; } } while(0)
+#define DOLOG_SHORT(code)  do{ if (opt_TraceReplacement > 0) { code; } } while(0)
 #else
 #define DOLOG(code)
 #define DOLOG_SHORT(code)
@@ -240,17 +250,17 @@ static void replace_create_replacement_point(jitdata *jd,
                                continue;
 
                        ra->index = i;
-                       if (index < UNUSED) {
-                               ra->regoff = (UNUSED - index) - 1;
-                               ra->type = TYPE_RET;
-                               ra->flags = 0;
-                       }
-                       else {
+                       if (index >= 0) {
                                v = VAR(index);
                                ra->flags = v->flags & (INMEMORY);
                                ra->regoff = v->vv.regoff;
                                ra->type = v->type;
                        }
+                       else {
+                               ra->regoff = RETADDR_FROM_JAVALOCAL(index);
+                               ra->type = TYPE_RET;
+                               ra->flags = 0;
+                       }
                        ra++;
                }
        }
@@ -419,11 +429,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)
@@ -468,6 +473,17 @@ bool replace_create_replacement_points(jitdata *jd)
 
                for (; iptr != iend; ++iptr) {
                        switch (iptr->opc) {
+#if defined(ENABLE_GC_CACAO)
+                               case ICMD_BUILTIN:
+                                       md = iptr->sx.s23.s3.bte->md;
+                                       count++;
+                                       COUNT_javalocals(javalocals, m, alloccount);
+                                       alloccount += iptr->s1.argcount;
+                                       if (iinfo)
+                                               alloccount -= iinfo->throughcount;
+                                       break;
+#endif
+
                                case ICMD_INVOKESTATIC:
                                case ICMD_INVOKESPECIAL:
                                case ICMD_INVOKEVIRTUAL:
@@ -607,6 +623,9 @@ bool replace_create_replacement_points(jitdata *jd)
                        replace_create_replacement_point(jd, iinfo, rp++,
                                        bptr->type, bptr->iinstr, &ra,
                                        bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
+
+                       if (JITDATA_HAS_FLAG_COUNTDOWN(jd))
+                               rp[-1].flags |= RPLPOINT_FLAG_COUNTDOWN;
                }
 
                /* iterate over the instructions */
@@ -616,6 +635,19 @@ bool replace_create_replacement_points(jitdata *jd)
 
                for (; iptr != iend; ++iptr) {
                        switch (iptr->opc) {
+#if defined(ENABLE_GC_CACAO)
+                               case ICMD_BUILTIN:
+                                       md = iptr->sx.s23.s3.bte->md;
+
+                                       i = (iinfo) ? iinfo->throughcount : 0;
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_CALL, iptr, &ra,
+                                                       javalocals, iptr->sx.s23.s2.args,
+                                                       iptr->s1.argcount - i,
+                                                       md->paramcount);
+                                       break;
+#endif
+
                                case ICMD_INVOKESTATIC:
                                case ICMD_INVOKESPECIAL:
                                case ICMD_INVOKEVIRTUAL:
@@ -703,6 +735,9 @@ bool replace_create_replacement_points(jitdata *jd)
        code->globalcount   = 0;
        code->savedintcount = INT_SAV_CNT - rd->savintreguse;
        code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
+#endif
        code->memuse        = rd->memuse;
        code->stackframesize = jd->cd->stackframesize;
 
@@ -766,7 +801,6 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable)
        rplpoint *rp;
        s4        i;
        s4        count;
-       s4        index;
        u1       *savedmcode;
 
        assert(code->savedmcode == NULL);
@@ -774,15 +808,12 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable)
        /* count trappable replacement points */
 
        count = 0;
-       index = 0;
        i = code->rplpointcount;
        rp = code->rplpoints;
        for (; i--; rp++) {
                if (rp->flags & RPLPOINT_FLAG_NOTRAP)
                        continue;
 
-               index++;
-
                if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
                        continue;
 
@@ -806,8 +837,6 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable)
                if (rp->flags & RPLPOINT_FLAG_NOTRAP)
                        continue;
 
-               index--;
-
                if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
                        continue;
 
@@ -816,9 +845,20 @@ void replace_activate_replacement_points(codeinfo *code, bool mappable)
 
                savedmcode -= REPLACEMENT_PATCH_SIZE;
 
-#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
-               md_patch_replacement_point(code, index, rp, savedmcode);
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction before: ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
+
+               md_patch_replacement_point(rp->pc, savedmcode, false);
+
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction after : ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
 #endif
+
                rp->flags |= RPLPOINT_FLAG_ACTIVE;
        }
 
@@ -844,6 +884,23 @@ void replace_deactivate_replacement_points(codeinfo *code)
        s4        count;
        u1       *savedmcode;
 
+       if (code->savedmcode == NULL) {
+               /* disarm countdown points by patching the branches */
+
+               i = code->rplpointcount;
+               rp = code->rplpoints;
+               for (; i--; rp++) {
+                       if ((rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))
+                                       == RPLPOINT_FLAG_COUNTDOWN)
+                       {
+#if 0
+                               *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
+#endif
+                       }
+               }
+               return;
+       }
+
        assert(code->savedmcode != NULL);
        savedmcode = code->savedmcode;
 
@@ -861,8 +918,18 @@ void replace_deactivate_replacement_points(codeinfo *code)
                DOLOG( printf("deactivate replacement point:\n");
                           replace_replacement_point_println(rp, 1); fflush(stdout); );
 
-#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
-               md_patch_replacement_point(code, -1, rp, savedmcode);
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction before: ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
+
+               md_patch_replacement_point(rp->pc, savedmcode, true);
+
+# if defined(ENABLE_DISASSEMBLER)
+               DOLOG( printf("\tinstruction before: ");
+                          disassinstr(rp->pc); fflush(stdout); );
+# endif
 #endif
 
                rp->flags &= ~RPLPOINT_FLAG_ACTIVE;
@@ -890,7 +957,6 @@ void replace_deactivate_replacement_points(codeinfo *code)
    
    IN:
           es...............execution state
-          sp...............stack pointer of the execution state (XXX eliminate?)
           ra...............allocation
           javaval..........where to put the value
 
@@ -900,7 +966,6 @@ void replace_deactivate_replacement_points(codeinfo *code)
 *******************************************************************************/
 
 static void replace_read_value(executionstate_t *es,
-                                                          stackslot_t *sp,
                                                           rplalloc *ra,
                                                           replace_val_t *javaval)
 {
@@ -908,11 +973,11 @@ static void replace_read_value(executionstate_t *es,
                /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
 #ifdef HAS_4BYTE_STACKSLOT
                if (IS_2_WORD_TYPE(ra->type)) {
-                       javaval->l = *(u8*)(sp + ra->regoff);
+                       javaval->l = *(u8*)(es->sp + ra->regoff);
                }
                else {
 #endif
-                       javaval->p = sp[ra->regoff];
+                       javaval->p = *(ptrint*)(es->sp + ra->regoff);
 #ifdef HAS_4BYTE_STACKSLOT
                }
 #endif
@@ -925,6 +990,11 @@ static void replace_read_value(executionstate_t *es,
                        if (ra->type == TYPE_FLT)
                                javaval->f = javaval->d;
                }
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+               else if (IS_ADR_TYPE(ra->type)) {
+                       javaval->p = es->adrregs[ra->regoff];
+               }
+#endif
                else {
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                        if (ra->type == TYPE_LNG) {
@@ -945,14 +1015,12 @@ static void replace_read_value(executionstate_t *es,
    
    IN:
           es...............execution state
-          sp...............stack pointer of the execution state (XXX eliminate?)
           ra...............allocation
           *javaval.........the value
 
 *******************************************************************************/
 
 static void replace_write_value(executionstate_t *es,
-                                                           stackslot_t *sp,
                                                            rplalloc *ra,
                                                            replace_val_t *javaval)
 {
@@ -960,11 +1028,11 @@ static void replace_write_value(executionstate_t *es,
                /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
 #ifdef HAS_4BYTE_STACKSLOT
                if (IS_2_WORD_TYPE(ra->type)) {
-                       *(u8*)(sp + ra->regoff) = javaval->l;
+                       *(u8*)(es->sp + ra->regoff) = javaval->l;
                }
                else {
 #endif
-                       sp[ra->regoff] = javaval->p;
+                       *(ptrint*)(es->sp + ra->regoff) = javaval->p;
 #ifdef HAS_4BYTE_STACKSLOT
                }
 #endif
@@ -983,6 +1051,10 @@ static void replace_write_value(executionstate_t *es,
                                es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
                                es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
                                break;
+#endif
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+                       case TYPE_ADR:
+                               es->adrregs[ra->regoff] = javaval->p;
 #endif
                        default:
                                es->intregs[ra->regoff] = javaval->p;
@@ -991,15 +1063,15 @@ static void replace_write_value(executionstate_t *es,
 }
 
 
-/* replace_read_executionstate *************************************************
+/* replace_new_sourceframe *****************************************************
 
-   Read the given executions state and translate it to a source frame.
+   Allocate a new source frame and insert it at the front of the frame list.
    
    IN:
           ss...............the source state
 
    OUT:
-          ss->frames.......set to new frame
+          ss->frames.......set to new frame (the new head of the frame list).
 
    RETURN VALUE:
        returns the new frame
@@ -1022,15 +1094,20 @@ static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
 
 /* replace_read_executionstate *************************************************
 
-   Read the given executions state and translate it to a source frame.
+   Read a source frame from the given executions state.
+   The new source frame is pushed to the front of the frame list of the
+   source state.
 
    IN:
        rp...............replacement point at which `es` was taken
           es...............execution state
-          ss...............where to put the source state
+          ss...............the source state to add the source frame to
+          topframe.........true, if the first (top-most) source frame on the
+                           stack is to be read
 
    OUT:
-       *ss..............the source state derived from the execution state
+       *ss..............the source state with the newly created source frame
+                           added
   
 *******************************************************************************/
 
@@ -1076,7 +1153,7 @@ static void replace_read_executionstate(rplpoint *rp,
 
        /* calculate base stack pointer */
 
-       basesp = sp + code_get_stack_frame_size(code);
+       basesp = sp + code->stackframesize;
 
        /* create the source frame */
 
@@ -1095,15 +1172,17 @@ static void replace_read_executionstate(rplpoint *rp,
        frame->javalocals = DMNEW(replace_val_t, count);
        frame->javalocaltype = DMNEW(u1, count);
 
-#if !defined(NDEBUG)
        /* mark values as undefined */
        for (i=0; i<count; ++i) {
+#if !defined(NDEBUG)
                frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
+#endif
                frame->javalocaltype[i] = TYPE_VOID;
        }
 
        /* some entries in the intregs array are not meaningful */
        /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
+#if !defined(NDEBUG)
        es->intregs[REG_SP   ] = (ptrint) 0x11dead1111dead11ULL;
 #ifdef REG_PV
        es->intregs[REG_PV   ] = (ptrint) 0x11dead1111dead11ULL;
@@ -1121,7 +1200,7 @@ static void replace_read_executionstate(rplpoint *rp,
                if (ra->type == TYPE_RET)
                        frame->javalocals[i].i = ra->regoff;
                else
-                       replace_read_value(es, sp, ra, frame->javalocals + i);
+                       replace_read_value(es, ra, frame->javalocals + i);
                ra++;
                count--;
        }
@@ -1146,12 +1225,12 @@ static void replace_read_executionstate(rplpoint *rp,
                instra.regoff = md->params[0].regoff;
                if (md->params[0].inmemory) {
                        instra.flags = INMEMORY;
-                       instra.regoff += (1 + code->stackframesize);
+                       instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
                }
                else {
                        instra.flags = 0;
                }
-               replace_read_value(es, sp, &instra, &(frame->instance));
+               replace_read_value(es, &instra, &(frame->instance));
 #endif
        }
 #endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
@@ -1223,7 +1302,7 @@ static void replace_read_executionstate(rplpoint *rp,
 
                                calleeframe->syncslotcount = 1;
                                calleeframe->syncslots = DMNEW(replace_val_t, 1);
-                               replace_read_value(es,sp,ra,calleeframe->syncslots);
+                               replace_read_value(es,ra,calleeframe->syncslots);
                        }
 
                        frame->javastackdepth--;
@@ -1241,7 +1320,7 @@ static void replace_read_executionstate(rplpoint *rp,
                        if (ra->type == TYPE_RET)
                                frame->javastack[i].i = ra->regoff;
                        else
-                               replace_read_value(es,sp,ra,frame->javastack + i);
+                               replace_read_value(es,ra,frame->javastack + i);
                        frame->javastacktype[i] = ra->type;
                        i++;
                }
@@ -1251,13 +1330,16 @@ static void replace_read_executionstate(rplpoint *rp,
 
 /* replace_write_executionstate ************************************************
 
-   Translate the given source state into an execution state.
-   
+   Pop a source frame from the front of the frame list of the given source state
+   and write its values into the execution state.
+
    IN:
        rp...............replacement point for which execution state should be
-                           creates
-          es...............where to put the execution state
+                           created
+          es...............the execution state to modify
           ss...............the given source state
+          topframe.........true, if this is the last (top-most) source frame to be
+                           translated
 
    OUT:
        *es..............the execution state derived from the source state
@@ -1293,7 +1375,7 @@ static void replace_write_executionstate(rplpoint *rp,
 
        sp = (stackslot_t *) es->sp;
 
-       basesp = sp + code_get_stack_frame_size(code);
+       basesp = sp + code->stackframesize;
 
        /* in some cases the top stack slot is passed in REG_ITMP1 */
 
@@ -1314,7 +1396,7 @@ static void replace_write_executionstate(rplpoint *rp,
                        /* XXX assert that it matches this rplpoint */
                }
                else
-                       replace_write_value(es, sp, ra, frame->javalocals + i);
+                       replace_write_value(es, ra, frame->javalocals + i);
                count--;
                ra++;
        }
@@ -1371,7 +1453,7 @@ static void replace_write_executionstate(rplpoint *rp,
                                assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
                                assert(frame->down->syncslots != NULL);
 
-                               replace_write_value(es,sp,ra,frame->down->syncslots);
+                               replace_write_value(es,ra,frame->down->syncslots);
                        }
                        continue;
                }
@@ -1390,7 +1472,7 @@ static void replace_write_executionstate(rplpoint *rp,
                                /* XXX assert that it matches this rplpoint */
                        }
                        else {
-                               replace_write_value(es,sp,ra,frame->javastack + i);
+                               replace_write_value(es,ra,frame->javastack + i);
                        }
                        i++;
                }
@@ -1436,14 +1518,14 @@ u1* replace_pop_activation_record(executionstate_t *es,
        /* read the return address */
 
 #if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (CODE_IS_LEAFMETHOD(es->code))
+       if (code_is_leafmethod(es->code))
                ra = (u1*) (ptrint) es->intregs[REPLACE_REG_RA];
        else
 #endif
                ra = md_stacktrace_get_returnaddress(es->sp,
                                SIZE_OF_STACKSLOT * es->code->stackframesize);
 
-       DOLOG( printf("return address: %p\n", (void*)ra); );
+       DOLOG( printf("RA = %p\n", (void*)ra); );
 
        assert(ra);
 
@@ -1467,14 +1549,14 @@ u1* replace_pop_activation_record(executionstate_t *es,
 
 #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;
 #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)];
 #endif /* REPLACE_RA_LINKAGE_AREA */
@@ -1499,6 +1581,17 @@ u1* replace_pop_activation_record(executionstate_t *es,
                es->fltregs[reg] = *(double*)basesp;
        }
 
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       /* restore saved adr registers */
+
+       reg = ADR_REG_CNT;
+       for (i=0; i<es->code->savedadrcount; ++i) {
+               while (nregdescadr[--reg] != REG_SAV)
+                       ;
+               es->adrregs[reg] = *--basesp;
+       }
+#endif
+
        /* adjust the stackpointer */
 
        es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
@@ -1515,14 +1608,9 @@ u1* replace_pop_activation_record(executionstate_t *es,
        /* 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);
-
+       code = code_get_codeinfo_for_pv(pv);
        DOLOG( printf("CODE = %p\n", (void*) code); );
 
        /* return NULL if we reached native code */
@@ -1544,6 +1632,11 @@ u1* replace_pop_activation_record(executionstate_t *es,
        for (i=0; i<FLT_REG_CNT; ++i)
                if (nregdescfloat[i] != REG_SAV)
                        *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i=0; i<ADR_REG_CNT; ++i)
+               if (nregdescadr[i] != REG_SAV)
+                       es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
+# endif
 #endif /* !defined(NDEBUG) */
 
        return (code) ? ra : NULL;
@@ -1575,8 +1668,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);
@@ -1592,6 +1685,97 @@ static void replace_patch_method_pointer(methodptr *mpp,
 }
 
 
+/* replace_patch_class *********************************************************
+
+   Patch a method in the given class.
+
+   IN:
+          vftbl............vftbl of the class
+          m................the method to patch
+          oldentrypoint....the old entrypoint to replace
+          entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+void replace_patch_class(vftbl_t *vftbl,
+                                                methodinfo *m,
+                                                u1 *oldentrypoint,
+                                                u1 *entrypoint)
+{
+       s4                 i;
+       methodptr         *mpp;
+       methodptr         *mppend;
+
+       /* patch the vftbl of the class */
+
+       replace_patch_method_pointer(vftbl->table + m->vftblindex,
+                                                                entrypoint,
+                                                                "virtual  ");
+
+       /* patch the interface tables */
+
+       assert(oldentrypoint);
+
+       for (i=0; i < vftbl->interfacetablelength; ++i) {
+               mpp = vftbl->interfacetable[-i];
+               mppend = mpp + vftbl->interfacevftbllength[i];
+               for (; mpp != mppend; ++mpp)
+                       if (*mpp == oldentrypoint) {
+                               replace_patch_method_pointer(mpp, entrypoint, "interface");
+                       }
+       }
+}
+
+
+/* replace_patch_class_hierarchy ***********************************************
+
+   Patch a method in all loaded classes.
+
+   IN:
+          m................the method to patch
+          oldentrypoint....the old entrypoint to replace
+          entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+struct replace_patch_data_t {
+       methodinfo *m;
+       u1         *oldentrypoint;
+       u1         *entrypoint;
+};
+
+void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
+{
+       vftbl_t *vftbl = c->vftbl;
+
+       if (vftbl != NULL
+               && vftbl->vftbllength > pd->m->vftblindex
+               && vftbl->table[pd->m->vftblindex] != &asm_abstractmethoderror
+               && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
+       {
+               replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
+       }
+}
+
+void replace_patch_class_hierarchy(methodinfo *m,
+                                                                  u1 *oldentrypoint,
+                                                                  u1 *entrypoint)
+{
+       struct replace_patch_data_t pd;
+
+       pd.m = m;
+       pd.oldentrypoint = oldentrypoint;
+       pd.entrypoint = entrypoint;
+
+       DOLOG_SHORT( printf("patching class hierarchy: ");
+                            method_println(m); );
+
+       classcache_foreach_loaded_class(
+                       (classcache_foreach_functionptr_t) &replace_patch_callback,
+                       (void*) &pd);
+}
+
+
 /* replace_patch_future_calls **************************************************
 
    Analyse a call site and depending on the kind of call patch the call, the
@@ -1608,18 +1792,15 @@ void replace_patch_future_calls(u1 *ra,
                                                                sourceframe_t *callerframe,
                                                                sourceframe_t *calleeframe)
 {
-       u1                *patchpos;
-       methodptr          entrypoint;
-       methodptr          oldentrypoint;
-       methodptr         *mpp;
-       methodptr         *mppend;
-       bool               atentry;
-       stackframeinfo     sfi;
-       codeinfo          *calleecode;
-       methodinfo        *calleem;
-       java_objectheader *obj;
-       struct _vftbl     *vftbl;
-       s4                 i;
+       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);
@@ -1642,8 +1823,8 @@ 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 */
@@ -1655,10 +1836,13 @@ void replace_patch_future_calls(u1 *ra,
 
                assert((calleem->flags & ACC_STATIC) == 0);
 
+               oldentrypoint = calleeframe->fromcode->entrypoint;
+
                /* we need to know the instance */
 
                if (!calleeframe->instance.a) {
                        DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
+                       replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
                        return;
                }
 
@@ -1671,25 +1855,7 @@ void replace_patch_future_calls(u1 *ra,
 
                DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->class); );
 
-               /* patch the vftbl of the class */
-
-               replace_patch_method_pointer(vftbl->table + calleem->vftblindex,
-                                                                        entrypoint,
-                                                                        "virtual  ");
-
-               /* patch the interface tables */
-
-               oldentrypoint = calleeframe->fromcode->entrypoint;
-               assert(oldentrypoint);
-
-               for (i=0; i < vftbl->interfacetablelength; ++i) {
-                       mpp = vftbl->interfacetable[-i];
-                       mppend = mpp + vftbl->interfacevftbllength[i];
-                       for (; mpp != mppend; ++mpp)
-                               if (*mpp == oldentrypoint) {
-                                       replace_patch_method_pointer(mpp, entrypoint, "interface");
-                               }
-               }
+               replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
        }
        else {
                /* the call was statically bound */
@@ -1794,14 +1960,14 @@ void replace_push_activation_record(executionstate_t *es,
 
 #if defined(REPLACE_RA_TOP_OF_FRAME)
 #if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
-       if (!CODE_IS_LEAFMETHOD(calleecode))
+       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))
+       if (!code_is_leafmethod(calleecode))
 #endif
                basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
 #endif /* REPLACE_RA_LINKAGE_AREA */
@@ -1836,6 +2002,22 @@ void replace_push_activation_record(executionstate_t *es,
 #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
+
        /* write slots used for synchronization */
 
        count = code_get_sync_slot_count(calleecode);
@@ -1949,7 +2131,9 @@ no_match:
 
 /* replace_find_replacement_point_for_pc ***************************************
 
-   Find the nearest replacement point at or before the given PC.
+   Find the nearest replacement point at or before the given PC. The
+   given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for
+   the replacement point to be found.
 
    IN:
        code.............compilation unit the PC is in
@@ -1967,7 +2151,7 @@ rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc)
        rplpoint *rp;
        s4        i;
 
-       DOLOG( printf("searching for rp in %p ", (void*)code);
+       DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code);
                   method_println(code->m); );
 
        found = NULL;
@@ -1975,7 +2159,7 @@ 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)
+               if (rp->pc <= pc && rp->pc + rp->callsize >= pc)
                        found = rp;
        }
 
@@ -2001,7 +2185,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;
@@ -2016,7 +2200,7 @@ static void replace_pop_native_frame(executionstate_t *es,
        /* remember pc and size of native frame */
 
        frame->nativepc = es->pc;
-       frame->nativeframesize = sfi->sp - es->sp;
+       frame->nativeframesize = (es->sp != 0) ? (sfi->sp - es->sp) : 0;
        assert(frame->nativeframesize >= 0);
 
        /* remember values of saved registers */
@@ -2033,45 +2217,68 @@ static void replace_pop_native_frame(executionstate_t *es,
                        frame->nativesavflt[j++] = es->fltregs[i];
        }
 
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       j = 0;
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       frame->nativesavadr[j++] = es->adrregs[i];
+       }
+#endif
+
        /* restore saved registers */
 
-#if 0
+#if defined(ENABLE_GC_CACAO) && !defined(HAS_ADDRESS_REGISTER_FILE)
+       j = 0;
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       es->intregs[i] = sfi->intregs[j++];
+       }
+#else
        /* XXX we don't have them, yet, in the sfi, so clear them */
 
        for (i=0; i<INT_REG_CNT; ++i) {
                if (nregdescint[i] == REG_SAV)
                        es->intregs[i] = 0;
        }
+#endif
+
+       /* XXX we don't have float registers in the sfi, so clear them */
 
        for (i=0; i<FLT_REG_CNT; ++i) {
                if (nregdescfloat[i] == REG_SAV)
                        es->fltregs[i] = 0.0;
        }
-#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);
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+# if defined(ENABLE_GC_CACAO)
+       j = 0;
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       es->adrregs[i] = sfi->adrregs[j++];
        }
-       else {
-               es->pv = sfi->pv;
+# else
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       es->adrregs[i] = 0;
        }
-       es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1;
-       es->sp = sfi->sp;
-
-       /* find the new codeinfo */
-
-       DOLOG( printf("PV = %p\n", (void*) es->pv); );
+# endif
+#endif
 
-       assert(es->pv != NULL);
+       /* restore codeinfo of the native stub */
 
-       code = *(codeinfo **)(es->pv + CodeinfoPointer);
+       code = code_get_codeinfo_for_pv(sfi->pv);
 
-       DOLOG( printf("CODE = %p\n", (void*) code); );
+       /* restore sp, pv, pc and codeinfo of the parent method */
 
-       es->code = code;
+       /* XXX michi: use this instead:
+       es->sp = sfi->sp + code->stackframesize; */
+       es->sp   = sfi->sp + (*(s4 *) (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   = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1;
+       es->code = code_get_codeinfo_for_pv(es->pv);
 }
 
 
@@ -2112,10 +2319,36 @@ 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 *) (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);
 
+       /* update saved registers in the stackframeinfo */
+
+#if defined(ENABLE_GC_CACAO)
+       j = 0;
+# if !defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i=0; i<INT_REG_CNT; ++i) {
+               if (nregdescint[i] == REG_SAV)
+                       frame->sfi->intregs[j++] = es->intregs[i];
+       }
+# else
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       frame->sfi->adrregs[j++] = es->adrregs[i];
+       }
+# endif
+
+       /* XXX leave float registers untouched here */
+#endif
+
        /* restore saved registers */
 
        j = 0;
@@ -2130,6 +2363,14 @@ static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
                        es->fltregs[i] = frame->nativesavflt[j++];
        }
 
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       j = 0;
+       for (i=0; i<ADR_REG_CNT; ++i) {
+               if (nregdescadr[i] == REG_SAV)
+                       es->adrregs[i] = frame->nativesavadr[j++];
+       }
+#endif
+
        /* skip the native frame on the machine stack */
 
        es->sp -= frame->nativeframesize;
@@ -2156,7 +2397,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;
@@ -2171,11 +2412,6 @@ sourcestate_t *replace_recover_source_state(rplpoint *rp,
        ss = DNEW(sourcestate_t);
        ss->frames = NULL;
 
-       /* get the stackframeinfo if none is given */
-
-       if (sfi == NULL)
-               sfi = *(STACKFRAMEINFO);
-
        /* each iteration of the loop recovers one source frame */
 
        depth = 0;
@@ -2208,6 +2444,10 @@ sourcestate_t *replace_recover_source_state(rplpoint *rp,
 
                replace_read_executionstate(rp, es, ss, ss->frames == NULL);
 
+#if defined(ENABLE_VMLOG)
+               vmlog_cacao_unrol_method(ss->frames->method);
+#endif
+
 #if defined(REPLACE_STATISTICS)
                REPLACE_COUNT(stat_frames);
                depth++;
@@ -2244,7 +2484,9 @@ sourcestate_t *replace_recover_source_state(rplpoint *rp,
 
                                rp = NULL;
 
+#if !defined(ENABLE_GC_CACAO)
                                break; /* XXX remove to activate native frames */
+#endif
                                continue;
                        }
 
@@ -2329,6 +2571,12 @@ static bool replace_map_source_state(sourcestate_t *ss)
 #if defined(REPLACE_STATISTICS)
                                oldcode = frame->method->code;
 #endif
+                               /* request optimization of hot methods and their callers */
+
+                               if (frame->method->hitcountdown < 0
+                                       || (frame->down && frame->down->method->hitcountdown < 0))
+                                       jit_request_optimization(frame->method);
+
                                code = jit_get_current_code(frame->method);
 
                                if (code == NULL)
@@ -2360,7 +2608,53 @@ static bool replace_map_source_state(sourcestate_t *ss)
 }
 
 
-/* replace_build_execution_state_intern ****************************************
+/* replace_map_source_state_identity *******************************************
+
+   Map each source frame in the given source state to the same replacement
+   point and compilation unit it was derived from. This is mainly used for
+   garbage collection.
+
+   IN:
+       ss...............the source state
+
+   OUT:
+       ss...............the source state, modified: The `torp` and `tocode`
+                           fields of each source frame are set.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+static void replace_map_source_state_identity(sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+
+       /* iterate over the source frames from outermost to innermost */
+
+       for (frame = ss->frames; frame != NULL; frame = frame->down) {
+
+               /* skip native frames */
+
+               if (REPLACE_IS_NATIVE_FRAME(frame)) {
+                       continue;
+               }
+
+               /* map frames using the identity mapping */
+
+               if (frame->tocode) {
+                       assert(frame->tocode == frame->fromcode);
+                       assert(frame->torp   == frame->fromrp);
+               } else {
+                       assert(frame->tocode == NULL);
+                       assert(frame->torp   == NULL);
+                       frame->tocode = frame->fromcode;
+                       frame->torp   = frame->fromrp;
+               }
+       }
+}
+#endif
+
+
+/* replace_build_execution_state ***********************************************
 
    Build an execution state for the given (mapped) source state.
 
@@ -2378,8 +2672,8 @@ static bool replace_map_source_state(sourcestate_t *ss)
 
 *******************************************************************************/
 
-static void replace_build_execution_state_intern(sourcestate_t *ss,
-                                                                                                executionstate_t *es)
+static void replace_build_execution_state(sourcestate_t *ss,
+                                                                                 executionstate_t *es)
 {
        rplpoint      *rp;
        sourceframe_t *prevframe;
@@ -2421,6 +2715,11 @@ static void replace_build_execution_state_intern(sourcestate_t *ss,
 
                es->code = ss->frames->tocode;
                prevframe = ss->frames;
+
+#if defined(ENABLE_VMLOG)
+               vmlog_cacao_rerol_method(ss->frames->method);
+#endif
+
                replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
 
                DOLOG( replace_executionstate_println(es); );
@@ -2436,197 +2735,254 @@ static void replace_build_execution_state_intern(sourcestate_t *ss,
 }
 
 
-/* replace_build_execution_state ***********************************************
-
-   This function contains the final phase of replacement. It builds the new
-   execution state, releases dump memory, and returns to the calling
-   assembler function which finishes replacement.
-
-   NOTE: This function is called from asm_replacement_in, with the stack
-         pointer at the start of the safe stack area.
+/* replace_me ******************************************************************
+   This function is called by the signal handler when a thread reaches
+   a replacement point. `replace_me` must map the execution state to the
+   target replacement point and let execution continue there.
 
    THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
 
-   CAUTION: This function and its children must not use a lot of stack!
-            There are only REPLACE_SAFESTACK_SIZE bytes of C stack
-                       available.
-
    IN:
-       st...............the safestack contained the necessary data
-
+       rp...............replacement point that has been reached
+       es...............execution state read by signal handler
+  
 *******************************************************************************/
 
-void replace_build_execution_state(replace_safestack_t *st)
+static void replace_me(rplpoint *rp, executionstate_t *es)
 {
-       replace_build_execution_state_intern(st->ss, &(st->es));
-
-       DOLOG( replace_executionstate_println(&(st->es)); );
+       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
 
-       /* release dump area */
+       origcode = es->code;
+       origrp   = rp;
 
-       dump_release(st->dumpsize);
+       DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
+                                stat_replacements, (void*)THREADOBJECT,
+                                rp->id, (void*)rp);
+                                method_println(es->code->m); );
 
-       /* new code is entered after returning */
+       DOLOG( replace_replacement_point_println(rp, 1); );
 
-       DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
-}
+       REPLACE_COUNT(stat_replacements);
 
+       /* mark start of dump memory area */
 
-/* replace_alloc_safestack *****************************************************
+       dumpsize = dump_size();
 
-   Allocate a safe stack area to use during the final phase of replacement.
-   The returned area is not initialized. This must be done by the caller.
+       /* get the stackframeinfo for the current thread */
 
-   RETURN VALUE:
-       a newly allocated replace_safestack_t *
+       sfi = STACKFRAMEINFO;
 
-*******************************************************************************/
+       /* recover source state */
 
-static replace_safestack_t *replace_alloc_safestack()
-{
-       u1 *mem;
-       replace_safestack_t *st;
+       ss = replace_recover_source_state(rp, sfi, es);
 
-       mem = MNEW(u1, sizeof(replace_safestack_t) + REPLACE_STACK_ALIGNMENT - 1);
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       /* if there is a collection pending, we assume the replacement point should
+          suspend this thread */
 
-       st = (replace_safestack_t *) ((ptrint)(mem + REPLACE_STACK_ALIGNMENT - 1)
-                                                                               & ~(REPLACE_STACK_ALIGNMENT - 1));
+       if (gc_pending) {
 
-#if !defined(NDEBUG)
-       memset(st, 0xa5, sizeof(replace_safestack_t));
-#endif
+               thread = THREADOBJECT;
 
-       st->mem = mem;
+               DOLOG_SHORT( printf("REPLACEMENT: Suspending thread for GC now!\n"); );
 
-       return st;
-}
+               /* map the sourcestate using the identity mapping */
+               replace_map_source_state_identity(ss);
 
+               /* since we enter the same method again, we turn off rps now */
+               /* XXX michi: can we really do this? what if the rp was active before
+                  we activated it for the gc? */
+               replace_deactivate_replacement_points(origcode);
 
-/* replace_free_safestack ******************************************************
+               /* remember executionstate and sourcestate for this thread */
+               GC_EXECUTIONSTATE = es;
+               GC_SOURCESTATE    = ss;
 
-   Free the given safestack structure, making a copy of the contained
-   execution state before freeing it.
+               /* really suspend this thread now (PC = 0) */
+               threads_suspend_ack(NULL, NULL);
 
-   NOTE: This function is called from asm_replacement_in.
+               DOLOG_SHORT( printf("REPLACEMENT: Resuming thread after GC now!\n"); );
 
-   IN:
-       st...............the safestack to free
-          tmpes............where to copy the execution state to
+       } else {
+#endif /*defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)*/
 
-   OUT:
-          *tmpes...........receives a copy of st->es
+       /* map the source state */
 
-*******************************************************************************/
+       if (!replace_map_source_state(ss))
+               vm_abort("exception during method replacement");
 
-void replace_free_safestack(replace_safestack_t *st, executionstate_t *tmpes)
-{
-       u1 *mem;
+       DOLOG( replace_sourcestate_println(ss); );
 
-       /* copy the executionstate_t to the temporary location */
+       DOLOG_SHORT( replace_sourcestate_println_short(ss); );
 
-       *tmpes = st->es;
+#if !defined(NDEBUG)
+       /* avoid infinite loops by self-replacement, only if not in testing mode */
+
+       if (!opt_TestReplacement) {
+               frame = ss->frames;
+               while (frame->down)
+                       frame = frame->down;
+
+               if (frame->torp == origrp) {
+                       DOLOG_SHORT(
+                               printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
+                       );
+                       replace_deactivate_replacement_points(origcode);
+               }
+       }
+#endif
 
-       /* get the memory address to free */
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+       }
+#endif
 
-       mem = st->mem;
+       /* build the new execution state */
 
-       /* destroy memory (in debug mode) */
+       replace_build_execution_state(ss, es);
 
 #if !defined(NDEBUG)
-       memset(st, 0xa5, sizeof(replace_safestack_t));
+       /* continue execution after patched machine code, if testing mode enabled */
+
+       if (opt_TestReplacement)
+               es->pc += REPLACEMENT_PATCH_SIZE;
 #endif
 
-       /* free the safe stack struct */
+       /* release dump area */
 
-       MFREE(mem, u1, sizeof(replace_safestack_t) + REPLACE_STACK_ALIGNMENT - 1);
+       dump_release(dumpsize);
 }
 
 
-/* replace_me ******************************************************************
-   This function is called by asm_replacement_out when a thread reaches
-   a replacement point. `replace_me` must map the execution state to the
-   target replacement point and let execution continue there.
+/* replace_me_wrapper **********************************************************
+
+   This function is called by the signal handler. It determines if there
+   is an active replacement point pending at the given PC and returns
+   accordingly.
+
+   THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
 
-   This function never returns!
-  
    IN:
-       rp...............replacement point that has been reached
-          es...............execution state read by asm_replacement_out
-  
+       pc...............the program counter that triggered the replacement.
+       context..........the context (machine state) to which the
+                           replacement should be applied.
+
+   OUT:
+       context..........the context after replacement finished.
+
+   RETURN VALUE:
+       true.............replacement done, everything went ok
+       false............no replacement done, context unchanged
+
 *******************************************************************************/
 
-void replace_me(rplpoint *rp, executionstate_t *es)
+bool replace_me_wrapper(u1 *pc, void *context)
 {
-       sourcestate_t       *ss;
-       sourceframe_t       *frame;
-       s4                   dumpsize;
-       rplpoint            *origrp;
-       replace_safestack_t *safestack;
+       codeinfo         *code;
+       rplpoint         *rp;
+       executionstate_t  es;
 
-       origrp = rp;
-       es->code = code_find_codeinfo_for_pc(rp->pc);
+       /* search the codeinfo for the given PC */
 
-       DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
-                                stat_replacements, (void*)THREADOBJECT,
-                                rp->id, (void*)rp);
-                                method_println(es->code->m); );
+       code = code_find_codeinfo_for_pc(pc);
+       assert(code);
 
-       DOLOG( replace_replacement_point_println(rp, 1);
-                  replace_executionstate_println(es); );
+       /* search for a replacement point at the given PC */
 
-       REPLACE_COUNT(stat_replacements);
+       rp = replace_find_replacement_point_for_pc(code, pc);
 
-       /* mark start of dump memory area */
+       /* check if the replacement point belongs to given PC and is active */
 
-       dumpsize = dump_size();
+       if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
 
-       /* recover source state */
+               /* set codeinfo pointer in execution state */
 
-       ss = replace_recover_source_state(rp, NULL, es);
-
-       /* map the source state */
+               es.code = code;
 
-       if (!replace_map_source_state(ss))
-               vm_abort("exception during method replacement");
+               /* read execution state from current context */
 
-       DOLOG( replace_sourcestate_println(ss); );
+               md_replace_executionstate_read(&es, context);
 
-       DOLOG_SHORT( replace_sourcestate_println_short(ss); );
+               DOLOG( printf("REPLACEMENT READ: ");
+                          replace_executionstate_println(&es); );
 
-       /* avoid infinite loops by self-replacement */
+               /* do the actual replacement */
 
-       frame = ss->frames;
-       while (frame->down)
-               frame = frame->down;
+               replace_me(rp, &es);
 
-       if (frame->torp == origrp) {
-               DOLOG_SHORT(
-                       printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
-               );
-               replace_deactivate_replacement_points(frame->tocode);
-       }
+               /* write execution state to current context */
 
-       /* write execution state of new code */
+               md_replace_executionstate_write(&es, context);
 
-       DOLOG( replace_executionstate_println(es); );
+               DOLOG( printf("REPLACEMENT WRITE: ");
+                          replace_executionstate_println(&es); );
 
-       /* allocate a safe stack area and copy all needed data there */
+               /* new code is entered after returning */
 
-       safestack = replace_alloc_safestack();
+               DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
+               return true;
+       }
+       else
+               return false;
+}
 
-       safestack->es = *es;
-       safestack->ss = ss;
-       safestack->dumpsize = dumpsize;
 
-       /* call the assembler code for the last phase of replacement */
+/******************************************************************************/
+/* NOTE: Stuff specific to the exact GC is below.                             */
+/******************************************************************************/
 
-#if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
-       asm_replacement_in(&(safestack->es), safestack);
+#if defined(ENABLE_GC_CACAO)
+void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
+{
+       stackframeinfo_t *sfi;
+       executionstate_t *es;
+       sourcestate_t    *ss;
+
+       /* get the stackframeinfo of this thread */
+       assert(thread == THREADOBJECT);
+       sfi = STACKFRAMEINFO;
+
+       /* create the execution state */
+       es = DNEW(executionstate_t);
+       es->pc = pc;
+       es->sp = sp;
+       es->pv = 0;      /* since we are in a native, PV is invalid! */
+       es->code = NULL; /* since we are in a native, we do not have a codeinfo */
+
+       /* we assume we are in a native (no replacement point)! */
+       ss = replace_recover_source_state(NULL, sfi, es);
+
+       /* map the sourcestate using the identity mapping */
+       replace_map_source_state_identity(ss);
+
+       /* remember executionstate and sourcestate for this thread */
+       GC_EXECUTIONSTATE = es;
+       GC_SOURCESTATE    = ss;
+}
 #endif
 
-       abort(); /* NOT REACHED */
+#if defined(ENABLE_GC_CACAO)
+void replace_gc_into_native(threadobject *thread)
+{
+       executionstate_t *es;
+       sourcestate_t    *ss;
+
+       /* get the executionstate and sourcestate for the given thread */
+       es = GC_EXECUTIONSTATE;
+       ss = GC_SOURCESTATE;
+
+       /* rebuild the stack of the given thread */
+       replace_build_execution_state(ss, es);
 }
+#endif
 
 
 /******************************************************************************/
@@ -2778,6 +3134,8 @@ void replace_replacement_point_println(rplpoint *rp, int depth)
                        replace_type_str[rp->type]);
        if (rp->flags & RPLPOINT_FLAG_NOTRAP)
                printf(" NOTRAP");
+       if (rp->flags & RPLPOINT_FLAG_COUNTDOWN)
+               printf(" COUNTDOWN");
        if (rp->flags & RPLPOINT_FLAG_ACTIVE)
                printf(" ACTIVE");
        printf(" parent:%p\n", (void*)rp->parent);
@@ -2842,6 +3200,9 @@ void replace_show_replacement_points(codeinfo *code)
        printf("\ttotal allocations : %d\n",code->regalloccount);
        printf("\tsaved int regs    : %d\n",code->savedintcount);
        printf("\tsaved flt regs    : %d\n",code->savedfltcount);
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       printf("\tsaved adr regs    : %d\n",code->savedadrcount);
+#endif
        printf("\tmemuse            : %d\n",code->memuse);
 
        printf("\n");
@@ -2894,9 +3255,9 @@ void replace_executionstate_println(executionstate_t *es)
                else
                        printf(" ");
 #if SIZEOF_VOID_P == 8
-               printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
+               printf("%-3s = %016llx",abi_registers_integer_name[i],(unsigned long long)es->intregs[i]);
 #else
-               printf("%-3s = %08lx",regs[i],(unsigned long)es->intregs[i]);
+               printf("%-3s = %08lx",abi_registers_integer_name[i],(unsigned long)es->intregs[i]);
 #endif
                if (i%4 == 3)
                        printf("\n");
@@ -2910,6 +3271,17 @@ void replace_executionstate_println(executionstate_t *es)
                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;
@@ -2918,7 +3290,7 @@ void replace_executionstate_println(executionstate_t *es)
 
        if (es->code) {
                methoddesc *md = es->code->m->parseddesc;
-               slots = code_get_stack_frame_size(es->code);
+               slots = es->code->stackframesize;
                extraslots = 1 + md->memuse;
        }
        else
@@ -2955,8 +3327,8 @@ void replace_executionstate_println(executionstate_t *es)
 #if !defined(NDEBUG)
 static void java_value_print(s4 type, replace_val_t value)
 {
-       java_objectheader *obj;
-       utf               *u;
+       java_object_t *obj;
+       utf           *u;
 
        printf("%016llx",(unsigned long long) value.l);
 
@@ -2972,7 +3344,7 @@ static void java_value_print(s4 type, replace_val_t value)
 
                if (obj->vftbl->class == class_java_lang_String) {
                        printf(" \"");
-                       u = javastring_toutf((java_lang_String *)obj, false);
+                       u = javastring_toutf(obj, false);
                        utf_display_printable_ascii(u);
                        printf("\"");
                }
@@ -3008,7 +3380,7 @@ void replace_source_frame_println(sourceframe_t *frame)
                j = 0;
                for (i=0; i<INT_REG_CNT; ++i) {
                        if (nregdescint[i] == REG_SAV)
-                               printf("\t%s = %p\n", regs[i], (void*)frame->nativesavint[j++]);
+                               printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
                }
 
                j = 0;
@@ -3177,14 +3549,14 @@ 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");
 }