Merge change 3625

* changes:
  Bump from 1.0.1 to 1.1.0.
diff --git a/vm/Globals.h b/vm/Globals.h
index 528185d..147bb22 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -654,7 +654,13 @@
     unsigned char *pProfTableCopy;
 
     /* Size of JIT hash table in entries.  Must be a power of 2 */
-    unsigned int maxTableEntries;
+    unsigned int jitTableSize;
+
+    /* Mask used in hash function for JitTable.  Should be jitTableSize-1 */
+    unsigned int jitTableMask;
+
+    /* How many entries in the JitEntryTable are in use */
+    unsigned int jitTableEntriesUsed;
 
     /* Trigger for trace selection */
     unsigned short threshold;
@@ -708,9 +714,6 @@
     /* Disable JIT for selected methods */
     HashTable *methodTable;
 
-    /* Record how many times an opcode has been JIT'ed */
-    int opHistogram[256];
-
     /* Flag to dump all compiled code */
     bool printMe;
 };
diff --git a/vm/Init.c b/vm/Init.c
index 5295f49..7486ad9 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -1011,7 +1011,8 @@
      *        frameworks/base/core/jni/AndroidRuntime.cpp
      */
     gDvmJit.blockingMode = false;
-    gDvmJit.maxTableEntries = 2048;
+    gDvmJit.jitTableSize = 512;
+    gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
     gDvmJit.threshold = 200;
 #else
     gDvm.executionMode = kExecutionModeInterpFast;
diff --git a/vm/SignalCatcher.c b/vm/SignalCatcher.c
index adcff9f..495fbf2 100644
--- a/vm/SignalCatcher.c
+++ b/vm/SignalCatcher.c
@@ -240,6 +240,10 @@
 
             logThreadStacks();
 
+#if defined(WITH_JIT) && defined(WITH_JIT_TUNING)
+            dvmCompilerDumpStats();
+#endif
+
             if (false) {
                 dvmLockMutex(&gDvm.jniGlobalRefLock);
                 dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
diff --git a/vm/Thread.h b/vm/Thread.h
index fef8b24..f1e5651 100644
--- a/vm/Thread.h
+++ b/vm/Thread.h
@@ -255,6 +255,9 @@
     SUSPEND_FOR_DEBUG_EVENT,
     SUSPEND_FOR_STACK_DUMP,
     SUSPEND_FOR_DEX_OPT,
+#if defined(WITH_JIT)
+    SUSPEND_FOR_JIT,
+#endif
 } SuspendCause;
 void dvmSuspendThread(Thread* thread);
 void dvmSuspendSelf(bool jdwpActivity);
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index dc24977..0b5c211 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -123,6 +123,11 @@
                 dvmUnlockMutex(&gDvmJit.compilerLock);
                 /* Check whether there is a suspend request on me */
                 dvmCheckSuspendPending(NULL);
