Extend a trace with a backward branch into a loop.

When seeing a trace that ends with a backward branch, exhaust all code
blocks reachable from that trace and try to identify if there exists a
non-nested loop. If the derived loop is found to be too complex or only
acyclic code is seen, revert to the original compilation mechanism to
translate a simple trace.

This CL uses the whole-method parser/dataflow analysis framework to
identify such loops. No optimization/codegen are performed yet.

Bug: 4086718

Change-Id: I19ed3ee53ea1cbda33940c533de8e9220e647156
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 1149aff..3fbdc64 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -50,6 +50,7 @@
 $(call add-clean-step, rm -rf $(OUT)/obj/SHARED_LIBRARIES/libdvm*)
 $(call add-clean-step, rm -rf $(OUT)/obj/SHARED_LIBRARIES/libdvm*)
 $(call add-clean-step, rm -rf $(OUT)/obj/SHARED_LIBRARIES/libdvm*)
+$(call add-clean-step, rm -rf $(OUT)/obj/SHARED_LIBRARIES/libdvm*)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index aea0b53..c9a776b 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -218,7 +218,7 @@
 	compiler/InlineTransformation.c \
 	compiler/IntermediateRep.c \
 	compiler/Dataflow.c \
-	compiler/MethodSSATransformation.c \
+	compiler/SSATransformation.c \
 	compiler/Loop.c \
 	compiler/Ralloc.c \
 	interp/Jit.c
diff --git a/vm/Globals.h b/vm/Globals.h
index ad28e14..df10e36 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -878,6 +878,9 @@
     /* Flag to dump all compiled code */
     bool printMe;
 
+    /* Per-process debug flag toggled when receiving a SIGUSR2 */
+    bool receivedSIGUSR2;
+
     /* Trace profiling mode */
     TraceProfilingModes profileMode;
 
diff --git a/vm/SignalCatcher.c b/vm/SignalCatcher.c
index 9381312..5a5e037 100644
--- a/vm/SignalCatcher.c
+++ b/vm/SignalCatcher.c
@@ -230,6 +230,7 @@
 static void handleSigUsr2(void)
 {
     static int codeCacheResetCount = 0;
+    gDvmJit.receivedSIGUSR2 ^= true;
     if ((--codeCacheResetCount & 7) == 0) {
         /* Dump all class pointers in the traces */
         dvmJitScanAllClassPointers(printAllClass);
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 2a0eef4..5d5036f 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -232,6 +232,7 @@
                 DataFlowAnalysisMode dfaMode,
                 bool isIterative);
 void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit);
+bool dvmCompilerBuildLoop(struct CompilationUnit *cUnit);
 void dvmCompilerStateRefresh(void);
 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
                                             const struct JitEntry *desc);
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index c807877..7b9987b 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -64,6 +64,12 @@
     kCatchEntry,
 } BBType;
 
