Implement method parser and SSA transformation.

Change-Id: If3fb3a36f33aaee8e5fdded4e9fa607be54f0bfb
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 76783ae..ab04215 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -16,36 +16,42 @@
 
 #include "Dalvik.h"
 #include "libdex/DexOpcodes.h"
+#include "libdex/DexCatch.h"
 #include "interp/Jit.h"
 #include "CompilerInternals.h"
 #include "Dataflow.h"
 
+static inline bool contentIsInsn(const u2 *codePtr) {
+    u2 instr = *codePtr;
+    Opcode opcode = instr & 0xff;
+
+    /*
+     * Since the low 8-bit in metadata may look like OP_NOP, we need to check
+     * both the low and whole sub-word to determine whether it is code or data.
+     */
+    return (opcode != OP_NOP || instr == 0);
+}
+
 /*
  * Parse an instruction, return the length of the instruction
  */
 static inline int parseInsn(const u2 *codePtr, DecodedInstruction *decInsn,
                             bool printMe)
 {
+    // Don't parse instruction data
+    if (!contentIsInsn(codePtr)) {
+        return 0;
+    }
+
     u2 instr = *codePtr;
     Opcode opcode = dexOpcodeFromCodeUnit(instr);
-    int insnWidth;
-
-    // Don't parse instruction data
-    if (opcode == OP_NOP && instr != 0) {
-        return 0;
-    } else {
-        insnWidth = dexGetWidthFromOpcode(opcode);
-        if (insnWidth < 0) {
-            insnWidth = -insnWidth;
-        }
-    }
 
     dexDecodeInstruction(codePtr, decInsn);
     if (printMe) {
         char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn, NULL);
         LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
     }
-    return insnWidth;
+    return dexGetWidthFromOpcode(opcode);
 }
 
 #define UNKNOWN_TARGET 0xffffffff
@@ -419,10 +425,11 @@
     const u2 *codePtr = dexCode->insns + curOffset;
     int traceSize = 0;  // # of half-words
     const u2 *startCodePtr = codePtr;
-    BasicBlock *startBB, *curBB, *lastBB;
+    BasicBlock *curBB, *entryCodeBB;
     int numBlocks = 0;
     static int compilationId;
     CompilationUnit cUnit;
+    GrowableList *blockList;
 #if defined(WITH_JIT_TUNING)
     CompilerMethodStats *methodStats;
 #endif
@@ -460,6 +467,10 @@
     /* Initialize the PC reconstruction list */
     dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
 
+    /* Initialize the basic block list */
+    blockList = &cUnit.blockList;
+    dvmInitGrowableList(blockList, 8);
+
     /* Identify traces that we don't want to compile */
     if (gDvmJit.methodTable) {
         int len = strlen(desc->method->clazz->descriptor) +
@@ -534,18 +545,15 @@
     }
 
     /* Allocate the entry block */
-    lastBB = startBB = curBB = dvmCompilerNewBB(kTraceEntryBlock);
+    curBB = dvmCompilerNewBB(kTraceEntryBlock, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) curBB);
     curBB->startOffset = curOffset;
-    curBB->id = numBlocks++;
 
-    curBB = dvmCompilerNewBB(kDalvikByteCode);
-    curBB->startOffset = curOffset;
-    curBB->id = numBlocks++;
-
-    /* Make the first real dalvik block the fallthrough of the entry block */
-    startBB->fallThrough = curBB;
-    lastBB->next = curBB;
-    lastBB = curBB;
+    entryCodeBB = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) entryCodeBB);
+    entryCodeBB->startOffset = curOffset;
+    curBB->fallThrough = entryCodeBB;
+    curBB = entryCodeBB;
 
     if (cUnit.printMe) {
         LOGD("--------\nCompiler: Building trace for %s, offset 0x%x\n",
@@ -599,10 +607,8 @@
                     break;
                 }
 
-                curBB = dvmCompilerNewBB(kDalvikByteCode);
-                lastBB->next = curBB;
-                lastBB = curBB;
-                curBB->id = numBlocks++;
+                curBB = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
+                dvmInsertGrowableList(blockList, (intptr_t) curBB);
                 curOffset = currRun->frag.startOffset;
                 numInsts = currRun->frag.numInsts;
                 curBB->startOffset = curOffset;
@@ -624,7 +630,9 @@
      * taken/fallthrough links. Also create chaining cells for code not included
      * in the trace.
      */
-    for (curBB = startBB; curBB; curBB = curBB->next) {
+    size_t blockId;
+    for (blockId = 0; blockId < blockList->numUsed; blockId++) {
+        curBB = (BasicBlock *) dvmGrowableListGetElement(blockList, blockId);
         MIR *lastInsn = curBB->lastMIRInsn;
         /* Skip empty blocks */
         if (lastInsn == NULL) {
@@ -649,7 +657,11 @@
         }
 
         /* No backward branch in the trace - start searching the next BB */
-        for (searchBB = curBB->next; searchBB; searchBB = searchBB->next) {
+        size_t searchBlockId;
+        for (searchBlockId = blockId+1; searchBlockId < blockList->numUsed;
+             searchBlockId++) {
+            searchBB = (BasicBlock *) dvmGrowableListGetElement(blockList,
+                                                                searchBlockId);
             if (targetOffset == searchBB->startOffset) {
                 curBB->taken = searchBB;
             }
@@ -681,7 +693,7 @@
         if (curBB->taken == NULL &&
             curBB->fallThrough == NULL &&
             flags == (kInstrCanBranch | kInstrCanContinue) &&
-            fallThroughOffset == startBB->startOffset &&
+            fallThroughOffset == entryCodeBB->startOffset &&
             JIT_OPT_NO_LOOP != (optHints & JIT_OPT_NO_LOOP)) {
             BasicBlock *loopBranch = curBB;
             BasicBlock *exitBB;
@@ -690,48 +702,37 @@
             if (cUnit.printMe) {
                 LOGD("Natural loop detected!");
             }
-            exitBB = dvmCompilerNewBB(kTraceExitBlock);
-            lastBB->next = exitBB;
-            lastBB = exitBB;
-
+            exitBB = dvmCompilerNewBB(kTraceExitBlock, numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) exitBB);
             exitBB->startOffset = targetOffset;
-            exitBB->id = numBlocks++;
             exitBB->needFallThroughBranch = true;
 
             loopBranch->taken = exitBB;
 #if defined(WITH_SELF_VERIFICATION)
             BasicBlock *backwardCell =
-                dvmCompilerNewBB(kChainingCellBackwardBranch);
-            lastBB->next = backwardCell;
-            lastBB = backwardCell;
-
-            backwardCell->startOffset = startBB->startOffset;
-            backwardCell->id = numBlocks++;
+                dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
+            backwardCell->startOffset = entryCodeBB->startOffset;
             loopBranch->fallThrough = backwardCell;
 #elif defined(WITH_JIT_TUNING)
             if (gDvmJit.profile) {
                 BasicBlock *backwardCell =
-                    dvmCompilerNewBB(kChainingCellBackwardBranch);
-                lastBB->next = backwardCell;
-                lastBB = backwardCell;
-
-                backwardCell->startOffset = startBB->startOffset;
-                backwardCell->id = numBlocks++;
+                    dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
+                dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
+                backwardCell->startOffset = entryCodeBB->startOffset;
                 loopBranch->fallThrough = backwardCell;
             } else {
-                loopBranch->fallThrough = startBB->next;
+                loopBranch->fallThrough = entryCodeBB;
             }
 #else
-            loopBranch->fallThrough = startBB->next;
+            loopBranch->fallThrough = entryCodeBB;
 #endif
 
             /* Create the chaining cell as the fallthrough of the exit block */
-            exitChainingCell = dvmCompilerNewBB(kChainingCellNormal);
-            lastBB->next = exitChainingCell;
-            lastBB = exitChainingCell;
-
+            exitChainingCell = dvmCompilerNewBB(kChainingCellNormal,
+                                                numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) exitChainingCell);
             exitChainingCell->startOffset = targetOffset;
-            exitChainingCell->id = numBlocks++;
 
             exitBB->fallThrough = exitChainingCell;
 
@@ -762,38 +763,35 @@
 
             /* One chaining cell for the first MAX_CHAINED_SWITCH_CASES cases */
             for (i = 0; i < maxChains; i++) {
-                BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal);
-                lastBB->next = caseChain;
-                lastBB = caseChain;
-
+                BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal,
+                                                         numBlocks++);
+                dvmInsertGrowableList(blockList, (intptr_t) caseChain);
                 caseChain->startOffset = lastInsn->offset + targets[i];
-                caseChain->id = numBlocks++;
             }
 
             /* One more chaining cell for the default case */
-            BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal);
-            lastBB->next = caseChain;
-            lastBB = caseChain;
-
+            BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal,
+                                                     numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) caseChain);
             caseChain->startOffset = lastInsn->offset + lastInsn->width;