+                /* Is JitTable filling up? */
+                if (gDvmJit.jitTableEntriesUsed >
+                    (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
+                    dvmJitResizeJitTable(gDvmJit.jitTableSize * 2);
+                }
                 if (gDvmJit.haltCompilerThread) {
                     LOGD("Compiler shutdown in progress - discarding request");
                 } else {
@@ -173,7 +178,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..f874f48 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);
@@ -650,7 +583,7 @@
     if (gDvmJit.pJitEntryTable != NULL) {
         COMPILER_TRACE_CHAINING(LOGD("Jit Runtime: unchaining all"));
         dvmLockMutex(&gDvmJit.tableLock);
-        for (i = 0; i < gDvmJit.maxTableEntries; i++) {
+        for (i = 0; i < gDvmJit.jitTableSize; i++) {
             if (gDvmJit.pJitEntryTable[i].dPC &&
                    gDvmJit.pJitEntryTable[i].codeAddress) {
                 u4* lastAddress;
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;
diff --git a/vm/interp/InterpDefs.h b/vm/interp/InterpDefs.h
index 6c67cb5..cbb78f0 100644
--- a/vm/interp/InterpDefs.h
+++ b/vm/interp/InterpDefs.h
@@ -122,7 +122,6 @@
     /*
      * Local copies of field from gDvm placed here for fast access
      */
-    struct JitEntry*   pJitTable;
     unsigned char*     pJitProfTable;
     JitState           jitState;
     void*              jitResume;
diff --git a/vm/interp/Jit.c b/vm/interp/Jit.c
index f2b3c50..031d46d 100644
--- a/vm/interp/Jit.c
+++ b/vm/interp/Jit.c
@@ -65,17 +65,17 @@
     dvmInitMutex(&gDvmJit.tableLock);
     if (res && gDvm.executionMode == kExecutionModeJit) {
         struct JitEntry *pJitTable = NULL;
-        int tableSize = sizeof(*pJitTable) * gDvmJit.maxTableEntries;
         unsigned char *pJitProfTable = NULL;
+        assert(gDvm.jitTableSize &&
+            !(gDvm.jitTableSize & (gDvmJit.jitTableSize - 1))); // Power of 2?
         dvmLockMutex(&gDvmJit.tableLock);
-        assert(sizeof(*pJitTable) == 12);
-        pJitTable = (struct JitEntry*)malloc(tableSize);
+        pJitTable = (struct JitEntry*)
+                    calloc(gDvmJit.jitTableSize, sizeof(*pJitTable));
         if (!pJitTable) {
             LOGE("jit table allocation failed\n");
             res = false;
             goto done;
         }
-        memset(pJitTable,0,tableSize);
         /*
          * NOTE: the profile table must only be allocated once, globally.
          * Profiling is turned on and off by nulling out gDvm.pJitProfTable
@@ -91,8 +91,8 @@
             goto done;
         }
         memset(pJitProfTable,0,JIT_PROF_SIZE);
-        for (i=0; i < gDvmJit.maxTableEntries; i++) {
-           pJitTable[i].chain = gDvmJit.maxTableEntries;
+        for (i=0; i < gDvmJit.jitTableSize; i++) {
+           pJitTable[i].chain = gDvmJit.jitTableSize;
         }
         /* Is chain field wide enough for termination pattern? */
         assert(pJitTable[0].chain == gDvm.maxJitTableEntries);
@@ -100,6 +100,8 @@
 
 done:
         gDvmJit.pJitEntryTable = pJitTable;
+        gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
+        gDvmJit.jitTableEntriesUsed = 0;
         gDvmJit.pProfTableCopy = gDvmJit.pProfTable = pJitProfTable;
         dvmUnlockMutex(&gDvmJit.tableLock);
     }
@@ -155,13 +157,13 @@
     int chains;
     if (gDvmJit.pJitEntryTable) {
         for (i=0, chains=hit=not_hit=0;
-             i < (int) gDvmJit.maxTableEntries;
+             i < (int) gDvmJit.jitTableSize;
              i++) {
             if (gDvmJit.pJitEntryTable[i].dPC != 0)
                 hit++;
             else
                 not_hit++;
-            if (gDvmJit.pJitEntryTable[i].chain != gDvmJit.maxTableEntries)
+            if (gDvmJit.pJitEntryTable[i].chain != gDvmJit.jitTableSize)
                 chains++;
         }
         LOGD(
@@ -222,7 +224,6 @@
  * because returns cannot throw in a way that causes problems for the
  * translated code.
  */
-#define MAX_TRACE_LEN 100
 int dvmCheckJit(const u2* pc, Thread* self, InterpState* interpState)
 {
     int flags,i,len;
@@ -278,7 +279,7 @@
                 if (decInsn.opCode == OP_THROW) {
                     interpState->jitState = kJitTSelectEnd;
                 }
-                if (interpState->totalTraceLen >= MAX_TRACE_LEN) {
+                if (interpState->totalTraceLen >= JIT_MAX_TRACE_LEN) {
                     interpState->jitState = kJitTSelectEnd;
                 }
                 if (debugOrProfile) {
@@ -355,7 +356,7 @@
     if (gDvmJit.pJitEntryTable[idx].dPC == pc)
         return &gDvmJit.pJitEntryTable[idx];
     else {
-        int chainEndMarker = gDvmJit.maxTableEntries;
+        int chainEndMarker = gDvmJit.jitTableSize;
         while (gDvmJit.pJitEntryTable[idx].chain != chainEndMarker) {
             idx = gDvmJit.pJitEntryTable[idx].chain;
             if (gDvmJit.pJitEntryTable[idx].dPC == pc)
@@ -365,6 +366,46 @@
     return NULL;
 }
 
+struct JitEntry *dvmFindJitEntry(const u2* pc)
+{
+    return findJitEntry(pc);
+}
+
+/*
+ * Allocate an entry in a JitTable.  Assumes caller holds lock, if
+ * applicable.  Normally used for table resizing.  Will complain (die)
+ * if entry already exists in the table or if table is full.
+ */
+static struct JitEntry *allocateJitEntry(const u2* pc, struct JitEntry *table,
+                                  u4 size)
+{
+    struct JitEntry *p;
+    unsigned int idx;
+    unsigned int prev;
+    idx = dvmJitHashMask(pc, size-1);
+    while ((table[idx].chain != size) && (table[idx].dPC != pc)) {
+        idx = table[idx].chain;
+    }
+    assert(table[idx].dPC != pc);  /* Already there */
+    if (table[idx].dPC == NULL) {
+        /* use this slot */
+        return &table[idx];
+    }
+    /* Find a free entry and chain it in */
+    prev = idx;
+    while (true) {
+        idx++;
+        if (idx == size)
+            idx = 0;  /* Wraparound */
+        if ((table[idx].dPC == NULL) || (idx == prev))
+            break;
+    }
+    assert(idx != prev);
+    table[prev].chain = idx;
+    assert(table[idx].dPC == NULL);
+    return &table[idx];
+}
+
 /*
  * If a translated code address exists for the davik byte code
  * pointer return it.  This routine needs to be fast.
@@ -385,7 +426,7 @@
 #endif
         return gDvmJit.pJitEntryTable[idx].codeAddress;
     } else {
-        int chainEndMarker = gDvmJit.maxTableEntries;
+        int chainEndMarker = gDvmJit.jitTableSize;
         while (gDvmJit.pJitEntryTable[idx].chain != chainEndMarker) {
             idx = gDvmJit.pJitEntryTable[idx].chain;
             if (gDvmJit.pJitEntryTable[idx].dPC == dPC) {
@@ -445,7 +486,7 @@
             resetProfileCounts();
             res = true;   /* Stale profile - abort */
         } else if (interpState->jitState == kJitTSelectRequest) {
-            u4 chainEndMarker = gDvmJit.maxTableEntries;
+            u4 chainEndMarker = gDvmJit.jitTableSize;
             u4 idx = dvmJitHash(interpState->pc);
 
             /* Walk the bucket chain to find an exact match for our PC */
@@ -504,6 +545,7 @@
                 if (gDvmJit.pJitEntryTable[idx].dPC == NULL) {
                    /* Allocate the slot */
                     gDvmJit.pJitEntryTable[idx].dPC = interpState->pc;
+                    gDvmJit.jitTableEntriesUsed++;
                 } else {
                    /*
                     * Table is full.  We could resize it, but that would
@@ -547,4 +589,68 @@
     return res;
 }
 
+/*
+ * Resizes the JitTable.  Must be a power of 2, and returns true on failure.
+ * Stops all threads, and thus is a heavyweight operation.
+ */
+bool dvmJitResizeJitTable( unsigned int size )
+{
+    struct JitEntry *pNewTable;
+    u4 newMask;
+    unsigned int i;
+
+    assert(gDvm.pJitEntryTable != NULL);
+    assert(size && !(size & (size - 1)));   /* Is power of 2? */
+
+    LOGD("Jit: resizing JitTable from %d to %d", gDvmJit.jitTableSize, size);
+
+    newMask = size - 1;
+
+    if (size <= gDvmJit.jitTableSize) {
+        return true;
+    }
+
+    pNewTable = (struct JitEntry*)calloc(size, sizeof(*pNewTable));
+    if (pNewTable == NULL) {
+        return true;
+    }
+    for (i=0; i< size; i++) {
+        pNewTable[i].chain = size;  /* Initialize chain termination */
+    }
+
+    /* Stop all other interpreting/jit'ng threads */
+    dvmSuspendAllThreads(SUSPEND_FOR_JIT);
+
+    /*
+     * At this point, only the compiler thread may be in contention
+     * for the jitEntryTable (it is not affected by the thread suspension).
+     * Aquire the lock.
+     */
+
+    dvmLockMutex(&gDvmJit.tableLock);
+
+    for (i=0; i < gDvmJit.jitTableSize; i++) {
+        if (gDvmJit.pJitEntryTable[i].dPC) {
+            struct JitEntry *p;
+            p = allocateJitEntry(gDvmJit.pJitEntryTable[i].dPC,
+                 pNewTable, size);
+            p->dPC = gDvmJit.pJitEntryTable[i].dPC;
+            p->codeAddress = gDvmJit.pJitEntryTable[i].codeAddress;
+        }
+    }
+
+    free(gDvmJit.pJitEntryTable);
+    gDvmJit.pJitEntryTable = pNewTable;
+    gDvmJit.jitTableSize = size;
+    gDvmJit.jitTableMask = size - 1;
+
+    dvmUnlockMutex(&gDvmJit.tableLock);
+
+    /* Restart the world */
+    dvmResumeAllThreads(SUSPEND_FOR_JIT);
+
+    return false;
+}
+
+
 #endif /* WITH_JIT */
diff --git a/vm/interp/Jit.h b/vm/interp/Jit.h
index 2b2cb8e..5d748d5 100644
--- a/vm/interp/Jit.h
+++ b/vm/interp/Jit.h
@@ -22,17 +22,23 @@
 #include "InterpDefs.h"
 
 #define JIT_PROF_SIZE 512
+
+#define JIT_MAX_TRACE_LEN 100
+
 /*
  * JitTable hash function.
  */
-static inline u4 dvmJitHash( const u2* p ) {
-    /*
-     * TODO - Might make sense to keep "maxTableEntries - 1" as its own
-     * variable for speed reasons.
-     */
-    return ((((u4)p>>12)^(u4)p)>>1) & (gDvmJit.maxTableEntries-1);
+
+static inline u4 dvmJitHashMask( const u2* p, u4 mask ) {
+    return ((((u4)p>>12)^(u4)p)>>1) & (mask);
 }
 
+static inline u4 dvmJitHash( const u2* p ) {
+    return dvmJitHashMask( p, gDvmJit.jitTableMask );
+}
+
+
+
 /*
  * Entries in the JIT's address lookup hash table.
  * with assembly hash function in mterp.
@@ -53,7 +59,10 @@
 void dvmJitSetCodeAddr(const u2* dPC, void *nPC);
 bool dvmJitCheckTraceRequest(Thread* self, InterpState* interpState);
 void* dvmJitChain(void* tgtAddr, u4* branchAddr);
-void dvmJitStopTranslationRequests();
-void dvmJitStats();
+void dvmJitStopTranslationRequests(void);
+void dvmJitStats(void);
+bool dvmJitResizeJitTable(unsigned int size);
+struct JitEntry *dvmFindJitEntry(const u2* pc);
+
 
 #endif /*_DALVIK_INTERP_JIT*/
diff --git a/vm/mterp/Mterp.c b/vm/mterp/Mterp.c
index 80a7b2b..60e2de8 100644
--- a/vm/mterp/Mterp.c
+++ b/vm/mterp/Mterp.c
@@ -78,7 +78,6 @@
     glue->interpStackEnd = self->interpStackEnd;
     glue->pSelfSuspendCount = &self->suspendCount;
 #if defined(WITH_JIT)
-    glue->pJitTable = gDvmJit.pJitEntryTable;
     glue->pJitProfTable = gDvmJit.pProfTable;
 #endif
 #if defined(WITH_DEBUGGER)
diff --git a/vm/mterp/armv5te/footer.S b/vm/mterp/armv5te/footer.S
index f4df342..295b5d4 100644
--- a/vm/mterp/armv5te/footer.S
+++ b/vm/mterp/armv5te/footer.S
@@ -69,7 +69,6 @@
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -111,7 +110,6 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -175,7 +173,6 @@
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
-    ldrne   rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     beq     common_selectTrace
     bxne    r0                          @ jump to the translation
 common_selectTrace:
@@ -184,9 +181,6 @@
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
-.LdvmCompilerTemplateStart:
-    .word   dvmCompilerTemplateStart
-
 #endif
 
 /*
@@ -542,14 +536,11 @@
     mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     cmp     r3, #0                      @ caller is compiled code
-    bne     1f
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     cmp     r0,#0
     bne     common_updateProfile
     GOTO_OPCODE(ip)                     @ jump to next instruction
-1:
-    ldr     rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
-    blx     r3
 #else
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     mov     rPC, r9                     @ publish new rPC
diff --git a/vm/mterp/armv5te/header.S b/vm/mterp/armv5te/header.S
index e5a82c2..e129b15 100644
--- a/vm/mterp/armv5te/header.S
+++ b/vm/mterp/armv5te/header.S
@@ -178,10 +178,7 @@
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
 #if defined(WITH_JIT)
-/*
- * Null definition for overhead measuring purposes
- */
-#define GET_JIT_TABLE(_reg)         ldr     _reg,[rGLUE,#offGlue_pJitTable]
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
 #endif
 
diff --git a/vm/mterp/common/asm-constants.h b/vm/mterp/common/asm-constants.h
index b4bb1c2..5c37af6 100644
--- a/vm/mterp/common/asm-constants.h
+++ b/vm/mterp/common/asm-constants.h
@@ -102,41 +102,37 @@
 MTERP_OFFSET(offGlue_pActiveProfilers,  MterpGlue, pActiveProfilers, 44)
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 48)
 #if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitTable,         MterpGlue, pJitTable, 56)
-MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 60)
-MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 64)
-MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 68)
-MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 72)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 56)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 60)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 64)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 68)
 #endif
 #elif defined(WITH_DEBUGGER)
 MTERP_OFFSET(offGlue_pDebuggerActive,   MterpGlue, pDebuggerActive, 40)
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 44)
 #if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitTable,         MterpGlue, pJitTable, 52)
-MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 56)
-MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 60)
-MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 64)
-MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 68)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 52)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 56)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 60)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 64)
 #endif
 #elif defined(WITH_PROFILER)
 MTERP_OFFSET(offGlue_pActiveProfilers,  MterpGlue, pActiveProfilers, 40)
 MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 44)
 #if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitTable,         MterpGlue, pJitTable, 52)
-MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 56)
-MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 60)
-MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 64)
-MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 68)
-#endif
-#else
-MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 40)
-#if defined(WITH_JIT)
-MTERP_OFFSET(offGlue_pJitTable,         MterpGlue, pJitTable, 48)
 MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 52)
 MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 56)
 MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 60)
 MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 64)
 #endif
+#else
+MTERP_OFFSET(offGlue_entryPoint,        MterpGlue, entryPoint, 40)
+#if defined(WITH_JIT)
+MTERP_OFFSET(offGlue_pJitProfTable,     MterpGlue, pJitProfTable, 48)
+MTERP_OFFSET(offGlue_jitState,          MterpGlue, jitState, 52)
+MTERP_OFFSET(offGlue_jitResume,         MterpGlue, jitResume, 56)
+MTERP_OFFSET(offGlue_jitResumePC,       MterpGlue, jitResumePC, 60)
+#endif
 #endif
 /* make sure all JValue union members are stored at the same offset */
 MTERP_OFFSET(offGlue_retval_z,          MterpGlue, retval.z, 8)
@@ -268,4 +264,3 @@
 
 /* opcode number */
 MTERP_CONSTANT(OP_MOVE_EXCEPTION,   0x0d)
-
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index b3c2dc1..5cf4a05 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -185,10 +185,7 @@
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
 #if defined(WITH_JIT)