+typedef enum JitMode {
+    kJitTrace = 0, // Acyclic - all instructions come from the trace descriptor
+    kJitLoop,      // Cycle - trace descriptor is used as a hint
+    kJitMethod,    // Whole method
+} JitMode;
+
 typedef struct ChainCellCounts {
     union {
         u1 count[kChainingCellLast]; /* include one more space for the gap # */
@@ -148,6 +154,7 @@
 typedef struct BasicBlock {
     int id;
     bool visited;
+    bool hidden;
     unsigned int startOffset;
     const Method *containingMethod;     // For blocks from the callee
     BBType blockType;
@@ -249,7 +256,7 @@
     const u2 *switchOverflowPad;
 
     /* New fields only for method-based compilation */
-    bool methodJitMode;
+    JitMode jitMode;
     int numReachableBlocks;
     int numDalvikRegisters;             // method->registersSize + inlined
     BasicBlock *entryBlock;
diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c
index 76744bd..26068a1 100644
--- a/vm/compiler/Dataflow.c
+++ b/vm/compiler/Dataflow.c
@@ -1694,7 +1694,6 @@
     const DecodedInstruction *insn = &mir->dalvikInsn;
     int opcode = insn->opcode;
     int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
-    int flags = dexGetFlagsFromOpcode(insn->opcode);
     char *ret;
     int length;
 
@@ -1719,6 +1718,7 @@
         strcpy(buffer, dexGetOpcodeName(opcode));
     }
 
+    int flags = dexGetFlagsFromOpcode(opcode);
     /* For branches, decode the instructions to print out the branch targets */
     if (flags & kInstrCanBranch) {
         InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
@@ -2393,6 +2393,7 @@
     while (true) {
         BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
         if (bb == NULL) break;
+        if (bb->hidden == true) continue;
         if (bb->blockType == kDalvikByteCode ||
             bb->blockType == kTraceEntryBlock ||
             bb->blockType == kMethodEntryBlock ||
@@ -2430,6 +2431,7 @@
                 BasicBlock *bb =
                     (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
                 if (bb == NULL) break;
+                if (bb->hidden == true) continue;
                 change |= (*func)(cUnit, bb);
             }
         }
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 8663c5c..8272fb6 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -416,6 +416,1072 @@
 }
 
 /*
+ * Since we are including instructions from possibly a cold method into the
+ * current trace, we need to make sure that all the associated information
+ * with the callee is properly initialized. If not, we punt on this inline
+ * target.
+ *
+ * TODO: volatile instructions will be handled later.
+ */
+bool dvmCompilerCanIncludeThisInstruction(const Method *method,
+                                          const DecodedInstruction *insn)
+{
+    switch (insn->opcode) {
+        case OP_NEW_INSTANCE:
+        case OP_NEW_INSTANCE_JUMBO:
+        case OP_CHECK_CAST:
+        case OP_CHECK_CAST_JUMBO: {
+            ClassObject *classPtr = (ClassObject *)(void*)
+              (method->clazz->pDvmDex->pResClasses[insn->vB]);
+
+            /* Class hasn't been initialized yet */
+            if (classPtr == NULL) {
+                return false;
+            }
+            return true;
+        }
+        case OP_SGET:
+        case OP_SGET_JUMBO:
+        case OP_SGET_WIDE:
+        case OP_SGET_WIDE_JUMBO:
+        case OP_SGET_OBJECT:
+        case OP_SGET_OBJECT_JUMBO:
+        case OP_SGET_BOOLEAN:
+        case OP_SGET_BOOLEAN_JUMBO:
+        case OP_SGET_BYTE:
+        case OP_SGET_BYTE_JUMBO:
+        case OP_SGET_CHAR:
+        case OP_SGET_CHAR_JUMBO:
+        case OP_SGET_SHORT:
+        case OP_SGET_SHORT_JUMBO:
+        case OP_SPUT:
+        case OP_SPUT_JUMBO:
+        case OP_SPUT_WIDE:
+        case OP_SPUT_WIDE_JUMBO:
+        case OP_SPUT_OBJECT:
+        case OP_SPUT_OBJECT_JUMBO:
+        case OP_SPUT_BOOLEAN:
+        case OP_SPUT_BOOLEAN_JUMBO:
+        case OP_SPUT_BYTE:
+        case OP_SPUT_BYTE_JUMBO:
+        case OP_SPUT_CHAR:
+        case OP_SPUT_CHAR_JUMBO:
+        case OP_SPUT_SHORT:
+        case OP_SPUT_SHORT_JUMBO: {
+            void *fieldPtr = (void*)
+              (method->clazz->pDvmDex->pResFields[insn->vB]);
+
+            if (fieldPtr == NULL) {
+                return false;
+            }
+            return true;
+        }
+        case OP_INVOKE_SUPER:
+        case OP_INVOKE_SUPER_RANGE:
+        case OP_INVOKE_SUPER_JUMBO: {
+            int mIndex = method->clazz->pDvmDex->
+                pResMethods[insn->vB]->methodIndex;
+            const Method *calleeMethod = method->clazz->super->vtable[mIndex];
+            if (calleeMethod == NULL) {
+                return false;
+            }
+            return true;
+        }
+        case OP_INVOKE_SUPER_QUICK:
+        case OP_INVOKE_SUPER_QUICK_RANGE: {
+            const Method *calleeMethod = method->clazz->super->vtable[insn->vB];
+            if (calleeMethod == NULL) {
+                return false;
+            }
+            return true;
+        }
+        case OP_INVOKE_STATIC:
+        case OP_INVOKE_STATIC_RANGE:
+        case OP_INVOKE_STATIC_JUMBO:
+        case OP_INVOKE_DIRECT:
+        case OP_INVOKE_DIRECT_RANGE:
+        case OP_INVOKE_DIRECT_JUMBO: {
+            const Method *calleeMethod =
+                method->clazz->pDvmDex->pResMethods[insn->vB];
+            if (calleeMethod == NULL) {
+                return false;
+            }
+            return true;
+        }
+        case OP_CONST_CLASS:
+        case OP_CONST_CLASS_JUMBO: {
+            void *classPtr = (void*)
+                (method->clazz->pDvmDex->pResClasses[insn->vB]);
+
+            if (classPtr == NULL) {
+                return false;
+            }
+            return true;
+        }
+        case OP_CONST_STRING_JUMBO:
+        case OP_CONST_STRING: {
+            void *strPtr = (void*)
+                (method->clazz->pDvmDex->pResStrings[insn->vB]);
+
+            if (strPtr == NULL) {
+                return false;
+            }
+            return true;
+        }
+        default:
+            return true;
+    }
+}
+
+/* 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;
+
+    /* 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) {
+            SuccessorBlockInfo *successorBlockInfo =
+                (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
+            if (successorBlockInfo == NULL) break;
+            BasicBlock *bb = successorBlockInfo->block;
+            dvmCompilerClearBit(bb->predecessors, origBlock->id);
+            dvmCompilerSetBit(bb->predecessors, bottomBlock->id);
+        }
+    }
+
+    origBlock->lastMIRInsn = insn->prev;
+
+    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 startOffset[80];
+    sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
+    char *fileName = (char *) dvmCompilerNew(
+                                  strlen(dirPrefix) +
+                                  strlen(method->clazz->descriptor) +
+                                  strlen(method->name) +
+                                  strlen(signature) +
+                                  strlen(startOffset) +
+                                  strlen(".dot") + 1, true);
+    sprintf(fileName, "%s%s%s%s%s.dot", dirPrefix,
+            method->clazz->descriptor, method->name, signature, startOffset);
+    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=record,label = \"{ \\\n",
+                    bb->startOffset);
+            const MIR *mir;
+            for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+                fprintf(file, "    {%04x %s\\l}%s\\\n", mir->offset,
+                        mir->ssaRep ?
+                            dvmCompilerFullDisassembler(cUnit, mir) :
+                            dexGetOpcodeName(mir->dalvikInsn.opcode),
+                        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);
+            SuccessorBlockInfo *successorBlockInfo =
+                (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
+
+            int succId = 0;
+            while (true) {
+                if (successorBlockInfo == NULL) break;
+
+                BasicBlock *destBlock = successorBlockInfo->block;
+                SuccessorBlockInfo *nextSuccessorBlockInfo =
+                  (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
+
+                fprintf(file, "    {<f%d> %04x: %04x\\l}%s\\\n",
+                        succId++,
+                        successorBlockInfo->key,
+                        destBlock->startOffset,
+                        (nextSuccessorBlockInfo != NULL) ? " | " : " ");
+
+                successorBlockInfo = nextSuccessorBlockInfo;
+            }
+            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) {
+                    SuccessorBlockInfo *successorBlockInfo =
+                        (SuccessorBlockInfo *)
+                            dvmGrowableListIteratorNext(&iterator);
+                    if (successorBlockInfo == NULL) break;
+
+                    BasicBlock *destBlock = successorBlockInfo->block;
+
+                    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 1
+        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) {
+                SuccessorBlockInfo *successorBlockInfo =
+                    (SuccessorBlockInfo *)
+                        dvmGrowableListIteratorNext(&iterator);
+                if (successorBlockInfo == NULL) break;
+                BasicBlock *succBB = successorBlockInfo->block;
+                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, "/sdcard/cfg/");
+            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;
+            }
+
+            /*
+             * Create dummy catch blocks first. Since these are created before
+             * other blocks are processed, "split" is specified as false.
+             */
+            findBlock(cUnit, handler->address,
+                      /* split */
+                      false,
+                      /* create */
+                      true);
+        }
+
+        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,
+                                                 /*
+                                                  * If the method is processed
+                                                  * in sequential order from the
+                                                  * beginning, we don't need to
+                                                  * specify split for continue
+                                                  * blocks. However, this
+                                                  * routine can be called by
+                                                  * compileLoop, which starts
+                                                  * parsing the method from an
+                                                  * arbitrary address in the
+                                                  * method body.
+                                                  */
+                                                 true,
+                                                 /* 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 *keyTable;
+    int *targetTable;
+    int i;
+    int firstKey;
+
+    /*
+     * 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];
+        firstKey = switchData[2] | (switchData[3] << 16);
+        targetTable = (int *) &switchData[4];
+        keyTable = NULL;        // Make the compiler happy
+    /*
+     * 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];
+        keyTable = (int *) &switchData[2];
+        targetTable = (int *) &switchData[2 + size*2];
+        firstKey = 0;   // To make the compiler happy
+    }
+
+    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);
+        SuccessorBlockInfo *successorBlockInfo =
+            (SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
+                                                  false);
+        successorBlockInfo->block = caseBlock;
+        successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
+                                  firstKey + i : keyTable[i];
+        dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
+                              (intptr_t) successorBlockInfo);
+        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);
+
+    /* 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);
+
+            SuccessorBlockInfo *successorBlockInfo =
+              (SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
+                                                    false);
+            successorBlockInfo->block = catchBlock;
+            successorBlockInfo->key = handler->typeIdx;
+            dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
+                                  (intptr_t) successorBlockInfo);
+            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.
+ *
+ * TODO: implementation will be revisited when the trace builder can provide
+ * whole-method traces.
+ */
+bool dvmCompileMethod(const Method *method, JitTranslationInfo *info)
+{
+    CompilationUnit cUnit;
+    const DexCode *dexCode = dvmGetMethodCode(method);
+    const u2 *codePtr = dexCode->insns;
+    const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
+    int numBlocks = 0;
+    unsigned int curOffset = 0;
+
+    /* Method already compiled */
+    if (dvmJitGetMethodAddr(codePtr)) {
+        info->codeAddress = NULL;
+        return false;
+    }
+
+    memset(&cUnit, 0, sizeof(cUnit));
+    cUnit.method = method;
+
+    cUnit.jitMode = kJitMethod;
+
+    /* Initialize the block list */
+    dvmInitGrowableList(&cUnit.blockList, 4);
+
+    /*
+     * FIXME - PC reconstruction list won't be needed after the codegen routines
+     * are enhanced to true method mode.
+     */
+    /* Initialize the PC reconstruction list */
+    dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
+
+    /* Allocate the bit-vector to track the beginning of basic blocks */
+    BitVector *tryBlockAddr = dvmCompilerAllocBitVector(dexCode->insnsSize,
+                                                        true /* expandable */);
+    cUnit.tryBlockAddr = tryBlockAddr;
+
+    /* 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);
+
+    /*
+     * 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);
+        insn->offset = curOffset;
+        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
+        insn->width = width;
+
+        /* Terminate when the data section is seen */
+        if (width == 0)
+            break;
+
+        dvmCompilerAppendMIR(curBlock, insn);
+
+        codePtr += width;
+        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);
+
+            if ((curBlock->fallThrough == NULL) &&
+                (flags & kInstrCanContinue)) {
+                curBlock->fallThrough = nextBlock;
+                dvmCompilerSetBit(nextBlock->predecessors, curBlock->id);
+            }
+            curBlock = nextBlock;
+        }
+    }
+
+    if (cUnit.printMe) {
+        dvmCompilerDumpCompilationUnit(&cUnit);
+    }
+
+    /* Adjust this value accordingly once inlining is performed */
+    cUnit.numDalvikRegisters = cUnit.method->registersSize;
+
+    /* Verify if all blocks are connected as claimed */
+    /* FIXME - to be disabled in the future */
+    dvmCompilerDataFlowAnalysisDispatcher(&cUnit, verifyPredInfo,
+                                          kAllNodes,
+                                          false /* isIterative */);
+
+
+    /* Perform SSA transformation for the whole method */
+    dvmCompilerMethodSSATransformation(&cUnit);
+
+    dvmCompilerInitializeRegAlloc(&cUnit);  // Needs to happen after SSA naming
+
+    /* Allocate Registers using simple local allocation scheme */
+    dvmCompilerLocalRegAlloc(&cUnit);
+
+    /* Convert MIR to LIR, etc. */
+    dvmCompilerMethodMIR2LIR(&cUnit);
+
+    // Debugging only
+    //dumpCFG(&cUnit, "/sdcard/cfg/");
+
+    /* Method is not empty */
+    if (cUnit.firstLIRInsn) {
+        /* Convert LIR into machine code. Loop for recoverable retries */
+        do {
+            dvmCompilerAssembleLIR(&cUnit, info);
+            cUnit.assemblerRetries++;
+            if (cUnit.printMe && cUnit.assemblerStatus != kSuccess)
+                LOGD("Assembler abort #%d on %d",cUnit.assemblerRetries,
+                      cUnit.assemblerStatus);
+        } while (cUnit.assemblerStatus == kRetryAll);
+
+        if (cUnit.printMe) {
+            dvmCompilerCodegenDump(&cUnit);
+        }
+
+        if (info->codeAddress) {
+            dvmJitSetCodeAddr(dexCode->insns, info->codeAddress,
+                              info->instructionSet, true, 0);
+            /*
+             * Clear the codeAddress for the enclosing trace to reuse the info
+             */
+            info->codeAddress = NULL;
+        }
+    }
+
+    return false;
+}
+
+/* Extending the trace by crawling the code from curBlock */
+static bool exhaustTrace(CompilationUnit *cUnit, BasicBlock *curBlock)
+{
+    unsigned int curOffset = curBlock->startOffset;
+    const u2 *codePtr = cUnit->method->insns + curOffset;
+
+    if (curBlock->visited == true) return false;
+
+    curBlock->visited = true;
+
+    if (curBlock->blockType == kMethodEntryBlock ||
+        curBlock->blockType == kMethodExitBlock) {
+        return false;
+    }
+
+    /*
+     * Block has been parsed - check the taken/fallThrough in case it is a split
+     * block.
+     */
+    if (curBlock->firstMIRInsn != NULL) {
+          bool changed = false;
+          if (curBlock->taken)
+              changed |= exhaustTrace(cUnit, curBlock->taken);
+          if (curBlock->fallThrough)
+              changed |= exhaustTrace(cUnit, curBlock->fallThrough);
+          return changed;
+    }
+    while (true) {
+        MIR *insn = (MIR *) dvmCompilerNew(sizeof(MIR), true);
+        insn->offset = curOffset;
+        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
+        insn->width = width;
+
+        /* Terminate when the data section is seen */
+        if (width == 0)
+            break;
+
+        dvmCompilerAppendMIR(curBlock, insn);
+
+        codePtr += width;
+        int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
+
+        /* Stop extending the trace after seeing these instructions */
+        if (flags & (kInstrCanReturn | kInstrCanSwitch | kInstrInvoke)) {
+            curBlock->fallThrough = cUnit->exitBlock;
+            dvmCompilerSetBit(cUnit->exitBlock->predecessors, curBlock->id);
+            break;
+        } else if (flags & kInstrCanBranch) {
+            processCanBranch(cUnit, curBlock, insn, curOffset, width, flags,
+                             codePtr, NULL);
+            if (curBlock->taken) {
+                exhaustTrace(cUnit, curBlock->taken);
+            }
+            if (curBlock->fallThrough) {
+                exhaustTrace(cUnit, curBlock->fallThrough);
+            }
+            break;
+        }
+        curOffset += width;
+    }
+    return true;
+}
+
+/* Compile a loop */
+static bool compileLoop(CompilationUnit *cUnit, unsigned int startOffset,
+                        JitTraceDescription *desc, int numMaxInsts,
+                        JitTranslationInfo *info, jmp_buf *bailPtr,
+                        int optHints)
+{
+    int numBlocks = 0;
+    unsigned int curOffset = startOffset;
+    bool changed;
+
+    cUnit->jitMode = kJitLoop;
+
+    /* Initialize the block list */
+    dvmInitGrowableList(&cUnit->blockList, 4);
+
+    /* Initialize the PC reconstruction list */
+    dvmInitGrowableList(&cUnit->pcReconstructionList, 8);
+
+    /* Create the default entry and exit blocks and enter them to the list */
+    BasicBlock *entryBlock = dvmCompilerNewBB(kMethodEntryBlock, numBlocks++);
+    entryBlock->startOffset = curOffset;
+    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 = curOffset;
+
+    dvmInsertGrowableList(&cUnit->blockList, (intptr_t) curBlock);
+    entryBlock->fallThrough = curBlock;
+    dvmCompilerSetBit(curBlock->predecessors, entryBlock->id);
+
+    /*
+     * Store back the number of blocks since new blocks may be created of
+     * accessing cUnit.
+     */
+    cUnit->numBlocks = numBlocks;
+
+    do {
+        dvmCompilerDataFlowAnalysisDispatcher(cUnit,
+                                              dvmCompilerClearVisitedFlag,
+                                              kAllNodes,
+                                              false /* isIterative */);
+        changed = exhaustTrace(cUnit, curBlock);
+    } while (changed);
+
+    cUnit->numDalvikRegisters = cUnit->method->registersSize;
+
+    /* Verify if all blocks are connected as claimed */
+    /* FIXME - to be disabled in the future */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, verifyPredInfo,
+                                          kAllNodes,
+                                          false /* isIterative */);
+
+
+    /* Try to identify a loop */
+    if (!dvmCompilerBuildLoop(cUnit))
+        goto bail;
+
+    dvmCompilerInitializeRegAlloc(cUnit);
+
+    /* Allocate Registers using simple local allocation scheme */
+    dvmCompilerLocalRegAlloc(cUnit);
+
+    if (gDvmJit.receivedSIGUSR2) {
+        dumpCFG(cUnit, "/sdcard/cfg/");
+    }
+
+bail:
+    /* Retry the original trace with JIT_OPT_NO_LOOP disabled */
+    dvmCompilerArenaReset();
+    return dvmCompileTrace(desc, numMaxInsts, info, bailPtr,
+                           optHints | JIT_OPT_NO_LOOP);
+}
+
+/*
  * Main entry point to start trace compilation. Basic blocks are constructed
  * first and they will be passed to the codegen routines to convert Dalvik
  * bytecode into machine code.
@@ -427,6 +1493,7 @@
     const DexCode *dexCode = dvmGetMethodCode(desc->method);
     const JitTraceRun* currRun = &desc->trace[0];
     unsigned int curOffset = currRun->info.frag.startOffset;
+    unsigned int startOffset = curOffset;
     unsigned int numInsts = currRun->info.frag.numInsts;
     const u2 *codePtr = dexCode->insns + curOffset;
     int traceSize = 0;  // # of half-words
@@ -670,6 +1737,17 @@
             cUnit.hasInvoke = true;
         }
 
+        /* Backward branch seen */
+        if (isInvoke == false &&
+            (flags & kInstrCanBranch) != 0 &&
+            targetOffset < curOffset &&
+            (optHints & JIT_OPT_NO_LOOP) == 0) {
+            dvmCompilerArenaReset();
+            /* TODO - constructed loop is abandoned for now */
+            return compileLoop(&cUnit, startOffset, desc, numMaxInsts,
+                               info, bailPtr, optHints);
+        }
+
         /* No backward branch in the trace - start searching the next BB */
         size_t searchBlockId;
         for (searchBlockId = blockId+1; searchBlockId < blockList->numUsed;
@@ -974,910 +2052,3 @@
 
     return info->codeAddress != NULL;
 }
