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/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;
 }