-            caseChain->id = numBlocks++;
         /* Fallthrough block not included in the trace */
         } else if (!isUnconditionalBranch(lastInsn) &&
                    curBB->fallThrough == NULL) {
+            BasicBlock *fallThroughBB;
             /*
              * If the chaining cell is after an invoke or
              * instruction that cannot change the control flow, request a hot
              * chaining cell.
              */
             if (isInvoke || curBB->needFallThroughBranch) {
-                lastBB->next = dvmCompilerNewBB(kChainingCellHot);
+                fallThroughBB = dvmCompilerNewBB(kChainingCellHot, numBlocks++);
             } else {
-                lastBB->next = dvmCompilerNewBB(kChainingCellNormal);
+                fallThroughBB = dvmCompilerNewBB(kChainingCellNormal,
+                                                 numBlocks++);
             }
-            lastBB = lastBB->next;
-            lastBB->id = numBlocks++;
-            lastBB->startOffset = fallThroughOffset;
-            curBB->fallThrough = lastBB;
+            dvmInsertGrowableList(blockList, (intptr_t) fallThroughBB);
+            fallThroughBB->startOffset = fallThroughOffset;
+            curBB->fallThrough = fallThroughBB;
         }
         /* Target block not included in the trace */
         if (curBB->taken == NULL &&
@@ -803,12 +801,14 @@
             if (isInvoke) {
                 /* Monomorphic callee */
                 if (callee) {
-                    newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton);
+                    newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton,
+                                             numBlocks++);
                     newBB->startOffset = 0;
                     newBB->containingMethod = callee;
                 /* Will resolve at runtime */
                 } else {
-                    newBB = dvmCompilerNewBB(kChainingCellInvokePredicted);
+                    newBB = dvmCompilerNewBB(kChainingCellInvokePredicted,
+                                             numBlocks++);
                     newBB->startOffset = 0;
                 }
             /* For unconditional branches, request a hot chaining cell */
@@ -816,40 +816,40 @@
 #if !defined(WITH_SELF_VERIFICATION)
                 newBB = dvmCompilerNewBB(dexIsGoto(flags) ?
                                                   kChainingCellHot :
-                                                  kChainingCellNormal);
+                                                  kChainingCellNormal,
+                                         numBlocks++);
                 newBB->startOffset = targetOffset;
 #else
                 /* Handle branches that branch back into the block */
                 if (targetOffset >= curBB->firstMIRInsn->offset &&
                     targetOffset <= curBB->lastMIRInsn->offset) {
-                    newBB = dvmCompilerNewBB(kChainingCellBackwardBranch);
+                    newBB = dvmCompilerNewBB(kChainingCellBackwardBranch,
+                                             numBlocks++);
                 } else {
                     newBB = dvmCompilerNewBB(dexIsGoto(flags) ?
                                                       kChainingCellHot :
-                                                      kChainingCellNormal);
+                                                      kChainingCellNormal,
+                                             numBlocks++);
                 }
                 newBB->startOffset = targetOffset;
 #endif
             }
-            newBB->id = numBlocks++;
             curBB->taken = newBB;
-            lastBB->next = newBB;
-            lastBB = newBB;
+            dvmInsertGrowableList(blockList, (intptr_t) newBB);
         }
     }
 
     /* Now create a special block to host PC reconstruction code */