-
-/*
- * Since we are including instructions from possibly a cold method into the
- * current trace, we need to make sure that all the associated information
- * with the callee is properly initialized. If not, we punt on this inline
- * target.
- *
- * TODO: volatile instructions will be handled later.
- */
-bool dvmCompilerCanIncludeThisInstruction(const Method *method,
-                                          const DecodedInstruction *insn)
-{
-    switch (insn->opcode) {
-        case OP_NEW_INSTANCE:
-        case OP_NEW_INSTANCE_JUMBO:
-        case OP_CHECK_CAST:
-        case OP_CHECK_CAST_JUMBO: {
-            ClassObject *classPtr = (ClassObject *)(void*)
-              (method->clazz->pDvmDex->pResClasses[insn->vB]);
-
-            /* Class hasn't been initialized yet */
-            if (classPtr == NULL) {
-                return false;
-            }
-            return true;
-        }
-        case OP_SGET:
-        case OP_SGET_JUMBO:
-        case OP_SGET_WIDE:
-        case OP_SGET_WIDE_JUMBO:
-        case OP_SGET_OBJECT:
-        case OP_SGET_OBJECT_JUMBO:
-        case OP_SGET_BOOLEAN:
-        case OP_SGET_BOOLEAN_JUMBO:
-        case OP_SGET_BYTE:
-        case OP_SGET_BYTE_JUMBO:
-        case OP_SGET_CHAR:
-        case OP_SGET_CHAR_JUMBO:
-        case OP_SGET_SHORT:
-        case OP_SGET_SHORT_JUMBO:
-        case OP_SPUT:
-        case OP_SPUT_JUMBO:
-        case OP_SPUT_WIDE:
-        case OP_SPUT_WIDE_JUMBO:
-        case OP_SPUT_OBJECT:
-        case OP_SPUT_OBJECT_JUMBO:
-        case OP_SPUT_BOOLEAN:
-        case OP_SPUT_BOOLEAN_JUMBO:
-        case OP_SPUT_BYTE:
-        case OP_SPUT_BYTE_JUMBO:
-        case OP_SPUT_CHAR:
-        case OP_SPUT_CHAR_JUMBO:
-        case OP_SPUT_SHORT:
-        case OP_SPUT_SHORT_JUMBO: {
-            void *fieldPtr = (void*)
-              (method->clazz->pDvmDex->pResFields[insn->vB]);
-
-            if (fieldPtr == NULL) {
-                return false;
-            }
-            return true;
-        }
-        case OP_INVOKE_SUPER:
-        case OP_INVOKE_SUPER_RANGE:
-        case OP_INVOKE_SUPER_JUMBO: {
-            int mIndex = method->clazz->pDvmDex->
-                pResMethods[insn->vB]->methodIndex;
-            const Method *calleeMethod = method->clazz->super->vtable[mIndex];
-            if (calleeMethod == NULL) {
-                return false;
-            }
-            return true;
-        }
-        case OP_INVOKE_SUPER_QUICK:
-        case OP_INVOKE_SUPER_QUICK_RANGE: {
-            const Method *calleeMethod = method->clazz->super->vtable[insn->vB];
-            if (calleeMethod == NULL) {
-                return false;
-            }
-            return true;
-        }
-        case OP_INVOKE_STATIC:
-        case OP_INVOKE_STATIC_RANGE:
-        case OP_INVOKE_STATIC_JUMBO:
-        case OP_INVOKE_DIRECT:
-        case OP_INVOKE_DIRECT_RANGE:
-        case OP_INVOKE_DIRECT_JUMBO: {
-            const Method *calleeMethod =
-                method->clazz->pDvmDex->pResMethods[insn->vB];
-            if (calleeMethod == NULL) {
-                return false;
-            }
-            return true;
-        }
-        case OP_CONST_CLASS:
-        case OP_CONST_CLASS_JUMBO: {
-            void *classPtr = (void*)
-                (method->clazz->pDvmDex->pResClasses[insn->vB]);
-
-            if (classPtr == NULL) {
-                return false;
-            }
-            return true;
-        }
-        case OP_CONST_STRING_JUMBO:
-        case OP_CONST_STRING: {
-            void *strPtr = (void*)
-                (method->clazz->pDvmDex->pResStrings[insn->vB]);
-
-            if (strPtr == NULL) {
-                return false;
-            }
-            return true;
-        }
-        default:
-            return true;
-    }
-}
-
-/* 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;
-
-    /* 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) {
-            SuccessorBlockInfo *successorBlockInfo =
-                (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
-            if (successorBlockInfo == NULL) break;
-            BasicBlock *bb = successorBlockInfo->block;
-            dvmCompilerClearBit(bb->predecessors, origBlock->id);
-            dvmCompilerSetBit(bb->predecessors, bottomBlock->id);
-        }
-    }
-
-    origBlock->lastMIRInsn = insn->prev;
-
-    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=record,label = \"{ \\\n",
-                    bb->startOffset);
-            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);
-            SuccessorBlockInfo *successorBlockInfo =
-                (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
-
-            int succId = 0;
-            while (true) {
-                if (successorBlockInfo == NULL) break;
-
-                BasicBlock *destBlock = successorBlockInfo->block;
-                SuccessorBlockInfo *nextSuccessorBlockInfo =
-                  (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
-
-                fprintf(file, "    {<f%d> %04x: %04x\\l}%s\\\n",
-                        succId++,
-                        successorBlockInfo->key,
-                        destBlock->startOffset,
-                        (nextSuccessorBlockInfo != NULL) ? " | " : " ");
-
-                successorBlockInfo = nextSuccessorBlockInfo;
-            }
-            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) {
-                    SuccessorBlockInfo *successorBlockInfo =
-                        (SuccessorBlockInfo *)
-                            dvmGrowableListIteratorNext(&iterator);
-                    if (successorBlockInfo == NULL) break;
-
-                    BasicBlock *destBlock = successorBlockInfo->block;
-
-                    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) {
-                SuccessorBlockInfo *successorBlockInfo =
-                    (SuccessorBlockInfo *)
-                        dvmGrowableListIteratorNext(&iterator);
-                if (successorBlockInfo == NULL) break;
-                BasicBlock *succBB = successorBlockInfo->block;
-                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;
-            }
-
-            /*
-             * Create dummy catch blocks first. Since these are created before
-             * other blocks are processed, "split" is specified as false.
-             */
-            findBlock(cUnit, handler->address,
-                      /* split */
-                      false,
-                      /* create */
-                      true);
-        }
-
-        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 *keyTable;
-    int *targetTable;
-    int i;
-    int firstKey;
-
-    /*
-     * 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];
-        firstKey = switchData[2] | (switchData[3] << 16);
-        targetTable = (int *) &switchData[4];
-        keyTable = NULL;        // Make the compiler happy
-    /*
-     * 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];
-        keyTable = (int *) &switchData[2];
-        targetTable = (int *) &switchData[2 + size*2];
-        firstKey = 0;   // To make the compiler happy
-    }
-
-    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);
-        SuccessorBlockInfo *successorBlockInfo =
-            (SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
-                                                  false);
-        successorBlockInfo->block = caseBlock;
-        successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
-                                  firstKey + i : keyTable[i];
-        dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
-                              (intptr_t) successorBlockInfo);
-        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);
-
-    /* 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);
-
-            SuccessorBlockInfo *successorBlockInfo =
-              (SuccessorBlockInfo *) dvmCompilerNew(sizeof(SuccessorBlockInfo),
-                                                    false);
-            successorBlockInfo->block = catchBlock;
-            successorBlockInfo->key = handler->typeIdx;
-            dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
-                                  (intptr_t) successorBlockInfo);
-            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.
- *
- * TODO: implementation will be revisited when the trace builder can provide
- * whole-method traces.
- */
-bool dvmCompileMethod(const Method *method, JitTranslationInfo *info)
-{
-    CompilationUnit cUnit;
-    const DexCode *dexCode = dvmGetMethodCode(method);
-    const u2 *codePtr = dexCode->insns;
-    const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
-    int numBlocks = 0;
-    unsigned int curOffset = 0;
-
-    /* Method already compiled */
-    if (dvmJitGetMethodAddr(codePtr)) {
-        info->codeAddress = NULL;
-        return false;
-    }
-
-    memset(&cUnit, 0, sizeof(cUnit));
-    cUnit.method = method;
-
-    cUnit.methodJitMode = true;
-
-    /* Initialize the block list */
-    dvmInitGrowableList(&cUnit.blockList, 4);
-
-    /*
-     * FIXME - PC reconstruction list won't be needed after the codegen routines
-     * are enhanced to true method mode.
-     */
-    /* Initialize the PC reconstruction list */
-    dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
-
-    /* Allocate the bit-vector to track the beginning of basic blocks */
-    BitVector *tryBlockAddr = dvmCompilerAllocBitVector(dexCode->insnsSize,
-                                                        true /* expandable */);
-    cUnit.tryBlockAddr = tryBlockAddr;
-
-    /* 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);
-
-    /*
-     * 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);
-        insn->offset = curOffset;
-        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
-        insn->width = width;
-
-        /* Terminate when the data section is seen */
-        if (width == 0)
-            break;
-
-        dvmCompilerAppendMIR(curBlock, insn);
-
-        codePtr += width;
-        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);
-
-            if ((curBlock->fallThrough == NULL) &&
-                (flags & kInstrCanContinue)) {
-                curBlock->fallThrough = nextBlock;
-                dvmCompilerSetBit(nextBlock->predecessors, curBlock->id);
-            }
-            curBlock = nextBlock;
-        }
-    }
-
-    if (cUnit.printMe) {
-        dvmCompilerDumpCompilationUnit(&cUnit);
-    }
-
-    /* Adjust this value accordingly once inlining is performed */
-    cUnit.numDalvikRegisters = cUnit.method->registersSize;
-
-    /* Verify if all blocks are connected as claimed */
-    /* FIXME - to be disabled in the future */
-    dvmCompilerDataFlowAnalysisDispatcher(&cUnit, verifyPredInfo,
-                                          kAllNodes,
-                                          false /* isIterative */);
-
-
-    /* Perform SSA transformation for the whole method */
-    dvmCompilerMethodSSATransformation(&cUnit);
-
-    dvmCompilerInitializeRegAlloc(&cUnit);  // Needs to happen after SSA naming
-
-    /* Allocate Registers using simple local allocation scheme */
-    dvmCompilerLocalRegAlloc(&cUnit);
-
-    /* Convert MIR to LIR, etc. */
-    dvmCompilerMethodMIR2LIR(&cUnit);
-
-    // Debugging only
-    //dumpCFG(&cUnit, "/data/tombstones/");
-
-    /* Method is not empty */
-    if (cUnit.firstLIRInsn) {
-        /* Convert LIR into machine code. Loop for recoverable retries */
-        do {
-            dvmCompilerAssembleLIR(&cUnit, info);
-            cUnit.assemblerRetries++;
-            if (cUnit.printMe && cUnit.assemblerStatus != kSuccess)
-                LOGD("Assembler abort #%d on %d",cUnit.assemblerRetries,
-                      cUnit.assemblerStatus);
-        } while (cUnit.assemblerStatus == kRetryAll);
-
-        if (cUnit.printMe) {
-            dvmCompilerCodegenDump(&cUnit);
-        }
-
-        if (info->codeAddress) {
-            dvmJitSetCodeAddr(dexCode->insns, info->codeAddress,
-                              info->instructionSet, true, 0);
-            /*
-             * Clear the codeAddress for the enclosing trace to reuse the info
-             */
-            info->codeAddress = NULL;
-        }
-    }
-
-    return false;
-}
diff --git a/vm/compiler/Loop.c b/vm/compiler/Loop.c
index 9ee430d..b9ad3d3 100644
--- a/vm/compiler/Loop.c
+++ b/vm/compiler/Loop.c
@@ -552,3 +552,125 @@
     genHoistedChecks(cUnit);
     return true;
 }
