summaryrefslogtreecommitdiffstats
path: root/vm/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler')
-rw-r--r--vm/compiler/Compiler.c38
-rw-r--r--vm/compiler/Compiler.h9
-rw-r--r--vm/compiler/CompilerIR.h2
-rw-r--r--vm/compiler/Frontend.c20
-rw-r--r--vm/compiler/codegen/arm/ArmLIR.h2
-rw-r--r--vm/compiler/codegen/arm/Assemble.c88
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c69
-rw-r--r--vm/compiler/codegen/arm/Thumb/Gen.c56
-rw-r--r--vm/compiler/codegen/arm/Thumb2/Gen.c53
-rw-r--r--vm/compiler/template/armv5te-vfp/TemplateOpList.h1
-rw-r--r--vm/compiler/template/armv5te/TEMPLATE_PERIODIC_PROFILING.S26
-rw-r--r--vm/compiler/template/armv5te/TemplateOpList.h1
-rw-r--r--vm/compiler/template/armv5te/footer.S2
-rw-r--r--vm/compiler/template/armv7-a-neon/TemplateOpList.h1
-rw-r--r--vm/compiler/template/armv7-a/TemplateOpList.h1
-rw-r--r--vm/compiler/template/config-armv5te-vfp1
-rw-r--r--vm/compiler/template/config-armv7-a1
-rw-r--r--vm/compiler/template/config-armv7-a-neon1
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S34
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv5te.S34
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S34
-rw-r--r--vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S34
22 files changed, 379 insertions, 129 deletions
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index c8ff62ee3..adb58dd4b 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -332,6 +332,7 @@ static bool compilerThreadStartup(void)
{
JitEntry *pJitTable = NULL;
unsigned char *pJitProfTable = NULL;
+ JitTraceProfCounters *pJitTraceProfCounters = NULL;
unsigned int i;
if (!dvmCompilerArchInit())
@@ -398,6 +399,15 @@ static bool compilerThreadStartup(void)
/* Is chain field wide enough for termination pattern? */
assert(pJitTable[0].u.info.chain == gDvmJit.jitTableSize);
+ /* Allocate the trace profiling structure */
+ pJitTraceProfCounters = (JitTraceProfCounters*)
+ calloc(1, sizeof(*pJitTraceProfCounters));
+ if (!pJitTraceProfCounters) {
+ LOGE("jit trace prof counters allocation failed\n");
+ dvmUnlockMutex(&gDvmJit.tableLock);
+ goto fail;
+ }
+
gDvmJit.pJitEntryTable = pJitTable;
gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
gDvmJit.jitTableEntriesUsed = 0;
@@ -409,6 +419,7 @@ static bool compilerThreadStartup(void)
*/
gDvmJit.pProfTable = dvmDebuggerOrProfilerActive() ? NULL : pJitProfTable;
gDvmJit.pProfTableCopy = pJitProfTable;
+ gDvmJit.pJitTraceProfCounters = pJitTraceProfCounters;
dvmUnlockMutex(&gDvmJit.tableLock);
/* Signal running threads to refresh their cached pJitTable pointers */
@@ -620,27 +631,19 @@ static void *compilerThreadStart(void *arg)
if (gDvmJit.haltCompilerThread) {
LOGD("Compiler shutdown in progress - discarding request");
} else if (!gDvmJit.codeCacheFull) {
- bool compileOK = false;
jmp_buf jmpBuf;
work.bailPtr = &jmpBuf;
bool aborted = setjmp(jmpBuf);
if (!aborted) {
- compileOK = dvmCompilerDoWork(&work);
- }
- if (aborted || !compileOK) {
-#if 0 // for x86 JIT testing
- dvmJitSetCodeAddr(work.pc,
- dvmCompilerGetInterpretTemplate(),
- work.result.instructionSet);
-#endif
- dvmCompilerArenaReset();
- } else if (!work.result.discardResult &&
- work.result.codeAddress) {
- /* Make sure that proper code addr is installed */
- assert(work.result.codeAddress != NULL);
- dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
- work.result.instructionSet);
+ bool codeCompiled = dvmCompilerDoWork(&work);
+ if (codeCompiled && !work.result.discardResult &&
+ work.result.codeAddress) {
+ dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
+ work.result.instructionSet,
+ work.result.profileCodeSize);
+ }
}
+ dvmCompilerArenaReset();
}
free(work.info);
#if defined(WITH_JIT_TUNING)
@@ -697,7 +700,8 @@ void dvmCompilerShutdown(void)
gDvmJit.pProfTable = NULL;
gDvmJit.pProfTableCopy = NULL;
- if (gDvm.verboseShutdown) {
+ if (gDvm.verboseShutdown ||
+ gDvmJit.profileMode == kTraceProfilingContinuous) {
dvmCompilerDumpStats();
while (gDvmJit.compilerQueueLength)
sleep(5);
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 0a43df3c9..cd9d21bb3 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -45,15 +45,8 @@
#define COMPILER_TRACE_CHAINING(X)
/* Macro to change the permissions applied to a chunk of the code cache */
-#if !defined(WITH_JIT_TUNING)
#define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC)
#define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE)
-#else
-/* When doing JIT profiling always grant the write permission */
-#define PROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | \
- (gDvmJit.profile ? PROT_WRITE : 0))
-#define UNPROTECT_CODE_CACHE_ATTRS (PROT_READ | PROT_EXEC | PROT_WRITE)
-#endif
/* Acquire the lock before removing PROT_WRITE from the specified mem region */
#define UNPROTECT_CODE_CACHE(addr, size) \
@@ -90,6 +83,7 @@ typedef enum JitInstructionSetType {
typedef struct JitTranslationInfo {
void *codeAddress;
JitInstructionSetType instructionSet;
+ int profileCodeSize;
bool discardResult; // Used for debugging divergence and IC patching
bool methodCompilationAborted; // Cannot compile the whole method
Thread *requestingThread; // For debugging purpose
@@ -100,6 +94,7 @@ typedef enum WorkOrderKind {
kWorkOrderMethod = 1, // Work is to compile a whole method
kWorkOrderTrace = 2, // Work is to compile code fragment(s)
kWorkOrderTraceDebug = 3, // Work is to compile/debug code fragment(s)
+ kWorkOrderProfileMode = 4, // Change profiling mode
} WorkOrderKind;
typedef struct CompilerWorkOrder {
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index caf6fa617..54d41a5c5 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -206,11 +206,11 @@ typedef struct CompilationUnit {
void *baseAddr;
bool printMe;
bool allSingleStep;
- bool executionCount; // Add code to count trace executions
bool hasLoop; // Contains a loop
bool hasInvoke; // Contains an invoke instruction
bool heapMemOp; // Mark mem ops for self verification
bool wholeMethod;
+ int profileCodeSize; // Size of the profile prefix in bytes
int numChainingCells[kChainingCellGap];
LIR *firstChainingLIR[kChainingCellGap];
LIR *chainingCellBottom;
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 95ef026c0..915e5f3fe 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -458,9 +458,6 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
/* Initialize the printMe flag */
cUnit.printMe = gDvmJit.printMe;
- /* Initialize the profile flag */
- cUnit.executionCount = gDvmJit.profile;
-
/* Setup the method */
cUnit.method = desc->method;
@@ -634,6 +631,7 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
for (blockId = 0; blockId < blockList->numUsed; blockId++) {
curBB = (BasicBlock *) dvmGrowableListGetElement(blockList, blockId);
MIR *lastInsn = curBB->lastMIRInsn;
+ BasicBlock *backwardCell;
/* Skip empty blocks */
if (lastInsn == NULL) {
continue;
@@ -708,25 +706,11 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
exitBB->needFallThroughBranch = true;
loopBranch->taken = exitBB;
-#if defined(WITH_SELF_VERIFICATION)
- BasicBlock *backwardCell =
+ backwardCell =
dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
backwardCell->startOffset = entryCodeBB->startOffset;
loopBranch->fallThrough = backwardCell;
-#elif defined(WITH_JIT_TUNING)
- if (gDvmJit.profile) {
- BasicBlock *backwardCell =
- dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
- dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
- backwardCell->startOffset = entryCodeBB->startOffset;
- loopBranch->fallThrough = backwardCell;
- } else {
- loopBranch->fallThrough = entryCodeBB;
- }
-#else
- loopBranch->fallThrough = entryCodeBB;
-#endif
/* Create the chaining cell as the fallthrough of the exit block */
exitChainingCell = dvmCompilerNewBB(kChainingCellNormal,
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index 4f3434dec..437c2ed96 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -619,6 +619,8 @@ typedef enum ArmOpcode {
kThumb2Bfc, /* bfc [11110011011011110] [0] imm3[14-12]
rd[11-8] imm2[7-6] [0] msb[4-0] */
kThumb2Dmb, /* dmb [1111001110111111100011110101] option[3-0] */
+ kThumb2LdrPcReln12, /* ldr rd,[pc,-#imm12] [1111100011011111] rt[15-12]
+ imm12[11-0] */
kArmLast,
} ArmOpcode;
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 4154387ba..b5c04f5d0 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -876,6 +876,11 @@ ArmEncodingMap EncodingMap[kArmLast] = {
kFmtBitBlt, 3, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
kFmtUnused, -1, -1, IS_UNARY_OP,
"dmb","#!0B",2),
+ ENCODING_MAP(kThumb2LdrPcReln12, 0xf85f0000,
+ kFmtBitBlt, 15, 12, kFmtBitBlt, 11, 0, kFmtUnused, -1, -1,
+ kFmtUnused, -1, -1,
+ IS_BINARY_OP | REG_DEF0 | REG_USE_PC | IS_LOAD,
+ "ldr", "r!0d, [rpc, -#!1d]", 2),
};
/*
@@ -1163,21 +1168,21 @@ static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
/*
* Translation layout in the code cache. Note that the codeAddress pointer
* in JitTable will point directly to the code body (field codeAddress). The
- * chain cell offset codeAddress - 2, and (if present) executionCount is at
- * codeAddress - 6.
+ * chain cell offset codeAddress - 2, and the address of the trace profile
+ * counter is at codeAddress - 6.
*
* +----------------------------+
- * | Execution count | -> [Optional] 4 bytes
+ * | Trace Profile Counter addr | -> 4 bytes
* +----------------------------+
* +--| Offset to chain cell counts| -> 2 bytes
* | +----------------------------+
- * | | Code body | -> Start address for translation
- * | | | variable in 2-byte chunks
- * | . . (JitTable's codeAddress points here)
+ * | | Trace profile code | <- entry point when profiling
+ * | . - - - - - - - .
+ * | | Code body | <- entry point when not profiling
* | . .
* | | |
* | +----------------------------+
- * | | Chaining Cells | -> 12/16 bytes each, must be 4 byte aligned
+ * | | Chaining Cells | -> 12/16 bytes, 4 byte aligned
* | . .
* | . .
* | | |
@@ -1251,13 +1256,10 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
chainCellOffsetLIR->operands[0] == CHAIN_CELL_OFFSET_TAG);
/*
- * Replace the CHAIN_CELL_OFFSET_TAG with the real value. If trace
- * profiling is enabled, subtract 4 (occupied by the counter word) from
- * the absolute offset as the value stored in chainCellOffsetLIR is the
- * delta from &chainCellOffsetLIR to &ChainCellCounts.
+ * Adjust the CHAIN_CELL_OFFSET_TAG LIR's offset to remove the
+ * space occupied by the pointer to the trace profiling counter.
*/
- chainCellOffsetLIR->operands[0] =
- gDvmJit.profile ? (chainCellOffset - 4) : chainCellOffset;
+ chainCellOffsetLIR->operands[0] = chainCellOffset - 4;
offset += sizeof(chainCellCounts) + descSize;
@@ -1363,6 +1365,8 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
/* If applicable, mark low bit to denote thumb */
if (info->instructionSet != DALVIK_JIT_ARM)
info->codeAddress = (char*)info->codeAddress + 1;
+ /* transfer the size of the profiling code */
+ info->profileCodeSize = cUnit->profileCodeSize;
}
/*
@@ -1836,14 +1840,37 @@ static char *getTraceBase(const JitEntry *p)
(6 + (p->u.info.instructionSet == DALVIK_JIT_ARM ? 0 : 1));
}
+/* Handy function to retrieve the profile count */
+static inline JitTraceCounter_t getProfileCount(const JitEntry *entry)
+{
+ if (entry->dPC == 0 || entry->codeAddress == 0 ||
+ entry->codeAddress == dvmCompilerGetInterpretTemplate())
+ return 0;
+
+ JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry);
+
+ return **p;
+}
+
+/* Handy function to reset the profile count */
+static inline void resetProfileCount(const JitEntry *entry)
+{
+ if (entry->dPC == 0 || entry->codeAddress == 0 ||
+ entry->codeAddress == dvmCompilerGetInterpretTemplate())
+ return;
+
+ JitTraceCounter_t **p = (JitTraceCounter_t **) getTraceBase(entry);
+
+ **p = 0;
+}
+
/* Dumps profile info for a single trace */
static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
unsigned long sum)
{
ChainCellCounts* pCellCounts;
char* traceBase;
- u4* pExecutionCount;
- u4 executionCount;
+ JitTraceCounter_t count;
u2* pCellOffset;
JitTraceDescription *desc;
const Method* method;
@@ -1861,14 +1888,12 @@ static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
LOGD("TRACEPROFILE 0x%08x 0 INTERPRET_ONLY 0 0", (int)traceBase);
return 0;
}
-
- pExecutionCount = (u4*) (traceBase);
- executionCount = *pExecutionCount;
+ count = getProfileCount(p);
if (reset) {
- *pExecutionCount =0;
+ resetProfileCount(p);
}
if (silent) {
- return executionCount;
+ return count;
}
pCellOffset = (u2*) (traceBase + 4);
pCellCounts = (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
@@ -1893,8 +1918,8 @@ static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
LOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s",
(int)traceBase,
- executionCount,
- ((float ) executionCount) / sum * 100.0,
+ count,
+ ((float ) count) / sum * 100.0,
desc->trace[0].frag.startOffset,
desc->trace[0].frag.numInsts,
addrToLine.lineNum,
@@ -1919,7 +1944,7 @@ static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
methodDesc);
}
- return executionCount;
+ return count;
}
/* Create a copy of the trace descriptor of an existing compilation */
@@ -1948,27 +1973,14 @@ JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
return newCopy;
}
-/* Handy function to retrieve the profile count */
-static inline int getProfileCount(const JitEntry *entry)
-{
- if (entry->dPC == 0 || entry->codeAddress == 0 ||
- entry->codeAddress == dvmCompilerGetInterpretTemplate())
- return 0;
-
- u4 *pExecutionCount = (u4 *) getTraceBase(entry);
-
- return *pExecutionCount;
-}
-
-
/* qsort callback function */
static int sortTraceProfileCount(const void *entry1, const void *entry2)
{
const JitEntry *jitEntry1 = (const JitEntry *)entry1;
const JitEntry *jitEntry2 = (const JitEntry *)entry2;
- int count1 = getProfileCount(jitEntry1);
- int count2 = getProfileCount(jitEntry2);
+ JitTraceCounter_t count1 = getProfileCount(jitEntry1);
+ JitTraceCounter_t count2 = getProfileCount(jitEntry2);
return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1);
}
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 6473edb50..181a128fd 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -3536,7 +3536,6 @@ static void handleHotChainingCell(CompilationUnit *cUnit,
addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
}
-#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
/* Chaining cell for branches that branch back into the same basic block */
static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
unsigned int offset)
@@ -3558,7 +3557,6 @@ static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
}
-#endif
/* Chaining cell for monomorphic method invocations. */
static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
const Method *callee)
@@ -3944,39 +3942,8 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
GrowableListIterator iterator;
dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
- if (cUnit->executionCount) {
- /*
- * Reserve 6 bytes at the beginning of the trace
- * +----------------------------+
- * | execution count (4 bytes) |
- * +----------------------------+
- * | chain cell offset (2 bytes)|
- * +----------------------------+
- * ...and then code to increment the execution
- * count:
- * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
- * sub r0, #10 @ back up to addr of executionCount
- * ldr r1, [r0]
- * add r1, #1
- * str r1, [r0]
- */
- newLIR1(cUnit, kArm16BitData, 0);
- newLIR1(cUnit, kArm16BitData, 0);
- cUnit->chainCellOffsetLIR =
- (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
- cUnit->headerSize = 6;
- /* Thumb instruction used directly here to ensure correct size */
- newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
- newLIR2(cUnit, kThumbSubRI8, r0, 10);
- newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
- newLIR2(cUnit, kThumbAddRI8, r1, 1);
- newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
- } else {
- /* Just reserve 2 bytes for the chain cell offset */
- cUnit->chainCellOffsetLIR =
- (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
- cUnit->headerSize = 2;
- }
+ /* Traces start with a profiling entry point. Generate it here */
+ cUnit->profileCodeSize = genTraceProfileEntry(cUnit);
/* Handle the content in each basic block */
for (i = 0; ; i++) {
@@ -4062,7 +4029,6 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
opReg(cUnit, kOpBlx, r1);
}
break;
-#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
case kChainingCellBackwardBranch:
labelList[i].opcode =
kArmPseudoChainingCellBackwardBranch;
@@ -4071,7 +4037,6 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
&chainingListByType[kChainingCellBackwardBranch],
i);
break;
-#endif
default:
break;
}
@@ -4303,12 +4268,10 @@ gen_fallthrough:
case kChainingCellHot:
handleHotChainingCell(cUnit, chainingBlock->startOffset);
break;
-#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
case kChainingCellBackwardBranch:
handleBackwardBranchChainingCell(cUnit,
chainingBlock->startOffset);
break;
-#endif
default:
LOGE("Bad blocktype %d", chainingBlock->blockType);
dvmCompilerAbort(cUnit);
@@ -4342,11 +4305,15 @@ gen_fallthrough:
#endif
}
-/* Accept the work and start compiling */
+/*
+ * Accept the work and start compiling. Returns true if compilation
+ * is attempted.
+ */
bool dvmCompilerDoWork(CompilerWorkOrder *work)
{
JitTraceDescription *desc;
- bool res;
+ bool isCompile;
+ bool success = true;
if (gDvmJit.codeCacheFull) {
return false;
@@ -4354,27 +4321,35 @@ bool dvmCompilerDoWork(CompilerWorkOrder *work)
switch (work->kind) {
case kWorkOrderTrace:
+ isCompile = true;
/* Start compilation with maximally allowed trace length */
desc = (JitTraceDescription *)work->info;
- res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
- work->bailPtr, 0 /* no hints */);
+ success = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
+ work->bailPtr, 0 /* no hints */);
break;
case kWorkOrderTraceDebug: {
bool oldPrintMe = gDvmJit.printMe;
gDvmJit.printMe = true;
+ isCompile = true;
/* Start compilation with maximally allowed trace length */
desc = (JitTraceDescription *)work->info;
- res = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
- work->bailPtr, 0 /* no hints */);
+ success = dvmCompileTrace(desc, JIT_MAX_TRACE_LEN, &work->result,
+ work->bailPtr, 0 /* no hints */);
gDvmJit.printMe = oldPrintMe;
break;
}
+ case kWorkOrderProfileMode:
+ dvmJitChangeProfileMode((TraceProfilingModes)work->info);
+ isCompile = false;
+ break;
default:
- res = false;
+ isCompile = false;
LOGE("Jit: unknown work order type");
assert(0); // Bail if debug build, discard otherwise
}
- return res;
+ if (!success)
+ work->result.codeAddress = NULL;
+ return isCompile;
}
/* Architectural-specific debugging helpers go here */
diff --git a/vm/compiler/codegen/arm/Thumb/Gen.c b/vm/compiler/codegen/arm/Thumb/Gen.c
index 07f3f092f..b80696595 100644
--- a/vm/compiler/codegen/arm/Thumb/Gen.c
+++ b/vm/compiler/codegen/arm/Thumb/Gen.c
@@ -23,6 +23,62 @@
*/
/*
+ * Reserve 6 bytes at the beginning of the trace
+ * +----------------------------+
+ * | prof count addr (4 bytes) |
+ * +----------------------------+
+ * | chain cell offset (2 bytes)|
+ * +----------------------------+
+ *
+ * ...and then code to increment the execution
+ *
+ * For continuous profiling (12 bytes):
+ *
+ * mov r0, pc @ move adr of "mov r0,pc" + 4 to r0
+ * sub r0, #10 @ back up to addr prof count pointer
+ * ldr r0, [r0] @ get address of counter
+ * ldr r1, [r0]
+ * add r1, #1
+ * str r1, [r0]
+ *
+ * For periodic profiling (4 bytes):
+ * call TEMPLATE_PERIODIC_PROFILING
+ *
+ * and return the size (in bytes) of the generated code.
+ */
+
+static int genTraceProfileEntry(CompilationUnit *cUnit)
+{
+ intptr_t addr = (intptr_t)dvmJitNextTraceCounter();
+ assert(__BYTE_ORDER == __LITTLE_ENDIAN);
+ newLIR1(cUnit, kArm16BitData, addr & 0xffff);
+ newLIR1(cUnit, kArm16BitData, (addr >> 16) & 0xffff);
+ cUnit->chainCellOffsetLIR =
+ (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
+ cUnit->headerSize = 6;
+ if ((gDvmJit.profileMode == kTraceProfilingContinuous) ||
+ (gDvmJit.profileMode == kTraceProfilingDisabled)) {
+ /* Thumb instruction used directly here to ensure correct size */
+ newLIR2(cUnit, kThumbMovRR_H2L, r0, rpc);
+ newLIR2(cUnit, kThumbSubRI8, r0, 10);
+ newLIR3(cUnit, kThumbLdrRRI5, r0, r0, 0);
+ newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
+ newLIR2(cUnit, kThumbAddRI8, r1, 1);
+ newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
+ return 12;
+ } else {
+ int opcode = TEMPLATE_PERIODIC_PROFILING;
+ newLIR2(cUnit, kThumbBlx1,
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
+ newLIR2(cUnit, kThumbBlx2,
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
+ return 4;
+ }
+}
+
+/*
* Perform a "reg cmp imm" operation and jump to the PCR region if condition
* satisfies.
*/
diff --git a/vm/compiler/codegen/arm/Thumb2/Gen.c b/vm/compiler/codegen/arm/Thumb2/Gen.c
index 0891524f7..f5e1096ea 100644
--- a/vm/compiler/codegen/arm/Thumb2/Gen.c
+++ b/vm/compiler/codegen/arm/Thumb2/Gen.c
@@ -15,13 +15,64 @@
*/
/*
- * This file contains codegen for the Thumb ISA and is intended to be
+ * This file contains codegen for the Thumb2 ISA and is intended to be
* includes by:
*
* Codegen-$(TARGET_ARCH_VARIANT).c
*
*/
+/*
+ * Reserve 6 bytes at the beginning of the trace
+ * +----------------------------+
+ * | prof count addr (4 bytes) |
+ * +----------------------------+
+ * | chain cell offset (2 bytes)|
+ * +----------------------------+
+ *
+ * ...and then code to increment the execution
+ *
+ * For continuous profiling (10 bytes)
+ * ldr r0, [pc-8] @ get prof count addr [4 bytes]
+ * ldr r1, [r0] @ load counter [2 bytes]
+ * add r1, #1 @ increment [2 bytes]
+ * str r1, [r0] @ store [2 bytes]
+ *
+ * For periodic profiling (4 bytes)
+ * call TEMPLATE_PERIODIC_PROFILING
+ *
+ * and return the size (in bytes) of the generated code.
+ */
+
+static int genTraceProfileEntry(CompilationUnit *cUnit)
+{
+ intptr_t addr = (intptr_t)dvmJitNextTraceCounter();
+ assert(__BYTE_ORDER == __LITTLE_ENDIAN);
+ newLIR1(cUnit, kArm16BitData, addr & 0xffff);
+ newLIR1(cUnit, kArm16BitData, (addr >> 16) & 0xffff);
+ cUnit->chainCellOffsetLIR =
+ (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
+ cUnit->headerSize = 6;
+ if ((gDvmJit.profileMode == kTraceProfilingContinuous) ||
+ (gDvmJit.profileMode == kTraceProfilingDisabled)) {
+ /* Thumb[2] instruction used directly here to ensure correct size */
+ newLIR2(cUnit, kThumb2LdrPcReln12, r0, 8);
+ newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
+ newLIR2(cUnit, kThumbAddRI8, r1, 1);
+ newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
+ return 10;
+ } else {
+ int opcode = TEMPLATE_PERIODIC_PROFILING;
+ newLIR2(cUnit, kThumbBlx1,
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
+ newLIR2(cUnit, kThumbBlx2,
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
+ (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
+ return 4;
+ }
+}
+
static void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest,
RegLocation rlSrc)
{
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index d991bedb0..97addfaf8 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -57,3 +57,4 @@ JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
+JIT_TEMPLATE(PERIODIC_PROFILING)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_PERIODIC_PROFILING.S b/vm/compiler/template/armv5te/TEMPLATE_PERIODIC_PROFILING.S
new file mode 100644
index 000000000..7f7109646
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_PERIODIC_PROFILING.S
@@ -0,0 +1,26 @@
+ /*
+ * Increment profile counter for this trace, and decrement
+ * sample counter. If sample counter goes below zero, turn
+ * off profiling.
+ *
+ * On entry
+ * (lr-11) is address of pointer to counter. Note: the counter
+ * actually exists 10 bytes before the return target, but because
+ * we are arriving from thumb mode, lr will have its low bit set.
+ */
+ ldr r0, [lr,#-11]
+ ldr r1, [rGLUE, #offGlue_pProfileCountdown]
+ ldr r2, [r0] @ get counter
+ ldr r3, [r1] @ get countdown timer
+ add r2, #1
+ subs r2, #1
+ blt .L${opcode}_disable_profiling
+ str r2, [r0]
+ str r3, [r1]
+ bx lr
+
+.L${opcode}_disable_profiling:
+ mov r4, lr @ preserve lr
+ ldr r0, .LdvmJitTraceProfilingOff
+ blx r0
+ bx r4
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index e81383c5b..663e0df68 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -42,3 +42,4 @@ JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
+JIT_TEMPLATE(PERIODIC_PROFILING)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index ba0335b30..7b35e8a1c 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -104,6 +104,8 @@
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+.LdvmJitTraceProfilingOff:
+ .word dvmJitTraceProfilingOff
#if defined(WITH_JIT_TUNING)
.LdvmICHitCount:
.word gDvmICHitCount
diff --git a/vm/compiler/template/armv7-a-neon/TemplateOpList.h b/vm/compiler/template/armv7-a-neon/TemplateOpList.h
index d991bedb0..97addfaf8 100644
--- a/vm/compiler/template/armv7-a-neon/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a-neon/TemplateOpList.h
@@ -57,3 +57,4 @@ JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
+JIT_TEMPLATE(PERIODIC_PROFILING)
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index d991bedb0..97addfaf8 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -57,3 +57,4 @@ JIT_TEMPLATE(STRING_INDEXOF)
JIT_TEMPLATE(INTERPRET)
JIT_TEMPLATE(MONITOR_ENTER)
JIT_TEMPLATE(MONITOR_ENTER_DEBUG)
+JIT_TEMPLATE(PERIODIC_PROFILING)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index 1b02261eb..30b9200a8 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -48,6 +48,7 @@ op-start armv5te-vfp
op TEMPLATE_INTERPRET armv5te
op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
+ op TEMPLATE_PERIODIC_PROFILING armv5te
op-end
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index be7af31e4..1408ca117 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -48,6 +48,7 @@ op-start armv5te-vfp
op TEMPLATE_INTERPRET armv5te
op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
+ op TEMPLATE_PERIODIC_PROFILING armv5te
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/compiler/template/config-armv7-a-neon b/vm/compiler/template/config-armv7-a-neon
index be7af31e4..1408ca117 100644
--- a/vm/compiler/template/config-armv7-a-neon
+++ b/vm/compiler/template/config-armv7-a-neon
@@ -48,6 +48,7 @@ op-start armv5te-vfp
op TEMPLATE_INTERPRET armv5te
op TEMPLATE_MONITOR_ENTER armv5te
op TEMPLATE_MONITOR_ENTER_DEBUG armv5te
+ op TEMPLATE_PERIODIC_PROFILING armv5te
op-end
# "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 8efbcaa60..a107b24de 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -1473,6 +1473,38 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
#endif
ldr pc, .LdvmJitToInterpNoChain
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
+dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
+/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
+ /*
+ * Increment profile counter for this trace, and decrement
+ * sample counter. If sample counter goes below zero, turn
+ * off profiling.
+ *
+ * On entry
+ * (lr-11) is address of pointer to counter. Note: the counter
+ * actually exists 10 bytes before the return target, but because
+ * we are arriving from thumb mode, lr will have its low bit set.
+ */
+ ldr r0, [lr,#-11]
+ ldr r1, [rGLUE, #offGlue_pProfileCountdown]
+ ldr r2, [r0] @ get counter
+ ldr r3, [r1] @ get countdown timer
+ add r2, #1
+ subs r2, #1
+ blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
+ str r2, [r0]
+ str r3, [r1]
+ bx lr
+
+.LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
+ mov r4, lr @ preserve lr
+ ldr r0, .LdvmJitTraceProfilingOff
+ blx r0
+ bx r4
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1581,6 +1613,8 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+.LdvmJitTraceProfilingOff:
+ .word dvmJitTraceProfilingOff
#if defined(WITH_JIT_TUNING)
.LdvmICHitCount:
.word gDvmICHitCount
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index 0df3ae65a..a6a0e9ff8 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -1204,6 +1204,38 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
#endif
ldr pc, .LdvmJitToInterpNoChain
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
+dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
+/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
+ /*
+ * Increment profile counter for this trace, and decrement
+ * sample counter. If sample counter goes below zero, turn
+ * off profiling.
+ *
+ * On entry
+ * (lr-11) is address of pointer to counter. Note: the counter
+ * actually exists 10 bytes before the return target, but because
+ * we are arriving from thumb mode, lr will have its low bit set.
+ */
+ ldr r0, [lr,#-11]
+ ldr r1, [rGLUE, #offGlue_pProfileCountdown]
+ ldr r2, [r0] @ get counter
+ ldr r3, [r1] @ get countdown timer
+ add r2, #1
+ subs r2, #1
+ blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
+ str r2, [r0]
+ str r3, [r1]
+ bx lr
+
+.LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
+ mov r4, lr @ preserve lr
+ ldr r0, .LdvmJitTraceProfilingOff
+ blx r0
+ bx r4
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1312,6 +1344,8 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+.LdvmJitTraceProfilingOff:
+ .word dvmJitTraceProfilingOff
#if defined(WITH_JIT_TUNING)
.LdvmICHitCount:
.word gDvmICHitCount
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
index ee3f8cbec..e4ed30bef 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
@@ -1473,6 +1473,38 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
#endif
ldr pc, .LdvmJitToInterpNoChain
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
+dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
+/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
+ /*
+ * Increment profile counter for this trace, and decrement
+ * sample counter. If sample counter goes below zero, turn
+ * off profiling.
+ *
+ * On entry
+ * (lr-11) is address of pointer to counter. Note: the counter
+ * actually exists 10 bytes before the return target, but because
+ * we are arriving from thumb mode, lr will have its low bit set.
+ */
+ ldr r0, [lr,#-11]
+ ldr r1, [rGLUE, #offGlue_pProfileCountdown]
+ ldr r2, [r0] @ get counter
+ ldr r3, [r1] @ get countdown timer
+ add r2, #1
+ subs r2, #1
+ blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
+ str r2, [r0]
+ str r3, [r1]
+ bx lr
+
+.LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
+ mov r4, lr @ preserve lr
+ ldr r0, .LdvmJitTraceProfilingOff
+ blx r0
+ bx r4
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1581,6 +1613,8 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+.LdvmJitTraceProfilingOff:
+ .word dvmJitTraceProfilingOff
#if defined(WITH_JIT_TUNING)
.LdvmICHitCount:
.word gDvmICHitCount
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 3875f5a24..fc26b3a95 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -1473,6 +1473,38 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
#endif
ldr pc, .LdvmJitToInterpNoChain
+/* ------------------------------ */
+ .balign 4
+ .global dvmCompiler_TEMPLATE_PERIODIC_PROFILING
+dvmCompiler_TEMPLATE_PERIODIC_PROFILING:
+/* File: armv5te/TEMPLATE_PERIODIC_PROFILING.S */
+ /*
+ * Increment profile counter for this trace, and decrement
+ * sample counter. If sample counter goes below zero, turn
+ * off profiling.
+ *
+ * On entry
+ * (lr-11) is address of pointer to counter. Note: the counter
+ * actually exists 10 bytes before the return target, but because
+ * we are arriving from thumb mode, lr will have its low bit set.
+ */
+ ldr r0, [lr,#-11]
+ ldr r1, [rGLUE, #offGlue_pProfileCountdown]
+ ldr r2, [r0] @ get counter
+ ldr r3, [r1] @ get countdown timer
+ add r2, #1
+ subs r2, #1
+ blt .LTEMPLATE_PERIODIC_PROFILING_disable_profiling
+ str r2, [r0]
+ str r3, [r1]
+ bx lr
+
+.LTEMPLATE_PERIODIC_PROFILING_disable_profiling:
+ mov r4, lr @ preserve lr
+ ldr r0, .LdvmJitTraceProfilingOff
+ blx r0
+ bx r4
+
.size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
/* File: armv5te/footer.S */
/*
@@ -1581,6 +1613,8 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
.word dvmMterpCommonExceptionThrown
.LdvmLockObject:
.word dvmLockObject
+.LdvmJitTraceProfilingOff:
+ .word dvmJitTraceProfilingOff
#if defined(WITH_JIT_TUNING)
.LdvmICHitCount:
.word gDvmICHitCount