-    lastBB->next = dvmCompilerNewBB(kPCReconstruction);
-    lastBB = lastBB->next;
-    lastBB->id = numBlocks++;
+    curBB = dvmCompilerNewBB(kPCReconstruction, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) curBB);
 
     /* And one final block that publishes the PC and raise the exception */
-    lastBB->next = dvmCompilerNewBB(kExceptionHandling);
-    lastBB = lastBB->next;
-    lastBB->id = numBlocks++;
+    curBB = dvmCompilerNewBB(kExceptionHandling, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) curBB);
 
     if (cUnit.printMe) {
-        char* signature = dexProtoCopyMethodDescriptor(&desc->method->prototype);
+        char* signature =
+            dexProtoCopyMethodDescriptor(&desc->method->prototype);
         LOGD("TRACEINFO (%d): 0x%08x %s%s.%s 0x%x %d of %d, %d blocks",
             compilationId,
             (intptr_t) desc->method->insns,
@@ -863,21 +863,8 @@
         free(signature);
     }
 
-    BasicBlock **blockList;
-
     cUnit.traceDesc = desc;
     cUnit.numBlocks = numBlocks;
-    blockList = cUnit.blockList =
-        (BasicBlock **)dvmCompilerNew(sizeof(BasicBlock *) * numBlocks, true);
-
-    int i;
-
-    for (i = 0, curBB = startBB; i < numBlocks; i++) {
-        blockList[i] = curBB;
-        curBB = curBB->next;
-    }
-    /* Make sure all blocks are added to the cUnit */
-    assert(curBB == NULL);
 
     /* Set the instruction set to use (NOTE: later components may change it) */
     cUnit.instructionSet = dvmCompilerInstructionSet();
@@ -887,6 +874,8 @@
         dvmCompilerInlineMIR(&cUnit);
     }
 
+    cUnit.numDalvikRegisters = cUnit.method->registersSize;
+
     /* Preparation for SSA conversion */
     dvmInitializeSSAConversion(&cUnit);
 
@@ -952,6 +941,15 @@
 #if defined(WITH_JIT_TUNING)
     methodStats->nativeSize += cUnit.totalSize;
 #endif
+
+    /* FIXME - to exercise the method parser, uncomment the following code */
+#if 0
+    bool dvmCompileMethod(const Method *method);
+    if (desc->trace[0].frag.startOffset == 0) {
+        dvmCompileMethod(desc->method);
+    }
+#endif
+
     return info->codeAddress != NULL;
 }
 
@@ -1053,6 +1051,588 @@
     }
 }
 