+
+void resetBlockEdges(BasicBlock *bb)
+{
+    bb->taken = NULL;
+    bb->fallThrough = NULL;
+    bb->successorBlockList.blockListType = kNotUsed;
+}
+
+static bool clearPredecessorVector(struct CompilationUnit *cUnit,
+                                   struct BasicBlock *bb)
+{
+    dvmClearAllBits(bb->predecessors);
+    return false;
+}
+
+bool dvmCompilerFilterLoopBlocks(CompilationUnit *cUnit)
+{
+    BasicBlock *firstBB = cUnit->entryBlock->fallThrough;
+
+    int numPred = dvmCountSetBits(firstBB->predecessors);
+    /*
+     * A loop body should have at least two incoming edges. Here we go with the
+     * simple case and only form loops if numPred == 2.
+     */
+    if (numPred != 2) return false;
+
+    BitVectorIterator bvIterator;
+    GrowableList *blockList = &cUnit->blockList;
+    BasicBlock *predBB = NULL;
+
+    dvmBitVectorIteratorInit(firstBB->predecessors, &bvIterator);
+    while (true) {
+        int predIdx = dvmBitVectorIteratorNext(&bvIterator);
+        if (predIdx == -1) break;
+        predBB = (BasicBlock *) dvmGrowableListGetElement(blockList, predIdx);
+        if (predBB != cUnit->entryBlock) break;
+    }
+
+    /* Used to record which block is in the loop */
+    dvmClearAllBits(cUnit->tempBlockV);
+
+    dvmCompilerSetBit(cUnit->tempBlockV, predBB->id);
+
+    /* Form a loop by only including iDom block that is also a predecessor */
+    while (predBB != firstBB) {
+        BasicBlock *iDom = predBB->iDom;
+        if (!dvmIsBitSet(predBB->predecessors, iDom->id)) {
+            return false;
+        /*
+         * And don't form nested loops (ie by detecting if the branch target
+         * of iDom dominates iDom).
+         */
+        } else if (iDom->taken &&
+                   dvmIsBitSet(iDom->dominators, iDom->taken->id) &&
+                   iDom != firstBB) {
+            return false;
+        }
+        dvmCompilerSetBit(cUnit->tempBlockV, iDom->id);
+        predBB = iDom;
+    }
+
+    /* Add the entry block and first block */
+    dvmCompilerSetBit(cUnit->tempBlockV, firstBB->id);
+    dvmCompilerSetBit(cUnit->tempBlockV, cUnit->entryBlock->id);
+
+    /* Now mark blocks not included in the loop as hidden */
+    GrowableListIterator iterator;
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
+    while (true) {
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
+        if (!dvmIsBitSet(cUnit->tempBlockV, bb->id)) {
+            bb->hidden = true;
+            /* Clear the insn list */
+            bb->firstMIRInsn = bb->lastMIRInsn = NULL;
+            resetBlockEdges(bb);
+        }
+    }
+
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, clearPredecessorVector,
+                                          kAllNodes, false /* isIterative */);
+
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
+    while (true) {
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
+        if (dvmIsBitSet(cUnit->tempBlockV, bb->id)) {
+            if (bb->taken) {
+                /*
+                 * exit block means we run into control-flow that we don't want
+                 * to handle.
+                 */
+                if (bb->taken == cUnit->exitBlock) {
+                    return false;
+                }
+                if (bb->taken->hidden) {
+                    bb->taken->blockType = kChainingCellNormal;
+                    bb->taken->hidden = false;
+                }
+                dvmCompilerSetBit(bb->taken->predecessors, bb->id);
+            }
+            if (bb->fallThrough) {
+                /*
+                 * exit block means we run into control-flow that we don't want
+                 * to handle.
+                 */
+                if (bb->fallThrough == cUnit->exitBlock) {
+                    return false;
+                }
+                if (bb->fallThrough->hidden) {
+                    bb->fallThrough->blockType = kChainingCellNormal;
+                    bb->fallThrough->hidden = false;
+                }
+                dvmCompilerSetBit(bb->fallThrough->predecessors, bb->id);
+            }
+            /* Loop blocks shouldn't contain any successor blocks (yet) */
+            assert(bb->successorBlockList.blockListType == kNotUsed);
+        }
+    }
+
+    return true;
+}
diff --git a/vm/compiler/Loop.h b/vm/compiler/Loop.h
index 8981dae..ec87e57 100644
--- a/vm/compiler/Loop.h
+++ b/vm/compiler/Loop.h
@@ -34,4 +34,6 @@
     bool bodyIsClean;                   // loop body cannot throw any exceptions
 } LoopAnalysis;
 
