* src/vm/jit/tools/genoffsets.c (executionstate): Renamed to
authoredwin <none@none>
Sat, 11 Nov 2006 17:08:14 +0000 (17:08 +0000)
committeredwin <none@none>
Sat, 11 Nov 2006 17:08:14 +0000 (17:08 +0000)
executionstate_t.
* src/vm/jit/asmpart.h: Likewise.

* src/vm/jit/show.c (show_variable_intern): New function. Does not
append ' '. Regard variables above vartop as invalid.
(show_method): Only show variables up to vartop.
(show_inline_info): New function.
(show_basicblock): Show right number of javalocals, show inlining
info at the start of blocks.
(show_variable): Moved body to show_variable_intern.
(show_icmd): Use show_inline_info.

* src/vm/jit/inline/inline.c: Handle javalocals.

* src/vm/jit/i386/codegen.c (codegen): Handle replacement points
for INLINE_START, RETURN and INVOKEs.

* src/vm/jit/replace.c: Many changes for making replacement work
over multiple stack frames.
* src/vm/jit/replace.h: Likewise.

* src/vm/jit/jit.h (insinfo_inline): Added fields.
(basicblock): Added field `inlineinfo`.

src/vm/jit/asmpart.h
src/vm/jit/i386/codegen.c
src/vm/jit/inline/inline.c
src/vm/jit/jit.h
src/vm/jit/replace.c
src/vm/jit/replace.h
src/vm/jit/show.c
src/vm/jit/tools/genoffsets.c

index 3dde90b3d12b147ca70219084d2475c397d8aeae..a64e09b7b03c10b41adc5b9f0437e53fac7ce5d2 100644 (file)
@@ -30,7 +30,7 @@
    Changes: Christian Thalinger
             Edwin Steiner
 
-   $Id: asmpart.h 5812 2006-10-20 14:22:23Z twisti $
+   $Id: asmpart.h 5950 2006-11-11 17:08:14Z edwin $
 
 */
 
@@ -151,7 +151,7 @@ void asm_patcher_wrapper(void);
 
 /* functions for on-stack replacement */
 void asm_replacement_out(void);
-void asm_replacement_in(executionstate *es);
+void asm_replacement_in(executionstate_t *es);
 
 #if defined(ENABLE_THREADS)
 extern critical_section_node_t asm_criticalsections;
index f583d6eea56215ecce41c9231ed6059a0823ab1a..6b9417ef04c4b0ffe8236444effcf50bfad30f0b 100644 (file)
@@ -30,7 +30,7 @@
             Christian Ullrich
             Edwin Steiner
 
-   $Id: codegen.c 5932 2006-11-07 09:06:18Z twisti $
+   $Id: codegen.c 5950 2006-11-11 17:08:14Z edwin $
 
 */
 
