Fix two codegen problems: out-of-bound PC-relative addresses and missing branch to the chaining cell at the end of non-branch-ending basic blocks.
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index dc24977..98a4e1d 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -173,7 +173,7 @@
 bool dvmCompilerStartup(void)
 {
     /* Make sure the BBType enum is in sane state */
-    assert(CHAINING_CELL_GENERIC == 0);
+    assert(CHAINING_CELL_NORMAL == 0);
 
     /* Architecture-specific chores to initialize */
     if (!dvmCompilerArchInit())
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 9bcee12..1ab6687 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -92,7 +92,7 @@
 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
 void *dvmCheckCodeCache(void *method);
 void *dvmCompileMethod(Method *method);
-void *dvmCompileTrace(JitTraceDescription *trace);
+void *dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts);
 void dvmCompilerDumpStats(void);
 void dvmCompilerDrainQueue(void);
 void dvmJitUnchainAll(void);
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index 67cb637..712cbae 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -19,8 +19,8 @@
 
 typedef enum BBType {
     /* For coding convenience reasons chaining cell types should appear first */
-    CHAINING_CELL_GENERIC = 0,
-    CHAINING_CELL_POST_INVOKE,
+    CHAINING_CELL_NORMAL = 0,
+    CHAINING_CELL_HOT,
     CHAINING_CELL_INVOKE,
     CHAINING_CELL_LAST,
     DALVIK_BYTECODE,
@@ -56,6 +56,7 @@
     unsigned int startOffset;
     const Method *containingMethod;     // For blocks from the callee
     BBType blockType;
+    bool needFallThroughBranch;         // For blocks ended due to length limit
     MIR *firstMIRInsn;
     MIR *lastMIRInsn;
     struct BasicBlock *fallThrough;
@@ -64,6 +65,7 @@
 } BasicBlock;
 
 typedef struct CompilationUnit {
+    int numInsts;
     int numBlocks;
     BasicBlock **blockList;
     const Method *method;
@@ -72,12 +74,14 @@
     LIR *lastLIRInsn;
     LIR *wordList;
     GrowableList pcReconstructionList;
-    int dataOffset;
-    int totalSize;
+    int headerSize;                     // bytes before the first code ptr
+    int dataOffset;                     // starting offset of literal pool
+    int totalSize;                      // header + code size
     unsigned char *codeBuffer;
     void *baseAddr;
     bool printMe;
     bool allSingleStep;
+    bool halveInstCount;
     int numChainingCells[CHAINING_CELL_LAST];
     LIR *firstChainingLIR[CHAINING_CELL_LAST];
 } CompilationUnit;
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 59a7455..6e8d964 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -183,11 +183,10 @@
  * first and they will be passed to the codegen routines to convert Dalvik
  * bytecode into machine code.
  */
-void *dvmCompileTrace(JitTraceDescription *desc)
+void *dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts)
 {
     const DexCode *dexCode = dvmGetMethodCode(desc->method);
     const JitTraceRun* currRun = &desc->trace[0];
-    bool done = false;
     unsigned int curOffset = currRun->frag.startOffset;
     unsigned int numInsts = currRun->frag.numInsts;
     const u2 *codePtr = dexCode->insns + curOffset;
@@ -275,7 +274,11 @@
              desc->method->name, curOffset);
     }
 