+bool dvmCompilerFilterLoopBlocks(CompilationUnit *cUnit);
+
 #endif /* _DALVIK_VM_LOOP */
diff --git a/vm/compiler/MethodSSATransformation.c b/vm/compiler/SSATransformation.c
similarity index 82%
rename from vm/compiler/MethodSSATransformation.c
rename to vm/compiler/SSATransformation.c
index bacf43c..b045a1e 100644
--- a/vm/compiler/MethodSSATransformation.c
+++ b/vm/compiler/SSATransformation.c
@@ -23,7 +23,7 @@
 static void recordDFSPreOrder(CompilationUnit *cUnit, BasicBlock *block)
 {
 
-    if (block->visited) return;
+    if (block->visited || block->hidden) return;
     block->visited = true;
 
     /* Enqueue the block id */
@@ -49,9 +49,13 @@
 /* Sort the blocks by the Depth-First-Search pre-order */
 static void computeDFSOrder(CompilationUnit *cUnit)
 {
-    /* Initialize the DFS order list */
-    dvmInitGrowableList(&cUnit->dfsOrder, cUnit->numBlocks);
-
+    /* Initialize or reset the DFS order list */
+    if (cUnit->dfsOrder.elemList == NULL) {
+        dvmInitGrowableList(&cUnit->dfsOrder, cUnit->numBlocks);
+    } else {
+        /* Just reset the used length on the counter */
+        cUnit->dfsOrder.numUsed = 0;
+    }
 
     dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerClearVisitedFlag,
                                           kAllNodes,
@@ -101,14 +105,16 @@
                                           kAllNodes,
                                           false /* isIterative */);
 
-    /*
-     * Also set the incoming parameters as defs in the entry block.
-     * Only need to handle the parameters for the outer method.
-     */
-    int inReg = cUnit->method->registersSize - cUnit->method->insSize;
-    for (; inReg < cUnit->method->registersSize; inReg++) {
-        dvmCompilerSetBit(cUnit->defBlockMatrix[inReg],
-                          cUnit->entryBlock->id);
+    if (cUnit->jitMode == kJitMethod) {
+        /*
+         * Also set the incoming parameters as defs in the entry block.
+         * Only need to handle the parameters for the outer method.
+         */
+        int inReg = cUnit->method->registersSize - cUnit->method->insSize;
+        for (; inReg < cUnit->method->registersSize; inReg++) {
+            dvmCompilerSetBit(cUnit->defBlockMatrix[inReg],
+                              cUnit->entryBlock->id);
+        }
     }
 }
 
@@ -137,17 +143,31 @@
     }
 }
 
