PR148 again: don't defuse IF_LCMPxx
[cacao.git] / src / vm / jit / stack.c
index eaa452e25f8060b93d6881f0b85cf91f40a8d8d4..40810e0d22ddf122b2e81a3b5b8131987b116a74 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/jit/stack.c - stack analysis
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-
-   Changes: Edwin Steiner
-            Christian Thalinger
-            Christian Ullrich
-
-   $Id: stack.c 5902 2006-11-04 22:40:13Z edwin $
-
 */
 
 
 #include "arch.h"
 #include "md-abi.h"
 
-#include "mm/memory.h"
+#include "mm/memory.hpp"
 
-#include "native/native.h"
+#include "native/native.hpp"
 
-#include "toolbox/logging.h"
+#include "toolbox/logging.hpp"
 
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
 #include "vm/global.h"
-#include "vm/builtin.h"
 #include "vm/options.h"
-#include "vm/resolve.h"
-#include "vm/statistics.h"
-#include "vm/stringlocal.h"
+#include "vm/resolve.hpp"
+#include "vm/string.hpp"
 #include "vm/types.h"
 
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
 #include "vm/jit/abi.h"
 #include "vm/jit/cfg.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/parse.hpp"
+#include "vm/jit/show.hpp"
 
 #if defined(ENABLE_DISASSEMBLER)
 # include "vm/jit/disass.h"
 #endif
 
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
 #include "vm/jit/stack.h"
 
+#if 0
 #if defined(ENABLE_SSA)
 # include "vm/jit/optimizing/lsra.h"
 # include "vm/jit/optimizing/ssa.h"
 #elif defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
 #endif
+#endif
 
 /*#define STACK_VERBOSE*/
 
@@ -99,9 +93,6 @@
 #endif
 
 
-#define MIN(a,b)  (((a) < (b)) ? (a) : (b))
-
-
 /* For returnAddresses we use a field of the typeinfo to store from which  */
 /* subroutine the returnAddress will return, if used.                      */
 /* XXX It would be nicer to use typeinfo.typeclass, but the verifier seems */
@@ -122,19 +113,21 @@ typedef struct stackdata_t stackdata_t;
 
 struct stackdata_t {
     basicblock *bptr;             /* the current basic block being analysed   */
-    stackptr new;                 /* next free stackelement                   */
+    stackelement_t *new;          /* next free stackelement                   */
     s4 vartop;                    /* next free variable index                 */
     s4 localcount;                /* number of locals (at the start of var)   */
     s4 varcount;                  /* maximum number of variables expected     */
        s4 varsallocated;             /* total number of variables allocated      */
+       s4 maxlocals;                 /* max. number of Java locals               */
     varinfo *var;                 /* variable array (same as jd->var)         */
+       s4 *javalocals;               /* map from Java locals to jd->var indices  */
        methodinfo *m;                /* the method being analysed                */
        jitdata *jd;                  /* current jitdata                          */
        basicblock *last_real_block;  /* the last block before the empty one      */
        bool repeat;                  /* if true, iterate the analysis again      */
        exception_entry **handlers;   /* exception handlers for the current block */
        exception_entry *extableend;  /* points to the last exception entry       */
-       stackelement exstack;         /* instack for exception handlers           */
+       stackelement_t exstack;         /* instack for exception handlers           */
 };
 
 
@@ -324,15 +317,18 @@ struct stackdata_t {
 #if defined(ENABLE_VERIFIER)
 #define COPY_VAL_AND_TYPE_VAR(sv, dv)                                \
     do {                                                             \
-        (dv)->type = (sv)->type;                                     \
-        (dv)->vv  = (sv)->vv;                                        \
-        (dv)->SBRSTART = (sv)->SBRSTART;                             \
+        if (((dv)->type = (sv)->type) == TYPE_RET) {                 \
+            (dv)->vv  = (sv)->vv;                                    \
+            (dv)->SBRSTART = (sv)->SBRSTART;                         \
+        }                                                            \
     } while (0)
 #else
 #define COPY_VAL_AND_TYPE_VAR(sv, dv)                                \
     do {                                                             \
         (dv)->type = (sv)->type;                                     \
-        (dv)->vv  = (sv)->vv;                                        \
+        if (((dv)->type = (sv)->type) == TYPE_RET) {                 \
+            (dv)->vv  = (sv)->vv;                                    \
+        }                                                            \
     } while (0)
 #endif
 
@@ -493,7 +489,7 @@ struct stackdata_t {
 
 #define BRANCH_TARGET(bt, tempbptr)                                  \
     do {                                                             \
-        tempbptr = BLOCK_OF((bt).insindex);                          \
+        tempbptr = (bt).block;                                       \
         tempbptr = stack_mark_reached(&sd, tempbptr, curstack,       \
                                       stackdepth);                   \
         if (tempbptr == NULL)                                        \
@@ -508,7 +504,7 @@ struct stackdata_t {
 /* forward declarations *******************************************************/
 
 static void stack_create_invars(stackdata_t *sd, basicblock *b, 
-                                                               stackptr curstack, int stackdepth);
+                                                               stackelement_t * curstack, int stackdepth);
 static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b);
 
 #if defined(STACK_VERBOSE)
@@ -517,6 +513,8 @@ static void stack_verbose_show_variable(stackdata_t *sd, s4 index);
 static void stack_verbose_show_block(stackdata_t *sd, basicblock *bptr);
 static void stack_verbose_block_enter(stackdata_t *sd, bool reanalyse);
 static void stack_verbose_block_exit(stackdata_t *sd, bool superblockend);
+static void stack_verbose_show_state(stackdata_t *sd, instruction *iptr, 
+                                                                        stackelement_t * curstack);
 #endif
 
 
@@ -619,6 +617,7 @@ static basicblock * stack_clone_block(stackdata_t *sd, basicblock *b)
 
        clone->iinstr = NULL;
        clone->inlocals = NULL;
+       clone->javalocals = NULL;
        clone->invars = NULL;
 
        clone->original = (b->original) ? b->original : b;
@@ -641,6 +640,89 @@ static basicblock * stack_clone_block(stackdata_t *sd, basicblock *b)
 }
 
 
+/* stack_create_locals *********************************************************
+   Create the local variables for the start of the given basic block.
+
+   IN:
+      sd...........stack analysis data
+         b............block to create the locals for
+
+*******************************************************************************/
+
+static void stack_create_locals(stackdata_t *sd, basicblock *b)
+{
+       s4       i;
+       s4      *jl;
+       varinfo *dv;
+
+       /* copy the current state of the local variables */
+       /* (one extra local is needed by the verifier)   */
+
+       dv = DMNEW(varinfo, sd->localcount + VERIFIER_EXTRA_LOCALS);
+       b->inlocals = dv;
+       for (i=0; i<sd->localcount; ++i)
+               *dv++ = sd->var[i];
+
+       /* the current map from java locals to cacao variables */
+
+       jl = DMNEW(s4, sd->maxlocals);
+       b->javalocals = jl;
+       MCOPY(jl, sd->javalocals, s4, sd->maxlocals);
+}
+
+
+/* stack_merge_locals **********************************************************
+   Merge local variables at the beginning of the given basic block.
+
+   IN:
+      sd...........stack analysis data
+         b............the block that is reached
+
+*******************************************************************************/
+
+static void stack_merge_locals(stackdata_t *sd, basicblock *b)
+{
+       s4 i;
+       varinfo *dv;
+       varinfo *sv;
+
+       /* If a javalocal is mapped to different cacao locals along the */
+       /* incoming control-flow edges, it becomes undefined.           */
+
+       for (i=0; i<sd->maxlocals; ++i) {
+               if (b->javalocals[i] != UNUSED && b->javalocals[i] != sd->javalocals[i]) {
+                       b->javalocals[i] = UNUSED;
+                       if (b->flags >= BBFINISHED)
+                               b->flags = BBTYPECHECK_REACHED;
+                       if (b->nr <= sd->bptr->nr)
+                               sd->repeat = true;
+               }
+       }
+
+#if defined(ENABLE_VERIFIER)
+       if (b->inlocals) {
+               for (i=0; i<sd->localcount; ++i) {
+                       dv = b->inlocals + i;
+                       sv = sd->var + i;
+                       if ((sv->type == TYPE_RET && dv->type == TYPE_RET)
+                                       && (sv->SBRSTART != dv->SBRSTART))
+                       {
+#if defined(STACK_VERBOSE)
+                               printf("JSR MISMATCH: setting variable %d to VOID\n", i);
+#endif
+                               dv->type = TYPE_VOID;
+                               if (b->flags >= BBFINISHED)
+                                       b->flags = BBTYPECHECK_REACHED;
+                               sd->repeat = true; /* This is very rare, so just repeat */
+                       }
+               }
+       }
+#endif /* defined(ENABLE_VERIFIER) */
+}
+
+
 /* stack_create_invars *********************************************************
 
    Create the invars for the given basic block. Also make a copy of the locals.
@@ -657,9 +739,9 @@ static basicblock * stack_clone_block(stackdata_t *sd, basicblock *b)
 *******************************************************************************/
 
 static void stack_create_invars(stackdata_t *sd, basicblock *b, 
-                                                               stackptr curstack, int stackdepth)
+                                                               stackelement_t * curstack, int stackdepth)
 {
-       stackptr sp;
+       stackelement_t * sp;
        int i;
        int index;
        varinfo *dv;
@@ -682,13 +764,7 @@ static void stack_create_invars(stackdata_t *sd, basicblock *b,
                COPY_VAL_AND_TYPE_VAR(sv, dv);
        }
 
-       /* copy the current state of the local variables */
-       /* (one extra local is needed by the verifier)   */
-
-       dv = DMNEW(varinfo, sd->localcount + VERIFIER_EXTRA_LOCALS);
-       b->inlocals = dv;
-       for (i=0; i<sd->localcount; ++i)
-               *dv++ = sd->var[i];
+       stack_create_locals(sd, b);
 }
 
 
