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