+static void checkForDominanceFrontier(BasicBlock *domBB,
+                                      const BasicBlock *succBB)
+{
+    /*
+     * TODO - evaluate whether phi will ever need to be inserted into exit
+     * blocks.
+     */
+    if (succBB->iDom != domBB &&
+        succBB->blockType == kDalvikByteCode &&
+        succBB->hidden == false) {
+        dvmSetBit(domBB->domFrontier, succBB->id);
+    }
+}
+
 /* Worker function to compute the dominance frontier */
 static bool computeDominanceFrontier(CompilationUnit *cUnit, BasicBlock *bb)
 {
     GrowableList *blockList = &cUnit->blockList;
 
     /* Calculate DF_local */
-    if (bb->taken && (bb->taken->iDom != bb)) {
-        dvmSetBit(bb->domFrontier, bb->taken->id);
+    if (bb->taken) {
+        checkForDominanceFrontier(bb, bb->taken);
     }
-    if (bb->fallThrough && (bb->fallThrough->iDom != bb)) {
-        dvmSetBit(bb->domFrontier, bb->fallThrough->id);
+    if (bb->fallThrough) {
+        checkForDominanceFrontier(bb, bb->fallThrough);
     }
     if (bb->successorBlockList.blockListType != kNotUsed) {
         GrowableListIterator iterator;
@@ -158,9 +178,7 @@
                 (SuccessorBlockInfo *) dvmGrowableListIteratorNext(&iterator);
             if (successorBlockInfo == NULL) break;
             BasicBlock *succBB = successorBlockInfo->block;
-            if (succBB->iDom != bb) {
-                dvmSetBit(bb->domFrontier, succBB->id);
-            }
+            checkForDominanceFrontier(bb, succBB);
         }
     }
 
@@ -179,11 +197,10 @@
             if (dfUpIdx == -1) break;
             BasicBlock *dfUpBlock = (BasicBlock *)
                 dvmGrowableListGetElement(blockList, dfUpIdx);
-            if (dfUpBlock->iDom != bb) {
-                dvmSetBit(bb->domFrontier, dfUpBlock->id);
-            }
+            checkForDominanceFrontier(bb, dfUpBlock);
         }
     }