-    while (!done) {
+    /*
+     * Analyze the trace descriptor and include up to the maximal number
+     * of Dalvik instructions into the IR.
+     */
+    while (1) {
         MIR *insn;
         int width;
         insn = dvmCompilerNew(sizeof(MIR),false);
@@ -284,9 +287,14 @@
         insn->width = width;
         traceSize += width;
         dvmCompilerAppendMIR(curBB, insn);
-        if (--numInsts==0) {
+        cUnit.numInsts++;
+        /* Instruction limit reached - terminate the trace here */
+        if (cUnit.numInsts >= numMaxInsts) {
+            break;
+        }
+        if (--numInsts == 0) {
             if (currRun->frag.runEnd) {
-                done = true;
+                break;
             } else {
                 curBB = dvmCompilerNewBB(DALVIK_BYTECODE);
                 lastBB->next = curBB;
@@ -337,10 +345,29 @@
             }
         }
 
+        int flags = dexGetInstrFlags(gDvm.instrFlags,
+                                     lastInsn->dalvikInsn.opCode);
+
+        /*
+         * Some blocks are ended by non-control-flow-change instructions,
+         * currently only due to trace length constraint. In this case we need
+         * to generate an explicit branch at the end of the block to jump to
+         * the chaining cell.
+         */
+        curBB->needFallThroughBranch =
+            (flags & (kInstrCanBranch | kInstrCanSwitch | kInstrCanReturn |
+                      kInstrInvoke)) == 0;
+
         /* Target block not included in the trace */
         if (targetOffset != curOffset && curBB->taken == NULL) {
-            lastBB->next = dvmCompilerNewBB(
-                isInvoke ? CHAINING_CELL_INVOKE : CHAINING_CELL_GENERIC);
+            if (isInvoke) {
+                lastBB->next = dvmCompilerNewBB(CHAINING_CELL_INVOKE);
+            /* For unconditional branches, request a hot chaining cell */
+            } else {
+                lastBB->next = dvmCompilerNewBB(flags & kInstrUnconditional ?
+                                                  CHAINING_CELL_HOT :
+                                                  CHAINING_CELL_NORMAL);
+            }
             lastBB = lastBB->next;
             lastBB->id = numBlocks++;
             if (isInvoke) {
@@ -354,8 +381,16 @@
 
         /* Fallthrough block not included in the trace */
         if (!isUnconditionalBranch(lastInsn) && curBB->fallThrough == NULL) {
-            lastBB->next = dvmCompilerNewBB(
-                isInvoke ? CHAINING_CELL_POST_INVOKE : CHAINING_CELL_GENERIC);
+            /*
+             * If the chaining cell is after an invoke or
+             * instruction that cannot change the control flow, request a hot
+             * chaining cell.
+             */
+            if (isInvoke || curBB->needFallThroughBranch) {
+                lastBB->next = dvmCompilerNewBB(CHAINING_CELL_HOT);
+            } else {
+                lastBB->next = dvmCompilerNewBB(CHAINING_CELL_NORMAL);
+            }
             lastBB = lastBB->next;
             lastBB->id = numBlocks++;
             lastBB->startOffset = fallThroughOffset;
@@ -410,18 +445,34 @@
     /* Convert MIR to LIR, etc. */
     dvmCompilerMIR2LIR(&cUnit);
 
-    /* Convert LIR into machine code */
+    /* Convert LIR into machine code. */
     dvmCompilerAssembleLIR(&cUnit);
 
     if (cUnit.printMe) {
-        dvmCompilerCodegenDump(&cUnit);
-        LOGD("End %s%s", desc->method->clazz->descriptor, desc->method->name);
+        if (cUnit.halveInstCount) {
+            LOGD("Assembler aborted");
+        } else {
+            dvmCompilerCodegenDump(&cUnit);
+        }
+        LOGD("End %s%s, %d Dalvik instructions",
+             desc->method->clazz->descriptor, desc->method->name,
+             cUnit.numInsts);
     }
 
     /* Reset the compiler resource pool */
     dvmCompilerArenaReset();
 
-    return cUnit.baseAddr;
+    /*
+     * Things have gone smoothly - publish the starting address of
+     * translation's entry point.
+     */
+    if (!cUnit.halveInstCount) {
+        return cUnit.baseAddr + cUnit.headerSize;
+
+    /* Halve the instruction count and retry again */
+    } else {
+        return dvmCompileTrace(desc, cUnit.numInsts / 2);
+    }
 }
 
 /*
@@ -599,5 +650,5 @@
 
     dvmCompilerArenaReset();
 
-    return cUnit.baseAddr;
+    return cUnit.baseAddr + cUnit.headerSize;
 }
diff --git a/vm/compiler/codegen/armv5te/ArchUtility.c b/vm/compiler/codegen/armv5te/ArchUtility.c
index 58b181b..a64b54f 100644
--- a/vm/compiler/codegen/armv5te/ArchUtility.c
+++ b/vm/compiler/codegen/armv5te/ArchUtility.c
@@ -161,11 +161,11 @@
     switch(lir->opCode) {
         case ARMV5TE_PSEUDO_TARGET_LABEL:
             break;
-        case ARMV5TE_PSEUDO_CHAINING_CELL_GENERIC:
-            LOGD("-------- chaining cell (generic): 0x%04x\n", dest);
+        case ARMV5TE_PSEUDO_CHAINING_CELL_NORMAL:
+            LOGD("-------- chaining cell (normal): 0x%04x\n", dest);
             break;
-        case ARMV5TE_PSEUDO_CHAINING_CELL_POST_INVOKE:
-            LOGD("-------- chaining cell (post-invoke): 0x%04x\n", dest);
+        case ARMV5TE_PSEUDO_CHAINING_CELL_HOT:
+            LOGD("-------- chaining cell (hot): 0x%04x\n", dest);
             break;
         case ARMV5TE_PSEUDO_CHAINING_CELL_INVOKE:
             LOGD("-------- chaining cell (invoke): %s/%p\n",
diff --git a/vm/compiler/codegen/armv5te/Armv5teLIR.h b/vm/compiler/codegen/armv5te/Armv5teLIR.h
index 208e6c0..5268ee8 100644
--- a/vm/compiler/codegen/armv5te/Armv5teLIR.h
+++ b/vm/compiler/codegen/armv5te/Armv5teLIR.h
@@ -59,9 +59,9 @@
  */
 typedef enum Armv5teOpCode {
     ARMV5TE_PSEUDO_TARGET_LABEL = -10,
-    ARMV5TE_PSEUDO_CHAINING_CELL_POST_INVOKE = -9,
+    ARMV5TE_PSEUDO_CHAINING_CELL_HOT = -9,
     ARMV5TE_PSEUDO_CHAINING_CELL_INVOKE = -8,
-    ARMV5TE_PSEUDO_CHAINING_CELL_GENERIC = -7,
+    ARMV5TE_PSEUDO_CHAINING_CELL_NORMAL = -7,
     ARMV5TE_PSEUDO_DALVIK_BYTECODE_BOUNDARY = -6,
     ARMV5TE_PSEUDO_ALIGN4 = -5,
     ARMV5TE_PSEUDO_PC_RECONSTRUCTION_CELL = -4,
@@ -178,4 +178,6 @@
 #define NEXT_LIR_LVALUE(lir) (lir)->generic.next
 #define PREV_LIR_LVALUE(lir) (lir)->generic.prev
 
+#define CHAIN_CELL_OFFSET_TAG   0xcdab
+
 #endif /* _DALVIK_VM_COMPILER_CODEGEN_ARMV5TE_H */
diff --git a/vm/compiler/codegen/armv5te/Assemble.c b/vm/compiler/codegen/armv5te/Assemble.c
index baa6ced..12cb158 100644
--- a/vm/compiler/codegen/armv5te/Assemble.c
+++ b/vm/compiler/codegen/armv5te/Assemble.c
@@ -242,13 +242,12 @@
 {
     short *bufferAddr = (short *) cUnit->codeBuffer;
     Armv5teLIR *lir;
-    bool retry = false;
 
     for (lir = (Armv5teLIR *) cUnit->firstLIRInsn; lir; lir = NEXT_LIR(lir)) {
         if (lir->opCode < 0) {
             if ((lir->opCode == ARMV5TE_PSEUDO_ALIGN4) &&
-                (lir->operands[0] == 1) &&
-                !retry) {
+                /* 1 means padding is needed */
+                (lir->operands[0] == 1)) {
                 *bufferAddr++ = PADDING_MOV_R0_R0;
             }
             continue;
@@ -264,6 +263,9 @@
                 LOGE("PC-rel distance is not multiples of 4: %d\n", delta);
                 dvmAbort();
             }
+            if (delta > 1023) {
+                return true;
+            }
             lir->operands[1] = delta >> 2;
         } else if (lir->opCode == ARMV5TE_B_COND) {
             Armv5teLIR *targetLIR = (Armv5teLIR *) lir->generic.target;
@@ -271,74 +273,7 @@
             intptr_t target = targetLIR->generic.offset;
             int delta = target - pc;
             if (delta > 254 || delta < -256) {
-                /* Pull in the PC reconstruction code inline */
-                if (targetLIR->opCode == ARMV5TE_PSEUDO_PC_RECONSTRUCTION_CELL){
-                    /*
-                     * The original code is:
-                     *
-                     * bxx targetLIR
-                     * origNextLir
-                     *       :
-                     *       :
-                     * targetLIR (a PC reconstruction cell)
-                     *       :
-                     * lastLIR (should be a unconditional branch)
-                     *
-                     * The distance from bxx to targetLIR is too far, so we want
-                     * to rearrange the code to be:
-                     *
-                     * bxx targetLIR
-                     * branchoverLIR to origNextLir
-                     * targetLIR (a PC reconstruction cell)
-                     *       :
-                     * lastLIR (should be a unconditional branch)
-                     * origNextLir
-                     *
-                     * Although doing so adds a unconditional branchover
-                     * instruction, it can be predicted for free by ARM so
-                     * the penalty should be minimal.
-                     */
-                    Armv5teLIR *pcrLIR = targetLIR;
-                    Armv5teLIR *lastLIR = pcrLIR;
-                    Armv5teLIR *origNextLIR = NEXT_LIR(lir);
-
-                    /*
-                     * Find out the last instruction in the PC reconstruction
-                     * cell
-                     */
-                    while (lastLIR->opCode != ARMV5TE_B_UNCOND) {
-                        lastLIR = NEXT_LIR(lastLIR);
-                    }
-
-                    /* Yank out the PCR code */
-                    PREV_LIR_LVALUE(NEXT_LIR(lastLIR)) =
-                        (LIR *) PREV_LIR(targetLIR);
-                    NEXT_LIR_LVALUE(PREV_LIR(targetLIR)) =
-                        (LIR *) NEXT_LIR(lastLIR);
-
-                    /* Create the branch over instruction */
-                    Armv5teLIR *branchoverLIR =
-                        dvmCompilerNew(sizeof(Armv5teLIR), true);
-                    branchoverLIR->opCode = ARMV5TE_B_UNCOND;
-                    branchoverLIR->generic.target = (LIR *) origNextLIR;
-
-                    /* Reconnect the instructions */
-                    NEXT_LIR_LVALUE(lir) = (LIR *) branchoverLIR;
-                    PREV_LIR_LVALUE(branchoverLIR) = (LIR *) lir;
-
-                    NEXT_LIR_LVALUE(branchoverLIR) = (LIR *) targetLIR;
-                    PREV_LIR_LVALUE(targetLIR) = (LIR *) branchoverLIR;
-
-                    NEXT_LIR_LVALUE(lastLIR) = (LIR *) origNextLIR;
-                    PREV_LIR_LVALUE(origNextLIR) = (LIR *) lastLIR;
-
-                    retry = true;
-                    continue;
-                } else {
-                    LOGE("Conditional branch distance out of range: %d\n",
-                         delta);
-                    dvmAbort();
-                }
+                return true;
             }
             lir->operands[0] = delta >> 1;
         } else if (lir->opCode == ARMV5TE_B_UNCOND) {
@@ -368,14 +303,6 @@
             NEXT_LIR(lir)->operands[0] = (delta>> 1) & 0x7ff;
         }
 
-        /*
-         * The code offset will be recalculated, just continue to check if
-         * there are other places where code will be rescheduled and do not
-         * write to the output buffer
-         */
-        if (retry) {
-            continue;
-        }
         Armv5teEncodingMap *encoder = &EncodingMap[lir->opCode];
         short bits = encoder->skeleton;
         int i;
@@ -390,7 +317,7 @@
         }
         *bufferAddr++ = bits;
     }
-    return retry;
+    return false;
 }
 
 /*
@@ -436,16 +363,13 @@
 {
     LIR *lir;
     Armv5teLIR *armLIR;
-    int offset;
+    int offset = 0;
     int i;
     ChainCellCounts chainCellCounts;
-    u2 chainCellOffset;
     int descSize = jitTraceDescriptionSize(cUnit->traceDesc);
 
-retry:
     /* Beginning offset needs to allow space for chain cell offset */
-    for (armLIR = (Armv5teLIR *) cUnit->firstLIRInsn,
-         offset = CHAIN_CELL_OFFSET_SIZE;
+    for (armLIR = (Armv5teLIR *) cUnit->firstLIRInsn;
          armLIR;
          armLIR = NEXT_LIR(armLIR)) {
         armLIR->generic.offset = offset;
@@ -466,7 +390,15 @@
     offset = (offset + 3) & ~3;
 
     /* Add space for chain cell counts & trace description */
-    chainCellOffset = offset;
+    u4 chainCellOffset = offset;
+    Armv5teLIR *chainCellOffsetLIR = (Armv5teLIR *) (cUnit->firstLIRInsn);
+    assert(chainCellOffset < 0x10000);
+    assert(chainCellOffsetLIR->opCode == ARMV5TE_16BIT_DATA &&
+           chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG);
+
+    /* Replace the CHAIN_CELL_OFFSET_TAG with the real value */
+    chainCellOffsetLIR->operands[0] = chainCellOffset;
+
     offset += sizeof(chainCellCounts) + descSize;
 
     assert((offset & 0x3) == 0);  /* Should still be word aligned */
@@ -495,20 +427,24 @@
         return;
     }
 
-    bool needRetry = assembleInstructions(
+    bool assemblerFailure = assembleInstructions(
         cUnit, (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed);
 
-    if (needRetry)
-        goto retry;
+    /*
+     * Currently the only reason that can cause the assembler to fail is due to
+     * trace length - cut it in half and retry.
+     */
+    if (assemblerFailure) {
+        cUnit->halveInstCount = true;
+        return;
+    }
 
     cUnit->baseAddr = (char *) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed;
+    cUnit->headerSize = CHAIN_CELL_OFFSET_SIZE;
     gDvmJit.codeCacheByteUsed += offset;
 
-    /* Install the chain cell offset */
-    *((char*)cUnit->baseAddr) = chainCellOffset;
-
     /* Install the code block */
-    memcpy((char*)cUnit->baseAddr + 2, cUnit->codeBuffer, chainCellOffset - 2);
+    memcpy((char*)cUnit->baseAddr, cUnit->codeBuffer, chainCellOffset);
     gDvmJit.numCompilations++;
 
     /* Install the chaining cell counts */
@@ -528,9 +464,6 @@
     /* Flush dcache and invalidate the icache to maintain coherence */
     cacheflush((long)cUnit->baseAddr,
                (long)(cUnit->baseAddr + offset), 0);
-
-    /* Adjust baseAddr to point to executable code */
-    cUnit->baseAddr = (char*)cUnit->baseAddr + CHAIN_CELL_OFFSET_SIZE;
 }
 
 /*
@@ -611,11 +544,11 @@
         for (j = 0; j < pChainCellCounts->u.count[i]; j++) {
             int targetOffset;
             switch(i) {
-                case CHAINING_CELL_GENERIC:
+                case CHAINING_CELL_NORMAL:
                     targetOffset = offsetof(InterpState,
                           jitToInterpEntries.dvmJitToInterpNormal);
                     break;
-                case CHAINING_CELL_POST_INVOKE:
+                case CHAINING_CELL_HOT:
                 case CHAINING_CELL_INVOKE:
                     targetOffset = offsetof(InterpState,
                           jitToInterpEntries.dvmJitToTraceSelect);
diff --git a/vm/compiler/codegen/armv5te/Codegen.c b/vm/compiler/codegen/armv5te/Codegen.c
index 178e536..257272c 100644
--- a/vm/compiler/codegen/armv5te/Codegen.c
+++ b/vm/compiler/codegen/armv5te/Codegen.c
@@ -602,10 +602,11 @@
 
     loadValue(cUnit, vArray, r2);
     loadValue(cUnit, vIndex, r3);
-    genNullCheck(cUnit, r2, mir->offset, NULL); /* null object? */
+    /* null object? */
+    Armv5teLIR * pcrLabel = genNullCheck(cUnit, r2, mir->offset, NULL);
     newLIR3(cUnit, ARMV5TE_LDR_RRI5, r0, r2, lenOffset >> 2);  /* Get len */
     newLIR2(cUnit, ARMV5TE_ADD_RI8, r2, dataOffset); /* r2 -> array data */
-    genBoundsCheck(cUnit, r3, r0, mir->offset, NULL);
+    genBoundsCheck(cUnit, r3, r0, mir->offset, pcrLabel);
     /* at this point, r2 points to array, r3 is unscaled index */
     if (scale==3) {
         loadValuePair(cUnit, vSrc, r0, r1);
@@ -2491,9 +2492,9 @@
  * Dalvik PC and special-purpose registers are reconstructed here.
  */
 
-/* Chaining cell for normal-ending compiles (eg branches) */
-static void handleGenericChainingCell(CompilationUnit *cUnit,
-                                      unsigned int offset)
+/* Chaining cell for code that may need warmup. */
+static void handleNormalChainingCell(CompilationUnit *cUnit,
+                                     unsigned int offset)
 {
     newLIR3(cUnit, ARMV5TE_LDR_RRI5, r0, rGLUE,
         offsetof(InterpState, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
@@ -2502,11 +2503,11 @@
 }
 
 /*
- * Chaining cell for instructions that immediately following a method
- * invocation.
+ * Chaining cell for instructions that immediately following already translated
+ * code.
  */
-static void handlePostInvokeChainingCell(CompilationUnit *cUnit,
-                                         unsigned int offset)
+static void handleHotChainingCell(CompilationUnit *cUnit,
+                                  unsigned int offset)
 {
     newLIR3(cUnit, ARMV5TE_LDR_RRI5, r0, rGLUE,
         offsetof(InterpState, jitToInterpEntries.dvmJitToTraceSelect) >> 2);
@@ -2559,6 +2560,12 @@
 
     BasicBlock **blockList = cUnit->blockList;
 
+    /*
+     * Reserve space at the beginning of each translation with fillers
+     * + Chain cell count (2 bytes)
+     */
+    newLIR1(cUnit, ARMV5TE_16BIT_DATA, CHAIN_CELL_OFFSET_TAG);
+
     /* Handle the content in each basic block */
     for (i = 0; i < cUnit->numBlocks; i++) {
         blockList[i]->visited = true;
@@ -2578,11 +2585,11 @@
             labelList[i].opCode = ARMV5TE_PSEUDO_NORMAL_BLOCK_LABEL;
         } else {
             switch (blockList[i]->blockType) {
-                case CHAINING_CELL_GENERIC:
-                    labelList[i].opCode = ARMV5TE_PSEUDO_CHAINING_CELL_GENERIC;
+                case CHAINING_CELL_NORMAL:
+                    labelList[i].opCode = ARMV5TE_PSEUDO_CHAINING_CELL_NORMAL;
                     /* handle the codegen later */
                     dvmInsertGrowableList(
-                        &chainingListByType[CHAINING_CELL_GENERIC], (void *) i);
+                        &chainingListByType[CHAINING_CELL_NORMAL], (void *) i);
                     break;
                 case CHAINING_CELL_INVOKE:
                     labelList[i].opCode = ARMV5TE_PSEUDO_CHAINING_CELL_INVOKE;
@@ -2592,12 +2599,12 @@
                     dvmInsertGrowableList(
                         &chainingListByType[CHAINING_CELL_INVOKE], (void *) i);
                     break;
-                case CHAINING_CELL_POST_INVOKE:
+                case CHAINING_CELL_HOT:
                     labelList[i].opCode =
-                        ARMV5TE_PSEUDO_CHAINING_CELL_POST_INVOKE;
+                        ARMV5TE_PSEUDO_CHAINING_CELL_HOT;
                     /* handle the codegen later */
                     dvmInsertGrowableList(
-                        &chainingListByType[CHAINING_CELL_POST_INVOKE],
+                        &chainingListByType[CHAINING_CELL_HOT],
                         (void *) i);
                     break;
                 case PC_RECONSTRUCTION:
@@ -2732,10 +2739,17 @@
                      dalvikFormat);
                 dvmAbort();
                 break;
-            } else {
-              gDvmJit.opHistogram[dalvikOpCode]++;
             }
         }
+        /*
+         * Check if the block is terminated due to trace length constraint -
+         * insert an unconditional branch to the chaining cell.
+         */
+        if (blockList[i]->needFallThroughBranch) {
+            genUnconditionalBranch(cUnit,
+                                   &labelList[blockList[i]->fallThrough->id]);
+        }
+
     }
 
     /* Handle the codegen in predefined order */
@@ -2763,16 +2777,16 @@
 
 
             switch (blockList[blockId]->blockType) {
-                case CHAINING_CELL_GENERIC:
-                    handleGenericChainingCell(cUnit,
+                case CHAINING_CELL_NORMAL:
+                    handleNormalChainingCell(cUnit,
                       blockList[blockId]->startOffset);
                     break;
                 case CHAINING_CELL_INVOKE:
                     handleInvokeChainingCell(cUnit,
                         blockList[blockId]->containingMethod);
                     break;
-                case CHAINING_CELL_POST_INVOKE:
-                    handlePostInvokeChainingCell(cUnit,
+                case CHAINING_CELL_HOT:
+                    handleHotChainingCell(cUnit,
                         blockList[blockId]->startOffset);
                     break;
                 default:
@@ -2797,7 +2811,8 @@
            res = dvmCompileMethod(work->info);
            break;
        case kWorkOrderTrace:
-           res = dvmCompileTrace(work->info);
+           /* Start compilation with maximally allowed trace length */
+           res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN);
            break;
        default:
            res = NULL;