+/* Split an existing block from the specified code offset into two */
+static BasicBlock *splitBlock(CompilationUnit *cUnit,
+                              unsigned int codeOffset,
+                              BasicBlock *origBlock)
+{
+    MIR *insn = origBlock->firstMIRInsn;
+    while (insn) {
+        if (insn->offset == codeOffset) break;
+        insn = insn->next;
+    }
+    if (insn == NULL) {
+        LOGE("Break split failed");
+        dvmAbort();
+    }
+    BasicBlock *bottomBlock = dvmCompilerNewBB(kDalvikByteCode,
+                                               cUnit->numBlocks++);
+    dvmInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
+
+    bottomBlock->startOffset = codeOffset;
+    bottomBlock->firstMIRInsn = insn;
+    bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
+
+    /* Only the top half of split blocks is tagged as BA_CATCH_BLOCK */
+    bottomBlock->blockAttributes = origBlock->blockAttributes & ~BA_CATCH_BLOCK;
+
+    /* Handle the taken path */
+    bottomBlock->taken = origBlock->taken;
+    if (bottomBlock->taken) {
+        origBlock->taken = NULL;
+        dvmCompilerClearBit(bottomBlock->taken->predecessors, origBlock->id);
+        dvmCompilerSetBit(bottomBlock->taken->predecessors, bottomBlock->id);
+    }
+
+    /* Handle the fallthrough path */
+    bottomBlock->fallThrough = origBlock->fallThrough;
+    origBlock->fallThrough = bottomBlock;
+    dvmCompilerSetBit(bottomBlock->predecessors, origBlock->id);
+    if (bottomBlock->fallThrough) {
+        dvmCompilerClearBit(bottomBlock->fallThrough->predecessors,
+                            origBlock->id);
+        dvmCompilerSetBit(bottomBlock->fallThrough->predecessors,
+                          bottomBlock->id);
+    }
+
+    /* Handle the successor list */
+    if (origBlock->successorBlockList.blockListType != kNotUsed) {
+        bottomBlock->successorBlockList = origBlock->successorBlockList;
+        origBlock->successorBlockList.blockListType = kNotUsed;
+        GrowableListIterator iterator;
+
+        dvmGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
+                                    &iterator);
+        while (true) {
+            BasicBlock *bb =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+            if (bb == NULL) break;
+            dvmCompilerClearBit(bb->predecessors, origBlock->id);
+            dvmCompilerSetBit(bb->predecessors, bottomBlock->id);
+        }
+    }
+
+    origBlock->lastMIRInsn = insn->prev;
+    /* Only the bottom half of split blocks is tagged as BA_ENDS_WITH_THROW */
+    origBlock->blockAttributes &= ~BA_ENDS_WITH_THROW;
+
+    insn->prev->next = NULL;
+    insn->prev = NULL;
+    return bottomBlock;
+}
+
+/*
+ * Given a code offset, find out the block that starts with it. If the offset
+ * is in the middle of an existing block, split it into two.
+ */
+static BasicBlock *findBlock(CompilationUnit *cUnit,
+                             unsigned int codeOffset,
+                             bool split, bool create)
+{
+    GrowableList *blockList = &cUnit->blockList;
+    BasicBlock *bb;
+    unsigned int i;
+
+    for (i = 0; i < blockList->numUsed; i++) {
+        bb = (BasicBlock *) blockList->elemList[i];
+        if (bb->blockType != kDalvikByteCode) continue;
+        if (bb->startOffset == codeOffset) return bb;
+        /* Check if a branch jumps into the middle of an existing block */
+        if ((split == true) && (codeOffset > bb->startOffset) &&
+            (bb->lastMIRInsn != NULL) &&
+            (codeOffset <= bb->lastMIRInsn->offset)) {
+            BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb);
+            return newBB;
+        }
+    }
+    if (create) {
+          bb = dvmCompilerNewBB(kDalvikByteCode, cUnit->numBlocks++);
+          dvmInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
+          bb->startOffset = codeOffset;
+          return bb;
+    }
+    return NULL;
+}
+
+/* Dump the CFG into a DOT graph */
+void dumpCFG(CompilationUnit *cUnit, const char *dirPrefix)
+{
+    const Method *method = cUnit->method;
+    FILE *file;
+    char* signature = dexProtoCopyMethodDescriptor(&method->prototype);
+    char *fileName = (char *) dvmCompilerNew(
+                                  strlen(dirPrefix) +
+                                  strlen(method->clazz->descriptor) +
+                                  strlen(method->name) +
+                                  strlen(signature) +
+                                  strlen(".dot") + 1, true);
+    sprintf(fileName, "%s%s%s%s.dot", dirPrefix,
+            method->clazz->descriptor, method->name, signature);
+    free(signature);
+
+    /*
+     * Convert the special characters into a filesystem- and shell-friendly
+     * format.
+     */
+    int i;
+    for (i = strlen(dirPrefix); fileName[i]; i++) {
+        if (fileName[i] == '/') {
+            fileName[i] = '_';
+        } else if (fileName[i] == ';') {
+            fileName[i] = '#';
+        } else if (fileName[i] == '$') {
+            fileName[i] = '+';
+        } else if (fileName[i] == '(' || fileName[i] == ')') {
+            fileName[i] = '@';
+        } else if (fileName[i] == '<' || fileName[i] == '>') {
+            fileName[i] = '=';
+        }
+    }
+    file = fopen(fileName, "w");
+    if (file == NULL) {
+        return;
+    }
+    fprintf(file, "digraph G {\n");
+
+    fprintf(file, "  rankdir=TB\n");
+
+    int numReachableBlocks = cUnit->numReachableBlocks;
+    int idx;
+    const GrowableList *blockList = &cUnit->blockList;
+
+    for (idx = 0; idx < numReachableBlocks; idx++) {
+        int blockIdx = cUnit->dfsOrder.elemList[idx];
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListGetElement(blockList,
+                                                                  blockIdx);
+        if (bb == NULL) break;
+        if (bb->blockType == kMethodEntryBlock) {
+            fprintf(file, "  entry [shape=Mdiamond];\n");
+        } else if (bb->blockType == kMethodExitBlock) {
+            fprintf(file, "  exit [shape=Mdiamond];\n");
+        } else if (bb->blockType == kDalvikByteCode) {
+            fprintf(file, "  block%04x [shape=%s,label = \"{ \\\n",
+                    bb->startOffset,
+                    bb->blockAttributes & BA_CATCH_BLOCK ?
+                      "Mrecord" : "record");
+            if (bb->blockAttributes & BA_CATCH_BLOCK) {
+                if (bb->exceptionTypeIdx == kDexNoIndex) {
+                    fprintf(file, "    {any\\l} |\\\n");
+                } else {
+                    fprintf(file, "    {throwable type:%x\\l} |\\\n",
+                            bb->exceptionTypeIdx);
+                }
+            }
+            const MIR *mir;
+            for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+                fprintf(file, "    {%04x %s\\l}%s\\\n", mir->offset,
+                        dvmCompilerFullDisassembler(cUnit, mir),
+                        mir->next ? " | " : " ");
+            }
+            fprintf(file, "  }\"];\n\n");
+        } else if (bb->blockType == kExceptionHandling) {
+            char blockName[BLOCK_NAME_LEN];
+
+            dvmGetBlockName(bb, blockName);
+            fprintf(file, "  %s [shape=invhouse];\n", blockName);
+        }
+
+        char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
+
+        if (bb->taken) {
+            dvmGetBlockName(bb, blockName1);
+            dvmGetBlockName(bb->taken, blockName2);
+            fprintf(file, "  %s:s -> %s:n [style=dotted]\n",
+                    blockName1, blockName2);
+        }
+        if (bb->fallThrough) {
+            dvmGetBlockName(bb, blockName1);
+            dvmGetBlockName(bb->fallThrough, blockName2);
+            fprintf(file, "  %s:s -> %s:n\n", blockName1, blockName2);
+        }
+
+        if (bb->successorBlockList.blockListType != kNotUsed) {
+            fprintf(file, "  succ%04x [shape=%s,label = \"{ \\\n",
+                    bb->startOffset,
+                    (bb->successorBlockList.blockListType == kCatch) ?
+                        "Mrecord" : "record");
+            GrowableListIterator iterator;
+            dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
+                                        &iterator);
+
+            BasicBlock *destBlock =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+
+            int succId = 0;
+            while (true) {
+                if (destBlock == NULL) break;
+                BasicBlock *nextBlock =
+                    (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                fprintf(file, "    {<f%d> %04x\\l}%s\\\n",
+                        succId++,
+                        destBlock->startOffset,
+                        (nextBlock != NULL) ? " | " : " ");
+                destBlock = nextBlock;
+            }
+            fprintf(file, "  }\"];\n\n");
+
+            dvmGetBlockName(bb, blockName1);
+            fprintf(file, "  %s:s -> succ%04x:n [style=dashed]\n",
+                    blockName1, bb->startOffset);
+
+            if (bb->successorBlockList.blockListType == kPackedSwitch ||
+                bb->successorBlockList.blockListType == kSparseSwitch) {
+
+                dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
+                                            &iterator);
+
+                succId = 0;
+                while (true) {
+                    BasicBlock *destBlock =
+                        (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                    if (destBlock == NULL) break;
+
+                    dvmGetBlockName(destBlock, blockName2);
+                    fprintf(file, "  succ%04x:f%d:e -> %s:n\n",
+                            bb->startOffset, succId++,
+                            blockName2);
+                }
+            }
+        }
+        fprintf(file, "\n");
+
+        /*
+         * If we need to debug the dominator tree, uncomment the following code
+         */
+#if 0
+        dvmGetBlockName(bb, blockName1);
+        fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
+                blockName1, blockName1);
+        if (bb->iDom) {
+            dvmGetBlockName(bb->iDom, blockName2);
+            fprintf(file, "  cfg%s:s -> cfg%s:n\n\n",
+                    blockName2, blockName1);
+        }
+#endif
+    }
+    fprintf(file, "}\n");
+    fclose(file);
+}
+
+/* Verify if all the successor is connected with all the claimed predecessors */
+static bool verifyPredInfo(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    BitVectorIterator bvIterator;
+
+    dvmBitVectorIteratorInit(bb->predecessors, &bvIterator);
+    while (true) {
+        int blockIdx = dvmBitVectorIteratorNext(&bvIterator);
+        if (blockIdx == -1) break;
+        BasicBlock *predBB = (BasicBlock *)
+            dvmGrowableListGetElement(&cUnit->blockList, blockIdx);
+        bool found = false;
+        if (predBB->taken == bb) {
+            found = true;
+        } else if (predBB->fallThrough == bb) {
+            found = true;
+        } else if (predBB->successorBlockList.blockListType != kNotUsed) {
+            GrowableListIterator iterator;
+            dvmGrowableListIteratorInit(&predBB->successorBlockList.blocks,
+                                        &iterator);
+            while (true) {
+                BasicBlock *succBB =
+                    (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                if (succBB == NULL) break;
+                if (succBB == bb) {
+                    found = true;
+                    break;
+                }
+            }
+        }
+        if (found == false) {
+            char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
+            dvmGetBlockName(bb, blockName1);
+            dvmGetBlockName(predBB, blockName2);
+            dumpCFG(cUnit, "/data/tombstones/");
+            LOGE("Successor %s not found from %s",
+                 blockName1, blockName2);
+            dvmAbort();
+        }
+    }
+    return true;
+}
+
+/* Identify code range in try blocks and set up the empty catch blocks */
+static void processTryCatchBlocks(CompilationUnit *cUnit)
+{
+    const Method *meth = cUnit->method;
+    const DexCode *pCode = dvmGetMethodCode(meth);
+    int triesSize = pCode->triesSize;
+    int i;
+    int offset;
+
+    if (triesSize == 0) {
+        return;
+    }
+
+    const DexTry *pTries = dexGetTries(pCode);
+    BitVector *tryBlockAddr = cUnit->tryBlockAddr;
+
+    /* Mark all the insn offsets in Try blocks */
+    for (i = 0; i < triesSize; i++) {
+        const DexTry* pTry = &pTries[i];
+        /* all in 16-bit units */
+        int startOffset = pTry->startAddr;
+        int endOffset = startOffset + pTry->insnCount;
+
+        for (offset = startOffset; offset < endOffset; offset++) {
+            dvmCompilerSetBit(tryBlockAddr, offset);
+        }
+    }
+
+    /* Iterate over each of the handlers to enqueue the empty Catch blocks */
+    offset = dexGetFirstHandlerOffset(pCode);
+    int handlersSize = dexGetHandlersSize(pCode);
+
+    for (i = 0; i < handlersSize; i++) {
+        DexCatchIterator iterator;
+        dexCatchIteratorInit(&iterator, pCode, offset);
+
+        for (;;) {
+            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
+
+            if (handler == NULL) {
+                break;
+            }
+
+            BasicBlock *catchBlock = findBlock(cUnit, handler->address,
+                                               /* split */
+                                               false,
+                                               /* create */
+                                               true);
+            catchBlock->blockAttributes |= BA_CATCH_BLOCK;
+            catchBlock->exceptionTypeIdx = handler->typeIdx;
+        }
+
+        offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
+    }
+}
+
+/* Process instructions with the kInstrCanBranch flag */
+static void processCanBranch(CompilationUnit *cUnit, BasicBlock *curBlock,
+                             MIR *insn, int curOffset, int width, int flags,
+                             const u2* codePtr, const u2* codeEnd)
+{
+    int target = curOffset;
+    switch (insn->dalvikInsn.opcode) {
+        case OP_GOTO:
+        case OP_GOTO_16:
+        case OP_GOTO_32:
+            target += (int) insn->dalvikInsn.vA;
+            break;
+        case OP_IF_EQ:
+        case OP_IF_NE:
+        case OP_IF_LT:
+        case OP_IF_GE:
+        case OP_IF_GT:
+        case OP_IF_LE:
+            target += (int) insn->dalvikInsn.vC;
+            break;
+        case OP_IF_EQZ:
+        case OP_IF_NEZ:
+        case OP_IF_LTZ:
+        case OP_IF_GEZ:
+        case OP_IF_GTZ:
+        case OP_IF_LEZ:
+            target += (int) insn->dalvikInsn.vB;
+            break;
+        default:
+            LOGE("Unexpected opcode(%d) with kInstrCanBranch set",
+                 insn->dalvikInsn.opcode);
+            dvmAbort();
+    }
+    BasicBlock *takenBlock = findBlock(cUnit, target,
+                                       /* split */
+                                       true,
+                                       /* create */
+                                       true);
+    curBlock->taken = takenBlock;
+    dvmCompilerSetBit(takenBlock->predecessors, curBlock->id);
+
+    /* Always terminate the current block for conditional branches */
+    if (flags & kInstrCanContinue) {
+        BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                                 curOffset +  width,
+                                                 /* split */
+                                                 false,
+                                                 /* create */
+                                                 true);
+        curBlock->fallThrough = fallthroughBlock;
+        dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
+    } else if (codePtr < codeEnd) {
+        /* Create a fallthrough block for real instructions (incl. OP_NOP) */
+        if (contentIsInsn(codePtr)) {
+            findBlock(cUnit, curOffset + width,
+                      /* split */
+                      false,
+                      /* create */
+                      true);
+        }
+    }
+}
+
+/* Process instructions with the kInstrCanSwitch flag */
+static void processCanSwitch(CompilationUnit *cUnit, BasicBlock *curBlock,
+                             MIR *insn, int curOffset, int width, int flags)
+{
+    u2 *switchData= (u2 *) (cUnit->method->insns + curOffset +
+                            insn->dalvikInsn.vB);
+    int size;
+    int *targetTable;
+    int i;
+
+    /*
+     * Packed switch data format:
+     *  ushort ident = 0x0100   magic value
+     *  ushort size             number of entries in the table
+     *  int first_key           first (and lowest) switch case value
+     *  int targets[size]       branch targets, relative to switch opcode
+     *
+     * Total size is (4+size*2) 16-bit code units.
+     */
+    if (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) {
+        assert(switchData[0] == kPackedSwitchSignature);
+        size = switchData[1];
+        targetTable = (int *) &switchData[4];
+    /*
+     * Sparse switch data format:
+     *  ushort ident = 0x0200   magic value
+     *  ushort size             number of entries in the table; > 0
+     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
+     *  int targets[size]       branch targets, relative to switch opcode
+     *
+     * Total size is (2+size*4) 16-bit code units.
+     */
+    } else {
+        assert(switchData[0] == kSparseSwitchSignature);
+        size = switchData[1];
+        targetTable = (int *) &switchData[2 + size*2];
+    }
+
+    if (curBlock->successorBlockList.blockListType != kNotUsed) {
+        LOGE("Successor block list already in use: %d",
+             curBlock->successorBlockList.blockListType);
+        dvmAbort();
+    }
+    curBlock->successorBlockList.blockListType =
+        (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
+        kPackedSwitch : kSparseSwitch;
+    dvmInitGrowableList(&curBlock->successorBlockList.blocks, size);
+
+    for (i = 0; i < size; i++) {
+        BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
+                                          /* split */
+                                          true,
+                                          /* create */
+                                          true);
+        dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
+                              (intptr_t) caseBlock);
+        dvmCompilerSetBit(caseBlock->predecessors, curBlock->id);
+    }
+
+    /* Fall-through case */
+    BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                             curOffset +  width,
+                                             /* split */
+                                             false,
+                                             /* create */
+                                             true);
+    curBlock->fallThrough = fallthroughBlock;
+    dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
+}
+
+/* Process instructions with the kInstrCanThrow flag */
+static void processCanThrow(CompilationUnit *cUnit, BasicBlock *curBlock,
+                            MIR *insn, int curOffset, int width, int flags,
+                            BitVector *tryBlockAddr, const u2 *codePtr,
+                            const u2* codeEnd)
+{
+    const Method *method = cUnit->method;
+    const DexCode *dexCode = dvmGetMethodCode(method);
+
+    curBlock->blockAttributes |= BA_ENDS_WITH_THROW;
+    /* In try block */
+    if (dvmIsBitSet(tryBlockAddr, curOffset)) {
+        DexCatchIterator iterator;
+
+        if (!dexFindCatchHandler(&iterator, dexCode, curOffset)) {
+            LOGE("Catch block not found in dexfile for insn %x in %s",
+                 curOffset, method->name);
+            dvmAbort();
+
+        }
+        if (curBlock->successorBlockList.blockListType != kNotUsed) {
+            LOGE("Successor block list already in use: %d",
+                 curBlock->successorBlockList.blockListType);
+            dvmAbort();
+        }
+        curBlock->successorBlockList.blockListType = kCatch;
+        dvmInitGrowableList(&curBlock->successorBlockList.blocks, 2);
+
+        for (;;) {
+            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
+
+            if (handler == NULL) {
+                break;
+            }
+
+            BasicBlock *catchBlock = findBlock(cUnit, handler->address,
+                                               /* split */
+                                               false,
+                                               /* create */
+                                               false);
+
+            assert(catchBlock->blockAttributes & BA_CATCH_BLOCK);
+            dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
+                                  (intptr_t) catchBlock);
+            dvmCompilerSetBit(catchBlock->predecessors, curBlock->id);
+        }
+    } else {
+        BasicBlock *ehBlock = dvmCompilerNewBB(kExceptionHandling,
+                                               cUnit->numBlocks++);
+        curBlock->taken = ehBlock;
+        dvmInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
+        ehBlock->startOffset = curOffset;
+        dvmCompilerSetBit(ehBlock->predecessors, curBlock->id);
+    }
+
+    /*
+     * Force the current block to terminate.
+     *
+     * Data may be present before codeEnd, so we need to parse it to know
+     * whether it is code or data.
+     */
+    if (codePtr < codeEnd) {
+        /* Create a fallthrough block for real instructions (incl. OP_NOP) */
+        if (contentIsInsn(codePtr)) {
+            BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                                     curOffset + width,
+                                                     /* split */
+                                                     false,
+                                                     /* create */
+                                                     true);
+            /*
+             * OP_THROW and OP_THROW_VERIFICATION_ERROR are unconditional
+             * branches.
+             */
+            if (insn->dalvikInsn.opcode != OP_THROW_VERIFICATION_ERROR &&
+                insn->dalvikInsn.opcode != OP_THROW) {
+                curBlock->fallThrough = fallthroughBlock;
+                dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
+            }
+        }
+    }
+}
+
 /*
  * Similar to dvmCompileTrace, but the entity processed here is the whole
  * method.
@@ -1060,248 +1640,141 @@
  * TODO: implementation will be revisited when the trace builder can provide
  * whole-method traces.
  */