+
     return true;
 }
 
@@ -192,12 +209,18 @@
 {
     int numTotalBlocks = cUnit->blockList.numUsed;
 
-    bb->dominators = dvmCompilerAllocBitVector(numTotalBlocks,
-                                               false /* expandable */);
-    bb->iDominated = dvmCompilerAllocBitVector(numTotalBlocks,
-                                               false /* expandable */);
-    bb->domFrontier = dvmCompilerAllocBitVector(numTotalBlocks,
-                                               false /* expandable */);
+    if (bb->dominators == NULL ) {
+        bb->dominators = dvmCompilerAllocBitVector(numTotalBlocks,
+                                                   false /* expandable */);
+        bb->iDominated = dvmCompilerAllocBitVector(numTotalBlocks,
+                                                   false /* expandable */);
+        bb->domFrontier = dvmCompilerAllocBitVector(numTotalBlocks,
+                                                   false /* expandable */);
+    } else {
+        dvmClearAllBits(bb->dominators);
+        dvmClearAllBits(bb->iDominated);
+        dvmClearAllBits(bb->domFrontier);
+    }
     /* Set all bits in the dominator vector */
     dvmSetInitialBits(bb->dominators, numTotalBlocks);
 
@@ -296,8 +319,12 @@
     dvmClearAllBits(cUnit->entryBlock->dominators);
     dvmSetBit(cUnit->entryBlock->dominators, cUnit->entryBlock->id);
 
-    cUnit->tempBlockV = dvmCompilerAllocBitVector(numTotalBlocks,
-                                              false /* expandable */);
+    if (cUnit->tempBlockV == NULL) {
+        cUnit->tempBlockV = dvmCompilerAllocBitVector(numTotalBlocks,
+                                                  false /* expandable */);
+    } else {
+        dvmClearAllBits(cUnit->tempBlockV);
+    }
     dvmCompilerDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
                                           kPreOrderDFSTraversal,
                                           true /* isIterative */);
