* Removed all Id tags.
[cacao.git] / src / vm / jit / parse.c
index 387cad4120012e530401b00fecb8006e37254865..068dc65afed4e81e1d102e31ffbf3505206554c9 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Author: Andreas Krall
-
-   Changes: Carolyn Oates
-            Edwin Steiner
-            Joseph Wenninger
-            Christian Thalinger
-
-   $Id: parse.c 5520 2006-09-15 16:44:37Z edwin $
-
 */
 
 
 #include "vm/types.h"
 
 #include "mm/memory.h"
+
 #include "native/native.h"
 
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "threads/lock-common.h"
 
 #include "toolbox/logging.h"
+
 #include "vm/builtin.h"
 #include "vm/exceptions.h"
 #include "vm/global.h"
-#include "vm/linker.h"
-#include "vm/loader.h"
-#include "vm/resolve.h"
-#include "vm/options.h"
-#include "vm/statistics.h"
 #include "vm/stringlocal.h"
-#include "vm/suck.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/parse.h"
-#include "vm/jit/patcher.h"
 #include "vm/jit/loop/loop.h"
 
+#include "vmcore/linker.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+#include "vm/resolve.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
+#include "vmcore/suck.h"
+
 #define INSTRUCTIONS_INCREMENT  5  /* number of additional instructions to    */
                                    /* allocate if space runs out              */
 
 
+/* local macros ***************************************************************/
+
+#define BYTECODEINDEX_TO_BASICBLOCK(dst) \
+    do { \
+        (dst).block = \
+            parse_bytecodeindex_to_basicblock(jd, &pd, (dst).insindex); \
+    } while (0)
+
+
 /* parserdata_t ***************************************************************/
 
 typedef struct parsedata_t parsedata_t;
 
 struct parsedata_t {
+       u1          *bytecodestart;         /* start of bytecode instructions     */
+       u1          *basicblockstart;       /* start of bytecode basic-blocks     */
+
+       s4          *bytecodemap;           /* bytecode to IR mapping             */
+       
        instruction *instructions;          /* instruction array                  */
        s4           instructionslength;    /* length of the instruction array    */
-       u1          *instructionstart;
+
+       s4          *instructionmap;        /* IR to basic-block mapping          */
 };
 
 
@@ -96,28 +105,35 @@ static void parse_setup(jitdata *jd, parsedata_t *pd)
 
        m = jd->m;
 
-       /* Allocate instruction array and block index table (1 additional
-          for end ipc). */
+       /* bytecode start array */
 
-       jd->new_basicblockindex = DMNEW(s4, m->jcodelength + 1);
-       pd->instructionstart = DMNEW(u1, m->jcodelength + 1);
+       pd->bytecodestart = DMNEW(u1, m->jcodelength + 1);
+       MZERO(pd->bytecodestart, u1, m->jcodelength + 1);
 
-       MZERO(jd->new_basicblockindex, s4, m->jcodelength + 1);
-       MZERO(pd->instructionstart, u1, m->jcodelength + 1);
+       /* bytecode basic-block start array */
 
-       /* Set the length of the instruction array.  We simply add 5 more
-          instruction, as this seems to be a reasonable value. */
+       pd->basicblockstart = DMNEW(u1, m->jcodelength + 1);
+       MZERO(pd->basicblockstart, u1, m->jcodelength + 1);
 
-       pd->instructionslength = m->jcodelength + 1;
+       /* bytecode instruction index to IR instruction mapping */
+
+       pd->bytecodemap = DMNEW(s4, m->jcodelength + 1);
+       MSET(pd->bytecodemap, -1, s4, m->jcodelength + 1);
 
        /* allocate the instruction array */
 
+       pd->instructionslength = m->jcodelength + 1;
        pd->instructions = DMNEW(instruction, pd->instructionslength);
 
        /* Zero the intermediate instructions array so we don't have any
           invalid pointers in it if we cannot finish stack_analyse(). */
 
        MZERO(pd->instructions, instruction, pd->instructionslength);
+
+       /* The instructionmap is allocated later when we know the count of
+          instructions. */
+
+       pd->instructionmap = NULL;
 }
 
 
@@ -131,7 +147,7 @@ static void parse_setup(jitdata *jd, parsedata_t *pd)
 
 *******************************************************************************/
 