-/*
- * Null definition for overhead measuring purposes
- */
-#define GET_JIT_TABLE(_reg)         ldr     _reg,[rGLUE,#offGlue_pJitTable]
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
 #endif
 
@@ -9551,7 +9548,6 @@
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9593,7 +9589,6 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9657,7 +9652,6 @@
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
-    ldrne   rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     beq     common_selectTrace
     bxne    r0                          @ jump to the translation
 common_selectTrace:
@@ -9666,9 +9660,6 @@
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
-.LdvmCompilerTemplateStart:
-    .word   dvmCompilerTemplateStart
-
 #endif
 
 /*
@@ -10024,14 +10015,11 @@
     mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     cmp     r3, #0                      @ caller is compiled code
-    bne     1f
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     cmp     r0,#0
     bne     common_updateProfile
     GOTO_OPCODE(ip)                     @ jump to next instruction
-1:
-    ldr     rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
-    blx     r3
 #else
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     mov     rPC, r9                     @ publish new rPC
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index bd30e90..3fb16ff 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -185,10 +185,7 @@
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
 #if defined(WITH_JIT)
-/*
- * Null definition for overhead measuring purposes
- */
-#define GET_JIT_TABLE(_reg)         ldr     _reg,[rGLUE,#offGlue_pJitTable]
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
 #endif
 