@@ -523,6 +523,14 @@ bool codegen(jitdata *jd)
                case ICMD_INLINE_START:
                        {
                                insinfo_inline *insinfo = iptr->sx.s23.s3.inlineinfo;
+
+                               /* handle replacement point */
+
+                               replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+                               replacementpoint++;
+                               /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+                               cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+
 #if defined(ENABLE_THREADS)
                                if (insinfo->synchronize) {
                                        /* add monitor enter code */
@@ -3031,6 +3039,13 @@ nowperformreturn:
                        {
                        s4 i, p;
                        
+                       /* handle replacement point */
+
+                       replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+                       replacementpoint++;
+                       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+                       cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+
                        p = cd->stackframesize;
                        
 #if !defined(NDEBUG)
@@ -3197,6 +3212,13 @@ nowperformreturn:
                case ICMD_INVOKEVIRTUAL:/* op1 = arg count, val.a = method pointer    */
                case ICMD_INVOKEINTERFACE:
 
+                       /* handle replacement point */
+
+                       replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+                       replacementpoint++;
+                       /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+                       cd->lastmcodeptr = cd->mcodeptr + 5; /* 5 byte jmp patch */
+
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
                                md = iptr->sx.s23.s3.um->methodref->parseddesc.md;
                                lm = NULL;
@@ -3359,6 +3381,12 @@ gen_method:
                                break;
                        }
 
+                       /* store size of call code in replacement point */
+
+                       if (iptr->opc != ICMD_BUILTIN)
+                               replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)
+                                       - (ptrint) replacementpoint[-1].pc;
+
                        /* d contains return type */
 
                        if (d != TYPE_VOID) {
index e16e6a37579168ec997230b41c1aa77bcb5681ca..6e0b5ca9331f0ac84eeaea7208f1a85337097c5c 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes:
 
-   $Id: inline.c 5925 2006-11-05 23:11:27Z edwin $
+   $Id: inline.c 5950 2006-11-11 17:08:14Z edwin $
 
 */
 
@@ -144,6 +144,7 @@ struct inline_node {
        /* temporary */
        inline_target_ref *refs;
        instruction *inline_start_instruction;
+       s4 *javalocals;
 
        /* XXX debug */
        char *indent;
@@ -412,7 +413,6 @@ static s4 *create_variable_map(inline_node *callee)
        s4 n_idx;
        s4 avail;
        varinfo *v;
-       varinfo vinfo;
 
        /* create the variable mapping */
 
@@ -602,6 +602,11 @@ static basicblock * create_block(inline_node *container,
        n_bptr->indepth = indepth;
        n_bptr->flags = BBFINISHED; /* XXX */
 
+       /* set the inlineinfo of the new block */
+
+       if (iln->inline_start_instruction)
+               n_bptr->inlineinfo = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
+
        if (indepth > container->ctx->maxinoutdepth)
                container->ctx->maxinoutdepth = indepth;
 
@@ -643,11 +648,11 @@ static basicblock * create_block(inline_node *container,
                inline_resolve_block_refs(refs, o_bptr, n_bptr);
        }
 
+       /* XXX for the verifier. should not be here */
+
        {
                varinfo *dv;
 
-               /* XXX for the verifier. should not be here */
-
                dv = DMNEW(varinfo, iln->ctx->resultjd->localcount + VERIFIER_EXTRA_LOCALS);
                MZERO(dv, varinfo,  iln->ctx->resultjd->localcount + VERIFIER_EXTRA_LOCALS);
                n_bptr->inlocals = dv;
@@ -657,6 +662,24 @@ static basicblock * create_block(inline_node *container,
 }
 
 
+static s4 *translate_javalocals(inline_node *iln, s4 *javalocals)
+{
+       s4 *jl;
+       s4 i, j;
+
+       jl = DMNEW(s4, iln->jd->maxlocals);
+
+       for (i=0; i<iln->jd->maxlocals; ++i) {
+               j = javalocals[i];
+               if (j != UNUSED)
+                       j = inline_translate_variable(iln->ctx->resultjd, iln->jd, iln->varmap, j);
+               jl[i] = j;
+       }
+
+       return jl;
+}
+
+
 static basicblock * create_body_block(inline_node *iln,
                                                                          basicblock *o_bptr, s4 *varmap)
 {
@@ -678,6 +701,10 @@ static basicblock * create_body_block(inline_node *iln,
                                o_bptr->invars[i]);
        }
 
+       /* translate javalocals info */
+
+       n_bptr->javalocals = translate_javalocals(iln, o_bptr->javalocals);
+
        return n_bptr;
 }
 
@@ -687,7 +714,6 @@ static basicblock * create_epilog_block(inline_node *caller, inline_node *callee
        basicblock *n_bptr;
        s4 retcount;
        s4 idx;
-       varinfo vinfo;
 
        /* number of return variables */
 
@@ -708,6 +734,13 @@ static basicblock * create_epilog_block(inline_node *caller, inline_node *callee
                varmap[callee->callerins->dst.varindex] = idx;
        }
 
+       /* set javalocals */
+
+       n_bptr->javalocals = DMNEW(s4, caller->jd->maxlocals);
+       MCOPY(n_bptr->javalocals, caller->javalocals, s4, caller->jd->maxlocals);
+
+       /* set block flags & type */
+
        n_bptr->flags = /* XXX original block flags */ BBFINISHED;
        n_bptr->type = BBTYPE_STD;
 
@@ -916,11 +949,30 @@ static s4 emit_inlining_prolog(inline_node *iln,
        insinfo->outer = iln->m;
        insinfo->synclocal = callee->synclocal;
        insinfo->synchronize = callee->synchronize;
+       insinfo->javalocals_start = NULL;
+       insinfo->javalocals_end = NULL;
+
+       /* info about stack vars live at the INLINE_START */
+
+       insinfo->throughcount = callee->n_passthroughcount;
+       insinfo->stackvarscount = callee->n_selfpassthroughcount;
+       insinfo->stackvars = DMNEW(s4, callee->n_selfpassthroughcount);
+       for (i=0; i<callee->n_selfpassthroughcount; ++i)
+               insinfo->stackvars[i] = iln->varmap[callee->n_passthroughvars[i]];
+
+       /* info about the surrounding inlining */
+
+       if (iln->inline_start_instruction)
+               insinfo->parent = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
+       else
+               insinfo->parent = NULL;
+
+       /* finish the INLINE_START instruction */
 
        n_ins->opc = ICMD_INLINE_START;
        n_ins->sx.s23.s3.inlineinfo = insinfo;
        n_ins->line = o_iptr->line;
-       iln->inline_start_instruction = n_ins;
+       callee->inline_start_instruction = n_ins;
 
        DOLOG( printf("%sprolog: ", iln->indent);
                   show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
@@ -932,9 +984,10 @@ static s4 emit_inlining_prolog(inline_node *iln,
 static void emit_inlining_epilog(inline_node *iln, inline_node *callee, instruction *o_iptr)
 {
        instruction *n_ins;
+       s4          *jl;
 
        assert(iln && callee && o_iptr);
-       assert(iln->inline_start_instruction);
+       assert(callee->inline_start_instruction);
 
        /* INLINE_END instruction */
 
@@ -942,9 +995,15 @@ static void emit_inlining_epilog(inline_node *iln, inline_node *callee, instruct
        assert((n_ins - iln->inlined_iinstr) < iln->cumul_instructioncount);
 
        n_ins->opc = ICMD_INLINE_END;
-       n_ins->sx.s23.s3.inlineinfo = iln->inline_start_instruction->sx.s23.s3.inlineinfo;
+       n_ins->sx.s23.s3.inlineinfo = callee->inline_start_instruction->sx.s23.s3.inlineinfo;
        n_ins->line = o_iptr->line;
 
+       /* set the javalocals */
+
+       jl = DMNEW(s4, iln->jd->maxlocals);
+       MCOPY(jl, iln->javalocals, s4, iln->jd->maxlocals);
+       n_ins->sx.s23.s3.inlineinfo->javalocals_end = jl;
+
        DOLOG( printf("%sepilog: ", iln->indent);
                   show_icmd(iln->ctx->resultjd, n_ins, false, SHOW_STACK); printf("\n"); );
 }
@@ -1074,6 +1133,28 @@ clone_call:
                        }
                        break;
        }
+
+       /* XXX move this to dataflow section? */
+
+       switch (n_iptr->opc) {
+               case ICMD_ISTORE:
+               case ICMD_LSTORE:
+               case ICMD_FSTORE:
+               case ICMD_DSTORE:
+               case ICMD_ASTORE:
+                       /* XXX share code with stack.c */
+                       j = n_iptr->dst.varindex;
+                       i = n_iptr->sx.s23.s3.javaindex;
+                       if (n_iptr->flags.bits & INS_FLAG_RETADDR)
+                               iln->javalocals[i] = UNUSED;
+                       else
+                               iln->javalocals[i] = j;
+                       if (n_iptr->flags.bits & INS_FLAG_KILL_PREV)
+                               iln->javalocals[i-1] = UNUSED;
+                       if (n_iptr->flags.bits & INS_FLAG_KILL_NEXT)
+                               iln->javalocals[i+1] = UNUSED;
+                       break;
+       }
 }
 
 
@@ -1118,6 +1199,10 @@ static void rewrite_method(inline_node *iln)
        iln->inlined_iinstr_cursor = iln->inlined_iinstr;
        iln->inlined_basicblocks_cursor = iln->inlined_basicblocks;
 
+       /* allocate temporary buffers */
+
+       iln->javalocals = DMNEW(s4, iln->jd->maxlocals);
+
        /* loop over basic blocks */
 
        o_bptr = iln->jd->basicblocks;
@@ -1172,14 +1257,29 @@ static void rewrite_method(inline_node *iln)
                        /* enter it in the blockmap */
 
                        inline_block_translation(iln, o_bptr, n_bptr);
+
+                       /* initialize the javalocals */
+
+                       MCOPY(iln->javalocals, n_bptr->javalocals, s4, iln->jd->maxlocals);
                }
                else {
+                       s4 *jl;
+
                        /* continue caller block */
 
                        n_bptr = iln->inlined_basicblocks_cursor - 1;
                        icount = n_bptr->icount;
+
+                       /* translate the javalocals */
+
+                       jl = translate_javalocals(iln, o_bptr->javalocals);
+                       iln->inline_start_instruction->sx.s23.s3.inlineinfo->javalocals_start = jl;
+
+                       MCOPY(iln->javalocals, jl, s4, iln->jd->maxlocals);
                }
 
+               /* iterate over the ICMDs of this block */
+
                retcount = 0;
                retidx = UNUSED;
 
@@ -1559,7 +1659,6 @@ static void inline_write_exception_handlers(inline_node *master, inline_node *il
        builtintable_entry *bte;
        s4 exvar;
        s4 syncvar;
-       varinfo vinfo;
        s4 i;
 
        child = iln->children;
@@ -1646,8 +1745,8 @@ static bool test_inlining(inline_node *iln, jitdata *jd,
        s4 i;
 
 
-       static int debug_verify_inlined_code = 1; /* XXX */
 #if !defined(NDEBUG)
+       static int debug_verify_inlined_code = 1; /* XXX */
        static int debug_compile_inlined_code_counter = 0;
 #endif
 
@@ -1658,6 +1757,7 @@ static bool test_inlining(inline_node *iln, jitdata *jd,
        *resultjd = jd;
 
        n_ins = DMNEW(instruction, iln->cumul_instructioncount);
+       MZERO(n_ins, instruction, iln->cumul_instructioncount);
        iln->inlined_iinstr = n_ins;
 
        n_bb = DMNEW(basicblock, iln->cumul_basicblockcount);
@@ -1690,6 +1790,7 @@ static bool test_inlining(inline_node *iln, jitdata *jd,
 
        /* extra variables for verification (DEBUG) */
 
+#if !defined(NDEBUG)
        if (debug_verify_inlined_code) {
                n_jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + 100 /* XXX m->maxstack */;
                if (n_jd->vartop > n_jd->varcount) {
@@ -1698,6 +1799,7 @@ static bool test_inlining(inline_node *iln, jitdata *jd,
                        n_jd->varcount = n_jd->vartop;
                }
        }
+#endif
 
        /* write inlined code */
 
@@ -1766,7 +1868,7 @@ static bool test_inlining(inline_node *iln, jitdata *jd,
 
        inline_interface_variables(iln);
 
-#if defined(ENABLE_VERIFIER)
+#if defined(ENABLE_VERIFIER) && !defined(NDEBUG)
        if (debug_verify_inlined_code) {
                debug_verify_inlined_code = 0;
                DOLOG( printf("VERIFYING INLINED RESULT...\n"); fflush(stdout); );
@@ -1839,7 +1941,6 @@ static bool inline_analyse_callee(inline_node *caller,
        bool         isstatic;
        s4           i, j;
        basicblock  *bptr;
-       instruction *iptr;
 
        /* create an inline tree node */
 
@@ -2136,9 +2237,10 @@ static bool inline_inline_intern(methodinfo *m, inline_node *iln)
                                                        if (0
                                                                && strncmp(callee->class->name->text, "java/", 5) != 0
                                                                && strncmp(callee->class->name->text, "gnu/", 4) != 0
+                                                               &&  strstr(callee->class->name->text, "compress") != NULL
                                                           )
                                                        {
-                                                               printf("SPECULATIVE INLINE: "); method_println(callee);
+                                                               DOLOG( printf("SPECULATIVE INLINE: "); method_println(callee); );
                                                                speculative = true;
                                                                goto maybe_inline;
                                                        }
@@ -2154,8 +2256,9 @@ maybe_inline:
                                                                goto dont_inline;
                                                        }
                                                }
-
+#if 0
 force_inline:
+#endif
                                                if (!inline_analyse_callee(iln, callee,
                                                                        bptr,
                                                                        iptr,
index f50f5e2b6e98fd6958b176222d027fe507754a57..52ad4f64a5ade5a614b56a1ecc226e1d792a64d4 100644 (file)
@@ -30,7 +30,7 @@
    Changes: Christian Thalinger
                        Edwin Steiner
 
-   $Id: jit.h 5923 2006-11-05 22:46:11Z edwin $
+   $Id: jit.h 5950 2006-11-11 17:08:14Z edwin $
 
 */
 
@@ -62,6 +62,7 @@ typedef struct exception_entry exception_entry;
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/reg.h"
 #include "vm/jit/stacktrace.h"
+#include "vm/jit/replace.h"
 
 #if defined(ENABLE_INLINING)
 # include "vm/jit/inline/inline.h"
@@ -402,15 +403,30 @@ struct instruction {
 /* for ICMD_INLINE_START and ICMD_INLINE_END */
 
 struct insinfo_inline {
-       methodinfo *method;         /* the inlined method starting/ending here    */
-       methodinfo *outer;          /* the outer method suspended/resumed here    */
-       s4          startmpc;       /* machine code offset of start of inlining   */          
-       s4          synclocal;      /* local index used for synchronization       */
-       bool        synchronize;    /* true if synchronization is needed          */
+       /* fields copied from the inlining tree ----------------------------------*/
+       insinfo_inline *parent;     /* insinfo of the surrounding inlining, if any*/
+       methodinfo     *method;     /* the inlined method starting/ending here    */
+       methodinfo     *outer;      /* the outer method suspended/resumed here    */
+       s4              synclocal;      /* local index used for synchronization   */
+       bool            synchronize;    /* true if synchronization is needed      */
+       s4              throughcount;   /* total # of pass-through variables      */
+       s4              stackvarscount; /* source stackdepth at INLINE_START      */
+       s4             *stackvars;      /* stack vars at INLINE_START             */
+
+       /* fields set by inlining ------------------------------------------------*/
+       s4         *javalocals_start; /* javalocals at start of inlined body      */
+       s4         *javalocals_end;   /* javalocals after inlined body            */
+
+       /* fields set by replacement point creation ------------------------------*/
+       rplpoint   *rp;             /* replacement point at INLINE_START          */
+
+       /* fields set by the codegen ---------------------------------------------*/
+       s4          startmpc;       /* machine code offset of start of inlining   */
 };
 
+
 /* basicblock *****************************************************************/
+
 /* flags */
 
 #define BBDELETED            -2
@@ -466,6 +482,7 @@ struct basicblock {
        basicblock   *original;     /* block of which this block is a clone       */
                                    /* NULL for the original block itself         */
        methodinfo   *method;       /* method this block belongs to               */
+       insinfo_inline *inlineinfo; /* inlineinfo for the start of this block     */
 
        s4            mpc;          /* machine code pc at start of block          */
 };
index 3f7ee7a50296b0d0bd702b259e9c318297a2c50b..44437aa3924fb05987399f5f56abdf94347d7ddf 100644 (file)
 
 #include "native/include/java_lang_String.h"
 
+
+/*** configuration of native stack slot size **********************************/
+
+/* XXX this should be in md-abi.h files, probably */
+
 #if defined(HAS_4BYTE_STACKSLOT)
-#define SIZE_OF_STACKSLOT  4
+#define SIZE_OF_STACKSLOT      4
+#define STACK_SLOTS_PER_FLOAT  2
+typedef u4 stackslot_t;
 #else
-#define SIZE_OF_STACKSLOT  8
+#define SIZE_OF_STACKSLOT      8
+#define STACK_SLOTS_PER_FLOAT  1
+typedef u8 stackslot_t;
 #endif
 
 
 #define TOP_IS_ON_STACK  1
 #define TOP_IS_IN_ITMP1  2
 
+
+/* replace_create_replacement_point ********************************************
+   Create a replacement point.
+  
+   IN:
+       jd...............current jitdata
+          iinfo............inlining info for the current position
+          rp...............pre-allocated (uninitialized) rplpoint
+          type.............RPLPOINT_TYPE constant
+          *pra.............current rplalloc pointer
+          javalocals.......the javalocals at the current point
+          stackvars........the stack variables at the current point
+          stackdepth.......the stack depth at the current point
+  
+   OUT:
+       *rpa.............points to the next free rplalloc
+  
+*******************************************************************************/
+
 static void replace_create_replacement_point(jitdata *jd,
+                                                                                        insinfo_inline *iinfo,
                                                                                         rplpoint *rp,
+                                                                                        s4 type,
                                                                                         rplalloc **pra,
-                                                                                        basicblock *bptr,
                                                                                         s4 *javalocals,
                                                                                         s4 *stackvars,
                                                                                         s4 stackdepth)
@@ -80,22 +110,30 @@ static void replace_create_replacement_point(jitdata *jd,
        varinfo  *v;
        s4        index;
 
+       static s4 fake_id = 0;
+
        ra = *pra;
 
        /* there will be a replacement point at the start of this block */
 
+       rp->method = (iinfo) ? iinfo->method : jd->m;
        rp->pc = NULL;        /* set by codegen */
        rp->outcode = NULL;   /* set by codegen */
-       rp->code = jd->code;
+       rp->callsize = 0;     /* set by codegen */
        rp->target = NULL;
        rp->regalloc = ra;
        rp->flags = 0;
-       rp->type = (bptr != NULL) ? bptr->type : -1;
+       rp->type = type;
+       rp->id = ++fake_id; /* XXX need a real invariant id */
 
-       /* store local allocation info */
+       /* XXX unify these two fields */
+       rp->code = jd->code;
+       rp->parent = (iinfo) ? iinfo->rp : NULL;
+
+       /* store local allocation info of javalocals */
 
        if (javalocals) {
-               for (i = 0; i < jd->maxlocals; ++i) {
+               for (i = 0; i < rp->method->maxlocals; ++i) {
                        index = javalocals[i];
                        if (index == UNUSED)
                                continue;
@@ -109,6 +147,8 @@ static void replace_create_replacement_point(jitdata *jd,
                }
        }
 
+       /* store allocation info of java stack vars */
+
        for (i = 0; i < stackdepth; ++i) {
                v = VAR(stackvars[i]);
                ra->flags = v->flags & (INMEMORY);
@@ -118,6 +158,8 @@ static void replace_create_replacement_point(jitdata *jd,
                ra++;
        }
 
+       /* total number of allocations */
+
        rp->regalloccount = ra - rp->regalloc;
 
        *pra = ra;
@@ -129,10 +171,7 @@ static void replace_create_replacement_point(jitdata *jd,
    Create the replacement points for the given code.
   
    IN:
-       code.............codeinfo where replacement points should be stored
-                           code->rplpoints must be NULL.
-                                               code->rplpointcount must be 0.
-          rd...............registerdata containing allocation info.
+       jd...............current jitdata, must not have any replacement points
   
    OUT:
        code->rplpoints.......set to the list of replacement points
@@ -150,23 +189,24 @@ static void replace_create_replacement_point(jitdata *jd,
 
 bool replace_create_replacement_points(jitdata *jd)
 {
-       codeinfo     *code;
-       registerdata *rd;
-       basicblock *bptr;
-       int count;
-       methodinfo *m;
-       rplpoint *rplpoints;
-       rplpoint *rp;
-       int alloccount;
-       int globalcount;
-       rplalloc *regalloc;
-       rplalloc *ra;
-       int i;
-       instruction *iptr;
-       instruction *iend;
-       s4 *javalocals;
-       methoddesc *md;
-       s4 j;
+       codeinfo        *code;
+       registerdata    *rd;
+       basicblock      *bptr;
+       int              count;
+       methodinfo      *m;
+       rplpoint        *rplpoints;
+       rplpoint        *rp;
+       int              alloccount;
+       rplalloc        *regalloc;
+       rplalloc        *ra;
+       int              i;
+       instruction     *iptr;
+       instruction     *iend;
+       s4              *javalocals;
+       methoddesc      *md;
+       s4               j;
+       insinfo_inline  *iinfo;
+       insinfo_inline  *calleeinfo;
 
        /* get required compiler data */
 
@@ -174,7 +214,7 @@ bool replace_create_replacement_points(jitdata *jd)
        rd   = jd->rd;
 
        /* assert that we wont overwrite already allocated data */
-       
+
        assert(code);
        assert(code->m);
        assert(code->rplpoints == NULL);
@@ -194,22 +234,36 @@ bool replace_create_replacement_points(jitdata *jd)
 
        for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
 
+               /* skip dead code */
+
                if (bptr->flags < BBFINISHED)
                        continue;
 
-               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+               /* get info about this block */
+
+               m = bptr->method;
+               iinfo = bptr->inlineinfo;
+
+               /* initialize javalocals at the start of this block */
 
-                       /* there will be a replacement point at the start of this block */
-                       
+               if (bptr->javalocals)
+                       MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
+               else
+                       for (i=0; i<m->maxlocals; ++i)
+                               javalocals[i] = UNUSED;
+
+               /* create replacement points at targets of backward branches */
+
+               if (bptr->bitflags & BBFLAG_REPLACEMENT) {
                        count++;
                        alloccount += bptr->indepth;
 
-                       for (i=0; i<jd->maxlocals; ++i)
+                       for (i=0; i<m->maxlocals; ++i)
                                if (bptr->javalocals[i] != UNUSED)
                                        alloccount++;
                }
 
-               MCOPY(javalocals, bptr->javalocals, s4, jd->maxlocals);
+               /* iterate over the instructions */
 
                iptr = bptr->iinstr;
                iend = iptr + bptr->icount;
@@ -222,10 +276,12 @@ bool replace_create_replacement_points(jitdata *jd)
                                case ICMD_INVOKEINTERFACE:
                                        INSTRUCTION_GET_METHODDESC(iptr, md);
                                        count++;
-                                       for (i=0; i<jd->maxlocals; ++i)
+                                       for (i=0; i<m->maxlocals; ++i)
                                                if (javalocals[i] != UNUSED)
                                                        alloccount++;
                                        alloccount += iptr->s1.argcount - md->paramcount;
+                                       if (iinfo)
+                                               alloccount -= iinfo->throughcount;
                                        break;
 
                                case ICMD_ISTORE:
@@ -252,103 +308,82 @@ bool replace_create_replacement_points(jitdata *jd)
                                case ICMD_DRETURN:
                                case ICMD_ARETURN:
                                        alloccount += 1;
-                                       /* FALLTHROUGH */
-
+                                       /* FALLTHROUGH! */
                                case ICMD_RETURN:
                                        count++;
                                        break;
-                       }
-               }
-       }
 
-       /* if no points were found, there's nothing to do */
-       
-       if (!count)
-               return true;
+                               case ICMD_INLINE_START:
+                                       iinfo = iptr->sx.s23.s3.inlineinfo;
 
-       /* count global register allocations */
+                                       count++;
+                                       for (i=0; i<m->maxlocals; ++i)
+                                               if (javalocals[i] != UNUSED)
+                                                       alloccount++;
+                                       alloccount += iinfo->stackvarscount;
 
-       globalcount = 0;
+                                       m = iinfo->method;
+                                       if (iinfo->javalocals_start)
+                                               MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
+                                       break;
 
-#if 0
-       for (i=0; i<m->maxlocals; ++i) {
-               indexused = false;
-               for (t=0; t<5; ++t) {
-#if defined(ENABLE_INTRP)
-                       if (!opt_intrp) {
-#endif
-                               if (jd->local_map[5*i + t] != UNUSED) {
-                                       globalcount++;
-                                       indexused = true;
-                               }
-#if defined(ENABLE_INTRP)
+                               case ICMD_INLINE_END:
+                                       iinfo = iptr->sx.s23.s3.inlineinfo;
+                                       m = iinfo->outer;
+                                       if (iinfo->javalocals_end)
+                                               MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
+                                       iinfo = iinfo->parent;
+                                       break;
                        }
-#endif
                }
-               if (!indexused)
-                       globalcount++; /* dummy rplalloc */
        }
-#endif
 
-       alloccount += globalcount;
+       /* if no points were found, there's nothing to do */
 
-       /* allocate replacement point array and allocation array */
-       
-       rplpoints = MNEW(rplpoint,count);
-       regalloc = MNEW(rplalloc,alloccount);
-       ra = regalloc;
+       if (!count)
+               return true;
 
-       /* store global register allocations */
+       /* allocate replacement point array and allocation array */
 
-#if 0
-       for (i=0; i<m->maxlocals; ++i) {
-               indexused = false;
-               for (t=0; t<5; ++t) {
-#if defined(ENABLE_INTRP)
-                       if (!opt_intrp) {
-#endif
-                               if (jd->local_map[5*i + t] != UNUSED) {
-                                       v = VAR(jd->local_map[5*i + t]);
-                                       ra->flags = v->flags & (INMEMORY);
-                                       ra->regoff = v->vv.regoff;
-                                       ra->type  = t;
-                                       ra->next = (indexused) ? 0 : 1;
-                                       ra++;
-                                       indexused = true;
-                               }
-#if defined(ENABLE_INTRP)
-                       }
-#endif
-               }
-               if (!indexused) {
-                       /* dummy rplalloc */
-                       ra->type = -1;
-                       ra->flags = 0;
-                       ra->regoff = 0;
-                       ra->next = 1;
-                       ra++;
-               }
-       }
-#endif
+       rplpoints = MNEW(rplpoint, count);
+       regalloc = MNEW(rplalloc, alloccount);
+       ra = regalloc;
 
        /* initialize replacement point structs */
 
        rp = rplpoints;
 
+       /* XXX try to share code with the counting loop! */
+
        for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+               /* skip dead code */
+
                if (bptr->flags < BBFINISHED)
                        continue;
 
+               /* get info about this block */
+
+               m = bptr->method;
+               iinfo = bptr->inlineinfo;
+
+               /* initialize javalocals at the start of this block */
+
+               if (bptr->javalocals)
+                       MCOPY(javalocals, bptr->javalocals, s4, m->maxlocals);
+               else
+                       for (i=0; i<m->maxlocals; ++i)
+                               javalocals[i] = UNUSED;
+
+               /* create replacement points at targets of backward branches */
+
                if (bptr->bitflags & BBFLAG_REPLACEMENT) {
 
-                       replace_create_replacement_point(jd, rp, &ra,
-                                       bptr,
+                       replace_create_replacement_point(jd, iinfo, rp++,
+                                       bptr->type, &ra,
                                        bptr->javalocals, bptr->invars, bptr->indepth);
-
-                       rp++;
                }
 
-               MCOPY(javalocals, bptr->javalocals, s4, jd->maxlocals);
+               /* iterate over the instructions */
 
                iptr = bptr->iinstr;
                iend = iptr + bptr->icount;
@@ -361,11 +396,11 @@ bool replace_create_replacement_points(jitdata *jd)
                                case ICMD_INVOKEINTERFACE:
                                        INSTRUCTION_GET_METHODDESC(iptr, md);
 
-                                       replace_create_replacement_point(jd, rp, &ra,
-                                                       NULL,
+                                       i = (iinfo) ? iinfo->throughcount : 0;
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_CALL, &ra,
                                                        javalocals, iptr->sx.s23.s2.args + md->paramcount,
-                                                       iptr->s1.argcount - md->paramcount);
-                                       rp++;
+                                                       iptr->s1.argcount - md->paramcount - i);
                                        break;
 
                                case ICMD_ISTORE:
@@ -391,17 +426,38 @@ bool replace_create_replacement_points(jitdata *jd)
                                case ICMD_FRETURN:
                                case ICMD_DRETURN:
                                case ICMD_ARETURN:
-                                       replace_create_replacement_point(jd, rp, &ra,
-                                                       NULL,
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_RETURN, &ra,
                                                        NULL, &(iptr->s1.varindex), 1);
-                                       rp++;
                                        break;
 
                                case ICMD_RETURN:
-                                       replace_create_replacement_point(jd, rp, &ra,
-                                                       NULL,
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_RETURN, &ra,
                                                        NULL, NULL, 0);
-                                       rp++;
+                                       break;
+
+                               case ICMD_INLINE_START:
+                                       calleeinfo = iptr->sx.s23.s3.inlineinfo;
+
+                                       calleeinfo->rp = rp;
+                                       replace_create_replacement_point(jd, iinfo, rp++,
+                                                       RPLPOINT_TYPE_INLINE, &ra,
+                                                       javalocals,
+                                                       calleeinfo->stackvars, calleeinfo->stackvarscount);
+
+                                       iinfo = calleeinfo;
+                                       m = iinfo->method;
+                                       if (iinfo->javalocals_start)
+                                               MCOPY(javalocals, iinfo->javalocals_start, s4, m->maxlocals);
+                                       break;
+
+                               case ICMD_INLINE_END:
+                                       iinfo = iptr->sx.s23.s3.inlineinfo;
+                                       m = iinfo->outer;
+                                       if (iinfo->javalocals_end)
+                                               MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
+                                       iinfo = iinfo->parent;
                                        break;
                        }
                }
@@ -413,7 +469,7 @@ bool replace_create_replacement_points(jitdata *jd)
        code->rplpointcount = count;
        code->regalloc      = regalloc;
        code->regalloccount = alloccount;
-       code->globalcount   = globalcount;
+       code->globalcount   = 0;
        code->savedintcount = INT_SAV_CNT - rd->savintreguse;
        code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
        code->memuse        = rd->memuse;
@@ -424,6 +480,7 @@ bool replace_create_replacement_points(jitdata *jd)
        return true;
 }
 
+
 /* replace_free_replacement_points *********************************************
  
    Free memory used by replacement points.
@@ -450,6 +507,7 @@ void replace_free_replacement_points(codeinfo *code)
        code->globalcount = 0;
 }
 
+
 /* replace_activate_replacement_point ******************************************
  
    Activate a replacement point. When this function returns, the
@@ -465,20 +523,21 @@ void replace_free_replacement_points(codeinfo *code)
 void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
 {
        assert(rp->target == NULL);
-       
-#ifndef NDEBUG
+
+#if !defined(NDEBUG)
        printf("activate replacement point: ");
-       replace_replacement_point_println(rp);
+       replace_replacement_point_println(rp, 0);
        fflush(stdout);
 #endif
-       
+
        rp->target = target;
-       
+
 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
        md_patch_replacement_point(rp);
 #endif
 }
 
+
 /* replace_deactivate_replacement_point ****************************************
  
    Deactivate a replacement point. When this function returns, the
@@ -493,42 +552,40 @@ void replace_activate_replacement_point(rplpoint *rp,rplpoint *target)
 void replace_deactivate_replacement_point(rplpoint *rp)
 {
        assert(rp->target);
-       
-#ifndef NDEBUG
+
+#if !defined(NDEBUG)
        printf("deactivate replacement point: ");
-       replace_replacement_point_println(rp);
+       replace_replacement_point_println(rp, 0);
        fflush(stdout);
 #endif
-       
+
        rp->target = NULL;
-       
+
 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
        md_patch_replacement_point(rp);
 #endif
 }
 
-/* replace_read_executionstate *************************************************
 
-   Read the given executions state and translate it to a source state.
+/* replace_read_value **********************************************************
+
+   Read a value with the given allocation from the execution state.
    
    IN:
-       rp...............replacement point at which `es` was taken
           es...............execution state
-          ss...............where to put the source state
+          sp...............stack pointer of the execution state (XXX eliminate?)
+          ra...............allocation
+          javaval..........where to put the value
 
    OUT:
-       *ss..............the source state derived from the execution state
+       *javaval.........the value
   
 *******************************************************************************/
 
-inline static void replace_read_value(executionstate *es,
-#ifdef HAS_4BYTE_STACKSLOT
-                                                                         u4 *sp,
-#else
-                                                                         u8 *sp,
-#endif
-                                                                         rplalloc *ra,
-                                                                         u8 *javaval)
+static void replace_read_value(executionstate_t *es,
+                                                          stackslot_t *sp,
+                                                          rplalloc *ra,
+                                                          u8 *javaval)
 {
        if (ra->flags & INMEMORY) {
                /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
@@ -554,14 +611,23 @@ inline static void replace_read_value(executionstate *es,
        }
 }
 
-inline static void replace_write_value(executionstate *es,
-#ifdef HAS_4BYTE_STACKSLOT
-                                                                         u4 *sp,
-#else
-                                                                         u8 *sp,
-#endif
-                                                                         rplalloc *ra,
-                                                                         u8 *javaval)
+
+/* replace_write_value *********************************************************
+
+   Write a value to the given allocation in the execution state.
+   
+   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,
+                                                           u8 *javaval)
 {
        if (ra->flags & INMEMORY) {
                /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
@@ -587,36 +653,41 @@ inline static void replace_write_value(executionstate *es,
        }
 }
 
-static void replace_read_executionstate(rplpoint *rp,executionstate *es,
-                                                                        sourcestate *ss)
+
+/* replace_read_executionstate *************************************************
+
+   Read the given executions state and translate it to a source state.
+   
+   IN:
+       rp...............replacement point at which `es` was taken
+          es...............execution state
+          ss...............where to put the source state
+
+   OUT:
+       *ss..............the source state derived from the execution state
+  
+*******************************************************************************/
+
+static void replace_read_executionstate(rplpoint *rp,executionstate_t *es,
+                                                                        sourcestate_t *ss)
 {
-       methodinfo *m;
-       codeinfo *code;
-       int count;
-       int i;
-       rplalloc *ra;
-       methoddesc *md;
-       int topslot;
-#ifdef HAS_4BYTE_STACKSLOT
-       u4 *sp;
-       u4 *basesp;
-#else
-       u8 *sp;
-       u8 *basesp;
-#endif
+       methodinfo    *m;
+       codeinfo      *code;
+       int            count;
+       int            i;
+       rplalloc      *ra;
+       sourceframe_t *frame;
+       int            topslot;
+       stackslot_t   *sp;
+       stackslot_t   *basesp;
 
        code = rp->code;
-       m = code->m;
-       md = m->parseddesc;
+       m = rp->method;
        topslot = TOP_IS_NORMAL;
 
-       /* stack pointers */
+       /* stack pointer */
 
-#ifdef HAS_4BYTE_STACKSLOT
-       sp = (u4*) es->sp;
-#else
-       sp = (u8*) es->sp;
-#endif
+       sp = (stackslot_t *) es->sp;
 
        /* on some architectures the returnAddress is passed on the stack by JSR */
 
@@ -639,23 +710,30 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        }
 
        /* calculate base stack pointer */
-       
+
        basesp = sp + code_get_stack_frame_size(code);
 
-       ss->stackbase = (u1*) basesp;
+       /* create the source frame */
+
+       frame = DNEW(sourceframe_t);
+       frame->up = ss->frames;
+       frame->method = rp->method;
+       frame->id = rp->id;
+
+       ss->frames = frame;
 
        /* read local variables */
 
-       count = m->maxlocals; /* XXX inlining */
-       ss->javalocalcount = count;
-       ss->javalocals = DMNEW(u8, count);
-       ss->javalocaltype = DMNEW(u1, count);
+       count = m->maxlocals;
+       frame->javalocalcount = count;
+       frame->javalocals = DMNEW(u8, count);
+       frame->javalocaltype = DMNEW(u1, count);
 
-#ifndef NDEBUG
+#if !defined(NDEBUG)
        /* mark values as undefined */
        for (i=0; i<count; ++i) {
-               ss->javalocals[i] = (u8) 0x00dead0000dead00ULL;
-               ss->javalocaltype[i] = TYPE_VOID;
+               frame->javalocals[i] = (u8) 0x00dead0000dead00ULL;
+               frame->javalocaltype[i] = TYPE_VOID;
        }
 
        /* some entries in the intregs array are not meaningful */
@@ -664,22 +742,7 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
 #ifdef REG_PV
        es->intregs[REG_PV   ] = (u8) 0x11dead1111dead11ULL;
 #endif
-#endif /* NDEBUG */
-       
-#if 0
-       ra = code->regalloc;
-
-       i = -1;
-       for (allocs = code->globalcount; allocs--; ra++) {
-               if (ra->next)
-                       i++;
-               t = ra->type;
-               if (t == -1)
-                       continue; /* dummy rplalloc */
-
-               replace_read_value(es,sp,ra,ss->javalocals + (5*i+t));
-       }
-#endif
+#endif /* !defined(NDEBUG) */
 
        /* read javalocals */
 
@@ -687,33 +750,36 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        ra = rp->regalloc;
 
        while (count && (i = ra->index) >= 0) {
-               ss->javalocaltype[i] = ra->type;
-               replace_read_value(es, sp, ra, ss->javalocals + i);
+               assert(i < m->maxlocals);
+               frame->javalocaltype[i] = ra->type;
+               replace_read_value(es, sp, ra, frame->javalocals + i);
                ra++;
                count--;
        }
 
        /* read stack slots */
 
-       ss->javastackdepth = count;
-       ss->javastack = DMNEW(u8, count);
-       ss->javastacktype = DMNEW(u1, count);
+       frame->javastackdepth = count;
+       frame->javastack = DMNEW(u8, count);
+       frame->javastacktype = DMNEW(u1, count);
 
-#ifndef NDEBUG
+#if !defined(NDEBUG)
        /* mark values as undefined */
-       for (i=0; i<count; ++i)
-               ss->javastack[i] = (u8) 0x00dead0000dead00ULL;
-#endif
-       
+       for (i=0; i<count; ++i) {
+               frame->javastack[i] = (u8) 0x00dead0000dead00ULL;
+               frame->javastacktype[i] = TYPE_VOID;
+       }
+#endif /* !defined(NDEBUG) */
+
        i = 0;
 
        /* the first stack slot is special in SBR and EXH blocks */
 
        if (topslot == TOP_IS_ON_STACK) {
                assert(count);
-               
-               ss->javastack[i] = sp[-1];
-               ss->javastacktype[i] = TYPE_ADR; /* XXX RET */
+
+               frame->javastack[i] = sp[-1];
+               frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
                count--;
                i++;
                ra++;
@@ -721,67 +787,33 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
        else if (topslot == TOP_IS_IN_ITMP1) {
                assert(count);
 
-               ss->javastack[i] = es->intregs[REG_ITMP1];
-               ss->javastacktype[i] = TYPE_ADR; /* XXX RET */
+               frame->javastack[i] = es->intregs[REG_ITMP1];
+               frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
                count--;
                i++;
                ra++;
        }
-       
+
        /* read remaining stack slots */
-       
+
        for (; count--; ra++, i++) {
                assert(ra->index == -1);
 
-               replace_read_value(es,sp,ra,ss->javastack + i);
-               ss->javastacktype[i] = ra->type;
-       }
-
-       /* read unused callee saved int regs */
-       
-       count = INT_SAV_CNT;
-       for (i=0; count > code->savedintcount; ++i) {
-               assert(i < INT_REG_CNT);
-               if (nregdescint[i] == REG_SAV)
-                       ss->savedintregs[--count] = es->intregs[i];
-       }
-
-       /* read saved int regs */
-
-       for (i=0; i<code->savedintcount; ++i) {
-               ss->savedintregs[i] = *--basesp;
-       }
-
-       /* read unused callee saved flt regs */
-       
-       count = FLT_SAV_CNT;
-       for (i=0; count > code->savedfltcount; ++i) {
-               assert(i < FLT_REG_CNT);
-               if (nregdescfloat[i] == REG_SAV)
-                       ss->savedfltregs[--count] = es->fltregs[i];
-       }
-
-       /* read saved flt regs */
-
-       for (i=0; i<code->savedfltcount; ++i) {
-#ifdef HAS_4BYTE_STACKSLOT
-               basesp -= 2;
-#else
-               basesp--;
-#endif
-               ss->savedfltregs[i] = *(u8*)basesp;
+               replace_read_value(es,sp,ra,frame->javastack + i);
+               frame->javastacktype[i] = ra->type;
        }
 
        /* read slots used for synchronization */
 
        count = code_get_sync_slot_count(code);
-       ss->syncslotcount = count;
-       ss->syncslots = DMNEW(u8,count);
+       frame->syncslotcount = count;
+       frame->syncslots = DMNEW(u8,count);
        for (i=0; i<count; ++i) {
-               ss->syncslots[i] = sp[code->memuse + i];
+               frame->syncslots[i] = sp[code->memuse + i];
        }
 }
 
+
 /* replace_write_executionstate ************************************************
 
    Translate the given source state into an execution state.
@@ -797,38 +829,35 @@ static void replace_read_executionstate(rplpoint *rp,executionstate *es,
   
 *******************************************************************************/
 
-static void replace_write_executionstate(rplpoint *rp,executionstate *es,
-                                                                                sourcestate *ss)
+static void replace_write_executionstate(rplpoint *rp,
+                                                                                executionstate_t *es,
+                                                                                sourcestate_t *ss)
 {
-       methodinfo *m;
-       codeinfo *code;
-       int count;
-       int i;
-       rplalloc *ra;
-       methoddesc *md;
-       int topslot;
-#ifdef HAS_4BYTE_STACKSLOT
-       u4 *sp;
-       u4 *basesp;
-#else
-       u8 *sp;
-       u8 *basesp;
-#endif
+       methodinfo     *m;
+       codeinfo       *code;
+       int             count;
+       int             i;
+       rplalloc       *ra;
+       sourceframe_t  *frame;
+       int             topslot;
+       stackslot_t    *sp;
+       stackslot_t    *basesp;
 
        code = rp->code;
-       m = code->m;
-       md = m->parseddesc;
+       m = rp->method;
        topslot = TOP_IS_NORMAL;
-       
+
+       /* pop a source frame */
+
+       frame = ss->frames;
+       assert(frame);
+       ss->frames = frame->up;
+
        /* calculate stack pointer */
-       
-#ifdef HAS_4BYTE_STACKSLOT
-       basesp = (u4*) ss->stackbase;
-#else
-       basesp = (u8*) ss->stackbase;
-#endif
-       
-       sp = basesp - code_get_stack_frame_size(code);
+
+       sp = (stackslot_t *) es->sp;
+
+       basesp = sp + code_get_stack_frame_size(code);
 
        /* on some architectures the returnAddress is passed on the stack by JSR */
 
@@ -837,56 +866,27 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,
                topslot = TOP_IS_ON_STACK; /* XXX */
        }
 #endif
-       
+
        /* in some cases the top stack slot is passed in REG_ITMP1 */
 
        if (  (rp->type == BBTYPE_EXH)
 #if defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)
-          || (rp->type == BBTYPE_SBR) /* XXX */ 
+          || (rp->type == BBTYPE_SBR) /* XXX */
 #endif
           )
        {
                topslot = TOP_IS_IN_ITMP1;
        }
 
-       /* in debug mode, invalidate stack frame first */
-
-#ifndef NDEBUG
-       for (i=0; i<(basesp - sp); ++i) {
-               sp[i] = 0xdeaddeadU;
-       }
-#endif
-
-#if 0
-       /* write local variables */
-
-       count = m->maxlocals; /* XXX inlining */
-
-       ra = code->regalloc;
-
-       i = -1;
-       for (allocs = code->globalcount; allocs--; ra++) {
-               if (ra->next)
-                       i++;
-
-               assert(i >= 0 && i < m->maxlocals);
-               
-               t = ra->type;
-               if (t == -1)
-                       continue; /* dummy rplalloc */
-
-               replace_write_value(es,sp,ra,ss->javalocals + (5*i+t));
-       }
-#endif
-
        /* write javalocals */
 
        ra = rp->regalloc;
        count = rp->regalloccount;
 
        while (count && (i = ra->index) >= 0) {
-               assert(ra->type == ss->javalocaltype[i]);
-               replace_write_value(es, sp, ra, ss->javalocals + i);
+               assert(i < m->maxlocals);
+               assert(ra->type == frame->javalocaltype[i]);
+               replace_write_value(es, sp, ra, frame->javalocals + i);
                count--;
                ra++;
        }
@@ -899,9 +899,9 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,
 
        if (topslot == TOP_IS_ON_STACK) {
                assert(count);
-               
-               assert(ss->javastacktype[i] == TYPE_ADR);
-               sp[-1] = ss->javastack[i];
+
+               assert(frame->javastacktype[i] == TYPE_ADR);
+               sp[-1] = frame->javastack[i];
                count--;
                i++;
                ra++;
@@ -909,64 +909,29 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,
        else if (topslot == TOP_IS_IN_ITMP1) {
                assert(count);
 
-               assert(ss->javastacktype[i] == TYPE_ADR);
-               assert(ss->javastacktype[i] == TYPE_ADR);
-               es->intregs[REG_ITMP1] = ss->javastack[i];
+               assert(frame->javastacktype[i] == TYPE_ADR);
+               assert(frame->javastacktype[i] == TYPE_ADR);
+               es->intregs[REG_ITMP1] = frame->javastack[i];
                count--;
                i++;
                ra++;
        }
 
        /* write remaining stack slots */
-       
+
        for (; count--; ra++, i++) {
                assert(ra->index == -1);
 
-               assert(ra->type == ss->javastacktype[i]);
-               replace_write_value(es,sp,ra,ss->javastack + i);
-       }
-       
-       /* write unused callee saved int regs */
-       
-       count = INT_SAV_CNT;
-       for (i=0; count > code->savedintcount; ++i) {
-               assert(i < INT_REG_CNT);
-               if (nregdescint[i] == REG_SAV)
-                       es->intregs[i] = ss->savedintregs[--count];
-       }
-
-       /* write saved int regs */
-
-       for (i=0; i<code->savedintcount; ++i) {
-               *--basesp = ss->savedintregs[i];
-       }
-
-       /* write unused callee saved flt regs */
-       
-       count = FLT_SAV_CNT;
-       for (i=0; count > code->savedfltcount; ++i) {
-               assert(i < FLT_REG_CNT);
-               if (nregdescfloat[i] == REG_SAV)
-                       es->fltregs[i] = ss->savedfltregs[--count];
-       }
-
-       /* write saved flt regs */
-
-       for (i=0; i<code->savedfltcount; ++i) {
-#ifdef HAS_4BYTE_STACKSLOT
-               basesp -= 2;
-#else
-               basesp--;
-#endif
-               *(u8*)basesp = ss->savedfltregs[i];
+               assert(ra->type == frame->javastacktype[i]);
+               replace_write_value(es,sp,ra,frame->javastack + i);
        }
 
        /* write slots used for synchronization */
 
        count = code_get_sync_slot_count(code);
-       assert(count == ss->syncslotcount);
+       assert(count == frame->syncslotcount);
        for (i=0; i<count; ++i) {
-               sp[code->memuse + i] = ss->syncslots[i];
+               sp[code->memuse + i] = frame->syncslots[i];
        }
 
        /* set new pc */
@@ -975,30 +940,80 @@ static void replace_write_executionstate(rplpoint *rp,executionstate *es,
 }
 
 
-void replace_pop_activation_record(executionstate *es, sourcestate *ss)
+/* 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
+
+   OUT:
+       *es..............the execution state after popping the stack frame
+  
+*******************************************************************************/
+
+bool replace_pop_activation_record(executionstate_t *es)
 {
        u1 *ra;
        u1 *pv;
        s4 reg;
        s4 i;
+       codeinfo *code;
+       stackslot_t *basesp;
 
        assert(es->code);
 
-       /* restore saved registers */
+       /* read the return address */
+
+       ra = md_stacktrace_get_returnaddress(es->sp,
+                       SIZE_OF_STACKSLOT * es->code->stackframesize);
+
+       printf("return address: %p\n", (void*)ra);
+
+       /* find the new codeinfo */
+
+       pv = md_codegen_get_pv_from_pc(ra);
+
+       printf("PV = %p\n", (void*) pv);
+
+       if (pv == NULL)
+               return false;
+
+       code = *(codeinfo **)(pv + CodeinfoPointer);
+
+       printf("CODE = %p\n", (void*) code);
+
+       if (code == NULL)
+               return false;
+
+       /* calculate the base of the stack frame */
+
+       basesp = (stackslot_t *)es->sp + es->code->stackframesize;
+
+       /* restore saved int registers */
 
        reg = INT_REG_CNT;
-       for (i=0; i<INT_SAV_CNT; ++i) {
+       for (i=0; i<es->code->savedintcount; ++i) {
                while (nregdescint[--reg] != REG_SAV)
                        ;
-               es->intregs[reg] = ss->savedintregs[i];
+               es->intregs[reg] = *--basesp;
        }
 
-       /* read the return address */
+       /* restore saved flt registers */
 
-       ra = md_stacktrace_get_returnaddress(es->sp, 
-                       SIZE_OF_STACKSLOT * es->code->stackframesize);
+       /* XXX align? */
+       reg = FLT_REG_CNT;
+       for (i=0; i<es->code->savedfltcount; ++i) {
+               while (nregdescfloat[--reg] != REG_SAV)
+                       ;
+               basesp -= STACK_SLOTS_PER_FLOAT;
+               es->fltregs[reg] = *(u8*)basesp;
+       }
 
-       printf("return address: %p\n", (void*)ra);
+       /* set the new pc */
 
        es->pc = ra;
 
@@ -1007,14 +1022,159 @@ void replace_pop_activation_record(executionstate *es, sourcestate *ss)
        es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
        es->sp += SIZE_OF_STACKSLOT; /* skip return address */
 
-       /* find the new codeinfo */
-
-       pv = md_codegen_get_pv_from_pc(es->pc);
        es->pv = pv;
+       es->code = code;
+
+#if !defined(NDEBUG)
+       /* for debugging */
+       for (i=0; i<INT_REG_CNT; ++i)
+               if (nregdescint[i] != REG_SAV)
+                       es->intregs[i] = 0x33dead3333dead33ULL;
+       for (i=0; i<FLT_REG_CNT; ++i)
+               if (nregdescfloat[i] != REG_SAV)
+                       es->fltregs[i] = 0x33dead3333dead33ULL;
+#endif /* !defined(NDEBUG) */
+
+       return true;
+}
+
+
+/* replace_push_activation_record **********************************************
+
+   Push a stack frame onto the execution state.
+   
+   *** This function imitates the effects of a call and the ***
+   *** method prolog of the callee.                         ***
+
+   IN:
+          es...............execution state
+          rpcall...........the replacement point at the call site
+          calleecode.......the codeinfo of the callee
+
+   OUT:
+       *es..............the execution state after pushing the stack frame
+  
+*******************************************************************************/
+
+void replace_push_activation_record(executionstate_t *es,
+                                                                       rplpoint *rpcall,
+                                                                       codeinfo *calleecode)
+{
+       s4 reg;
+       s4 i;
+       stackslot_t *basesp;
+
+       /* write the return address */
+
+       *((stackslot_t *)es->sp) = (stackslot_t) (rpcall->pc + rpcall->callsize);
+
+       es->sp -= SIZE_OF_STACKSLOT;
+
+       /* we move into a new code unit */
 
-       if (pv) {
-               es->code = *(codeinfo **)(pv + CodeinfoPointer);
+       es->code = calleecode;
+
+       /* set the new pc XXX not needed */
+
+       es->pc = es->code->entrypoint;
+
+       /* build the stackframe */
+
+       basesp = (stackslot_t *) es->sp;
+       es->sp -= SIZE_OF_STACKSLOT * es->code->stackframesize;
+
+       /* in debug mode, invalidate stack frame first */
+
+#if !defined(NDEBUG)
+       {
+               stackslot_t *sp = (stackslot_t *) es->sp;
+               for (i=0; i<(basesp - sp); ++i) {
+                       sp[i] = 0xdeaddeadU;
+               }
        }
+#endif
+
+       /* save int registers */
+
+       reg = INT_REG_CNT;
+       for (i=0; i<es->code->savedintcount; ++i) {
+               while (nregdescint[--reg] != REG_SAV)
+                       ;
+               *--basesp = es->intregs[reg];
+
+#if !defined(NDEBUG)
+               es->intregs[reg] = 0x44dead4444dead44ULL;
+#endif
+       }
+
+       /* save flt registers */
+
+       /* XXX align? */
+       reg = FLT_REG_CNT;
+       for (i=0; i<es->code->savedfltcount; ++i) {
+               while (nregdescfloat[--reg] != REG_SAV)
+                       ;
+               basesp -= STACK_SLOTS_PER_FLOAT;
+               *(u8*)basesp = es->fltregs[reg];
+
+#if !defined(NDEBUG)
+               es->fltregs[reg] = 0x44dead4444dead44ULL;
+#endif
+       }
+
+       /* set the PV */
+
+       es->pv = es->code->entrypoint;
+}
+
+
+/* replace_find_replacement_point **********************************************
+
+   Find the replacement point in the given code corresponding to the
+   position given in the source frame.
+   
+   IN:
+          code.............the codeinfo in which to search the rplpoint
+          ss...............the source state defining the position to look for
+
+   RETURN VALUE:
+       the replacement point
+  
+*******************************************************************************/
+
+rplpoint * replace_find_replacement_point(codeinfo *code, sourcestate_t *ss)
+{
+       sourceframe_t *frame;
+       methodinfo *m;
+       rplpoint *rp;
+       s4        i;
+
+       assert(ss);
+
+       frame = ss->frames;
+       assert(frame);
+
+#if !defined(NDEBUG)
+       printf("searching replacement point for:\n");
+       replace_source_frame_println(frame);
+#endif
+
+       m = frame->method;
+
+#if !defined(NDEBUG)
+       printf("code = %p\n", (void*)code);
+#endif
+
+       rp = code->rplpoints;
+       i = code->rplpointcount;
+       while (i--) {
+               if (rp->id == frame->id)
+                       return rp;
+               rp++;
+       }
+
+       assert(0);
+       return NULL; /* NOT REACHED */
 }
 
 
@@ -1032,16 +1192,17 @@ void replace_pop_activation_record(executionstate *es, sourcestate *ss)
   
 *******************************************************************************/
 
-void replace_me(rplpoint *rp,executionstate *es)
+void replace_me(rplpoint *rp, executionstate_t *es)
 {
-       rplpoint *target;
-       sourcestate ss;
-       s4 dumpsize;
-       rplpoint *candidate;
-       s4 i;
+       rplpoint     *target;
+       sourcestate_t ss;
+       s4            dumpsize;
+       rplpoint     *candidate;
+       codeinfo     *code;
+       s4            i;
 
        es->code = rp->code;
-       
+
        /* mark start of dump memory area */
 
        dumpsize = dump_size();
@@ -1053,49 +1214,97 @@ void replace_me(rplpoint *rp,executionstate *es)
        /* XXX DEBUG turn off self-replacement */
        if (target == rp)
                replace_deactivate_replacement_point(rp);
-       
-#ifndef NDEBUG
+
+#if !defined(NDEBUG)
        printf("replace_me(%p,%p)\n",(void*)rp,(void*)es);
        fflush(stdout);
-       replace_replacement_point_println(rp);
+       replace_replacement_point_println(rp, 0);
        replace_executionstate_println(es);
 #endif
 
        /* read execution state of old code */
 
-       replace_read_executionstate(rp,es,&ss);
-
-#ifndef NDEBUG
-       replace_sourcestate_println(&ss);
-#endif
+       ss.frames = NULL;
 
        /* XXX testing */
 
+       candidate = rp;
        do {
-               replace_pop_activation_record(es, &ss);
-               replace_executionstate_println(es);
-               candidate = NULL;
-               rp = es->code->rplpoints;
-               for (i=0; i<es->code->rplpointcount; ++i, ++rp)
-                       if (rp->pc <= es->pc)
-                               candidate = rp;
-
-               if (candidate) {
-                       replace_read_executionstate(candidate,es,&ss);
-                       replace_sourcestate_println(&ss);
+#if !defined(NDEBUG)
+               printf("recovering source state for:\n");
+               replace_replacement_point_println(candidate, 1);
+#endif
+
+               replace_read_executionstate(candidate,es,&ss);
+
+               if (candidate->parent) {
+                       printf("INLINED!\n");
+                       candidate = candidate->parent;
+                       assert(candidate->type == RPLPOINT_TYPE_INLINE);
+               }
+               else {
+                       printf("UNWIND\n");
+                       if (!replace_pop_activation_record(es)) {
+                               printf("BREAKING\n");
+                               break;
+                       }
+#if !defined(NDEBUG)
+                       replace_executionstate_println(es);
+#endif
+                       candidate = NULL;
+                       rp = es->code->rplpoints;
+                       for (i=0; i<es->code->rplpointcount; ++i, ++rp)
+                               if (rp->pc <= es->pc)
+                                       candidate = rp;
+                       if (!candidate)
+                               printf("NO CANDIDATE!\n");
+                       else {
+                               printf("found replacement point.\n");
+                               assert(candidate->type == RPLPOINT_TYPE_CALL);
+                       }
                }
        } while (candidate);
 
+#if !defined(NDEBUG)
+       replace_sourcestate_println(&ss);
+#endif
+
        /* write execution state of new code */
 
-       replace_write_executionstate(target,es,&ss);
+#if !defined(NDEBUG)
+       replace_executionstate_println(es);
+#endif
+
+       code = es->code;
 
-       es->code = target->code;
 
-#ifndef NDEBUG
+       while (ss.frames) {
+
+               candidate = replace_find_replacement_point(code, &ss);
+
+#if !defined(NDEBUG)
+               printf("creating execution state for:\n");
+               replace_replacement_point_println(candidate, 1);
+#endif
+
+               replace_write_executionstate(candidate, es, &ss);
+               if (ss.frames == NULL)
+                       break;
+
+               if (candidate->type == RPLPOINT_TYPE_CALL) {
+                       code = ss.frames->method->code;
+                       assert(code);
+                       replace_push_activation_record(es, candidate, code);
+               }
+#if !defined(NDEBUG)
+               replace_executionstate_println(es);
+#endif
+       }
+
+#if !defined(NDEBUG)
        replace_executionstate_println(es);
 #endif
-       
+
        /* release dump area */
 
        dump_release(dumpsize);
@@ -1105,9 +1314,10 @@ void replace_me(rplpoint *rp,executionstate *es)
 #if (defined(__I386__) || defined(__X86_64__) || defined(__ALPHA__) || defined(__POWERPC__) || defined(__MIPS__)) && defined(ENABLE_JIT)
        asm_replacement_in(es);
 #endif
-       abort();
+       abort(); /* NOT REACHED */
 }
 
+
 /* replace_replacement_point_println *******************************************
  
    Print replacement point info.
@@ -1117,23 +1327,39 @@ void replace_me(rplpoint *rp,executionstate *es)
   
 *******************************************************************************/
 
-#ifndef NDEBUG
+#if !defined(NDEBUG)
 static const char *type_char = "IJFDA";
 
 #define TYPECHAR(t)  (((t) >= 0 && (t) <= 4) ? type_char[t] : '?')
 
-void replace_replacement_point_println(rplpoint *rp)
+static char *replace_type_str[] = {
+       "STD",
+       "EXH",
+       "SBR",
+       "CALL",
+       "INLINE",
+       "RETURN"
+};
+
+void replace_replacement_point_println(rplpoint *rp, int depth)
 {
        int j;
 
-       if (!rp) {
+       if (!rp) {
                printf("(rplpoint *)NULL\n");
                return;
        }
 
-       printf("rplpoint %p pc:%p out:%p target:%p mcode:%016llx type:%01d flags:%01x\n\t\tra:%d = [",
-                       (void*)rp,rp->pc,rp->outcode,(void*)rp->target,
-                       (unsigned long long)rp->mcode,rp->type,rp->flags,rp->regalloccount);
+       for (j=0; j<depth; ++j)
+               putchar('\t');
+
+       printf("rplpoint %p pc:%p+%d out:%p target:%p mcode:%016llx type:%s flags:%01x parent:%p\n",
+                       (void*)rp,rp->pc,rp->callsize,rp->outcode,(void*)rp->target,
+                       (unsigned long long)rp->mcode,replace_type_str[rp->type],rp->flags,
+                       (void*)rp->parent);
+       for (j=0; j<depth; ++j)
+               putchar('\t');
+       printf("ra:%d = [",     rp->regalloccount);
 
        for (j=0; j<rp->regalloccount; ++j) {
                if (j)
@@ -1145,13 +1371,17 @@ void replace_replacement_point_println(rplpoint *rp)
                show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
        }
 
-       printf("]\n\t\tmethod: ");
-       method_print(rp->code->m);
+       printf("]\n");
+       for (j=0; j<depth; ++j)
+               putchar('\t');
+       printf("method: ");
+       method_print(rp->method);
 
        printf("\n");
 }
 #endif
 
+
 /* replace_show_replacement_points *********************************************
  
    Print replacement point info.
@@ -1161,29 +1391,20 @@ void replace_replacement_point_println(rplpoint *rp)
   
 *******************************************************************************/
 
-#ifndef NDEBUG
+#if !defined(NDEBUG)
 void replace_show_replacement_points(codeinfo *code)
 {
        int i;
+       int depth;
        rplpoint *rp;
-       
+       rplpoint *parent;
+
        if (!code) {
                printf("(codeinfo *)NULL\n");
                return;
        }
 
        printf("\treplacement points: %d\n",code->rplpointcount);
-#if 0
-       printf("\tglobal allocations: %d = [",code->globalcount);
-
-       for (i=0; i<code->globalcount; ++i)
-               printf("%c%1c%01x:%02d",
-                               (code->regalloc[i].next) ? '^' : ' ',
-                               TYPECHAR(code->regalloc[i].type),
-                               code->regalloc[i].flags,code->regalloc[i].regoff);
-
-       printf("]\n");
-#endif
 
        printf("\ttotal allocations : %d\n",code->regalloccount);
        printf("\tsaved int regs    : %d\n",code->savedintcount);
@@ -1196,13 +1417,19 @@ void replace_show_replacement_points(codeinfo *code)
                rp = code->rplpoints + i;
 
                assert(rp->code == code);
-               
-               printf("\t");
-               replace_replacement_point_println(rp);
+
+               depth = 1;
+               parent = rp->parent;
+               while (parent) {
+                       depth++;
+                       parent = parent->parent;
+               }
+               replace_replacement_point_println(rp, depth);
        }
 }
 #endif
 
+
 /* replace_executionstate_println **********************************************
  
    Print execution state
@@ -1212,40 +1439,44 @@ void replace_show_replacement_points(codeinfo *code)
   
 *******************************************************************************/
 
-#ifndef NDEBUG
-void replace_executionstate_println(executionstate *es)
+#if !defined(NDEBUG)
+void replace_executionstate_println(executionstate_t *es)
 {
        int i;
        int slots;
-#ifdef HAS_4BYTE_STACKSLOT
-       u4 *sp;
-#else
-       u8 *sp;
-#endif
+       stackslot_t *sp;
 
-       if (!es) {
-               printf("(executionstate *)NULL\n");
+       if (!es) {
+               printf("(executionstate_t *)NULL\n");
                return;
        }
 
-       printf("executionstate %p:\n",(void*)es);
-       printf("\tpc = %p\n",(void*)es->pc);
-       printf("\tsp = %p\n",(void*)es->sp);
-       printf("\tpv = %p\n",(void*)es->pv);
+       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) {
-               printf("\t%-3s = %016llx\n",regs[i],(unsigned long long)es->intregs[i]);
+               if (i%4 == 0)
+                       printf("\t");
+               else
+                       printf(" ");
+               printf("%-3s = %016llx",regs[i],(unsigned long long)es->intregs[i]);
+               if (i%4 == 3)
+                       printf("\n");
        }
        for (i=0; i<FLT_REG_CNT; ++i) {
-               printf("\tfltregs[%2d] = %016llx\n",i,(unsigned long long)es->fltregs[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");
        }
 #endif
 
-#ifdef HAS_4BYTE_STACKSLOT
-       sp = (u4*) es->sp;
-#else
-       sp = (u8*) es->sp;
-#endif
+       sp = (stackslot_t *) es->sp;
 
        if (es->code)
                slots = code_get_stack_frame_size(es->code);
@@ -1253,14 +1484,23 @@ void replace_executionstate_println(executionstate *es)
                slots = 0;
 
        if (slots) {
-               printf("\tstack slots(+1) at sp:\n");
+               printf("\tstack slots(+1) at sp:");
                for (i=0; i<slots+1; ++i) {
+                       if (i%4 == 0)
+                               printf("\n\t\t");
+                       else
+                               printf(" ");
+                       if (i >= slots)
+                               putchar('(');
 #ifdef HAS_4BYTE_STACKSLOT
-                       printf("\t\t%08lx\n",(unsigned long)*sp++);
+                       printf("%08lx",(unsigned long)*sp++);
 #else
-                       printf("\t\t%016llx\n",(unsigned long long)*sp++);
+                       printf("%016llx",(unsigned long long)*sp++);
 #endif
+                       if (i >= slots)
+                               putchar(')');
                }
+               printf("\n");
        }
 
        printf("\tcode: %p", (void*)es->code);
@@ -1303,91 +1543,87 @@ void java_value_print(s4 type, u8 value)
                printf(" %lld", (long long) value);
        }
 }
-#endif /* defined(NDEBUG) */
+#endif /* !defined(NDEBUG) */
 
-/* replace_sourcestate_println *************************************************
-   Print source state
-  
-   IN:
-       ss...............the source state to print
-  
-*******************************************************************************/
 
-#ifndef NDEBUG
-void replace_sourcestate_println(sourcestate *ss)
+#if !defined(NDEBUG)
+void replace_source_frame_println(sourceframe_t *frame)
 {
-       int i;
-       int t;
-       int reg;
-
-       if (!ss) {
-               printf("(sourcestate *)NULL\n");
-               return;
-       }
+       s4 i;
+       s4 t;
 
-       printf("sourcestate %p: stackbase=%p\n",(void*)ss,(void*)ss->stackbase);
+       printf("\t");
+       method_println(frame->method);
+       printf("\n");
 
-       printf("\tlocals (%d):\n",ss->javalocalcount);
-       for (i=0; i<ss->javalocalcount; ++i) {
-               t = ss->javalocaltype[i];
-               if (t == TYPE_VOID) {
-                       printf("\tlocal[ %2d] = void\n",i);
-               }
-               else {
-                       printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
-                       java_value_print(t, ss->javalocals[i]);
-                       printf("\n");
+       if (frame->javalocalcount) {
+               printf("\tlocals (%d):\n",frame->javalocalcount);
+               for (i=0; i<frame->javalocalcount; ++i) {
+                       t = frame->javalocaltype[i];
+                       if (t == TYPE_VOID) {
+                               printf("\tlocal[ %2d] = void\n",i);
+                       }
+                       else {
+                               printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
+                               java_value_print(t, frame->javalocals[i]);
+                               printf("\n");
+                       }
                }
+               printf("\n");
        }
 
-       printf("\n");
-
-       printf("\tstack (depth %d):\n",ss->javastackdepth);
-       for (i=0; i<ss->javastackdepth; ++i) {
-               printf("\tstack[%2d] = ",i);
-               java_value_print(ss->javastacktype[i], ss->javastack[i]);
+       if (frame->javastackdepth) {
+               printf("\tstack (depth %d):\n",frame->javastackdepth);
+               for (i=0; i<frame->javastackdepth; ++i) {
+                       printf("\tstack[%2d] = ",i);
+                       java_value_print(frame->javastacktype[i], frame->javastack[i]);
+                       printf("\n");
+               }
                printf("\n");
        }
 
-       printf("\n");
-
-       printf("\tsaved int registers (%d):\n",INT_SAV_CNT);
-       reg = INT_REG_CNT;
-       for (i=0; i<INT_SAV_CNT; ++i) {
-               while (nregdescint[--reg] != REG_SAV)
-                       ;
-               if (ss->savedintregs[i] != 0x00dead0000dead00ULL) {
-#if defined(ENABLE_DISASSEMBLER)
-                       printf("\t%-3s = ",regs[reg]);
+       if (frame->syncslotcount) {
+               printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
+               for (i=0; i<frame->syncslotcount; ++i) {
+                       printf("\tslot[%2d] = ",i);
+#ifdef HAS_4BYTE_STACKSLOT
+                       printf("%08lx\n",(unsigned long) frame->syncslots[i]);
+#else
+                       printf("%016llx\n",(unsigned long long) frame->syncslots[i]);
 #endif
-                       printf("%016llx\n",(unsigned long long) ss->savedintregs[i]);
                }
+               printf("\n");
        }
+}
+#endif /* !defined(NDEBUG) */
 
-       printf("\n");
 
-       printf("\tsaved float registers (%d):\n",FLT_SAV_CNT);
-       for (i=0; i<FLT_SAV_CNT; ++i) {
-               if (ss->savedfltregs[i] != 0x00dead0000dead00ULL) {
-                       printf("\tsavedfltreg[%2d] = ",i);
-                       printf("%016llx\n",(unsigned long long) ss->savedfltregs[i]);
-               }
+/* replace_sourcestate_println *************************************************
+   Print source state
+  
+   IN:
+       ss...............the source state to print
+  
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_sourcestate_println(sourcestate_t *ss)
+{
+       int i;
+       sourceframe_t *frame;
+
+       if (!ss) {
+               printf("(sourcestate_t *)NULL\n");
+               return;
        }
-       
-       printf("\n");
 
-       printf("\tsynchronization slots (%d):\n",ss->syncslotcount);
-       for (i=0; i<ss->syncslotcount; ++i) {
-               printf("\tslot[%2d] = ",i);
-#ifdef HAS_4BYTE_STACKSLOT
-               printf("%08lx\n",(unsigned long) ss->syncslots[i]);
-#else
-               printf("%016llx\n",(unsigned long long) ss->syncslots[i]);
-#endif
+       printf("sourcestate_t:\n");
+
+       for (i=0, frame = ss->frames; frame != NULL; frame = frame->up, ++i) {
+               printf("    frame %d:\n", i);
+               replace_source_frame_println(frame);
        }
-       
-       printf("\n");
 }
 #endif
 
index 15a7125fd7cdd5e4a9ca6a966f8f74e831836aaa..0cd6b2d10cd99e9cf4165205a51c9934465eaf30 100644 (file)
@@ -39,8 +39,9 @@
 /* forward typedefs ***********************************************************/
 
 typedef struct rplpoint rplpoint;
-typedef struct executionstate executionstate;
-typedef struct sourcestate sourcestate;
+typedef struct executionstate_t executionstate_t;
+typedef struct sourcestate_t sourcestate_t;
+typedef struct sourceframe_t sourceframe_t;
 
 #include "config.h"
 #include "vm/types.h"
@@ -70,24 +71,39 @@ struct rplalloc {
 #error value of INMEMORY is too big to fit in rplalloc.flags
 #endif
 
+
+/* XXX what to do about overlapping rplpoints? */
+#define RPLPOINT_TYPE_STD     BBTYPE_STD
+#define RPLPOINT_TYPE_EXH     BBTYPE_EXH
+#define RPLPOINT_TYPE_SBR     BBTYPE_SBR
+#define RPLPOINT_TYPE_CALL    3
+#define RPLPOINT_TYPE_INLINE  4
+#define RPLPOINT_TYPE_RETURN  5
+
+
 /* An `rplpoint` represents a replacement point in a compiled method  */
 
 struct rplpoint {
        u1          *pc;           /* machine code PC of this point       */
-       u1          *outcode;      /* pointer to replacement-out code     */
-       codeinfo    *code;         /* codeinfo this point belongs to      */
-       rplpoint    *target;       /* target of the replacement           */
-       u8           mcode;        /* saved maching code for patching     */
+       u1          *outcode;      /* pointer to replacement-out code     */ /* XXX only for trappable rps */
+       methodinfo  *method;       /* source method this point is in      */
+       rplpoint    *target;       /* target of the replacement           */ /* XXX remove? */
+       codeinfo    *code;         /* codeinfo this point belongs to      */ /* XXX unify with parent */
+       rplpoint    *parent;       /* rplpoint of the inlined body        */ /* XXX unify with code */
        rplalloc    *regalloc;     /* pointer to register index table     */
+       u8           mcode;        /* saved maching code for patching     */ /* XXX only for trappable rps */
+       s4           id;           /* id of the rplpoint within method    */
+       s4           callsize;     /* size of call code in bytes          */
        unsigned int regalloccount:24; /* number of local allocations     */
-       unsigned int type:4;           /* BBTYPE_... constant             */
+       unsigned int type:4;           /* RPLPOINT_TYPE_... constant      */
        unsigned int flags:8;          /* OR of RPLPOINT_... constants    */
 };
 
+
 /* An `executionsstate` represents the state of a thread as it reached */
 /* an replacement point or is about to enter one.                      */
 
-struct executionstate {
+struct executionstate_t {
        u1           *pc;                               /* program counter */
        u1           *sp;                   /* stack pointer within method */
        u1           *pv;                   /* procedure value. NULL means */
@@ -96,29 +112,34 @@ struct executionstate {
        u8            intregs[INT_REG_CNT];             /* register values */
        u8            fltregs[FLT_REG_CNT];             /* register values */
 
-       codeinfo     *code;
+       codeinfo     *code;            /* codeinfo corresponding to the pv */
 };
 
-/* `sourcestate` will probably only be used for debugging              */
 
-struct sourcestate {
-       u8           *javastack;
-       u1           *javastacktype;
-       s4            javastackdepth;
+struct sourceframe_t {
+       sourceframe_t *up;                  /* source frame above this one */
 
-       u8           *javalocals;
-       u1           *javalocaltype;
-       s4            javalocalcount;
+       methodinfo    *method;                  /* method this frame is in */
+       s4             id;
 
-       u8            savedintregs[INT_SAV_CNT + 1]; /* XXX */
-       u8            savedfltregs[FLT_SAV_CNT + 1]; /* XXX */
+       u8            *javastack;                  /* values of stack vars */
+       u1            *javastacktype;              /*  types of stack vars */
+       s4             javastackdepth;             /* number of stack vars */
 
-       u8           *syncslots;
-       s4            syncslotcount;
+       u8            *javalocals;                 /* values of javalocals */
+       u1            *javalocaltype;              /*  types of javalocals */
+       s4             javalocalcount;             /* number of javalocals */
 
-       u1           *stackbase;
+       u8            *syncslots;
+       s4             syncslotcount; /* XXX do we need more than one? */
 };
 
+
+struct sourcestate_t {
+       sourceframe_t *frames;    /* list of source frames, from bottom up */
+};
+
+
 /*** prototypes ********************************************************/
 
 bool replace_create_replacement_points(jitdata *jd);
@@ -128,16 +149,16 @@ void replace_activate_replacement_point(rplpoint *rp,rplpoint *target);
 void replace_deactivate_replacement_point(rplpoint *rp);
 void replace_activate(codeinfo *code,codeinfo *target);
 
-void replace_pop_activation_record(executionstate *es,
-                                                                  sourcestate *ss);
+bool replace_pop_activation_record(executionstate_t *es);
 
-void replace_me(rplpoint *rp,executionstate *es);
+void replace_me(rplpoint *rp,executionstate_t *es);
 
-#ifndef NDEBUG
+#if !defined(NDEBUG)
 void replace_show_replacement_points(codeinfo *code);
-void replace_replacement_point_println(rplpoint *rp);
-void replace_executionstate_println(executionstate *es);
-void replace_sourcestate_println(sourcestate *ss);
+void replace_replacement_point_println(rplpoint *rp, int depth);
+void replace_executionstate_println(executionstate_t *es);
+void replace_sourcestate_println(sourcestate_t *ss);
+void replace_source_frame_println(sourceframe_t *frame);
 #endif
 
 /* machine dependent functions (code in ARCH_DIR/md.c) */
index 1dd2fd34e3263c826bb0979a684a900cce926a61..9655b00ca7fe1544d9a8e487af6f155f81d8e136 100644 (file)
@@ -66,6 +66,13 @@ static java_objectheader *show_global_lock;
 #endif
 
 
+/* prototypes *****************************************************************/
+
+#if !defined(NDEBUG)
+static void show_variable_intern(jitdata *jd, s4 index, int stage);
+#endif
+
+
 /* show_init *******************************************************************
 
    Initialized the show subsystem (called by jit_init).
@@ -325,7 +332,7 @@ void show_method(jitdata *jd, int stage)
 #else
                        printf("    M%02d = 0x%02x(sp): ", i, i * 8);
 #endif
-                       for (j = 0; j < jd->varcount; ++j) {
+                       for (j = 0; j < jd->vartop; ++j) {
                                varinfo *v = VAR(j);
                                if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
                                        show_variable(jd, j, irstage);
@@ -389,6 +396,36 @@ void show_method(jitdata *jd, int stage)
 #endif /* !defined(NDEBUG) */
 
 
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
+{
+       s4 *jl;
+       s4 n;
+
+       printf("(pt %d+%d st ", ii->throughcount - ii->stackvarscount,
+                       ii->stackvarscount);
+       show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
+
+       if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
+               printf(" jl ");
+               jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
+               n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
+               show_variable_array(jd, jl, n, stage);
+       }
+
+       printf(") ");
+
+#if 0
+       printf("(");
+       method_print(ii->outer);
+       printf(" ==> ");
+#endif
+
+       method_print(ii->method);
+}
+#endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
+
+
 /* show_basicblock *************************************************************
 
    Print the intermediate representation of a basic block.
@@ -478,10 +515,18 @@ void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
                        printf("IN:  ");
                        show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
                        printf(" javalocals: ");
-                       show_variable_array(jd, bptr->javalocals, jd->maxlocals, irstage);
+                       show_variable_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
                        printf("\n");
                }
 
+#if defined(ENABLE_INLINING)
+               if (bptr->inlineinfo) {
+                       printf("inlineinfo: ");
+                       show_inline_info(jd, bptr->inlineinfo, -1, irstage);
+                       printf("\n");
+               }
+#endif /* defined(ENABLE_INLINING) */
+
                iptr = bptr->iinstr;
 
                for (i = 0; i < bptr->icount; i++, iptr++) {
@@ -741,12 +786,18 @@ void show_allocation(s4 type, s4 flags, s4 regoff)
 }
 
 void show_variable(jitdata *jd, s4 index, int stage)
+{
+       show_variable_intern(jd, index, stage);
+       putchar(' ');
+}
+
+static void show_variable_intern(jitdata *jd, s4 index, int stage)
 {
        char type;
        char kind;
        varinfo *v;
 
-       if (index < 0 || index >= jd->varcount) {
+       if (index < 0 || index >= jd->vartop) {
                printf("<INVALID INDEX:%d>", index);
                return;
        }
@@ -790,8 +841,6 @@ void show_variable(jitdata *jd, s4 index, int stage)
                show_allocation(v->type, v->flags, v->vv.regoff);
                putchar(')');
        }
-       putchar(' ');
-       fflush(stdout);
 }
 
 void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
@@ -806,11 +855,11 @@ void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
        printf("[");
        for (i=0; i<n; ++i) {
                if (i)
-                       printf(" ");
+                       putchar(' ');
                if (vars[i] == UNUSED)
                        putchar('-');
                else
-                       show_variable(jd, vars[i], stage);
+                       show_variable_intern(jd, vars[i], stage);
        }
        printf("]");
 }
@@ -1140,11 +1189,7 @@ void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
 #if defined(ENABLE_INLINING)
                {
                        insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
-                       printf("(");
-                       method_print(ii->outer);
-                       printf(" ==> ");
-                       method_print(ii->method);
-                       printf(")");
+                       show_inline_info(jd, ii, opcode, stage);
                }
 #endif
                break;
@@ -1318,7 +1363,6 @@ void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
                }
                break;
 
-       case ICMD_ARETURN:
        case ICMD_FRETURN:
        case ICMD_IRETURN:
        case ICMD_DRETURN:
@@ -1326,8 +1370,15 @@ void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
                SHOW_S1(iptr);
                break;
 
+       case ICMD_ARETURN:
        case ICMD_ATHROW:
                SHOW_S1(iptr);
+               if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+                       /* XXX this needs more work */
+#if 0
+                       unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
+#endif
+               }
                break;
 
        case ICMD_COPY:
index f738b46bc60205268c7cc34b9364c861a7178124..12227a19053d0638d0af3250f68c15b8948f8aa6 100644 (file)
@@ -28,7 +28,7 @@
 
    Changes: Edwin Steiner
 
-   $Id: genoffsets.c 4643 2006-03-16 18:38:42Z edwin $
+   $Id: genoffsets.c 5950 2006-11-11 17:08:14Z edwin $
 
 */
 
@@ -58,7 +58,7 @@ int main(int argc, char **argv)
 
        printf("#define sizevmarg                  %3d\n", (s4) sizeof(vm_arg));
        printf("#define sizestackframeinfo         %3d\n", (s4) sizeof(stackframeinfo));
-       printf("#define sizeexecutionstate         %3d\n", (s4) sizeof(executionstate));
+       printf("#define sizeexecutionstate         %3d\n", (s4) sizeof(executionstate_t));
 
     printf("\n\n/* define some offsets */\n\n");
 
@@ -82,11 +82,11 @@ int main(int argc, char **argv)
        printf("#define offcast_super_diffval      %3d\n", (s4) OFFSET(castinfo, super_diffval));
        printf("#define offcast_sub_baseval        %3d\n", (s4) OFFSET(castinfo, sub_baseval));
 
-       printf("#define offes_pc                   %3d\n", (s4) OFFSET(executionstate, pc));
-       printf("#define offes_sp                   %3d\n", (s4) OFFSET(executionstate, sp));
-       printf("#define offes_pv                   %3d\n", (s4) OFFSET(executionstate, pv));
-       printf("#define offes_intregs              %3d\n", (s4) OFFSET(executionstate, intregs));
-       printf("#define offes_fltregs              %3d\n", (s4) OFFSET(executionstate, fltregs));
+       printf("#define offes_pc                   %3d\n", (s4) OFFSET(executionstate_t, pc));
+       printf("#define offes_sp                   %3d\n", (s4) OFFSET(executionstate_t, sp));
+       printf("#define offes_pv                   %3d\n", (s4) OFFSET(executionstate_t, pv));
+       printf("#define offes_intregs              %3d\n", (s4) OFFSET(executionstate_t, intregs));
+       printf("#define offes_fltregs              %3d\n", (s4) OFFSET(executionstate_t, fltregs));
 
        /* everything is ok */