-bool dvmCompileMethod(CompilationUnit *cUnit, const Method *method,
-                      JitTranslationInfo *info)
+bool dvmCompileMethod(const Method *method)
 {
+    CompilationUnit cUnit;
     const DexCode *dexCode = dvmGetMethodCode(method);
     const u2 *codePtr = dexCode->insns;
     const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
-    int blockID = 0;
+    int numBlocks = 0;
     unsigned int curOffset = 0;
 
-    /* If we've already compiled this trace, just return success */
-    if (dvmJitGetCodeAddr(codePtr) && !info->discardResult) {
-        return true;
-    }
+    memset(&cUnit, 0, sizeof(cUnit));
+    cUnit.method = method;
 
-    /* Doing method-based compilation */
-    cUnit->wholeMethod = true;
-
-    BasicBlock *firstBlock = dvmCompilerNewBB(kDalvikByteCode);
-    firstBlock->id = blockID++;
+    /* Initialize the block list */
+    dvmInitGrowableList(&cUnit.blockList, 4);
 
     /* Allocate the bit-vector to track the beginning of basic blocks */
-    BitVector *bbStartAddr = dvmCompilerAllocBitVector(dexCode->insnsSize+1,
-                                                       false);
-    dvmCompilerSetBit(bbStartAddr, 0);
+    BitVector *tryBlockAddr = dvmCompilerAllocBitVector(dexCode->insnsSize,
+                                                        true /* expandable */);
+    cUnit.tryBlockAddr = tryBlockAddr;
 
-    int numInvokeTargets = 0;
+    /* Create the default entry and exit blocks and enter them to the list */
+    BasicBlock *entryBlock = dvmCompilerNewBB(kMethodEntryBlock, numBlocks++);
+    BasicBlock *exitBlock = dvmCompilerNewBB(kMethodExitBlock, numBlocks++);
+
+    cUnit.entryBlock = entryBlock;
+    cUnit.exitBlock = exitBlock;
+
+    dvmInsertGrowableList(&cUnit.blockList, (intptr_t) entryBlock);
+    dvmInsertGrowableList(&cUnit.blockList, (intptr_t) exitBlock);
+
+    /* Current block to record parsed instructions */
+    BasicBlock *curBlock = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
+    curBlock->startOffset = 0;
+    dvmInsertGrowableList(&cUnit.blockList, (intptr_t) curBlock);
+    entryBlock->fallThrough = curBlock;
+    dvmCompilerSetBit(curBlock->predecessors, entryBlock->id);
 
     /*
-     * Sequentially go through every instruction first and put them in a single
-     * basic block. Identify block boundaries at the mean time.
+     * Store back the number of blocks since new blocks may be created of
+     * accessing cUnit.
      */
+    cUnit.numBlocks = numBlocks;
+
+    /* Identify code range in try blocks and set up the empty catch blocks */
+    processTryCatchBlocks(&cUnit);
+
+    /* Parse all instructions and put them into containing basic blocks */
     while (codePtr < codeEnd) {
-        MIR *insn = (MIR *)dvmCompilerNew(sizeof(MIR), true);
+        MIR *insn = (MIR *) dvmCompilerNew(sizeof(MIR), true);
         insn->offset = curOffset;
         int width = parseInsn(codePtr, &insn->dalvikInsn, false);
-        bool isInvoke = false;
-        const Method *callee;
         insn->width = width;
 
         /* Terminate when the data section is seen */
         if (width == 0)
             break;
 
-        if (!dvmCompilerCanIncludeThisInstruction(cUnit->method,
-						  &insn->dalvikInsn)) {
-            return false;
-        }
-
-        dvmCompilerAppendMIR(firstBlock, insn);
-        /*
-         * Check whether this is a block ending instruction and whether it
-         * suggests the start of a new block
-         */
-        unsigned int target = curOffset;
-
-        /*
-         * If findBlockBoundary returns true, it means the current instruction
-         * is terminating the current block. If it is a branch, the target
-         * address will be recorded in target.
-         */
-        if (findBlockBoundary(method, insn, curOffset, &target, &isInvoke,
-                              &callee)) {
-            dvmCompilerSetBit(bbStartAddr, curOffset + width);
-            /* Each invoke needs a chaining cell block */
-            if (isInvoke) {
-                numInvokeTargets++;
-            }
-            /* A branch will end the current block */
-            else if (target != curOffset && target != UNKNOWN_TARGET) {
-                dvmCompilerSetBit(bbStartAddr, target);
-            }
-        }
+        dvmCompilerAppendMIR(curBlock, insn);
 
         codePtr += width;
-        /* each bit represents 16-bit quantity */
+        int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
+
+        if (flags & kInstrCanBranch) {
+            processCanBranch(&cUnit, curBlock, insn, curOffset, width, flags,
+                             codePtr, codeEnd);
+        } else if (flags & kInstrCanReturn) {
+            curBlock->fallThrough = exitBlock;
+            dvmCompilerSetBit(exitBlock->predecessors, curBlock->id);
+            /*
+             * Terminate the current block if there are instructions
+             * afterwards.
+             */
+            if (codePtr < codeEnd) {
+                /*
+                 * Create a fallthrough block for real instructions
+                 * (incl. OP_NOP).
+                 */
+                if (contentIsInsn(codePtr)) {
+                    findBlock(&cUnit, curOffset + width,
+                              /* split */
+                              false,
+                              /* create */
+                              true);
+                }
+            }
+        } else if (flags & kInstrCanThrow) {
+            processCanThrow(&cUnit, curBlock, insn, curOffset, width, flags,
+                            tryBlockAddr, codePtr, codeEnd);
+        } else if (flags & kInstrCanSwitch) {
+            processCanSwitch(&cUnit, curBlock, insn, curOffset, width, flags);
+        }
         curOffset += width;
-    }
+        BasicBlock *nextBlock = findBlock(&cUnit, curOffset,
+                                          /* split */
+                                          false,
+                                          /* create */
+                                          false);
+        if (nextBlock) {
+            /*
+             * The next instruction could be the target of a previously parsed
+             * forward branch so a block is already created. If the current
+             * instruction is not an unconditional branch, connect them through
+             * the fall-through link.
+             */
+            assert(curBlock->fallThrough == NULL ||
+                   curBlock->fallThrough == nextBlock ||
+                   curBlock->fallThrough == exitBlock);
 
-    /*
-     * The number of blocks will be equal to the number of bits set to 1 in the
-     * bit vector minus 1, because the bit representing the location after the
-     * last instruction is set to one.
-     *
-     * We also add additional blocks for invoke chaining and the number is
-     * denoted by numInvokeTargets.
-     */
-    int numBlocks = dvmCountSetBits(bbStartAddr);
-    if (dvmIsBitSet(bbStartAddr, dexCode->insnsSize)) {
-        numBlocks--;
-    }
-
-    BasicBlock **blockList;
-    blockList = cUnit->blockList = (BasicBlock **)
-        dvmCompilerNew(sizeof(BasicBlock *) * (numBlocks + numInvokeTargets),
-                       true);
-
-    /*
-     * Register the first block onto the list and start splitting it into
-     * sub-blocks.
-     */
-    blockList[0] = firstBlock;
-    cUnit->numBlocks = 1;
-
-    int i;
-    for (i = 0; i < numBlocks; i++) {
-        MIR *insn;
-        BasicBlock *curBB = blockList[i];
-        curOffset = curBB->lastMIRInsn->offset;
-
-        for (insn = curBB->firstMIRInsn->next; insn; insn = insn->next) {
-            /* Found the beginning of a new block, see if it is created yet */
-            if (dvmIsBitSet(bbStartAddr, insn->offset)) {
-                int j;
-                for (j = 0; j < cUnit->numBlocks; j++) {
-                    if (blockList[j]->firstMIRInsn->offset == insn->offset)
-                        break;
-                }
-
-                /* Block not split yet - do it now */
-                if (j == cUnit->numBlocks) {
-                    BasicBlock *newBB = dvmCompilerNewBB(kDalvikByteCode);
-                    newBB->id = blockID++;
-                    newBB->firstMIRInsn = insn;
-                    newBB->startOffset = insn->offset;
-                    newBB->lastMIRInsn = curBB->lastMIRInsn;
-                    curBB->lastMIRInsn = insn->prev;
-                    insn->prev->next = NULL;
-                    insn->prev = NULL;
-
-                    /*
-                     * If the insn is not an unconditional branch, set up the
-                     * fallthrough link.
-                     */
-                    if (!isUnconditionalBranch(curBB->lastMIRInsn)) {
-                        curBB->fallThrough = newBB;
-                    }
-
-                    /*
-                     * Fallthrough block of an invoke instruction needs to be
-                     * aligned to 4-byte boundary (alignment instruction to be
-                     * inserted later.
-                     */
-                    if (dexGetFlagsFromOpcode(curBB->lastMIRInsn->dalvikInsn.opcode)
-                            & kInstrInvoke) {
-                        newBB->isFallThroughFromInvoke = true;
-                    }
-
-                    /* enqueue the new block */
-                    blockList[cUnit->numBlocks++] = newBB;
-                    break;
-                }
+            if ((curBlock->fallThrough == NULL) &&
+                !dexIsGoto(flags) &&
+                !(flags & kInstrCanReturn)) {
+                curBlock->fallThrough = nextBlock;
+                dvmCompilerSetBit(nextBlock->predecessors, curBlock->id);
             }
+            curBlock = nextBlock;
         }
     }
 
-    if (numBlocks != cUnit->numBlocks) {
-        LOGE("Expect %d vs %d basic blocks\n", numBlocks, cUnit->numBlocks);
-        dvmCompilerAbort(cUnit);
-    }
+    /* Adjust this value accordingly once inlining is performed */
+    cUnit.numDalvikRegisters = cUnit.method->registersSize;
 
-    /* Connect the basic blocks through the taken links */
-    for (i = 0; i < numBlocks; i++) {
-        BasicBlock *curBB = blockList[i];
-        MIR *insn = curBB->lastMIRInsn;
-        unsigned int target = insn->offset;
-        bool isInvoke = false;
-        const Method *callee = NULL;
+    /* Verify if all blocks are connected as claimed */
+    /* FIXME - to be disabled in the future */
+    dvmCompilerDataFlowAnalysisDispatcher(&cUnit, verifyPredInfo,
+                                          kAllNodes,
+                                          false /* isIterative */);
 
-        findBlockBoundary(method, insn, target, &target, &isInvoke, &callee);
 
-        /* Found a block ended on a branch (not invoke) */
-        if (isInvoke == false && target != insn->offset) {
-            int j;
-            /* Forward branch */
-            if (target > insn->offset) {
-                j = i + 1;
-            } else {
-                /* Backward branch */
-                j = 0;
-            }
-            for (; j < numBlocks; j++) {
-                if (blockList[j]->firstMIRInsn->offset == target) {
-                    curBB->taken = blockList[j];
-                    break;
-                }
-            }
-        }
+    /* Perform SSA transformation for the whole method */
+    dvmCompilerMethodSSATransformation(&cUnit);
 
-        if (isInvoke) {
-            BasicBlock *newBB;
-            /* Monomorphic callee */
-            if (callee) {
-                newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton);
-                newBB->startOffset = 0;
-                newBB->containingMethod = callee;
-            /* Will resolve at runtime */
-            } else {
-                newBB = dvmCompilerNewBB(kChainingCellInvokePredicted);
-                newBB->startOffset = 0;
-            }
-            newBB->id = blockID++;
-            curBB->taken = newBB;
-            /* enqueue the new block */
-            blockList[cUnit->numBlocks++] = newBB;
-        }
-    }
+    if (cUnit.printMe) dumpCFG(&cUnit, "/data/tombstones/");
 
-    if (cUnit->numBlocks != numBlocks + numInvokeTargets) {
-        LOGE("Expect %d vs %d total blocks\n", numBlocks + numInvokeTargets,
-             cUnit->numBlocks);
-        dvmCompilerDumpCompilationUnit(cUnit);
-        dvmCompilerAbort(cUnit);
-    }
-
-    /* Set the instruction set to use (NOTE: later components may change it) */
-    cUnit->instructionSet = dvmCompilerInstructionSet();
-
-    /* Preparation for SSA conversion */
-    dvmInitializeSSAConversion(cUnit);
-
-    /* SSA analysis */
-    dvmCompilerNonLoopAnalysis(cUnit);
-
-    /* Needs to happen after SSA naming */
-    dvmCompilerInitializeRegAlloc(cUnit);
-
-    /* Allocate Registers */
-    dvmCompilerRegAlloc(cUnit);
-
-    /* Convert MIR to LIR, etc. */
-    dvmCompilerMIR2LIR(cUnit);
-
-    /* Convert LIR into machine code. */
-    dvmCompilerAssembleLIR(cUnit, info);
-
-    if (cUnit->assemblerStatus != kSuccess) {
-        return false;
-    }
-
-    dvmCompilerDumpCompilationUnit(cUnit);
-
+    /* Reset the compiler resource pool */
     dvmCompilerArenaReset();
 
-    return info->codeAddress != NULL;
+    return false;
 }