@@ -728,13 +804,7 @@ static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b)
                }
        }
 
-       /* copy the current state of the local variables */
-       /* (one extra local is needed by the verifier)   */
-
-       dv = DMNEW(varinfo, sd->localcount + VERIFIER_EXTRA_LOCALS);
-       b->inlocals = dv;
-       for (i=0; i<sd->localcount; ++i)
-               *dv++ = sd->var[i];
+       stack_create_locals(sd, b);
 }
 
 
@@ -756,10 +826,10 @@ static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b)
 *******************************************************************************/
 
 static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
-                                                                          stackptr curstack, int stackdepth)
+                                                                          stackelement_t * curstack, int stackdepth)
 {
        int i;
-       stackptr sp;
+       stackelement_t * sp;
        basicblock *orig;
        bool separable;
        varinfo *sv;
@@ -840,24 +910,9 @@ static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
                }
 
                if (!separable) {
-                       /* XXX mark mixed type variables void */
                        /* XXX cascading collapse? */
-#if defined(ENABLE_VERIFIER)
-                       if (b->inlocals) {
-                               for (i=0; i<sd->localcount; ++i) {
-                                       dv = b->inlocals + i;
-                                       sv = sd->var + i;
-                                       if ((sv->type == TYPE_RET && dv->type == TYPE_RET)
-                                               && (sv->SBRSTART != dv->SBRSTART))
-                                       {
-                                               dv->type = TYPE_VOID;
-                                               if (b->flags >= BBFINISHED)
-                                                       b->flags = BBTYPECHECK_REACHED;
-                                               sd->repeat = true; /* This is very rare, so just repeat */
-                                       }
-                               }
-                       }
-#endif
+
+                       stack_merge_locals(sd, b);
 
 #if defined(STACK_VERBOSE)
                        printf("------> using L%03d\n", b->nr);
@@ -976,24 +1031,9 @@ static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock
                }
 
                if (!separable) {
-                       /* XXX mark mixed type variables void */
                        /* XXX cascading collapse? */
-#if defined(ENABLE_VERIFIER)
-                       if (b->inlocals) {
-                               for (i=0; i<sd->localcount; ++i) {
-                                       dv = b->inlocals + i;
-                                       sv = sd->var + i;
-                                       if ((sv->type == TYPE_RET && dv->type == TYPE_RET)
-                                                       && (sv->SBRSTART != dv->SBRSTART))
-                                       {
-                                               dv->type = TYPE_VOID;
-                                               if (b->flags >= BBFINISHED)
-                                                       b->flags = BBTYPECHECK_REACHED;
-                                               sd->repeat = true; /* This is very rare, so just repeat */
-                                       }
-                               }
-                       }
-#endif
+
+                       stack_merge_locals(sd, b);
 
 #if defined(STACK_VERBOSE)
                        printf("------> using L%03d\n", b->nr);
@@ -1023,9 +1063,9 @@ static basicblock * stack_check_invars_from_outvars(stackdata_t *sd, basicblock
 
 *******************************************************************************/
 
-static stackptr stack_create_instack(stackdata_t *sd)
+static stackelement_t * stack_create_instack(stackdata_t *sd)
 {
-    stackptr sp;
+    stackelement_t * sp;
        int depth;
        int index;
 
@@ -1069,13 +1109,17 @@ static stackptr stack_create_instack(stackdata_t *sd)
 
 *******************************************************************************/
 
-static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackptr curstack, int stackdepth) 
+static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackelement_t * curstack, int stackdepth) 
 {
+       assert(b != NULL);
+
 #if defined(STACK_VERBOSE)
        printf("stack_mark_reached(L%03d from L%03d)\n", b->nr, sd->bptr->nr);
 #endif
+
        /* mark targets of backward branches */
-       if (b <= sd->bptr)
+
+       if (b->nr <= sd->bptr->nr)
                b->bitflags |= BBFLAG_REPLACEMENT;
 
        if (b->flags < BBREACHED) {
@@ -1117,11 +1161,15 @@ static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackptr c
 
 static basicblock *stack_mark_reached_from_outvars(stackdata_t *sd, basicblock *b)
 {
+       assert(b != NULL);
+
 #if defined(STACK_VERBOSE)
        printf("stack_mark_reached_from_outvars(L%03d from L%03d)\n", b->nr, sd->bptr->nr);
 #endif
+
        /* mark targets of backward branches */
-       if (b <= sd->bptr)
+
+       if (b->nr <= sd->bptr->nr)
                b->bitflags |= BBFLAG_REPLACEMENT;
 
        if (b->flags < BBREACHED) {
@@ -1147,9 +1195,10 @@ static basicblock *stack_mark_reached_from_outvars(stackdata_t *sd, basicblock *
 
 /* stack_reach_next_block ******************************************************
 
-   Mark the following block reached and propagate the outvars of the current block
-   and the current locals to it. This function specializes the target block, 
-   if necessary, and returns a pointer to the specialized target.
+   Mark the following block reached and propagate the outvars of the
+   current block and the current locals to it.  This function
+   specializes the target block, if necessary, and returns a pointer
+   to the specialized target.
 
    IN:
       sd...........stack analysis data
@@ -1167,7 +1216,8 @@ static bool stack_reach_next_block(stackdata_t *sd)
 
        tbptr = (sd->bptr->original) ? sd->bptr->original : sd->bptr;
        tbptr = stack_mark_reached_from_outvars(sd, tbptr->next);
-       if (!tbptr)
+
+       if (tbptr == NULL)
                return false;
 
        if (tbptr != sd->bptr->next) {
@@ -1178,6 +1228,9 @@ static bool stack_reach_next_block(stackdata_t *sd)
                assert(iptr->opc == ICMD_NOP);
                iptr->opc = ICMD_GOTO;
                iptr->dst.block = tbptr;
+#if defined(STACK_VERBOSE)
+               if (iptr->line == 0) printf("goto with line 0 in L%03d\n", sd->bptr->nr);
+#endif
 
                if (tbptr->flags < BBFINISHED)
                        sd->repeat = true; /* XXX check if we really need to repeat */
@@ -1264,7 +1317,7 @@ bool stack_reanalyse_block(stackdata_t *sd)
        s4 blockvarstart;
        s4 invarshift;
        s4 blockvarshift;
-       s4 i, j;
+       s4 i, varindex;
        s4 *argp;
        branch_target_t *table;
        lookup_target_t *lookup;
@@ -1292,6 +1345,8 @@ bool stack_reanalyse_block(stackdata_t *sd)
 
                MCOPY(iptr, orig->iinstr, instruction, len);
                iptr[len].opc = ICMD_NOP;
+               iptr[len].line = 0;
+               iptr[len].flags.bits = 0;
                b->iinstr = iptr;
                b->icount = ++len;
 
@@ -1384,6 +1439,8 @@ bool stack_reanalyse_block(stackdata_t *sd)
        if (b->inlocals)
                MCOPY(sd->var, b->inlocals, varinfo, sd->localcount);
 
+       MCOPY(sd->javalocals, b->javalocals, s4, sd->maxlocals);
+
        /* reach exception handlers for this block */
 
        if (!stack_reach_handlers(sd))
@@ -1399,16 +1456,16 @@ bool stack_reanalyse_block(stackdata_t *sd)
 
                switch (iptr->opc) {
                        case ICMD_RET:
-                               j = iptr->s1.varindex;
+                               varindex = iptr->s1.varindex;
 
 #if defined(ENABLE_VERIFIER)
-                               if (sd->var[j].type != TYPE_RET) {
+                               if (sd->var[varindex].type != TYPE_RET) {
                                        exceptions_throw_verifyerror(sd->m, "RET with non-returnAddress value");
                                        return false;
                                }
 #endif
 
-                               iptr->dst.block = stack_mark_reached_from_outvars(sd, sd->var[j].vv.retaddr);
+                               iptr->dst.block = stack_mark_reached_from_outvars(sd, sd->var[varindex].vv.retaddr);
                                superblockend = true;
                                break;
 
@@ -1428,9 +1485,6 @@ bool stack_reanalyse_block(stackdata_t *sd)
 
                        case ICMD_NOP:
                        case ICMD_IINC:
-                       case ICMD_INLINE_START:
-                       case ICMD_INLINE_END:
-                       case ICMD_INLINE_GOTO:
                                break;
 
                        case ICMD_GOTO:
@@ -1495,8 +1549,20 @@ bool stack_reanalyse_block(stackdata_t *sd)
                        case ICMD_ASTORE:
                                RELOCATE(iptr->s1.varindex);
 
-                               j = iptr->dst.varindex;
-                               COPY_VAL_AND_TYPE(*sd, iptr->s1.varindex, j);
+                               varindex = iptr->dst.varindex;
+                               COPY_VAL_AND_TYPE(*sd, iptr->s1.varindex, varindex);
+                               i = iptr->sx.s23.s3.javaindex;
+                               if (iptr->flags.bits & INS_FLAG_RETADDR) {
+                                       iptr->sx.s23.s2.retaddrnr =
+                                               JAVALOCAL_FROM_RETADDR(sd->var[varindex].vv.retaddr->nr);
+                                       sd->javalocals[i] = iptr->sx.s23.s2.retaddrnr;
+                               }
+                               else
+                                       sd->javalocals[i] = varindex;
+                               if (iptr->flags.bits & INS_FLAG_KILL_PREV)
+                                       sd->javalocals[i-1] = UNUSED;
+                               if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
+                                       sd->javalocals[i+1] = UNUSED;
                                break;
 
                                /* pop 1 push 0 */
@@ -1601,32 +1667,6 @@ bool stack_reanalyse_block(stackdata_t *sd)
                        case ICMD_IF_LCMPGT:
                        case ICMD_IF_LCMPLE:
 
-                       case ICMD_IF_FCMPEQ:
-                       case ICMD_IF_FCMPNE:
-
-                       case ICMD_IF_FCMPL_LT:
-                       case ICMD_IF_FCMPL_GE:
-                       case ICMD_IF_FCMPL_GT:
-                       case ICMD_IF_FCMPL_LE:
-
-                       case ICMD_IF_FCMPG_LT:
-                       case ICMD_IF_FCMPG_GE:
-                       case ICMD_IF_FCMPG_GT:
-                       case ICMD_IF_FCMPG_LE:
-
-                       case ICMD_IF_DCMPEQ:
-                       case ICMD_IF_DCMPNE:
-
-                       case ICMD_IF_DCMPL_LT:
-                       case ICMD_IF_DCMPL_GE:
-                       case ICMD_IF_DCMPL_GT:
-                       case ICMD_IF_DCMPL_LE:
-
-                       case ICMD_IF_DCMPG_LT:
-                       case ICMD_IF_DCMPG_GE:
-                       case ICMD_IF_DCMPG_GT:
-                       case ICMD_IF_DCMPG_LE:
-
                        case ICMD_IF_ACMPEQ:
                        case ICMD_IF_ACMPNE:
                                RELOCATE(iptr->sx.s23.s2.varindex);
@@ -1789,9 +1829,8 @@ bool stack_reanalyse_block(stackdata_t *sd)
                                break;
 
                        default:
-                               *exceptionptr =
-                                       new_internalerror("Unknown ICMD %d during stack re-analysis",
-                                                       iptr->opc);
+                               exceptions_throw_internalerror("Unknown ICMD %d during stack re-analysis",
+                                                                                          iptr->opc);
                                return false;
                } /* switch */
 
@@ -1839,13 +1878,14 @@ bool stack_reanalyse_block(stackdata_t *sd)
 
 *******************************************************************************/
 
-static void stack_change_to_tempvar(stackdata_t *sd, stackptr sp, 
+static void stack_change_to_tempvar(stackdata_t *sd, stackelement_t * sp, 
                                                                        instruction *ilimit)
 {
        s4 newindex;
        s4 oldindex;
        instruction *iptr;
-       int i;
+       s4 depth;
+       s4 i;
 
        oldindex = sp->varnum;
 
@@ -1870,10 +1910,21 @@ static void stack_change_to_tempvar(stackdata_t *sd, stackptr sp,
        if (sp->flags & PASSTHROUGH) {
                iptr = (sp->creator) ? (sp->creator + 1) : sd->bptr->iinstr;
 
-               /* asser that the limit point to an ICMD, or after the last one */
+               /* assert that the limit points to an ICMD, or after the last one */
+
                assert(ilimit >= sd->bptr->iinstr);
                assert(ilimit <= sd->bptr->iinstr + sd->bptr->icount);
 
+               /* find the stackdepth under sp plus one */
+               /* Note: This number is usually known when this function is called, */
+               /* but calculating it here is less error-prone and should not be    */
+               /* a performance problem.                                           */
+
+               for (depth = 0; sp != NULL; sp = sp->prev)
+                       depth++;
+
+               /* iterate over all instructions in the range and replace */
+
                for (; iptr < ilimit; ++iptr) {
                        switch (iptr->opc) {
                                case ICMD_INVOKESTATIC:
@@ -1881,11 +1932,10 @@ static void stack_change_to_tempvar(stackdata_t *sd, stackptr sp,
                                case ICMD_INVOKEVIRTUAL:
                                case ICMD_INVOKEINTERFACE:
                                case ICMD_BUILTIN:
-
-                                       for (i=0; i<iptr->s1.argcount; ++i)
-                                               if (iptr->sx.s23.s2.args[i] == oldindex) {
-                                                       iptr->sx.s23.s2.args[i] = newindex;
-                                               }
+                                       i = iptr->s1.argcount - depth;
+                                       if (iptr->sx.s23.s2.args[i] == oldindex) {
+                                               iptr->sx.s23.s2.args[i] = newindex;
+                                       }
                                        break;
                                /* IMPORTANT: If any ICMD sets the PASSTHROUGH flag of a */
                                /* stackslot, it must be added in this switch!           */
@@ -1895,6 +1945,42 @@ static void stack_change_to_tempvar(stackdata_t *sd, stackptr sp,
 }
 
 
+/* stack_init_javalocals *******************************************************
+   Initialize the mapping from Java locals to cacao variables at method entry.
+
+   IN:
+      sd...........stack analysis data
+
+*******************************************************************************/
+
+static void stack_init_javalocals(stackdata_t *sd)
+{
+       s4         *jl;
+       s4          type,i,j;
+       methoddesc *md;
+       jitdata    *jd;
+
+       jd = sd->jd;
+
+       jl = DMNEW(s4, sd->maxlocals);
+       jd->basicblocks[0].javalocals = jl;
+
+       for (i=0; i<sd->maxlocals; ++i)
+               jl[i] = UNUSED;
+
+       md = jd->m->parseddesc;
+       j = 0;
+       for (i=0; i<md->paramcount; ++i) {
+               type = md->paramtypes[i].type;
+               jl[j] = jd->local_map[5*j + type];
+               j++;
+               if (IS_2_WORD_TYPE(type))
+                       j++;
+       }
+}
+
+
 /* stack_analyse ***************************************************************
 
    Analyse_stack uses the intermediate code created by parse.c to
@@ -1922,17 +2008,16 @@ static void stack_change_to_tempvar(stackdata_t *sd, stackptr sp,
 bool stack_analyse(jitdata *jd)
 {
        methodinfo   *m;              /* method being analyzed                    */
+       codeinfo     *code;
        registerdata *rd;
        stackdata_t   sd;
-#if defined(ENABLE_SSA)
-       lsradata     *ls;
-#endif
        int           stackdepth;
-       stackptr      curstack;       /* current stack top                        */
-       stackptr      copy;
+       stackelement_t *curstack;       /* current stack top                        */
+       stackelement_t *copy;
        int           opcode;         /* opcode of current instruction            */
-       int           i, j;
+       int           i, varindex;
        int           javaindex;
+       int           type;           /* operand type                             */
        int           len;            /* # of instructions after the current one  */
        bool          superblockend;  /* if true, no fallthrough to next block    */
        bool          deadcode;       /* true if no live code has been reached    */
@@ -1941,10 +2026,10 @@ bool stack_analyse(jitdata *jd)
        basicblock   *original;
        exception_entry *ex;
 
-       stackptr     *last_store_boundary;
-       stackptr      coalescing_boundary;
+       stackelement_t **last_store_boundary;
+       stackelement_t *coalescing_boundary;
 
-       stackptr      src1, src2, src3, src4, dst1, dst2;
+       stackelement_t *src1, *src2, *src3, *src4, *dst1, *dst2;
 
        branch_target_t *table;
        lookup_target_t *lookup;
@@ -1966,10 +2051,8 @@ bool stack_analyse(jitdata *jd)
        /* get required compiler data - initialization */
 
        m    = jd->m;
+       code = jd->code;
        rd   = jd->rd;
-#if defined(ENABLE_SSA)
-       ls   = jd->ls;
-#endif
 
        /* initialize the stackdata_t struct */
 
@@ -1980,6 +2063,8 @@ bool stack_analyse(jitdata *jd)
        sd.localcount = jd->localcount;
        sd.var = jd->var;
        sd.varsallocated = sd.varcount;
+       sd.maxlocals = m->maxlocals;
+       sd.javalocals = DMNEW(s4, sd.maxlocals);
        sd.handlers = DMNEW(exception_entry *, jd->exceptiontablelength + 1);
 
        /* prepare the variable for exception handler stacks               */
@@ -1990,10 +2075,6 @@ bool stack_analyse(jitdata *jd)
        sd.exstack.varnum = sd.localcount;
        sd.var[sd.exstack.varnum].type = TYPE_ADR;
 
-#if defined(ENABLE_LSRA)
-       m->maxlifetimes = 0;
-#endif
-
 #if defined(ENABLE_STATISTICS)
        iteration_count = 0;
 #endif
@@ -2017,11 +2098,12 @@ bool stack_analyse(jitdata *jd)
 
        /* init jd->interface_map */
 
+       jd->maxinterfaces = m->maxstack;
        jd->interface_map = DMNEW(interface_info, m->maxstack * 5);
        for (i = 0; i < m->maxstack * 5; i++)
                jd->interface_map[i].flags = UNUSED;
 
-       last_store_boundary = DMNEW(stackptr, m->maxlocals);
+       last_store_boundary = DMNEW(stackelement_t *, m->maxlocals);
 
        /* initialize flags and invars (none) of first block */
 
@@ -2033,6 +2115,10 @@ bool stack_analyse(jitdata *jd)
        MCOPY(jd->basicblocks[0].inlocals, jd->var, varinfo, 
                        jd->localcount + VERIFIER_EXTRA_LOCALS);
 
+       /* initialize java local mapping of first block */
+
+       stack_init_javalocals(&sd);
+
        /* stack analysis loop (until fixpoint reached) **************************/
 
        do {
@@ -2042,11 +2128,12 @@ bool stack_analyse(jitdata *jd)
 
                /* initialize loop over basic blocks */
 
-               sd.bptr = jd->basicblocks;
+               sd.bptr       = jd->basicblocks;
                superblockend = true;
-               sd.repeat = false;
-               curstack = NULL; stackdepth = 0;
-               deadcode = true;
+               sd.repeat     = false;
+               curstack      = NULL;
+               stackdepth    = 0;
+               deadcode      = true;
 
                /* iterate over basic blocks *****************************************/
 
@@ -2060,15 +2147,20 @@ bool stack_analyse(jitdata *jd)
 
                        if (sd.bptr->flags == BBTYPECHECK_REACHED) {
                                /* re-analyse a block because its input changed */
+
+                               deadcode = false;
+
                                if (!stack_reanalyse_block(&sd))
                                        return false;
+
                                superblockend = true; /* XXX */
                                continue;
                        }
 
                        if (superblockend && (sd.bptr->flags < BBREACHED)) {
-                               /* This block has not been reached so far, and we      */
-                               /* don't fall into it, so we'll have to iterate again. */
+                               /* This block has not been reached so far, and we
+                                  don't fall into it, so we'll have to iterate
+                                  again. */
 
                                sd.repeat = true;
                                continue;
@@ -2082,8 +2174,9 @@ bool stack_analyse(jitdata *jd)
                        }
 
                        if (sd.bptr->original && sd.bptr->original->flags < BBFINISHED) {
-                               /* This block is a clone and the original has not been */
-                               /* analysed, yet. Analyse it on the next iteration.    */
+                               /* This block is a clone and the original has not been
+                                  analysed, yet. Analyse it on the next
+                                  iteration. */
 
                                sd.repeat = true;
                                /* XXX superblockend? */
@@ -2092,6 +2185,8 @@ bool stack_analyse(jitdata *jd)
 
                        /* This block has to be analysed now. */
 
+                       deadcode = false;
+
                        /* XXX The rest of this block is still indented one level too */
                        /* much in order to avoid a giant diff by changing that.      */
 
@@ -2140,9 +2235,10 @@ bool stack_analyse(jitdata *jd)
                                if (sd.bptr->inlocals)
                                        MCOPY(sd.var, sd.bptr->inlocals, varinfo, sd.localcount);
 
+                               MCOPY(sd.javalocals, sd.bptr->javalocals, s4, sd.maxlocals);
+
                                /* set up local variables for analyzing this block */
 
-                               deadcode = false;
                                superblockend = false;
                                len = sd.bptr->icount;
                                iptr = sd.bptr->iinstr;
@@ -2175,16 +2271,7 @@ bool stack_analyse(jitdata *jd)
                                while (--len >= 0)  {
 
 #if defined(STACK_VERBOSE)
-                                       show_icmd(jd, iptr, false, SHOW_PARSE); printf("\n");
-                                       for( copy = curstack; copy; copy = copy->prev ) {
-                                               printf("%2d(%d", copy->varnum, copy->type);
-                                               if (IS_INOUT(copy))
-                                                       printf("S");
-                                               if (IS_PREALLOC(copy))
-                                                       printf("A");
-                                               printf(") ");
-                                       }
-                                       printf("\n");
+                                       stack_verbose_show_state(&sd, iptr, curstack);
 #endif
 
                                        /* fetch the current opcode */
@@ -2193,18 +2280,16 @@ bool stack_analyse(jitdata *jd)
 
                                        /* automatically replace some ICMDs with builtins */
 
-#if defined(USEBUILTINTABLE)
                                        bte = builtintable_get_automatic(opcode);
 
-                                       if (bte && bte->opcode == opcode) {
-                                               iptr->opc           = ICMD_BUILTIN;
-                                               iptr->flags.bits    = 0;
-                                               iptr->sx.s23.s3.bte = bte;
+                                       if ((bte != NULL) && (bte->opcode == opcode)) {
+                                               iptr->opc            = ICMD_BUILTIN;
+                                               iptr->flags.bits    &= INS_FLAG_ID_MASK;
+                                               iptr->sx.s23.s3.bte  = bte;
                                                /* iptr->line is already set */
-                                               jd->isleafmethod = false;
+                                               code_unflag_leafmethod(code);
                                                goto icmd_BUILTIN;
                                        }
-#endif /* defined(USEBUILTINTABLE) */
 
                                        /* main opcode switch *************************************/
 
@@ -2227,11 +2312,11 @@ icmd_NOP:
                                                break;
 
                                        case ICMD_RET:
-                                               j = iptr->s1.varindex = 
+                                               varindex = iptr->s1.varindex = 
                                                        jd->local_map[iptr->s1.varindex * 5 + TYPE_ADR];
 
 #if defined(ENABLE_VERIFIER)
-                                               if (sd.var[j].type != TYPE_RET) {
+                                               if (sd.var[varindex].type != TYPE_RET) {
                                                        exceptions_throw_verifyerror(m, "RET with non-returnAddress value");
                                                        return false;
                                                }
@@ -2239,7 +2324,7 @@ icmd_NOP:
                
                                                CLR_SX;
 
-                                               iptr->dst.block = stack_mark_reached(&sd, sd.var[j].vv.retaddr, curstack, stackdepth);
+                                               iptr->dst.block = stack_mark_reached(&sd, sd.var[varindex].vv.retaddr, curstack, stackdepth);
                                                superblockend = true;
                                                break;
 
@@ -2248,6 +2333,12 @@ icmd_NOP:
                                                CLR_SX;
                                                OP0_0;
                                                superblockend = true;
+                                               sd.jd->returncount++;
+                                               sd.jd->returnblock = sd.bptr;
+                                               break;
+
+                                       case ICMD_BREAKPOINT:
+                                               OP0_0;
                                                break;
 
 
@@ -2879,7 +2970,7 @@ normal_ICONST:
 
                                                                        icmd_lconst_lcmp_tail:
                                                                                /* convert LCONST, LCMP, IFXX to IF_LXX */
-                                                                               iptr->dst.insindex = iptr[2].dst.insindex;
+                                                                               iptr->dst.block = iptr[2].dst.block;
                                                                                iptr[1].opc = ICMD_NOP;
                                                                                iptr[2].opc = ICMD_NOP;
 
@@ -3046,29 +3137,18 @@ normal_ACONST:
                                        case ICMD_DLOAD:
                                        case ICMD_ALOAD:
                                                COUNT(count_load_instruction);
-                                               i = opcode - ICMD_ILOAD; /* type */
+                                               type = opcode - ICMD_ILOAD;
 
-                                               j = iptr->s1.varindex = 
-                                                       jd->local_map[iptr->s1.varindex * 5 + i];
+                                               varindex = iptr->s1.varindex = 
+                                                       jd->local_map[iptr->s1.varindex * 5 + type];
 
 #if defined(ENABLE_VERIFIER)
-                                               if (sd.var[j].type == TYPE_RET) {
+                                               if (sd.var[varindex].type == TYPE_RET) {
                                                        exceptions_throw_verifyerror(m, "forbidden load of returnAddress");
                                                        return false;
                                                }
 #endif
-               
-#if defined(ENABLE_SSA)
-                                               if (ls != NULL) {
-                                                       GET_NEW_VAR(sd, new_index, i);
-                                                       DST(i, new_index);
-                                                       stackdepth++;
-                                               }
-                                               else
-
-#else
-                                               LOAD(i, j);
-#endif
+                                               LOAD(type, varindex);
                                                break;
 
                                                /* pop 2 push 1 */
@@ -3101,23 +3181,17 @@ normal_ACONST:
 
                                        case ICMD_IINC:
                                                STATISTICS_STACKDEPTH_DISTRIBUTION(count_store_depth);
-#if defined(ENABLE_SSA)
-                                               if (ls != NULL) {
-                                                       iptr->s1.varindex = 
-                                                               jd->local_map[iptr->s1.varindex * 5 +TYPE_INT];
-                                               }
-                                               else {
-#endif
-                                               last_store_boundary[iptr->s1.varindex] = sd.new;
+                                               javaindex = iptr->s1.varindex;
+                                               last_store_boundary[javaindex] = sd.new;
 
                                                iptr->s1.varindex = 
-                                                       jd->local_map[iptr->s1.varindex * 5 + TYPE_INT];
+                                                       jd->local_map[javaindex * 5 + TYPE_INT];
 
                                                copy = curstack;
                                                i = stackdepth - 1;
                                                while (copy) {
                                                        if ((copy->varkind == LOCALVAR) &&
-                                                               (copy->varnum == iptr->s1.varindex))
+                                                               (jd->reverselocalmap[copy->varnum] == javaindex))
                                                        {
                                                                assert(IS_LOCALVAR(copy));
                                                                SET_TEMPVAR(copy);
@@ -3125,9 +3199,6 @@ normal_ACONST:
                                                        i--;
                                                        copy = copy->prev;
                                                }
-#if defined(ENABLE_SSA)
-                                               }
-#endif
 
                                                iptr->dst.varindex = iptr->s1.varindex;
                                                break;
@@ -3141,12 +3212,39 @@ normal_ACONST:
                                        case ICMD_ASTORE:
                                                REQUIRE(1);
 
-                                               i = opcode - ICMD_ISTORE; /* type */
+                                               type = opcode - ICMD_ISTORE;
                                                javaindex = iptr->dst.varindex;
-                                               j = iptr->dst.varindex = 
-                                                       jd->local_map[javaindex * 5 + i];
+                                               varindex = iptr->dst.varindex = 
+                                                       jd->local_map[javaindex * 5 + type];
+
+                                               COPY_VAL_AND_TYPE(sd, curstack->varnum, varindex);
+
+                                               iptr->sx.s23.s3.javaindex = javaindex;
+
+                                               if (curstack->type == TYPE_RET) {
+                                                       iptr->flags.bits |= INS_FLAG_RETADDR;
+                                                       iptr->sx.s23.s2.retaddrnr = 
+                                                               JAVALOCAL_FROM_RETADDR(sd.var[varindex].vv.retaddr->nr);
+                                                       sd.javalocals[javaindex] = iptr->sx.s23.s2.retaddrnr;
+                                               }
+                                               else
+                                                       sd.javalocals[javaindex] = varindex;
 
-                                               COPY_VAL_AND_TYPE(sd, curstack->varnum, j);
+                                               /* invalidate the following javalocal for 2-word types */
+
+                                               if (IS_2_WORD_TYPE(type)) {
+                                                       sd.javalocals[javaindex+1] = UNUSED;
+                                                       iptr->flags.bits |= INS_FLAG_KILL_NEXT;
+                                               }
+
+                                               /* invalidate 2-word types if second half was overwritten */
+
+                                               if (javaindex > 0 && (i = sd.javalocals[javaindex-1]) >= 0) {
+                                                       if (IS_2_WORD_TYPE(sd.var[i].type)) {
+                                                               sd.javalocals[javaindex-1] = UNUSED;
+                                                               iptr->flags.bits |= INS_FLAG_KILL_PREV;
+                                                       }
+                                               }
 
 #if defined(ENABLE_STATISTICS)
                                                if (opt_stat) {
@@ -3164,18 +3262,14 @@ normal_ACONST:
                                                }
 #endif
 
-#if defined(ENABLE_SSA)
-                                               if (ls != NULL) {
-#endif
                                                /* check for conflicts as described in Figure 5.2 */
 
                                                copy = curstack->prev;
                                                i = stackdepth - 2;
                                                while (copy) {
                                                        if ((copy->varkind == LOCALVAR) &&
-                                                               (copy->varnum == j))
+                                                               (jd->reverselocalmap[copy->varnum] == javaindex))
                                                        {
-                                                               copy->varkind = TEMPVAR;
                                                                assert(IS_LOCALVAR(copy));
                                                                SET_TEMPVAR(copy);
                                                        }
@@ -3201,11 +3295,11 @@ normal_ACONST:
                                                if (curstack < coalescing_boundary)
                                                        goto assume_conflict;
 
-                                               /* there is no DEF LOCALVAR(j) while curstack is live */
+                                               /* there is no DEF LOCALVAR(varindex) while curstack is live */
 
                                                copy = sd.new; /* most recent stackslot created + 1 */
                                                while (--copy > curstack) {
-                                                       if (copy->varkind == LOCALVAR && copy->varnum == j)
+                                                       if (copy->varkind == LOCALVAR && jd->reverselocalmap[copy->varnum] == javaindex)
                                                                goto assume_conflict;
                                                }
 
@@ -3221,14 +3315,14 @@ normal_ACONST:
                                                assert(!(curstack->flags & PASSTHROUGH));
                                                RELEASE_INDEX(sd, curstack);
                                                curstack->varkind = LOCALVAR;
-                                               curstack->varnum = j;
-                                               curstack->creator->dst.varindex = j;
+                                               curstack->varnum = varindex;
+                                               curstack->creator->dst.varindex = varindex;
                                                goto store_tail;
 
                                                /* revert the coalescing, if it has been done earlier */
 assume_conflict:
                                                if ((curstack->varkind == LOCALVAR)
-                                                       && (curstack->varnum == j))
+                                                       && (jd->reverselocalmap[curstack->varnum] == javaindex))
                                                {
                                                        assert(IS_LOCALVAR(curstack));
                                                        SET_TEMPVAR(curstack);
@@ -3237,14 +3331,11 @@ assume_conflict:
                                                /* remember the stack boundary at this store */
 store_tail:
                                                last_store_boundary[javaindex] = sd.new;
-#if defined(ENABLE_SSA)
-                                               } /* if (ls != NULL) */
-#endif
 
                                                if (opcode == ICMD_ASTORE && curstack->type == TYPE_RET)
-                                                       STORE(TYPE_RET, j);
+                                                       STORE(TYPE_RET, varindex);
                                                else
-                                                       STORE(opcode - ICMD_ISTORE, j);
+                                                       STORE(opcode - ICMD_ISTORE, varindex);
                                                break;
 
                                        /* pop 3 push 0 */
@@ -3256,7 +3347,7 @@ store_tail:
                                                COUNT(count_check_bound);
                                                COUNT(count_pcmd_mem);
 
-                                               bte = builtintable_get_internal(BUILTIN_canstore);
+                                               bte = builtintable_get_internal(BUILTIN_FAST_canstore);
                                                md = bte->md;
 
                                                if (md->memuse > rd->memuse)
@@ -3332,6 +3423,8 @@ store_tail:
                                                COUNT(count_pcmd_return);
                                                OP1_0(opcode - ICMD_IRETURN);
                                                superblockend = true;
+                                               sd.jd->returncount++;
+                                               sd.jd->returnblock = sd.bptr;
                                                break;
 
                                        case ICMD_ATHROW:
@@ -3881,7 +3974,7 @@ icmd_DUP_X2:
                                                case ICMD_IFEQ:
                                                        iptr->opc = ICMD_IF_LCMPEQ;
                                                icmd_lcmp_if_tail:
-                                                       iptr->dst.insindex = iptr[1].dst.insindex;
+                                                       iptr->dst.block = iptr[1].dst.block;
                                                        iptr[1].opc = ICMD_NOP;
 
                                                        OP2_BRANCH(TYPE_LNG, TYPE_LNG);
@@ -3910,175 +4003,17 @@ icmd_DUP_X2:
                                                break;
 normal_LCMP:
 #endif /* SUPPORT_LONG_CMP_CONST */
-                                                       OP2_1(TYPE_LNG, TYPE_LNG, TYPE_INT);
-                                               break;
-
-                                               /* XXX why is this deactivated? */
-#if 0
-                                       case ICMD_FCMPL:
-                                               COUNT(count_pcmd_op);
-                                               if ((len == 0) || (iptr[1].sx.val.i != 0))
-                                                       goto normal_FCMPL;
-
-                                               switch (iptr[1].opc) {
-                                               case ICMD_IFEQ:
-                                                       iptr->opc = ICMD_IF_FCMPEQ;
-                                               icmd_if_fcmpl_tail:
-                                                       iptr->dst.insindex = iptr[1].dst.insindex;
-                                                       iptr[1].opc = ICMD_NOP;
-
-                                                       OP2_BRANCH(TYPE_FLT, TYPE_FLT);
-                                                       BRANCH(tbptr);
-
-                                                       COUNT(count_pcmd_bra);
-                                                       break;
-                                               case ICMD_IFNE:
-                                                       iptr->opc = ICMD_IF_FCMPNE;
-                                                       goto icmd_if_fcmpl_tail;
-                                               case ICMD_IFLT:
-                                                       iptr->opc = ICMD_IF_FCMPL_LT;
-                                                       goto icmd_if_fcmpl_tail;
-                                               case ICMD_IFGT:
-                                                       iptr->opc = ICMD_IF_FCMPL_GT;
-                                                       goto icmd_if_fcmpl_tail;
-                                               case ICMD_IFLE:
-                                                       iptr->opc = ICMD_IF_FCMPL_LE;
-                                                       goto icmd_if_fcmpl_tail;
-                                               case ICMD_IFGE:
-                                                       iptr->opc = ICMD_IF_FCMPL_GE;
-                                                       goto icmd_if_fcmpl_tail;
-                                               default:
-                                                       goto normal_FCMPL;
-                                               }
-                                               break;
-
-normal_FCMPL:
-                                               OPTT2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
-                                               break;
-
-                                       case ICMD_FCMPG:
-                                               COUNT(count_pcmd_op);
-                                               if ((len == 0) || (iptr[1].sx.val.i != 0))
-                                                       goto normal_FCMPG;
-
-                                               switch (iptr[1].opc) {
-                                               case ICMD_IFEQ:
-                                                       iptr->opc = ICMD_IF_FCMPEQ;
-                                               icmd_if_fcmpg_tail:
-                                                       iptr->dst.insindex = iptr[1].dst.insindex;
-                                                       iptr[1].opc = ICMD_NOP;
-
-                                                       OP2_BRANCH(TYPE_FLT, TYPE_FLT);
-                                                       BRANCH(tbptr);
-
-                                                       COUNT(count_pcmd_bra);
-                                                       break;
-                                               case ICMD_IFNE:
-                                                       iptr->opc = ICMD_IF_FCMPNE;
-                                                       goto icmd_if_fcmpg_tail;
-                                               case ICMD_IFLT:
-                                                       iptr->opc = ICMD_IF_FCMPG_LT;
-                                                       goto icmd_if_fcmpg_tail;
-                                               case ICMD_IFGT:
-                                                       iptr->opc = ICMD_IF_FCMPG_GT;
-                                                       goto icmd_if_fcmpg_tail;
-                                               case ICMD_IFLE:
-                                                       iptr->opc = ICMD_IF_FCMPG_LE;
-                                                       goto icmd_if_fcmpg_tail;
-                                               case ICMD_IFGE:
-                                                       iptr->opc = ICMD_IF_FCMPG_GE;
-                                                       goto icmd_if_fcmpg_tail;
-                                               default:
-                                                       goto normal_FCMPG;
-                                               }
-                                               break;
-
-normal_FCMPG:
-                                               OP2_1(TYPE_FLT, TYPE_FLT, TYPE_INT);
-                                               break;
-
-                                       case ICMD_DCMPL:
-                                               COUNT(count_pcmd_op);
-                                               if ((len == 0) || (iptr[1].sx.val.i != 0))
-                                                       goto normal_DCMPL;
-
-                                               switch (iptr[1].opc) {
-                                               case ICMD_IFEQ:
-                                                       iptr->opc = ICMD_IF_DCMPEQ;
-                                               icmd_if_dcmpl_tail:
-                                                       iptr->dst.insindex = iptr[1].dst.insindex;
-                                                       iptr[1].opc = ICMD_NOP;
+                                               bte = builtintable_get_internal(BUILTIN_lcmp);
 
-                                                       OP2_BRANCH(TYPE_DBL, TYPE_DBL);
-                                                       BRANCH(tbptr);
-
-                                                       COUNT(count_pcmd_bra);
-                                                       break;
-                                               case ICMD_IFNE:
-                                                       iptr->opc = ICMD_IF_DCMPNE;
-                                                       goto icmd_if_dcmpl_tail;
-                                               case ICMD_IFLT:
-                                                       iptr->opc = ICMD_IF_DCMPL_LT;
-                                                       goto icmd_if_dcmpl_tail;
-                                               case ICMD_IFGT:
-                                                       iptr->opc = ICMD_IF_DCMPL_GT;
-                                                       goto icmd_if_dcmpl_tail;
-                                               case ICMD_IFLE:
-                                                       iptr->opc = ICMD_IF_DCMPL_LE;
-                                                       goto icmd_if_dcmpl_tail;
-                                               case ICMD_IFGE:
-                                                       iptr->opc = ICMD_IF_DCMPL_GE;
-                                                       goto icmd_if_dcmpl_tail;
-                                               default:
-                                                       goto normal_DCMPL;
-                                               }
-                                               break;
-
-normal_DCMPL:
-                                               OPTT2_1(TYPE_DBL, TYPE_INT);
-                                               break;
-
-                                       case ICMD_DCMPG:
-                                               COUNT(count_pcmd_op);
-                                               if ((len == 0) || (iptr[1].sx.val.i != 0))
-                                                       goto normal_DCMPG;
-
-                                               switch (iptr[1].opc) {
-                                               case ICMD_IFEQ:
-                                                       iptr->opc = ICMD_IF_DCMPEQ;
-                                               icmd_if_dcmpg_tail:
-                                                       iptr->dst.insindex = iptr[1].dst.insindex;
-                                                       iptr[1].opc = ICMD_NOP;
-
-                                                       OP2_BRANCH(TYPE_DBL, TYPE_DBL);
-                                                       BRANCH(tbptr);
+                                               iptr->opc            = ICMD_BUILTIN;
+                                               iptr->flags.bits    &= INS_FLAG_ID_MASK;
+                                               iptr->sx.s23.s3.bte  = bte;
+                                               /* iptr->line is already set */
+                                               code_unflag_leafmethod(code);
+                                               goto icmd_BUILTIN;
 
-                                                       COUNT(count_pcmd_bra);
-                                                       break;
-                                               case ICMD_IFNE:
-                                                       iptr->opc = ICMD_IF_DCMPNE;
-                                                       goto icmd_if_dcmpg_tail;
-                                               case ICMD_IFLT:
-                                                       iptr->opc = ICMD_IF_DCMPG_LT;
-                                                       goto icmd_if_dcmpg_tail;
-                                               case ICMD_IFGT:
-                                                       iptr->opc = ICMD_IF_DCMPG_GT;
-                                                       goto icmd_if_dcmpg_tail;
-                                               case ICMD_IFLE:
-                                                       iptr->opc = ICMD_IF_DCMPG_LE;
-                                                       goto icmd_if_dcmpg_tail;
-                                               case ICMD_IFGE:
-                                                       iptr->opc = ICMD_IF_DCMPG_GE;
-                                                       goto icmd_if_dcmpg_tail;
-                                               default:
-                                                       goto normal_DCMPG;
-                                               }
                                                break;
 
-normal_DCMPG:
-                                               OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
-                                               break;
-#else
                                        case ICMD_FCMPL:
                                        case ICMD_FCMPG:
                                                COUNT(count_pcmd_op);
@@ -4090,7 +4025,6 @@ normal_DCMPG:
                                                COUNT(count_pcmd_op);
                                                OP2_1(TYPE_DBL, TYPE_DBL, TYPE_INT);
                                                break;
-#endif
 
                                                /* pop 1 push 1 */
 
@@ -4225,7 +4159,7 @@ normal_DCMPG:
                                        case ICMD_JSR:
                                                OP0_1(TYPE_RET);
 
-                                               tbptr = BLOCK_OF(iptr->sx.s23.s3.jsrtarget.insindex);
+                                               tbptr = iptr->sx.s23.s3.jsrtarget.block;
                                                tbptr->type = BBTYPE_SBR;
 
                                                assert(sd.bptr->next);  /* XXX exception */
@@ -4235,7 +4169,7 @@ normal_DCMPG:
 #endif
 
                                                tbptr = stack_mark_reached(&sd, tbptr, curstack, stackdepth);
-                                               if (!tbptr)
+                                               if (tbptr == NULL)
                                                        return false;
 
                                                iptr->sx.s23.s3.jsrtarget.block = tbptr;
@@ -4327,20 +4261,20 @@ icmd_BUILTIN:
                                                                                assert(0); /* XXX is this assert ok? */
 #else
                                                                                sd.var[copy->varnum].vv.regoff = 
-                                                                       rd->argfltregs[md->params[i].regoff];
+                                                                                       md->params[i].regoff;
 #endif /* SUPPORT_PASS_FLOATARGS_IN_INTREGS */
                                                                        }
                                                                        else {
 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
                                                                                if (IS_2_WORD_TYPE(copy->type))
                                                                                        sd.var[copy->varnum].vv.regoff = 
-                       PACK_REGS( rd->argintregs[GET_LOW_REG(md->params[i].regoff)],
-                                          rd->argintregs[GET_HIGH_REG(md->params[i].regoff)]);
+                       PACK_REGS(GET_LOW_REG(md->params[i].regoff),
+                                         GET_HIGH_REG(md->params[i].regoff));
 
                                                                                else
 #endif /* SUPPORT_COMBINE_INTEGER_REGISTERS */
                                                                                        sd.var[copy->varnum].vv.regoff = 
-                                                                       rd->argintregs[md->params[i].regoff];
+                                                                                               md->params[i].regoff;
                                                                        }
                                                                }
                                                        }
@@ -4378,12 +4312,6 @@ icmd_BUILTIN:
                                                }
                                                break;
 
-                                       case ICMD_INLINE_START:
-                                       case ICMD_INLINE_END:
-                                               CLR_S1;
-                                               CLR_DST;
-                                               break;
-
                                        case ICMD_MULTIANEWARRAY:
                                                coalescing_boundary = sd.new;
                                                if (rd->argintreguse < MIN(3, INT_ARG_CNT))
@@ -4462,8 +4390,8 @@ icmd_BUILTIN:
                                                break;
 
                                        default:
-                                               *exceptionptr =
-                                                       new_internalerror("Unknown ICMD %d", opcode);
+                                               exceptions_throw_internalerror("Unknown ICMD %d during stack analysis",
+                                                                                                          opcode);
                                                return false;
                                        } /* switch */
 
@@ -4471,6 +4399,12 @@ icmd_BUILTIN:
                                        iptr++;
                                } /* while instructions */
 
+                               /* show state after last instruction */
+
+#if defined(STACK_VERBOSE)
+                               stack_verbose_show_state(&sd, NULL, curstack);
+#endif
+
                                /* stack slots at basic block end become interfaces */
 
                                sd.bptr->outdepth = stackdepth;
@@ -4479,7 +4413,6 @@ icmd_BUILTIN:
                                i = stackdepth - 1;
                                for (copy = curstack; copy; i--, copy = copy->prev) {
                                        varinfo *v;
-                                       s4 t;
 
                                        /* with the new vars rd->interfaces will be removed */
                                        /* and all in and outvars have to be STACKVARS!     */
@@ -4487,20 +4420,22 @@ icmd_BUILTIN:
                                        /* create an unresolvable conflict */
 
                                        SET_TEMPVAR(copy);
-                                       t = copy->type;
-                                       if (t == TYPE_RET)
-                                               t = TYPE_ADR;
+                                       type = copy->type;
 
                                        v = sd.var + copy->varnum;
                                        v->flags |= INOUT;
 
-                                       if (jd->interface_map[i*5 + t].flags == UNUSED) {
-                                               /* no interface var until now for this depth and */
-                                               /* type */
-                                               jd->interface_map[i*5 + t].flags = v->flags;
-                                       }
-                                       else {
-                                               jd->interface_map[i*5 + t].flags |= v->flags;
+                                       /* do not allocate variables for returnAddresses */
+
+                                       if (type != TYPE_RET) {
+                                               if (jd->interface_map[i*5 + type].flags == UNUSED) {
+                                                       /* no interface var until now for this depth and */
+                                                       /* type */
+                                                       jd->interface_map[i*5 + type].flags = v->flags;
+                                               }
+                                               else {
+                                                       jd->interface_map[i*5 + type].flags |= v->flags;
+                                               }
                                        }
 
                                        sd.bptr->outvars[i] = copy->varnum;
@@ -4510,19 +4445,18 @@ icmd_BUILTIN:
 
                                for (i=0; i<sd.bptr->indepth; ++i) {
                                        varinfo *v = sd.var + sd.bptr->invars[i];
-                                       s4 t;
 
-                                       t = v->type;
-                                       if (t == TYPE_RET)
-                                               t = TYPE_ADR;
+                                       type = v->type;
 
-                                       if (jd->interface_map[i*5 + t].flags == UNUSED) {
-                                               /* no interface var until now for this depth and */
-                                               /* type */
-                                               jd->interface_map[i*5 + t].flags = v->flags;
-                                       }
-                                       else {
-                                               jd->interface_map[i*5 + t].flags |= v->flags;
+                                       if (type != TYPE_RET) {
+                                               if (jd->interface_map[i*5 + type].flags == UNUSED) {
+                                                       /* no interface var until now for this depth and */
+                                                       /* type */
+                                                       jd->interface_map[i*5 + type].flags = v->flags;
+                                               }
+                                               else {
+                                                       jd->interface_map[i*5 + type].flags |= v->flags;
+                                               }
                                        }
                                }
 
@@ -4544,11 +4478,30 @@ icmd_BUILTIN:
 
        } while (sd.repeat && !deadcode);
 
-       /* XXX reset TYPE_RET to TYPE_ADR */
+    /* reset locals of TYPE_RET|VOID to TYPE_ADR */
+
+    /* A local variable may be used as both a returnAddress and a reference */
+    /* type variable, as we do not split variables between these types when */
+    /* renaming locals. While returnAddresses have been eliminated now, we  */
+    /* must assume that the variable is still used as TYPE_ADR.             */
+    /* The only way that a local can be TYPE_VOID at this point, is that it */
+    /* was a TYPE_RET variable for which incompatible returnAddresses were  */
+    /* merged. Thus we must treat TYPE_VOID in the same way as TYPE_RET     */
+    /* here.                                                                */
+    /* XXX: It would be nice to remove otherwise unused returnAddress       */
+    /*      variables from the local variable array, so they are not        */
+    /*      allocated by simplereg. (For LSRA this is not needed).          */
+
+       for (i=0; i<sd.localcount; ++i) {
+               if (sd.var[i].type == TYPE_RET || sd.var[i].type == TYPE_VOID)
+                       sd.var[i].type = TYPE_ADR;
+       }
 
-       for (i=0; i<sd.vartop; ++i) {
+       /* mark temporaries of TYPE_RET as PREALLOC to avoid allocation */
+
+       for (i=sd.localcount; i<sd.vartop; ++i) {
                if (sd.var[i].type == TYPE_RET)
-                       sd.var[i].type = TYPE_ADR;
+                       sd.var[i].flags |= PREALLOC;
        }
 
        /* XXX hack to fix up the ranges of the cloned single-block handlers */
@@ -4669,14 +4622,52 @@ throw_stack_category_error:
 }
 
 
+/* stack_javalocals_store ******************************************************
+   Model the effect of a ?STORE instruction upon the given javalocals array.
+  
+   IN:
+       iptr.............the ?STORE instruction
+          javalocals.......the javalocals array to modify
+  
+*******************************************************************************/
+
+void stack_javalocals_store(instruction *iptr, s4 *javalocals)
+{
+       s4 varindex;     /* index into the jd->var array */
+       s4 javaindex;    /* java local index             */
+
+       varindex = iptr->dst.varindex;
+       javaindex = iptr->sx.s23.s3.javaindex;
+
+       if (javaindex != UNUSED) {
+               assert(javaindex >= 0);
+               if (iptr->flags.bits & INS_FLAG_RETADDR)
+                       javalocals[javaindex] = iptr->sx.s23.s2.retaddrnr;
+               else
+                       javalocals[javaindex] = varindex;
+
+               if (iptr->flags.bits & INS_FLAG_KILL_PREV)
+                       javalocals[javaindex-1] = UNUSED;
+
+               if (iptr->flags.bits & INS_FLAG_KILL_NEXT)
+                       javalocals[javaindex+1] = UNUSED;
+       }
+}
+
+
 /* functions for verbose stack analysis output ********************************/
 
 #if defined(STACK_VERBOSE)
 static void stack_verbose_show_varinfo(stackdata_t *sd, varinfo *v)
 {
        printf("%c", show_jit_type_letters[v->type]);
-       if (v->type == TYPE_RET)
+       if (v->type == TYPE_RET) {
                printf("{L%03d}", v->vv.retaddr->nr);
+#if defined(ENABLE_VERIFIER)
+               printf("{start=L%03d}", ((basicblock *)v->SBRSTART)->nr);
+#endif
+       }
 }
 
 
@@ -4701,7 +4692,9 @@ static void stack_verbose_show_block(stackdata_t *sd, basicblock *bptr)
        }
        else
                putchar('-');
-       printf("] inlocals [");
+       printf("] javalocals ");
+       show_javalocals_array(sd->jd, sd->javalocals, sd->maxlocals, SHOW_STACK);
+       printf(" inlocals [");
        if (bptr->inlocals) {
                for (i=0; i<sd->localcount; ++i) {
                        if (i)
@@ -4742,7 +4735,7 @@ static void stack_verbose_block_enter(stackdata_t *sd, bool reanalyse)
        int i;
 
        printf("======================================== STACK %sANALYSE BLOCK ", 
-                       (reanalyse) ? "RE-" : "");
+                       (reanalyse) ? ((sd->bptr->iinstr == NULL) ? "CLONE-" : "RE-") : "");
        stack_verbose_show_block(sd, sd->bptr);
        printf("\n");
 
@@ -4763,6 +4756,47 @@ static void stack_verbose_block_exit(stackdata_t *sd, bool superblockend)
        stack_verbose_show_block(sd, sd->bptr);
        printf("\n");
 }
+
+static void stack_verbose_show_state(stackdata_t *sd, instruction *iptr, stackelement_t *curstack)
+{
+       stackelement_t *sp;
+       s4       i;
+       s4       depth;
+       varinfo *v;
+       stackelement_t **stack;
+
+       printf("    javalocals ");
+       show_javalocals_array(sd->jd, sd->javalocals, sd->maxlocals, SHOW_STACK);
+       printf(" stack [");
+
+       for(i = 0, sp = curstack; sp; sp = sp->prev)
+               i++;
+       depth = i;
+
+       stack = MNEW(stackelement_t *, depth);
+       for(sp = curstack; sp; sp = sp->prev)
+               stack[--i] = sp;
+
+       for(i=0; i<depth; ++i) {
+               if (i)
+                       putchar(' ');
+               sp = stack[i];
+               v = &(sd->var[sp->varnum]);
+
+               if (v->flags & INOUT)
+                       putchar('I');
+               if (v->flags & PREALLOC)
+                       putchar('A');
+               printf("%d:%c", sp->varnum, show_jit_type_letters[sp->type]);
+               if (v->type == TYPE_RET) {
+                       printf("(L%03d)", v->vv.retaddr->nr);
+               }
+       }
+       printf("] ... ");
+       if (iptr)
+               show_icmd(sd->jd, iptr, false, SHOW_PARSE); 
+       printf("\n");
+}
 #endif