@@ -311,7 +338,12 @@
      * Now go ahead and compute the post order traversal based on the
      * iDominated sets.
      */
-    dvmInitGrowableList(&cUnit->domPostOrderTraversal, numReachableBlocks);
+    if (cUnit->domPostOrderTraversal.elemList == NULL) {
+        dvmInitGrowableList(&cUnit->domPostOrderTraversal, numReachableBlocks);
+    } else {
+        cUnit->domPostOrderTraversal.numUsed = 0;
+    }
+
     computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
     assert(cUnit->domPostOrderTraversal.numUsed ==
            (unsigned) cUnit->numReachableBlocks);
@@ -411,16 +443,19 @@
 
         dvmCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
         dvmClearAllBits(phiBlocks);
+
         /* Calculate the phi blocks for each Dalvik register */
         do {
             change = false;
             dvmClearAllBits(tmpBlocks);
             dvmBitVectorIteratorInit(inputBlocks, &iterator);
+
             while (true) {
                 int idx = dvmBitVectorIteratorNext(&iterator);
                 if (idx == -1) break;
                 BasicBlock *defBB =
                     (BasicBlock *) dvmGrowableListGetElement(blockList, idx);
+
                 /* Merge the dominance frontier to tmpBlocks */
                 dvmUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
             }
@@ -552,3 +587,51 @@
                                           kReachableNodes,
                                           false /* isIterative */);
 }
+
+/* Build a loop. Return true if a loop structure is successfully identified. */
+bool dvmCompilerBuildLoop(CompilationUnit *cUnit)
+{
+    /* Compute the DFS order */
+    computeDFSOrder(cUnit);
+
+    /* Compute the dominator info */
+    computeDominators(cUnit);
+
+    /* Loop structure not recognized/supported - return false */
+    if (dvmCompilerFilterLoopBlocks(cUnit) == false)
+        return false;
+
+    /* Re-compute the DFS order just for the loop */
+    computeDFSOrder(cUnit);
+
+    /* Re-compute the dominator info just for the loop */
+    computeDominators(cUnit);
+
+    /* Allocate data structures in preparation for SSA conversion */
+    dvmInitializeSSAConversion(cUnit);
+
+    /* Find out the "Dalvik reg def x block" relation */
+    computeDefBlockMatrix(cUnit);
+
+    /* Insert phi nodes to dominance frontiers for all variables */
+    insertPhiNodes(cUnit);
+
+    /* Rename register names by local defs and phi nodes */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion,
+                                          kPreOrderDFSTraversal,
+                                          false /* isIterative */);
+
+    /*
+     * Shared temp bit vector used by each block to count the number of defs
+     * from all the predecessor blocks.
+     */
+    cUnit->tempSSARegisterV = dvmCompilerAllocBitVector(cUnit->numSSARegs,
+                                                        false);
+
+    /* Insert phi-operands with latest SSA names from predecessor blocks */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
+                                          kReachableNodes,
+                                          false /* isIterative */);
+
+    return true;
+}
diff --git a/vm/compiler/Utility.c b/vm/compiler/Utility.c
index 7be57ef..fb16388 100644
--- a/vm/compiler/Utility.c
+++ b/vm/compiler/Utility.c
@@ -352,7 +352,7 @@
     LOGE("%s", msg);
     for (i = 0; i < length; i++) {
         if (dvmIsBitSet(bv, i)) {
-            LOGE("Bit %d is set", i);
+            LOGE("    Bit %d is set", i);
         }
     }
 }
@@ -398,6 +398,9 @@
         case kDalvikByteCode:
             snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
             break;
+        case kChainingCellNormal:
+            snprintf(name, BLOCK_NAME_LEN, "chain%04x", bb->startOffset);
+            break;
         case kExceptionHandling:
             snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
             break;
diff --git a/vm/compiler/codegen/arm/ArchFactory.c b/vm/compiler/codegen/arm/ArchFactory.c
index 805a6fc..5a03b17 100644
--- a/vm/compiler/codegen/arm/ArchFactory.c
+++ b/vm/compiler/codegen/arm/ArchFactory.c
@@ -32,7 +32,7 @@
                                TGT_LIR *pcrLabel)
 {
     TGT_LIR *branch = genCmpImmBranch(cUnit, cond, reg, checkValue);
-    if (cUnit->methodJitMode) {
+    if (cUnit->jitMode == kJitMethod) {
         BasicBlock *bb = cUnit->curBlock;
         if (bb->taken) {
             ArmLIR  *exceptionLabel = (ArmLIR *) cUnit->blockLabelList;
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 9b24b75..17fef2b 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -1336,8 +1336,8 @@
     int offset = 0;
     int i;
     ChainCellCounts chainCellCounts;
-    int descSize =
-        cUnit->methodJitMode ? 0 : getTraceDescriptionSize(cUnit->traceDesc);
+    int descSize = (cUnit->jitMode == kJitMethod) ?
+        0 : getTraceDescriptionSize(cUnit->traceDesc);
     int chainingCellGap = 0;
 
     info->instructionSet = cUnit->instructionSet;
@@ -1367,7 +1367,7 @@
     u4 chainCellOffset = offset;
     ArmLIR *chainCellOffsetLIR = NULL;
 
-    if (!cUnit->methodJitMode) {
+    if (cUnit->jitMode != kJitMethod) {
         /*
          * Get the gap (# of u4) between the offset of chaining cell count and
          * the bottom of real chaining cells. If the translation has chaining
@@ -1430,7 +1430,7 @@
             break;
         case kRetryAll:
             if (cUnit->assemblerRetries < MAX_ASSEMBLER_RETRIES) {
-                if (!cUnit->methodJitMode) {
+                if (cUnit->jitMode != kJitMethod) {
                     /* Restore pristine chain cell marker on retry */
                     chainCellOffsetLIR->operands[0] = CHAIN_CELL_OFFSET_TAG;
                 }
@@ -1482,7 +1482,7 @@
     memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset);
     gDvmJit.numCompilations++;
 
-    if (!cUnit->methodJitMode) {
+    if (cUnit->jitMode != kJitMethod) {
         /* Install the chaining cell counts */
         for (i=0; i< kChainingCellGap; i++) {
             chainCellCounts.u.count[i] = cUnit->numChainingCells[i];