@@ -9065,7 +9062,6 @@
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9107,7 +9103,6 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9171,7 +9166,6 @@
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
-    ldrne   rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     beq     common_selectTrace
     bxne    r0                          @ jump to the translation
 common_selectTrace:
@@ -9180,9 +9174,6 @@
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
-.LdvmCompilerTemplateStart:
-    .word   dvmCompilerTemplateStart
-
 #endif
 
 /*
@@ -9538,14 +9529,11 @@
     mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     cmp     r3, #0                      @ caller is compiled code
-    bne     1f
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     cmp     r0,#0
     bne     common_updateProfile
     GOTO_OPCODE(ip)                     @ jump to next instruction
-1:
-    ldr     rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
-    blx     r3
 #else
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     mov     rPC, r9                     @ publish new rPC
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index b3db103..2b3090d 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -185,10 +185,7 @@
 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
 
 #if defined(WITH_JIT)
-/*
- * Null definition for overhead measuring purposes
- */
-#define GET_JIT_TABLE(_reg)         ldr     _reg,[rGLUE,#offGlue_pJitTable]
+#define GET_JIT_ENABLED(_reg)       ldr     _reg,[rGLUE,#offGlue_jitEnabled]
 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
 #endif
 
@@ -9545,7 +9542,6 @@
     beq    2f
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9587,7 +9583,6 @@
     beq    toInterpreter            @ go if not, otherwise do chain
     mov    r1,rINST
     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
-    ldr    rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     cmp    r0,#0                    @ successful chain?
     bxne   r0                       @ continue native execution
     b      toInterpreter            @ didn't chain - resume with interpreter
@@ -9651,7 +9646,6 @@
     mov     r0,rPC
     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
     cmp     r0,#0
-    ldrne   rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
     beq     common_selectTrace
     bxne    r0                          @ jump to the translation
 common_selectTrace:
@@ -9660,9 +9654,6 @@
     mov     r1,#1                       @ set changeInterp
     b       common_gotoBail
 
-.LdvmCompilerTemplateStart:
-    .word   dvmCompilerTemplateStart
-
 #endif
 
 /*
@@ -10018,14 +10009,11 @@
     mov     rPC, r9                     @ publish new rPC
     str     r1, [rGLUE, #offGlue_methodClassDex]
     cmp     r3, #0                      @ caller is compiled code
-    bne     1f
+    blxne   r3
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     cmp     r0,#0
     bne     common_updateProfile
     GOTO_OPCODE(ip)                     @ jump to next instruction
-1:
-    ldr     rINST, .LdvmCompilerTemplateStart @ rINST is rCBASE in compiled code
-    blx     r3
 #else
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     mov     rPC, r9                     @ publish new rPC