-static instruction *parse_realloc_instructions(parsedata_t *pd, s4 ipc, s4 n)
+static instruction *parse_realloc_instructions(parsedata_t *pd, s4 icount, s4 n)
 {
        /* increase the size of the instruction array */
 
@@ -139,92 +155,207 @@ static instruction *parse_realloc_instructions(parsedata_t *pd, s4 ipc, s4 n)
 
        /* reallocate the array */
 
-       pd->instructions = DMREALLOC(pd->instructions, instruction, ipc,
+       pd->instructions = DMREALLOC(pd->instructions, instruction, icount,
                                                                 pd->instructionslength);
+       MZERO(pd->instructions + icount, instruction,
+                 (pd->instructionslength - icount));
 
        /* return the iptr */
 
-       return pd->instructions + ipc;
+       return pd->instructions + icount;
 }
 
 
-/*******************************************************************************
+/* parse_bytecodeindex_to_basicblock *******************************************
 
-       function 'parse' scans the JavaVM code and generates intermediate code
+   Resolves a bytecode index to the corresponding basic block.
 
-       During parsing the block index table is used to store at bit pos 0
-       a flag which marks basic block starts and at position 1 to 31 the
-       intermediate instruction index. After parsing the block index table
-       is scanned, for marked positions a block is generated and the block
-       number is stored in the block index table.
+*******************************************************************************/
+
+static basicblock *parse_bytecodeindex_to_basicblock(jitdata *jd,
+                                                                                                        parsedata_t *pd,
+                                                                                                        s4 bcindex)
+{
+       s4          irindex;
+       basicblock *bb;
+
+       irindex = pd->bytecodemap[bcindex];
+       bb      = jd->basicblocks + pd->instructionmap[irindex];
+
+       return bb;
+}
+
+
+/* parse_mark_exception_boundaries *********************************************
+
+   Mark exception handlers and the boundaries of the handled regions as
+   basic block boundaries.
+
+   IN:
+       jd...............current jitdata
+
+   RETURN VALUE:
+       true.............everything ok
+          false............an exception has been thrown
 
 *******************************************************************************/
 
-static exceptiontable * new_fillextable(
-                                                                       jitdata *jd,
-                                                                       methodinfo *m, 
-                                                                       exceptiontable *extable, 
-                                                                       exceptiontable *raw_extable, 
-                                                               int exceptiontablelength, 
-                                                                       int *block_count)
+static bool parse_mark_exception_boundaries(jitdata *jd, parsedata_t *pd)
 {
-       int b_count, p, src;
+       s4                   bcindex;
+       s4                   i;
+       s4                   len;
+       raw_exception_entry *rex;
+       methodinfo          *m;
+
+       m = jd->m;
        
-       if (exceptiontablelength == 0) 
-               return extable;
+       len = m->rawexceptiontablelength;
+
+       if (len == 0)
+               return true;
+
+       rex = m->rawexceptiontable;
 
-       b_count = *block_count;
+       for (i = 0; i < len; ++i, ++rex) {
 
-       for (src = exceptiontablelength-1; src >=0; src--) {
                /* the start of the handled region becomes a basic block start */
-               p = raw_extable[src].startpc;
-               CHECK_BYTECODE_INDEX(p);
-               extable->startpc = p;
-               MARK_BASICBLOCK(p);
+
+               bcindex = rex->startpc;
+               CHECK_BYTECODE_INDEX(bcindex);
+               MARK_BASICBLOCK(pd, bcindex);
                
-               p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
-               CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
+               bcindex = rex->endpc; /* see JVM Spec 4.7.3 */
+               CHECK_BYTECODE_INDEX_EXCLUSIVE(bcindex);
+
+               /* check that the range is valid */
 
 #if defined(ENABLE_VERIFIER)
-               if (p <= raw_extable[src].startpc) {
-                       exceptions_throw_verifyerror(m,
-                               "Invalid exception handler range");
-                       return NULL;
+               if (bcindex <= rex->startpc) {
+                       exceptions_throw_verifyerror(m, "Invalid exception handler range");
+                       return false;
                }
 #endif
-               extable->endpc = p;
                
-               /* end of handled region becomes a basic block boundary  */
-               /* (If it is the bytecode end, we'll use the special     */
-               /* end block that is created anyway.)                    */
-               if (p < m->jcodelength) 
-                       MARK_BASICBLOCK(p);
+               /* End of handled region becomes a basic block boundary (if it
+                  is the bytecode end, we'll use the special end block that
+                  is created anyway). */
+
+               if (bcindex < m->jcodelength)
+                       MARK_BASICBLOCK(pd, bcindex);
+               else
+                       jd->branchtoend = true;
 
                /* the start of the handler becomes a basic block start  */
-               p = raw_extable[src].handlerpc;
-               CHECK_BYTECODE_INDEX(p);
-               extable->handlerpc = p;
-               MARK_BASICBLOCK(p);
-
-               extable->catchtype = raw_extable[src].catchtype;
-               extable->next = NULL;
-               extable->down = &extable[1];
-               extable--;
+
+               bcindex = rex->handlerpc;
+               CHECK_BYTECODE_INDEX(bcindex);
+               MARK_BASICBLOCK(pd, bcindex);
        }
 
-       *block_count = b_count;
-       
        /* everything ok */
-       return extable;
+
+       return true;
 
 #if defined(ENABLE_VERIFIER)
 throw_invalid_bytecode_index:
        exceptions_throw_verifyerror(m,
                                                                 "Illegal bytecode index in exception table");
-       return NULL;
+       return false;
 #endif
 }
 
+
+/* parse_resolve_exception_table ***********************************************
+
+   Enter the exception handlers and their ranges, resolved to basicblock *s,
+   in the jitdata.
+
+   IN:
+       jd...............current jitdata
+
+   RETURN VALUE:
+          true.............everything ok
+          false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool parse_resolve_exception_table(jitdata *jd, parsedata_t *pd)
+{
+       methodinfo          *m;
+       raw_exception_entry *rex;
+       exception_entry     *ex;
+       s4                   i;
+       s4                   len;
+       classinfo           *exclass;
+
+       m = jd->m;
+
+       len = m->rawexceptiontablelength;
+
+       /* common case: no handler entries */
+
+       if (len == 0)
+               return true;
+
+       /* allocate the exception table */
+
+       jd->exceptiontablelength = len;
+       jd->exceptiontable = DMNEW(exception_entry, len + 1); /* XXX why +1? */
+
+       /* copy and resolve the entries */
+
+       ex = jd->exceptiontable;
+       rex = m->rawexceptiontable;
+
+       for (i = 0; i < len; ++i, ++rex, ++ex) {
+               /* resolve instruction indices to basic blocks */
+
+               ex->start   = parse_bytecodeindex_to_basicblock(jd, pd, rex->startpc);
+               ex->end     = parse_bytecodeindex_to_basicblock(jd, pd, rex->endpc);
+               ex->handler = parse_bytecodeindex_to_basicblock(jd, pd, rex->handlerpc);
+
+               /* lazily resolve the catchtype */
+
+               if (rex->catchtype.any != NULL) {
+                       if (!resolve_classref_or_classinfo(m,
+                                                                                          rex->catchtype,
+                                                                                          resolveLazy, true, false,
+                                                                                          &exclass))
+                               return false;
+
+                       /* if resolved, enter the result of resolution in the table */
+
+                       if (exclass != NULL)
+                               rex->catchtype.cls = exclass;
+               }
+
+               ex->catchtype = rex->catchtype;
+               ex->next = NULL;   /* set by loop analysis */
+               ex->down = ex + 1; /* link to next exception entry */
+       }
+
+       /* terminate the ->down linked list */
+
+       assert(ex != jd->exceptiontable);
+       ex[-1].down = NULL;
+
+       return true;
+}
+
+
+/*******************************************************************************
+
+       function 'parse' scans the JavaVM code and generates intermediate code
+
+       During parsing the block index table is used to store at bit pos 0
+       a flag which marks basic block starts and at position 1 to 31 the
+       intermediate instruction index. After parsing the block index table
+       is scanned, for marked positions a block is generated and the block
+       number is stored in the block index table.
+
+*******************************************************************************/
+
 /*** macro for checking the length of the bytecode ***/
 
 #if defined(ENABLE_VERIFIER)
@@ -237,30 +368,34 @@ throw_invalid_bytecode_index:
 #define CHECK_END_OF_BYTECODE(neededlength)
 #endif /* ENABLE_VERIFIER */
 
-bool new_parse(jitdata *jd)
+bool parse(jitdata *jd)
 {
        methodinfo  *m;                     /* method being parsed                */
-       codeinfo    *code;
-       codegendata *cd;
        parsedata_t  pd;
        instruction *iptr;                  /* current ptr into instruction array */
-       s4           ipc;                   /* intermediate instruction counter   */
-       s4           p;                     /* java instruction counter           */
-       s4           nextp;                 /* start of next java instruction     */
-       s4           opcode;                /* java opcode                        */
-       s4           i;
-       s4           j;
-       int  b_count = 0;           /* basic block counter                      */
-       int  s_count = 0;           /* stack element counter                    */
-       bool blockend = false;      /* true if basic block end has been reached */
-       bool iswide = false;        /* true if last instruction was a wide      */
+
+       s4           bcindex;               /* bytecode instruction index         */
+       s4           nextbc;                /* start of next bytecode instruction */
+       s4           opcode;                /* bytecode instruction opcode        */
+
+       s4           irindex;               /* IR instruction index               */
+       s4           ircount;               /* IR instruction count               */
+
+       s4           bbcount;               /* basic block count                  */
+
+       int  s_count = 0;             /* stack element counter                    */
+       bool blockend;                /* true if basic block end has been reached */
+       bool iswide;                  /* true if last instruction was a wide      */
+
        constant_classref  *cr;
        constant_classref  *compr;
        classinfo          *c;
        builtintable_entry *bte;
-       constant_FMIref    *mr;
+       constant_FMIref    *fmi;
        methoddesc         *md;
        unresolved_method  *um;
+       unresolved_field   *uf;
+
        resolve_result_t    result;
        u2                  lineindex = 0;
        u2                  currentline = 0;
@@ -268,17 +403,22 @@ bool new_parse(jitdata *jd)
        u4                  flags;
        basicblock         *bptr;
 
-       int                *local_map; /* local pointer to renaming structore     */
+       int                *local_map; /* local pointer to renaming map           */
                                       /* is assigned to rd->local_map at the end */
+       branch_target_t *table;
+       lookup_target_t *lookup;
+       s4               i;
+       s4               j;
+
        /* get required compiler data */
 
-       m    = jd->m;
-       code = jd->code;
-       cd   = jd->cd;
+       m = jd->m;
 
        /* allocate buffers for local variable renaming */
-       local_map = DMNEW(int, cd->maxlocals * 5);
-       for (i = 0; i < cd->maxlocals; i++) {
+
+       local_map = DMNEW(int, m->maxlocals * 5);
+
+       for (i = 0; i < m->maxlocals; i++) {
                local_map[i * 5 + 0] = 0;
                local_map[i * 5 + 1] = 0;
                local_map[i * 5 + 2] = 0;
@@ -292,26 +432,20 @@ bool new_parse(jitdata *jd)
   
        /* initialize local variables */
   
-       iptr = pd.instructions;
-       ipc  = 0;
-  
-       /* compute branch targets of exception table */
+       iptr     = pd.instructions;
+       ircount  = 0;
+       bbcount  = 0;
+       blockend = false;
+       iswide   = false;
 
-       if (!new_fillextable(jd, m,
-                       &(cd->exceptiontable[cd->exceptiontablelength-1]),
-                       m->exceptiontable,
-                       m->exceptiontablelength,
-                       &b_count))
-       {
+       /* mark basic block boundaries for exception table */
+
+       if (!parse_mark_exception_boundaries(jd, &pd))
                return false;
-       }
 
-       s_count = 1 + m->exceptiontablelength; /* initialize stack element counter   */
+       /* initialize stack element counter */
 
-#if defined(ENABLE_THREADS)
-       if (checksync && (m->flags & ACC_SYNCHRONIZED))
-               jd->isleafmethod = false;
-#endif
+       s_count = 1 + m->rawexceptiontablelength;
 
        /* setup line number info */
 
@@ -327,24 +461,24 @@ bool new_parse(jitdata *jd)
 
        /*** LOOP OVER ALL BYTECODE INSTRUCTIONS **********************************/
 
-       for (p = 0; p < m->jcodelength; p = nextp) {
+       for (bcindex = 0; bcindex < m->jcodelength; bcindex = nextbc) {
 
-               /* mark this position as a valid instruction start */
+               /* mark this position as a valid bytecode instruction start */
 
-               pd.instructionstart[p] = 1;
+               pd.bytecodestart[bcindex] = 1;
 
                /* change the current line number, if necessary */
 
                /* XXX rewrite this using pointer arithmetic */
 
-               if (linepcchange == p) {
+               if (linepcchange == bcindex) {
                        if (m->linenumbercount > lineindex) {
 next_linenumber:
                                currentline = m->linenumbers[lineindex].line_number;
                                lineindex++;
                                if (lineindex < m->linenumbercount) {
                                        linepcchange = m->linenumbers[lineindex].start_pc;
-                                       if (linepcchange == p)
+                                       if (linepcchange == bcindex)
                                                goto next_linenumber;
                                }
                        }
@@ -353,26 +487,43 @@ next_linenumber:
 fetch_opcode:
                /* fetch next opcode  */        
 
-               opcode = SUCK_BE_U1(m->jcode + p);
+               opcode = SUCK_BE_U1(m->jcode + bcindex);
 
-               /* some compilers put a JAVA_NOP after a blockend instruction */
+               /* If the previous instruction was a block-end instruction,
+                  mark the current bytecode instruction as basic-block
+                  starting instruction. */
 
-               if (blockend && (opcode != JAVA_NOP)) {
-                       /* start new block */
+               /* NOTE: Some compilers put a JAVA_NOP after a blockend
+                  instruction. */
 
-                       MARK_BASICBLOCK(p);
+               if (blockend && (opcode != JAVA_NOP)) {
+                       MARK_BASICBLOCK(&pd, bcindex);
                        blockend = false;
                }
 
+               /* If the current bytecode instruction was marked as
+                  basic-block starting instruction before (e.g. blockend,
+                  forward-branch target), mark the current IR instruction
+                  too. */
+
+               if (pd.basicblockstart[bcindex] != 0) {
+                       /* We need a NOP as last instruction in each basic block
+                          for basic block reordering (may be replaced with a GOTO
+                          later). */
+
+                       INSTRUCTIONS_CHECK(1);
+                       OP(ICMD_NOP);
+               }
+
                /* store intermediate instruction count (bit 0 mark block starts) */
 
-               jd->new_basicblockindex[p] |= (ipc << 1);
+               pd.bytecodemap[bcindex] = ircount;
 
                /* compute next instruction start */
 
-               nextp = p + jcommandsize[opcode];
+               nextbc = bcindex + jcommandsize[opcode];
 
-               CHECK_END_OF_BYTECODE(nextp);
+               CHECK_END_OF_BYTECODE(nextbc);
 
                /* add stack elements produced by this instruction */
 
@@ -394,20 +545,20 @@ fetch_opcode:
                /* pushing constants onto the stack ***********************************/
 
                case JAVA_BIPUSH:
-                       OP_LOADCONST_I(SUCK_BE_S1(m->jcode + p + 1));
+                       OP_LOADCONST_I(SUCK_BE_S1(m->jcode + bcindex + 1));
                        break;
 
                case JAVA_SIPUSH:
-                       OP_LOADCONST_I(SUCK_BE_S2(m->jcode + p + 1));
+                       OP_LOADCONST_I(SUCK_BE_S2(m->jcode + bcindex + 1));
                        break;
 
                case JAVA_LDC1:
-                       i = SUCK_BE_U1(m->jcode + p + 1);
+                       i = SUCK_BE_U1(m->jcode + bcindex + 1);
                        goto pushconstantitem;
 
                case JAVA_LDC2:
                case JAVA_LDC2W:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
 
                pushconstantitem:
 
@@ -552,11 +703,11 @@ fetch_opcode:
                case JAVA_FLOAD:
                case JAVA_ALOAD:
                        if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + p + 1);
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
                        }
                        else {
-                               i = SUCK_BE_U2(m->jcode + p + 1);
-                               nextp = p + 3;
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
                                iswide = false;
                        }
                        OP_LOAD_ONEWORD(opcode, i, opcode - JAVA_ILOAD);
@@ -565,11 +716,11 @@ fetch_opcode:
                case JAVA_LLOAD:
                case JAVA_DLOAD:
                        if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + p + 1);
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
                        }
                        else {
-                               i = SUCK_BE_U2(m->jcode + p + 1);
-                               nextp = p + 3;
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
                                iswide = false;
                        }
                        OP_LOAD_TWOWORD(opcode, i, opcode - JAVA_ILOAD);
@@ -614,12 +765,12 @@ fetch_opcode:
                case JAVA_FSTORE:
                case JAVA_ASTORE:
                        if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + p + 1);
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
                        }
                        else {
-                               i = SUCK_BE_U2(m->jcode + p + 1);
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
                                iswide = false;
-                               nextp = p + 3;
                        }
                        OP_STORE_ONEWORD(opcode, i, opcode - JAVA_ISTORE);
                        break;
@@ -627,12 +778,12 @@ fetch_opcode:
                case JAVA_LSTORE:
                case JAVA_DSTORE:
                        if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + p + 1);
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
                        }
                        else {
-                               i = SUCK_BE_U2(m->jcode + p + 1);
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
                                iswide = false;
-                               nextp = p + 3;
                        }
                        OP_STORE_TWOWORD(opcode, i, opcode - JAVA_ISTORE);
                        break;
@@ -677,15 +828,15 @@ fetch_opcode:
                                int v;
 
                                if (iswide == false) {
-                                       i = SUCK_BE_U1(m->jcode + p + 1);
-                                       v = SUCK_BE_S1(m->jcode + p + 2);
+                                       i = SUCK_BE_U1(m->jcode + bcindex + 1);
+                                       v = SUCK_BE_S1(m->jcode + bcindex + 2);
 
                                }
                                else {
-                                       i = SUCK_BE_U2(m->jcode + p + 1);
-                                       v = SUCK_BE_S2(m->jcode + p + 3);
+                                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                                       v = SUCK_BE_S2(m->jcode + bcindex + 3);
+                                       nextbc = bcindex + 5;
                                        iswide = false;
-                                       nextp = p + 5;
                                }
                                INDEX_ONEWORD(i);
                                LOCALTYPE_USED(i, TYPE_INT);
@@ -696,14 +847,14 @@ fetch_opcode:
                /* wider index for loading, storing and incrementing ******************/
 
                case JAVA_WIDE:
+                       bcindex++;
                        iswide = true;
-                       p++;
                        goto fetch_opcode;
 
                /* managing arrays ****************************************************/
 
                case JAVA_NEWARRAY:
-                       switch (SUCK_BE_S1(m->jcode + p + 1)) {
+                       switch (SUCK_BE_S1(m->jcode + bcindex + 1)) {
                        case 4:
                                bte = builtintable_get_internal(BUILTIN_newarray_boolean);
                                break;
@@ -738,9 +889,9 @@ fetch_opcode:
                        break;
 
                case JAVA_ANEWARRAY:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
                        compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
-                       if (!compr)
+                       if (compr == NULL)
                                return false;
 
                        if (!(cr = class_get_classref_multiarray_of(1, compr)))
@@ -758,8 +909,8 @@ fetch_opcode:
 
                case JAVA_MULTIANEWARRAY:
                        jd->isleafmethod = false;
-                       i = SUCK_BE_U2(m->jcode + p + 1);
-                       j = SUCK_BE_U1(m->jcode + p + 3);
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       j = SUCK_BE_U1(m->jcode + bcindex + 3);
   
                        cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
                        if (cr == NULL)
@@ -771,7 +922,7 @@ fetch_opcode:
                        /* if unresolved, c == NULL */
   
                        iptr->s1.argcount = j;
-                       OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, 0 /* flags */);
+                       OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, INS_FLAG_CHECK);
                        break;
 
                /* control flow instructions ******************************************/
@@ -793,26 +944,26 @@ fetch_opcode:
                case JAVA_IF_ACMPEQ:
                case JAVA_IF_ACMPNE:
                case JAVA_GOTO:
-                       i = p + SUCK_BE_S2(m->jcode + p + 1);
+                       i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
                        CHECK_BYTECODE_INDEX(i);
-                       MARK_BASICBLOCK(i);
+                       MARK_BASICBLOCK(&pd, i);
                        blockend = true;
                        OP_INSINDEX(opcode, i);
                        break;
 
                case JAVA_GOTO_W:
-                       i = p + SUCK_BE_S4(m->jcode + p + 1);
+                       i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
                        CHECK_BYTECODE_INDEX(i);
-                       MARK_BASICBLOCK(i);
+                       MARK_BASICBLOCK(&pd, i);
                        blockend = true;
-                       OP_INSINDEX(opcode, i);
+                       OP_INSINDEX(ICMD_GOTO, i);
                        break;
 
                case JAVA_JSR:
-                       i = p + SUCK_BE_S2(m->jcode + p + 1);
+                       i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
 jsr_tail:
                        CHECK_BYTECODE_INDEX(i);
-                       MARK_BASICBLOCK(i);
+                       MARK_BASICBLOCK(&pd, i);
                        blockend = true;
                        OP_PREPARE_ZEROFLAGS(JAVA_JSR);
                        iptr->sx.s23.s3.jsrtarget.insindex = i;
@@ -820,16 +971,16 @@ jsr_tail:
                        break;
 
                case JAVA_JSR_W:
-                       i = p + SUCK_BE_S4(m->jcode + p + 1);
+                       i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
                        goto jsr_tail;
 
                case JAVA_RET:
                        if (iswide == false) {
-                               i = SUCK_BE_U1(m->jcode + p + 1);
+                               i = SUCK_BE_U1(m->jcode + bcindex + 1);
                        }
                        else {
-                               i = SUCK_BE_U2(m->jcode + p + 1);
-                               nextp = p + 3;
+                               i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                               nextbc = bcindex + 3;
                                iswide = false;
                        }
                        blockend = true;
@@ -865,25 +1016,25 @@ jsr_tail:
                                s4 prevvalue = 0;
 #endif
                                blockend = true;
-                               nextp = ALIGN((p + 1), 4);
+                               nextbc = MEMORY_ALIGN((bcindex + 1), 4);
 
-                               CHECK_END_OF_BYTECODE(nextp + 8);
+                               CHECK_END_OF_BYTECODE(nextbc + 8);
 
                                OP_PREPARE_ZEROFLAGS(opcode);
 
                                /* default target */
 
-                               j = p + SUCK_BE_S4(m->jcode + nextp);
+                               j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
                                iptr->sx.s23.s3.lookupdefault.insindex = j;
-                               nextp += 4;
+                               nextbc += 4;
                                CHECK_BYTECODE_INDEX(j);
-                               MARK_BASICBLOCK(j);
+                               MARK_BASICBLOCK(&pd, j);
 
                                /* number of pairs */
 
-                               num = SUCK_BE_U4(m->jcode + nextp);
+                               num = SUCK_BE_U4(m->jcode + nextbc);
                                iptr->sx.s23.s2.lookupcount = num;
-                               nextp += 4;
+                               nextbc += 4;
 
                                /* allocate the intermediate code table */
 
@@ -892,15 +1043,15 @@ jsr_tail:
 
                                /* iterate over the lookup table */
 
-                               CHECK_END_OF_BYTECODE(nextp + 8 * num);
+                               CHECK_END_OF_BYTECODE(nextbc + 8 * num);
 
                                for (i = 0; i < num; i++) {
                                        /* value */
 
-                                       j = SUCK_BE_S4(m->jcode + nextp);
+                                       j = SUCK_BE_S4(m->jcode + nextbc);
                                        lookup->value = j;
 
-                                       nextp += 4;
+                                       nextbc += 4;
 
 #if defined(ENABLE_VERIFIER)
                                        /* check if the lookup table is sorted correctly */
@@ -913,12 +1064,12 @@ jsr_tail:
 #endif
                                        /* target */
 
-                                       j = p + SUCK_BE_S4(m->jcode + nextp);
+                                       j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
                                        lookup->target.insindex = j;
                                        lookup++;
-                                       nextp += 4;
+                                       nextbc += 4;
                                        CHECK_BYTECODE_INDEX(j);
-                                       MARK_BASICBLOCK(j);
+                                       MARK_BASICBLOCK(&pd, j);
                                }
 
                                PINC;
@@ -933,30 +1084,30 @@ jsr_tail:
                                branch_target_t *table;
 
                                blockend = true;
-                               nextp = ALIGN((p + 1), 4);
+                               nextbc = MEMORY_ALIGN((bcindex + 1), 4);
 
-                               CHECK_END_OF_BYTECODE(nextp + 12);
+                               CHECK_END_OF_BYTECODE(nextbc + 12);
 
                                OP_PREPARE_ZEROFLAGS(opcode);
 
                                /* default target */
 
-                               deftarget = p + SUCK_BE_S4(m->jcode + nextp);
-                               nextp += 4;
+                               deftarget = bcindex + SUCK_BE_S4(m->jcode + nextbc);
+                               nextbc += 4;
                                CHECK_BYTECODE_INDEX(deftarget);
-                               MARK_BASICBLOCK(deftarget);
+                               MARK_BASICBLOCK(&pd, deftarget);
 
                                /* lower bound */
 
-                               j = SUCK_BE_S4(m->jcode + nextp);
+                               j = SUCK_BE_S4(m->jcode + nextbc);
                                iptr->sx.s23.s2.tablelow = j;
-                               nextp += 4;
+                               nextbc += 4;
 
                                /* upper bound */
 
-                               num = SUCK_BE_S4(m->jcode + nextp);
+                               num = SUCK_BE_S4(m->jcode + nextbc);
                                iptr->sx.s23.s3.tablehigh = num;
-                               nextp += 4;
+                               nextbc += 4;
 
                                /* calculate the number of table entries */
 
@@ -972,20 +1123,20 @@ jsr_tail:
                                /* create the intermediate code table */
                                /* the first entry is the default target */
 
-                               table = MNEW(branch_target_t, 1 + num);
+                               table = DMNEW(branch_target_t, 1 + num);
                                iptr->dst.table = table;
                                (table++)->insindex = deftarget;
 
                                /* iterate over the target table */
 
-                               CHECK_END_OF_BYTECODE(nextp + 4 * num);
+                               CHECK_END_OF_BYTECODE(nextbc + 4 * num);
 
                                for (i = 0; i < num; i++) {
-                                       j = p + SUCK_BE_S4(m->jcode + nextp);
+                                       j = bcindex + SUCK_BE_S4(m->jcode + nextbc);
                                        (table++)->insindex = j;
-                                       nextp += 4;
+                                       nextbc += 4;
                                        CHECK_BYTECODE_INDEX(j);
-                                       MARK_BASICBLOCK(j);
+                                       MARK_BASICBLOCK(&pd, j);
                                }
 
                                PINC;
@@ -1004,56 +1155,55 @@ jsr_tail:
                case JAVA_PUTSTATIC:
                case JAVA_GETFIELD:
                case JAVA_PUTFIELD:
-                       {
-                               constant_FMIref  *fr;
-                               unresolved_field *uf;
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = class_getconstant(m->class, i, CONSTANT_Fieldref);
 
-                               i = SUCK_BE_U2(m->jcode + p + 1);
-                               fr = class_getconstant(m->class, i, CONSTANT_Fieldref);
-                               if (!fr)
-                                       return false;
+                       if (fmi == NULL)
+                               return false;
 
-                               OP_PREPARE_ZEROFLAGS(opcode);
-                               iptr->sx.s23.s3.fmiref = fr;
+                       OP_PREPARE_ZEROFLAGS(opcode);
+                       iptr->sx.s23.s3.fmiref = fmi;
 
-                               /* only with -noverify, otherwise the typechecker does this */
+                       /* only with -noverify, otherwise the typechecker does this */
 
 #if defined(ENABLE_VERIFIER)
-                               if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
+                       if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
 #endif
-                                       result = new_resolve_field_lazy(jd, iptr, m);
-                                       if (result == resolveFailed)
-                                               return false;
+                               result = resolve_field_lazy(m, fmi);
 
-                                       if (result != resolveSucceeded) {
-                                               uf = new_create_unresolved_field(m->class, m, iptr);
+                               if (result == resolveFailed)
+                                       return false;
+
+                               if (result != resolveSucceeded) {
+                                       uf = resolve_create_unresolved_field(m->class, m, iptr);
 
-                                               if (uf == NULL)
-                                                       return false;
+                                       if (uf == NULL)
+                                               return false;
 
-                                               /* store the unresolved_field pointer */
+                                       /* store the unresolved_field pointer */
 
-                                               iptr->sx.s23.s3.uf = uf;
-                                               iptr->flags.bits = INS_FLAG_UNRESOLVED;
-                                       }
-#if defined(ENABLE_VERIFIER)
+                                       iptr->sx.s23.s3.uf = uf;
+                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
                                }
-#endif
-                               PINC;
+#if defined(ENABLE_VERIFIER)
                        }
+#endif
+                       PINC;
                        break;
 
 
                /* method invocation **************************************************/
 
                case JAVA_INVOKESTATIC:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
-                       mr = class_getconstant(m->class, i, CONSTANT_Methodref);
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = class_getconstant(m->class, i, CONSTANT_Methodref);
 
-                       if (mr == NULL)
+                       if (fmi == NULL)
                                return false;
 
-                       md = mr->parseddesc.md;
+                       md = fmi->parseddesc.md;
 
                        if (md->params == NULL)
                                if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
@@ -1061,23 +1211,33 @@ jsr_tail:
 
                        goto invoke_method;
 
+               case JAVA_INVOKESPECIAL:
+                       OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = class_getconstant(m->class, i, CONSTANT_Methodref);
+
+                       goto invoke_nonstatic_method;
+
                case JAVA_INVOKEINTERFACE:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
+                       OP_PREPARE_ZEROFLAGS(opcode);
 
-                       mr = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
 
                        goto invoke_nonstatic_method;
 
-               case JAVA_INVOKESPECIAL:
                case JAVA_INVOKEVIRTUAL:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
-                       mr = class_getconstant(m->class, i, CONSTANT_Methodref);
+                       OP_PREPARE_ZEROFLAGS(opcode);
+
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       fmi = class_getconstant(m->class, i, CONSTANT_Methodref);
 
 invoke_nonstatic_method:
-                       if (mr == NULL)
+                       if (fmi == NULL)
                                return false;
 
-                       md = mr->parseddesc.md;
+                       md = fmi->parseddesc.md;
 
                        if (md->params == NULL)
                                if (!descriptor_params_from_paramtypes(md, 0))
@@ -1086,28 +1246,46 @@ invoke_nonstatic_method:
 invoke_method:
                        jd->isleafmethod = false;
 
-                       OP_PREPARE_ZEROFLAGS(opcode);
-                       iptr->sx.s23.s3.fmiref = mr;
+                       iptr->sx.s23.s3.fmiref = fmi;
 
                        /* only with -noverify, otherwise the typechecker does this */
 
 #if defined(ENABLE_VERIFIER)
                        if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
 #endif
-                               result = new_resolve_method_lazy(jd, iptr, m);
+                               result = resolve_method_lazy(m, fmi, 
+                                                                                        (opcode == JAVA_INVOKESPECIAL));
+
                                if (result == resolveFailed)
                                        return false;
 
-                               if (result != resolveSucceeded) {
-                                       um = new_create_unresolved_method(m->class, m, iptr);
+                               if (result == resolveSucceeded) {
+                                       methodinfo *mi = iptr->sx.s23.s3.fmiref->p.method;
+
+                                       /* if this call is monomorphic, turn it into an
+                                          INVOKESPECIAL */
+
+                                       assert(IS_FMIREF_RESOLVED(iptr->sx.s23.s3.fmiref));
+
+                                       if ((iptr->opc == ICMD_INVOKEVIRTUAL)
+                                               && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
+                                       {
+                                               iptr->opc         = ICMD_INVOKESPECIAL;
+                                               iptr->flags.bits |= INS_FLAG_CHECK;
+                                       }
+                               }
+                               else {
+                                       um = resolve_create_unresolved_method(m->class, m, fmi,
+                                                       (opcode == JAVA_INVOKESTATIC),
+                                                       (opcode == JAVA_INVOKESPECIAL));
 
-                                       if (!um)
+                                       if (um == NULL)
                                                return false;
 
                                        /* store the unresolved_method pointer */
 
                                        iptr->sx.s23.s3.um = um;
-                                       iptr->flags.bits = INS_FLAG_UNRESOLVED;
+                                       iptr->flags.bits |= INS_FLAG_UNRESOLVED;
                                }
 #if defined(ENABLE_VERIFIER)
                        }
@@ -1118,9 +1296,10 @@ invoke_method:
                /* instructions taking class arguments ********************************/
 
                case JAVA_NEW:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
-                       cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
-                       if (!cr)
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       cr = class_getconstant(m->class, i, CONSTANT_Class);
+
+                       if (cr == NULL)
                                return false;
 
                        if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
@@ -1134,8 +1313,9 @@ invoke_method:
                        break;
 
                case JAVA_CHECKCAST:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
-                       cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       cr = class_getconstant(m->class, i, CONSTANT_Class);
+
                        if (cr == NULL)
                                return false;
 
@@ -1144,19 +1324,20 @@ invoke_method:
 
                        if (cr->name->text[0] == '[') {
                                /* array type cast-check */
-                               flags = INS_FLAG_ARRAY;
+                               flags = INS_FLAG_CHECK | INS_FLAG_ARRAY;
                                jd->isleafmethod = false;
                        }
                        else {
                                /* object type cast-check */
-                               flags = 0;
+                               flags = INS_FLAG_CHECK;
                        }
                        OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
                        break;
 
                case JAVA_INSTANCEOF:
-                       i = SUCK_BE_U2(m->jcode + p + 1);
-                       cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
+                       i = SUCK_BE_U2(m->jcode + bcindex + 1);
+                       cr = class_getconstant(m->class, i, CONSTANT_Class);
+
                        if (cr == NULL)
                                return false;
 
@@ -1188,7 +1369,8 @@ invoke_method:
                        else
 #endif
                        {
-                               OP(ICMD_CHECKNULL_POP);
+                               OP_CHECK_EXCEPTION(ICMD_CHECKNULL);
+                               OP(ICMD_POP);
                        }
                        break;
 
@@ -1201,7 +1383,8 @@ invoke_method:
                        else
 #endif
                        {
-                               OP(ICMD_CHECKNULL_POP);
+                               OP_CHECK_EXCEPTION(ICMD_CHECKNULL);
+                               OP(ICMD_POP);
                        }
                        break;
 
@@ -1212,7 +1395,11 @@ invoke_method:
                        bte = builtintable_get_internal(BUILTIN_idiv);
                        OP_BUILTIN_ARITHMETIC(opcode, bte);
 #else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
                        OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
 #endif
                        break;
 
@@ -1221,7 +1408,11 @@ invoke_method:
                        bte = builtintable_get_internal(BUILTIN_irem);
                        OP_BUILTIN_ARITHMETIC(opcode, bte);
 #else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
                        OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
 #endif
                        break;
 
@@ -1230,7 +1421,11 @@ invoke_method:
                        bte = builtintable_get_internal(BUILTIN_ldiv);
                        OP_BUILTIN_ARITHMETIC(opcode, bte);
 #else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
                        OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
 #endif
                        break;
 
@@ -1239,7 +1434,11 @@ invoke_method:
                        bte = builtintable_get_internal(BUILTIN_lrem);
                        OP_BUILTIN_ARITHMETIC(opcode, bte);
 #else
+# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
                        OP(opcode);
+# else
+                       OP_CHECK_EXCEPTION(opcode);
+# endif
 #endif
                        break;
 
@@ -1376,7 +1575,7 @@ invoke_method:
                case 254:
                case 255:
                        exceptions_throw_verifyerror(m, "Illegal opcode %d at instr %d\n",
-                                                                                opcode, ipc);
+                                                                                opcode, ircount);
                        return false;
                        break;
 #endif /* defined(ENABLE_VERIFIER) */
@@ -1403,22 +1602,24 @@ invoke_method:
 
        } /* end for */
 
-       /* add a NOP to the last basic block */
+       if (JITDATA_HAS_FLAG_REORDER(jd)) {
+               /* add a NOP to the last basic block */
 
-       INSTRUCTIONS_CHECK(1);
-       OP(ICMD_NOP);
+               INSTRUCTIONS_CHECK(1);
+               OP(ICMD_NOP);
+       }
 
        /*** END OF LOOP **********************************************************/
 
        /* assert that we did not write more ICMDs than allocated */
 
-       assert(ipc <= pd.instructionslength);
-       assert(ipc == (iptr - pd.instructions));
+       assert(ircount <= pd.instructionslength);
+       assert(ircount == (iptr - pd.instructions));
 
        /*** verifier checks ******************************************************/
 
 #if defined(ENABLE_VERIFIER)
-       if (p != m->jcodelength) {
+       if (bcindex != m->jcodelength) {
                exceptions_throw_verifyerror(m,
                                "Command-sequence crosses code-boundary");
                return false;
@@ -1432,119 +1633,182 @@ invoke_method:
 
        /*** setup the methodinfo, allocate stack and basic blocks ****************/
 
-       /* adjust block count if target 0 is not first intermediate instruction */
+       /* identify basic blocks */
+
+       /* check if first instruction is a branch target */
+
+       if (pd.basicblockstart[0] == 1) {
+               jd->branchtoentry = true;
+       }
+       else {
+               /* first instruction always starts a basic block */
 
-       if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1))
-               b_count++;
+               iptr = pd.instructions;
 
-       /* copy local to method variables */
+               iptr->flags.bits |= INS_FLAG_BASICBLOCK;
+       }
 
-       jd->new_instructions = pd.instructions;
-       jd->new_instructioncount = ipc;
-       jd->new_basicblockcount = b_count;
-       jd->new_stackcount = s_count + jd->new_basicblockcount * m->maxstack; /* in-stacks */
+       /* Iterate over all bytecode instructions and set missing
+          basic-block starts in IR instructions. */
 
-       /* allocate stack table */
+       for (bcindex = 0; bcindex < m->jcodelength; bcindex++) {
+               /* Does the current bytecode instruction start a basic
+                  block? */
+
+               if (pd.basicblockstart[bcindex] == 1) {
+#if defined(ENABLE_VERIFIER)
+                       /* Check if this bytecode basic-block start at the
+                          beginning of a bytecode instruction. */
+
+                       if (pd.bytecodestart[bcindex] == 0) {
+                               exceptions_throw_verifyerror(m,
+                                                                                "Branch into middle of instruction");
+                               return false;
+                       }
+#endif
+
+                       /* Get the IR instruction mapped to the bytecode
+                          instruction and set the basic block flag. */
 
-       jd->new_stack = DMNEW(stackelement, jd->new_stackcount);
+                       irindex = pd.bytecodemap[bcindex];
+                       iptr    = pd.instructions + irindex;
 
-       /* build basic block list */
+                       iptr->flags.bits |= INS_FLAG_BASICBLOCK;
+               }
+       }
 
-       bptr = jd->new_basicblocks = DMNEW(basicblock, b_count + 1);    /* one more for end ipc */
+       /* IR instruction index to basic-block index mapping */
 
-       /* zero out all basic block structures */
+       pd.instructionmap = DMNEW(s4, ircount);
+       MZERO(pd.instructionmap, s4, ircount);
 
-       MZERO(bptr, basicblock, b_count + 1);
+       /* Iterate over all IR instructions and count the basic blocks. */
 
-       b_count = 0;
-       jd->new_c_debug_nr = 0;
+       iptr = pd.instructions;
 
-       /* additional block if target 0 is not first intermediate instruction */
+       bbcount = 0;
 
-       if (!jd->new_basicblockindex[0] || (jd->new_basicblockindex[0] > 1)) {
-               BASICBLOCK_INIT(bptr, m);
+       for (i = 0; i < ircount; i++, iptr++) {
+               if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
+                       /* store the basic-block number in the IR instruction
+                          map */
 
-               bptr->iinstr = jd->new_instructions;
-               /* bptr->icount is set when the next block is allocated */
+                       pd.instructionmap[i] = bbcount;
 
-               bptr++;
-               b_count++;
-               bptr[-1].next = bptr;
+                       /* post-increment the basic-block count */
+
+                       bbcount++;
+               }
        }
 
-       /* allocate blocks */
+       /* Allocate basic block array (one more for end ipc). */
 
-       for (p = 0; p < m->jcodelength; p++) {
-               if (jd->new_basicblockindex[p] & 1) {
-#if defined(ENABLE_VERIFIER)
-                       /* Check if this block starts at the beginning of an
-                          instruction. */
+       jd->basicblocks = DMNEW(basicblock, bbcount + 1);
+       MZERO(jd->basicblocks, basicblock, bbcount + 1);
 
-                       if (!pd.instructionstart[p]) {
-                               exceptions_throw_verifyerror(m,
-                                               "Branch into middle of instruction");
-                               return false;
-                       }
-#endif
+       /* Now iterate again over all IR instructions and initialize the
+          basic block structures and, in the same loop, resolve the
+          branch-target instruction indices to basic blocks. */
+
+       iptr = pd.instructions;
+       bptr = jd->basicblocks;
+
+       bbcount = 0;
+
+       for (i = 0; i < ircount; i++, iptr++) {
+               /* check for basic block */
 
-                       /* allocate the block */
+               if (INSTRUCTION_STARTS_BASICBLOCK(iptr)) {
+                       /* intialize the basic block */
 
                        BASICBLOCK_INIT(bptr, m);
 
-                       bptr->iinstr = jd->new_instructions + (jd->new_basicblockindex[p] >> 1);
-                       if (b_count) {
+                       bptr->iinstr = iptr;
+
+                       if (bbcount > 0) {
                                bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
                        }
-                       /* bptr->icount is set when the next block is allocated */
 
-                       jd->new_basicblockindex[p] = b_count;
+                       /* bptr->icount is set when the next block is allocated */
 
+                       bptr->nr = bbcount++;
                        bptr++;
-                       b_count++;
                        bptr[-1].next = bptr;
                }
-       }
 
-       /* set instruction count of last real block */
+               /* resolve instruction indices to basic blocks */
 
-       if (b_count) {
-               bptr[-1].icount = (jd->new_instructions + jd->new_instructioncount) - bptr[-1].iinstr;
-       }
+               switch (iptr->opc) {
+               case JAVA_IFEQ:
+               case JAVA_IFLT:
+               case JAVA_IFLE:
+               case JAVA_IFNE:
+               case JAVA_IFGT:
+               case JAVA_IFGE:
+               case JAVA_IFNULL:
+               case JAVA_IFNONNULL:
+               case JAVA_IF_ICMPEQ:
+               case JAVA_IF_ICMPNE:
+               case JAVA_IF_ICMPLT:
+               case JAVA_IF_ICMPGT:
+               case JAVA_IF_ICMPLE:
+               case JAVA_IF_ICMPGE:
+               case JAVA_IF_ACMPEQ:
+               case JAVA_IF_ACMPNE:
+               case JAVA_GOTO:
+                       BYTECODEINDEX_TO_BASICBLOCK(iptr->dst);
+                       break;
 
-       /* allocate additional block at end */
+               case ICMD_JSR:
+                       BYTECODEINDEX_TO_BASICBLOCK(iptr->sx.s23.s3.jsrtarget);
+                       break;
 
-       BASICBLOCK_INIT(bptr,m);
+               case ICMD_TABLESWITCH:
+                       table = iptr->dst.table;
 
-       /* set basicblock pointers in exception table */
+                       BYTECODEINDEX_TO_BASICBLOCK(*table);
+                       table++;
 
-       if (cd->exceptiontablelength > 0) {
-               cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
-       }
+                       j = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
 
-       for (i = 0; i < cd->exceptiontablelength; ++i) {
-               p = cd->exceptiontable[i].startpc;
-               cd->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
+                       while (--j >= 0) {
+                               BYTECODEINDEX_TO_BASICBLOCK(*table);
+                               table++;
+                       }
+                       break;
 
-               p = cd->exceptiontable[i].endpc;
-               cd->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
+               case ICMD_LOOKUPSWITCH:
+                       BYTECODEINDEX_TO_BASICBLOCK(iptr->sx.s23.s3.lookupdefault);
 
-               p = cd->exceptiontable[i].handlerpc;
-               cd->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
-       }
+                       lookup = iptr->dst.lookup;
+
+                       j = iptr->sx.s23.s2.lookupcount;
 
-       /* XXX activate this if you want to try inlining */
-#if 0
-       for (i = 0; i < m->exceptiontablelength; ++i) {
-               p = m->exceptiontable[i].startpc;
-               m->exceptiontable[i].start = jd->new_basicblocks + jd->new_basicblockindex[p];
+                       while (--j >= 0) {
+                               BYTECODEINDEX_TO_BASICBLOCK(lookup->target);
+                               lookup++;
+                       }
+                       break;
+               }
+       }
 
-               p = m->exceptiontable[i].endpc;
-               m->exceptiontable[i].end = (p == m->jcodelength) ? (jd->new_basicblocks + jd->new_basicblockcount /*+ 1*/) : (jd->new_basicblocks + jd->new_basicblockindex[p]);
+       /* set instruction count of last real block */
 
-               p = m->exceptiontable[i].handlerpc;
-               m->exceptiontable[i].handler = jd->new_basicblocks + jd->new_basicblockindex[p];
+       if (bbcount > 0) {
+               bptr[-1].icount = (pd.instructions + ircount) - bptr[-1].iinstr;
        }
-#endif
+
+       /* allocate additional block at end */
+
+       BASICBLOCK_INIT(bptr, m);
+       bptr->nr = bbcount;
+
+       /* set basicblock pointers in exception table */
+
+       if (!parse_resolve_exception_table(jd, &pd))
+               return false;
+
+       /* store the local map */
 
        jd->local_map = local_map;
 
@@ -1553,15 +1817,16 @@ invoke_method:
        {
                s4 nlocals = 0;
                s4 i;
-
                s4 *mapptr;
 
                mapptr = local_map;
 
-               /* iterate over local_map[0..m->maxlocals*5] and set all existing  */
-               /* index,type pairs (local_map[index*5+type]==1) to an unique value */
-               /* -> == new local var index */
-               for(i = 0; i < (cd->maxlocals * 5); i++, mapptr++) {
+               /* iterate over local_map[0..m->maxlocals*5-1] and allocate a unique */
+               /* variable index for each _used_ (javaindex,type) pair.             */
+               /* (local_map[javaindex*5+type] = cacaoindex)                        */
+               /* Unused (javaindex,type) pairs are marked with UNUSED.             */
+
+               for (i = 0; i < (m->maxlocals * 5); i++, mapptr++) {
                        if (*mapptr)
                                *mapptr = nlocals++;
                        else
@@ -1574,21 +1839,24 @@ invoke_method:
 
                jd->varcount = 
                          nlocals                                      /* local variables */
-                       + jd->new_basicblockcount * m->maxstack                 /* invars */
+                       + bbcount * m->maxstack                                 /* invars */
                        + s_count;         /* variables created within blocks (non-invar) */
 
                /* reserve the first indices for local variables */
 
                jd->vartop = nlocals;
 
+               /* reserve extra variables needed by stack analyse */
+
+               jd->varcount += STACK_EXTRA_VARS;
+               jd->vartop   += STACK_EXTRA_VARS;
+
                /* The verifier needs space for saving invars in some cases and */
                /* extra variables.                                             */
 
 #if defined(ENABLE_VERIFIER)
-               if (JITDATA_HAS_FLAG_VERIFY(jd)) {
-                       jd->varcount += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
-                       jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
-               }
+               jd->varcount += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
+               jd->vartop   += VERIFIER_EXTRA_LOCALS + VERIFIER_EXTRA_VARS + m->maxstack;
 #endif
                /* allocate and initialize the variable array */
 
@@ -1597,11 +1865,22 @@ invoke_method:
 
                /* set types of all locals in jd->var */
 
-               for(mapptr = local_map, i = 0; i < (cd->maxlocals * 5); i++, mapptr++)
+               for (mapptr = local_map, i = 0; i < (m->maxlocals * 5); i++, mapptr++)
                        if (*mapptr != UNUSED)
-                               jd->var[*mapptr].type = i%5;
+                               VAR(*mapptr)->type = i%5;
        }
 
+       /* assign local variables to method variables */
+
+       jd->instructions     = pd.instructions;
+       jd->instructioncount = ircount;
+       jd->basicblockcount  = bbcount;
+       jd->stackcount       = s_count + bbcount * m->maxstack; /* in-stacks */
+
+       /* allocate stack table */
+
+       jd->stack = DMNEW(stackelement, jd->stackcount);
+
        /* everything's ok */
 
        return true;