summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen
diff options
context:
space:
mode:
authorBen Cheng <bccheng@android.com>2011-03-10 11:17:04 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-03-10 11:17:04 -0800
commit6d59d5584b793e597e94300bf95dea8ee8335ccf (patch)
treec78bf70af11ad28b43d715671dbf1cc23997ac42 /vm/compiler/codegen
parent9ea32b0a0fa0eb4c4bfcd73f0c7fe15ddb0f9ce2 (diff)
parent385828e36ea70effe9aa18a954d008b1f7dc1d63 (diff)
downloadandroid_dalvik-6d59d5584b793e597e94300bf95dea8ee8335ccf.tar.gz
android_dalvik-6d59d5584b793e597e94300bf95dea8ee8335ccf.tar.bz2
android_dalvik-6d59d5584b793e597e94300bf95dea8ee8335ccf.zip
Merge "Handle relocatable class objects in JIT'ed code." into dalvik-dev
Diffstat (limited to 'vm/compiler/codegen')
-rw-r--r--vm/compiler/codegen/CodegenFactory.c30
-rw-r--r--vm/compiler/codegen/CompilerCodegen.h7
-rw-r--r--vm/compiler/codegen/arm/ArchUtility.c9
-rw-r--r--vm/compiler/codegen/arm/Assemble.c480
-rw-r--r--vm/compiler/codegen/arm/CodegenCommon.c13
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c20
-rw-r--r--vm/compiler/codegen/arm/Thumb/Factory.c4
-rw-r--r--vm/compiler/codegen/arm/Thumb2/Factory.c8
-rw-r--r--vm/compiler/codegen/x86/Assemble.c4
9 files changed, 409 insertions, 166 deletions
diff --git a/vm/compiler/codegen/CodegenFactory.c b/vm/compiler/codegen/CodegenFactory.c
index 61e29d7d1..ef7a0a976 100644
--- a/vm/compiler/codegen/CodegenFactory.c
+++ b/vm/compiler/codegen/CodegenFactory.c
@@ -263,3 +263,33 @@ static void storeValueWide(CompilationUnit *cUnit, RegLocation rlDest,
}
}
}
+
+/*
+ * Load a class pointer value into a fixed or temp register. Target
+ * register is clobbered, and marked inUse.
+ */
+static ArmLIR *loadClassPointer(CompilationUnit *cUnit, int rDest, int value)
+{
+ ArmLIR *res;
+ cUnit->hasClassLiterals = true;
+ if (dvmCompilerIsTemp(cUnit, rDest)) {
+ dvmCompilerClobber(cUnit, rDest);
+ dvmCompilerMarkInUse(cUnit, rDest);
+ }
+ ArmLIR *dataTarget = scanLiteralPool(cUnit->classPointerList, value, 0);
+ if (dataTarget == NULL) {
+ dataTarget = addWordData(cUnit, &cUnit->classPointerList, value);
+ /* Counts the number of class pointers in this translation */
+ cUnit->numClassPointers++;
+ }
+ ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
+ loadPcRel->opcode = kThumb2LdrPcRel12;
+ loadPcRel->generic.target = (LIR *) dataTarget;
+ loadPcRel->operands[0] = rDest;
+ setupResourceMasks(loadPcRel);
+ setMemRefType(loadPcRel, true, kLiteral);
+ loadPcRel->aliasInfo = dataTarget->operands[0];
+ res = loadPcRel;
+ dvmCompilerAppendLIR(cUnit, (LIR *) loadPcRel);
+ return res;
+}
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
index 9cd4847c0..efa913f90 100644
--- a/vm/compiler/codegen/CompilerCodegen.h
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -34,6 +34,10 @@ void dvmCompilerMethodMIR2LIR(CompilationUnit *cUnit);
/* Assemble LIR into machine code */
void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info);
+/* Install class objects in the literal pool */
+void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit,
+ char *codeAddress);
+
/* Patch inline cache content for polymorphic callsites */
bool dvmJitPatchInlineCache(void *cellPtr, void *contentPtr);
@@ -41,9 +45,6 @@ bool dvmJitPatchInlineCache(void *cellPtr, void *contentPtr);
void dvmCompilerCodegenDump(CompilationUnit *cUnit);
/* Implemented in the codegen/<target>/Assembler.c */
-void* dvmJitChain(void *tgtAddr, u4* branchAddr);
-u4* dvmJitUnchain(void *codeAddr);
-void dvmJitUnchainAll(void);
void dvmCompilerPatchInlineCache(void);
/* Implemented in codegen/<target>/Ralloc.c */
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
index 02a02fa1f..d94b1a7e1 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -395,7 +395,14 @@ void dvmCompilerCodegenDump(CompilationUnit *cUnit)
for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr);
}
- for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
+ for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
+ armLIR = (ArmLIR *) lirInsn;
+ LOGD("%p (%04x): .class (%s)\n",
+ (char*)cUnit->baseAddr + armLIR->generic.offset,
+ armLIR->generic.offset,
+ ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
+ }
+ for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
armLIR = (ArmLIR *) lirInsn;
LOGD("%p (%04x): .word (0x%x)\n",
(char*)cUnit->baseAddr + armLIR->generic.offset,
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 8fc1add35..9b24b7588 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -897,28 +897,26 @@ ArmEncodingMap EncodingMap[kArmLast] = {
#define UPDATE_CODE_CACHE_PATCHES()
#endif
-/* Write the numbers in the literal pool to the codegen stream */
-static void installDataContent(CompilationUnit *cUnit)
+/* Write the numbers in the constant and class pool to the output stream */
+static void installLiteralPools(CompilationUnit *cUnit)
{
int *dataPtr = (int *) ((char *) cUnit->baseAddr + cUnit->dataOffset);
- ArmLIR *dataLIR = (ArmLIR *) cUnit->wordList;
+ /* Install number of class pointer literals */
+ *dataPtr++ = cUnit->numClassPointers;
+ ArmLIR *dataLIR = (ArmLIR *) cUnit->classPointerList;
while (dataLIR) {
+ /*
+ * Install the callsiteinfo pointers into the cells for now. They will
+ * be converted into real pointers in dvmJitInstallClassObjectPointers.
+ */
*dataPtr++ = dataLIR->operands[0];
dataLIR = NEXT_LIR(dataLIR);
}
-}
-
-/* Returns the size of a Jit trace description */
-static int jitTraceDescriptionSize(const JitTraceDescription *desc)
-{
- int runCount;
- /* Trace end is always of non-meta type (ie isCode == true) */
- for (runCount = 0; ; runCount++) {
- if (desc->trace[runCount].frag.isCode &&
- desc->trace[runCount].frag.runEnd)
- break;
+ dataLIR = (ArmLIR *) cUnit->literalList;
+ while (dataLIR) {
+ *dataPtr++ = dataLIR->operands[0];
+ dataLIR = NEXT_LIR(dataLIR);
}
- return sizeof(JitTraceDescription) + ((runCount+1) * sizeof(JitTraceRun));
}
/*
@@ -1146,35 +1144,24 @@ static AssemblerStatus assembleInstructions(CompilationUnit *cUnit,
return kSuccess;
}
-#if defined(SIGNATURE_BREAKPOINT)
-/* Inspect the assembled instruction stream to find potential matches */
-static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
- unsigned int size)
+static int assignLiteralOffsetCommon(LIR *lir, int offset)
{
- unsigned int i, j;
- u4 *ptr = (u4 *) cUnit->codeBuffer;
-
- for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) {
- if (ptr[i] == gDvmJit.signatureBreakpoint[0]) {
- for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) {
- if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) {
- break;
- }
- }
- if (j == gDvmJit.signatureBreakpointSize) {
- LOGD("Signature match starting from offset %#x (%d words)",
- i*4, gDvmJit.signatureBreakpointSize);
- int descSize = jitTraceDescriptionSize(cUnit->traceDesc);
- JitTraceDescription *newCopy =
- (JitTraceDescription *) malloc(descSize);
- memcpy(newCopy, cUnit->traceDesc, descSize);
- dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy);
- break;
- }
- }
+ for (;lir != NULL; lir = lir->next) {
+ lir->offset = offset;
+ offset += 4;
}
+ return offset;
+}
+
+/* Determine the offset of each literal field */
+static int assignLiteralOffset(CompilationUnit *cUnit, int offset)
+{
+ /* Reserved for the size field of class pointer pool */
+ offset += 4;
+ offset = assignLiteralOffsetCommon(cUnit->classPointerList, offset);
+ offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
+ return offset;
}
-#endif
/*
* Translation layout in the code cache. Note that the codeAddress pointer
@@ -1183,9 +1170,9 @@ static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
* counter is at codeAddress - 6.
*
* +----------------------------+
- * | Trace Profile Counter addr | -> 4 bytes
+ * | Trace Profile Counter addr | -> 4 bytes (PROF_COUNTER_ADDR_SIZE)
* +----------------------------+
- * +--| Offset to chain cell counts| -> 2 bytes
+ * +--| Offset to chain cell counts| -> 2 bytes (CHAIN_CELL_OFFSET_SIZE)
* | +----------------------------+
* | | Trace profile code | <- entry point when profiling
* | . - - - - - - - .
@@ -1206,25 +1193,151 @@ static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
* . .
* | |
* +----------------------------+
+ * | # Class pointer pool size | -> 4 bytes
+ * +----------------------------+
+ * | Class pointer pool | -> 4-byte aligned, variable size
+ * . .
+ * . .
+ * | |
+ * +----------------------------+
* | Literal pool | -> 4-byte aligned, variable size
* . .
* . .
* | |
* +----------------------------+
*
+ */
+
+#define PROF_COUNTER_ADDR_SIZE 4
+#define CHAIN_CELL_OFFSET_SIZE 2
+
+/*
+ * Utility functions to navigate various parts in a trace. If we change the
+ * layout/offset in the future, we just modify these functions and we don't need
+ * to propagate the changes to all the use cases.
+ */
+static inline char *getTraceBase(const JitEntry *p)
+{
+ return (char*)p->codeAddress -
+ (PROF_COUNTER_ADDR_SIZE + CHAIN_CELL_OFFSET_SIZE +
+ (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;
+}
+
+/* Get the pointer of the chain cell count */
+static inline ChainCellCounts* getChainCellCountsPointer(const char *base)
+{
+ /* 4 is the size of the profile count */
+ u2 *chainCellOffsetP = (u2 *) (base + PROF_COUNTER_ADDR_SIZE);
+ u2 chainCellOffset = *chainCellOffsetP;
+ return (ChainCellCounts *) ((char *) chainCellOffsetP + chainCellOffset);
+}
+
+/* Get the size of all chaining cells */
+static inline u4 getChainCellSize(const ChainCellCounts* pChainCellCounts)
+{
+ int cellSize = 0;
+ int i;
+
+ /* Get total count of chain cells */
+ for (i = 0; i < kChainingCellGap; i++) {
+ if (i != kChainingCellInvokePredicted) {
+ cellSize += pChainCellCounts->u.count[i] *
+ (CHAIN_CELL_NORMAL_SIZE >> 2);
+ } else {
+ cellSize += pChainCellCounts->u.count[i] *
+ (CHAIN_CELL_PREDICTED_SIZE >> 2);
+ }
+ }
+ return cellSize;
+}
+
+/* Get the starting pointer of the trace description section */
+static JitTraceDescription* getTraceDescriptionPointer(const char *base)
+{
+ ChainCellCounts* pCellCounts = getChainCellCountsPointer(base);
+ return (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
+}
+
+/* Get the size of a trace description */
+static int getTraceDescriptionSize(const JitTraceDescription *desc)
+{
+ int runCount;
+ /* Trace end is always of non-meta type (ie isCode == true) */
+ for (runCount = 0; ; runCount++) {
+ if (desc->trace[runCount].isCode &&
+ desc->trace[runCount].info.frag.runEnd)
+ break;
+ }
+ return sizeof(JitTraceDescription) + ((runCount+1) * sizeof(JitTraceRun));
+}
+
+#if defined(SIGNATURE_BREAKPOINT)
+/* Inspect the assembled instruction stream to find potential matches */
+static void matchSignatureBreakpoint(const CompilationUnit *cUnit,
+ unsigned int size)
+{
+ unsigned int i, j;
+ u4 *ptr = (u4 *) cUnit->codeBuffer;
+
+ for (i = 0; i < size - gDvmJit.signatureBreakpointSize + 1; i++) {
+ if (ptr[i] == gDvmJit.signatureBreakpoint[0]) {
+ for (j = 1; j < gDvmJit.signatureBreakpointSize; j++) {
+ if (ptr[i+j] != gDvmJit.signatureBreakpoint[j]) {
+ break;
+ }
+ }
+ if (j == gDvmJit.signatureBreakpointSize) {
+ LOGD("Signature match starting from offset %#x (%d words)",
+ i*4, gDvmJit.signatureBreakpointSize);
+ int descSize = getTraceDescriptionSize(cUnit->traceDesc);
+ JitTraceDescription *newCopy =
+ (JitTraceDescription *) malloc(descSize);
+ memcpy(newCopy, cUnit->traceDesc, descSize);
+ dvmCompilerWorkEnqueue(NULL, kWorkOrderTraceDebug, newCopy);
+ break;
+ }
+ }
+ }
+}
+#endif
+
+/*
* Go over each instruction in the list and calculate the offset from the top
* before sending them off to the assembler. If out-of-range branch distance is
* seen rearrange the instructions a bit to correct it.
*/
void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
{
- LIR *lir;
ArmLIR *armLIR;
int offset = 0;
int i;
ChainCellCounts chainCellCounts;
int descSize =
- cUnit->methodJitMode ? 0 : jitTraceDescriptionSize(cUnit->traceDesc);
+ cUnit->methodJitMode ? 0 : getTraceDescriptionSize(cUnit->traceDesc);
int chainingCellGap = 0;
info->instructionSet = cUnit->instructionSet;
@@ -1283,10 +1396,11 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
/* Set up offsets for literals */
cUnit->dataOffset = offset;
- for (lir = cUnit->wordList; lir; lir = lir->next) {
- lir->offset = offset;
- offset += 4;
- }
+ /*
+ * Assign each class pointer/constant an offset from the beginning of the
+ * compilation unit.
+ */
+ offset = assignLiteralOffset(cUnit, offset);
cUnit->totalSize = offset;
@@ -1387,8 +1501,7 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
}
/* Write the literals directly into the code cache */
- installDataContent(cUnit);
-
+ installLiteralPools(cUnit);
/* Flush dcache and invalidate the icache to maintain coherence */
dvmCompilerCacheFlush((long)cUnit->baseAddr,
@@ -1575,8 +1688,14 @@ static void inlineCachePatchEnqueue(PredictedChainingCell *cellAddr,
*/
} else if (gDvmJit.compilerICPatchIndex < COMPILER_IC_PATCH_QUEUE_SIZE) {
int index = gDvmJit.compilerICPatchIndex++;
+ const ClassObject *clazz = newContent->clazz;
+
gDvmJit.compilerICPatchQueue[index].cellAddr = cellAddr;
gDvmJit.compilerICPatchQueue[index].cellContent = *newContent;
+ gDvmJit.compilerICPatchQueue[index].classDescriptor = clazz->descriptor;
+ gDvmJit.compilerICPatchQueue[index].classLoader = clazz->classLoader;
+ /* For verification purpose only */
+ gDvmJit.compilerICPatchQueue[index].serialNumber = clazz->serialNumber;
#if defined(WITH_JIT_TUNING)
gDvmJit.icPatchQueued++;
#endif
@@ -1700,10 +1819,16 @@ void dvmCompilerPatchInlineCache(void)
maxAddr = (PredictedChainingCell *) gDvmJit.codeCache;
for (i = 0; i < gDvmJit.compilerICPatchIndex; i++) {
- PredictedChainingCell *cellAddr =
- gDvmJit.compilerICPatchQueue[i].cellAddr;
- PredictedChainingCell *cellContent =
- &gDvmJit.compilerICPatchQueue[i].cellContent;
+ ICPatchWorkOrder *workOrder = &gDvmJit.compilerICPatchQueue[i];
+ PredictedChainingCell *cellAddr = workOrder->cellAddr;
+ PredictedChainingCell *cellContent = &workOrder->cellContent;
+ ClassObject *clazz = dvmFindClassNoInit(workOrder->classDescriptor,
+ workOrder->classLoader);
+
+ assert(clazz->serialNumber == workOrder->serialNumber);
+
+ /* Use the newly resolved clazz pointer */
+ cellContent->clazz = clazz;
COMPILER_TRACE_CHAINING(
LOGD("Jit Runtime: predicted chain %p from %s to %s (%s) "
@@ -1736,35 +1861,22 @@ void dvmCompilerPatchInlineCache(void)
* the incoming codeAddr is a thumb code address, and therefore has
* the low bit set.
*/
-u4* dvmJitUnchain(void* codeAddr)
+static u4* unchainSingle(JitEntry *trace)
{
- u2* pChainCellOffset = (u2*)((char*)codeAddr - 3);
- u2 chainCellOffset = *pChainCellOffset;
- ChainCellCounts *pChainCellCounts =
- (ChainCellCounts*)((char*)codeAddr + chainCellOffset - 3);
- int cellSize;
+ const char *base = getTraceBase(trace);
+ ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
+ int cellSize = getChainCellSize(pChainCellCounts);
u4* pChainCells;
- u4* pStart;
u4 newInst;
int i,j;
PredictedChainingCell *predChainCell;
- /* Get total count of chain cells */
- for (i = 0, cellSize = 0; i < kChainingCellGap; i++) {
- if (i != kChainingCellInvokePredicted) {
- cellSize += pChainCellCounts->u.count[i] * (CHAIN_CELL_NORMAL_SIZE >> 2);
- } else {
- cellSize += pChainCellCounts->u.count[i] *
- (CHAIN_CELL_PREDICTED_SIZE >> 2);
- }
- }
-
if (cellSize == 0)
return (u4 *) pChainCellCounts;
/* Locate the beginning of the chain cell region */
- pStart = pChainCells = ((u4 *) pChainCellCounts) - cellSize -
- pChainCellCounts->u.count[kChainingCellGap];
+ pChainCells = ((u4 *) pChainCellCounts) - cellSize -
+ pChainCellCounts->u.count[kChainingCellGap];
/* The cells are sorted in order - walk through them and reset */
for (i = 0; i < kChainingCellGap; i++) {
@@ -1833,8 +1945,7 @@ void dvmJitUnchainAll()
(gDvmJit.pJitEntryTable[i].codeAddress !=
dvmCompilerGetInterpretTemplate())) {
u4* lastAddress;
- lastAddress =
- dvmJitUnchain(gDvmJit.pJitEntryTable[i].codeAddress);
+ lastAddress = unchainSingle(&gDvmJit.pJitEntryTable[i]);
if (lowAddress == NULL ||
(u4*)gDvmJit.pJitEntryTable[i].codeAddress <
lowAddress)
@@ -1872,73 +1983,33 @@ static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum)
return 0;
}
-static char *getTraceBase(const JitEntry *p)
-{
- return (char*)p->codeAddress -
- (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;
- JitTraceCounter_t count;
- u2* pCellOffset;
- JitTraceDescription *desc;
- const Method* method;
int idx;
- traceBase = getTraceBase(p);
-
if (p->codeAddress == NULL) {
if (!silent)
- LOGD("TRACEPROFILE 0x%08x 0 NULL 0 0", (int)traceBase);
+ LOGD("TRACEPROFILE NULL");
return 0;
}
if (p->codeAddress == dvmCompilerGetInterpretTemplate()) {
if (!silent)
- LOGD("TRACEPROFILE 0x%08x 0 INTERPRET_ONLY 0 0", (int)traceBase);
+ LOGD("TRACEPROFILE INTERPRET_ONLY");
return 0;
}
- count = getProfileCount(p);
+ JitTraceCounter_t count = getProfileCount(p);
if (reset) {
resetProfileCount(p);
}
if (silent) {
return count;
}
- pCellOffset = (u2*) (traceBase + 4);
- pCellCounts = (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
- desc = (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
- method = desc->method;
+ JitTraceDescription *desc = getTraceDescriptionPointer(getTraceBase(p));
+ const Method *method = desc->method;
char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
- jitProfileAddrToLine addrToLine = {0, desc->trace[0].frag.startOffset};
+ jitProfileAddrToLine addrToLine = {0, desc->trace[0].info.frag.startOffset};
/*
* We may end up decoding the debug information for the same method
@@ -1955,18 +2026,18 @@ static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
addrToLineCb, NULL, &addrToLine);
LOGD("TRACEPROFILE 0x%08x % 10d %5.2f%% [%#x(+%d), %d] %s%s;%s",
- (int)traceBase,
+ (int) getTraceBase(p),
count,
((float ) count) / sum * 100.0,
- desc->trace[0].frag.startOffset,
- desc->trace[0].frag.numInsts,
+ desc->trace[0].info.frag.startOffset,
+ desc->trace[0].info.frag.numInsts,
addrToLine.lineNum,
method->clazz->descriptor, method->name, methodDesc);
free(methodDesc);
/* Find the last fragment (ie runEnd is set) */
for (idx = 0;
- desc->trace[idx].frag.isCode && !desc->trace[idx].frag.runEnd;
+ desc->trace[idx].isCode && !desc->trace[idx].info.frag.runEnd;
idx++) {
}
@@ -1974,8 +2045,9 @@ static int dumpTraceProfile(JitEntry *p, bool silent, bool reset,
* runEnd must comes with a JitCodeDesc frag. If isCode is false it must
* be a meta info field (only used by callsite info for now).
*/
- if (!desc->trace[idx].frag.isCode) {
- const Method *method = (const Method *)desc->trace[idx+1].meta;
+ if (!desc->trace[idx].isCode) {
+ const Method *method = (const Method *)
+ desc->trace[idx+JIT_TRACE_CUR_METHOD-1].info.meta;
char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
/* Print the callee info in the trace */
LOGD(" -> %s%s;%s", method->clazz->descriptor, method->name,
@@ -1994,20 +2066,11 @@ JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
if ((jitEntry == NULL) || (jitEntry->codeAddress == 0))
return NULL;
- /* Find out the startint point */
- char *traceBase = getTraceBase(jitEntry);
-
- /* Then find out the starting point of the chaining cell */
- u2 *pCellOffset = (u2*) (traceBase + 4);
- ChainCellCounts *pCellCounts =
- (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
-
- /* From there we can find out the starting point of the trace descriptor */
JitTraceDescription *desc =
- (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
+ getTraceDescriptionPointer(getTraceBase(jitEntry));
/* Now make a copy and return */
- int descSize = jitTraceDescriptionSize(desc);
+ int descSize = getTraceDescriptionSize(desc);
JitTraceDescription *newCopy = (JitTraceDescription *) malloc(descSize);
memcpy(newCopy, desc, descSize);
return newCopy;
@@ -2091,6 +2154,145 @@ done:
return;
}
+static void findClassPointersSingleTrace(char *base, void (*callback)(void *))
+{
+ unsigned int chainTypeIdx, chainIdx;
+ ChainCellCounts *pChainCellCounts = getChainCellCountsPointer(base);
+ int cellSize = getChainCellSize(pChainCellCounts);
+ /* Scan the chaining cells */
+ if (cellSize) {
+ /* Locate the beginning of the chain cell region */
+ u4 *pChainCells = ((u4 *) pChainCellCounts) - cellSize -
+ pChainCellCounts->u.count[kChainingCellGap];
+ /* The cells are sorted in order - walk through them */
+ for (chainTypeIdx = 0; chainTypeIdx < kChainingCellGap;
+ chainTypeIdx++) {
+ if (chainTypeIdx != kChainingCellInvokePredicted) {
+ /* In 32-bit words */
+ pChainCells += (CHAIN_CELL_NORMAL_SIZE >> 2) *
+ pChainCellCounts->u.count[chainTypeIdx];
+ continue;
+ }
+ for (chainIdx = 0;
+ chainIdx < pChainCellCounts->u.count[chainTypeIdx];
+ chainIdx++) {
+ PredictedChainingCell *cell =
+ (PredictedChainingCell *) pChainCells;
+ /*
+ * Report the cell if it contains a sane class
+ * pointer.
+ */
+ if (cell->clazz != NULL &&
+ cell->clazz !=
+ (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ) {
+ callback(&cell->clazz);
+ }
+ pChainCells += CHAIN_CELL_PREDICTED_SIZE >> 2;
+ }
+ }
+ }
+
+ /* Scan the class pointer pool */
+ JitTraceDescription *desc = getTraceDescriptionPointer(base);
+ int descSize = getTraceDescriptionSize(desc);
+ int *classPointerP = (int *) ((char *) desc + descSize);
+ int numClassPointers = *classPointerP++;
+ for (; numClassPointers; numClassPointers--, classPointerP++) {
+ callback(classPointerP);
+ }
+}
+
+/*
+ * Scan class pointers in each translation and pass its address to the callback
+ * function. Currently such a pointers can be found in the pointer pool and the
+ * clazz field in the predicted chaining cells.
+ */
+void dvmJitScanAllClassPointers(void (*callback)(void *))
+{
+ UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
+
+ /* Handle the inflight compilation first */
+ if (gDvmJit.inflightBaseAddr)
+ findClassPointersSingleTrace((char *) gDvmJit.inflightBaseAddr,
+ callback);
+
+ if (gDvmJit.pJitEntryTable != NULL) {
+ unsigned int traceIdx;
+ dvmLockMutex(&gDvmJit.tableLock);
+ for (traceIdx = 0; traceIdx < gDvmJit.jitTableSize; traceIdx++) {
+ const JitEntry *entry = &gDvmJit.pJitEntryTable[traceIdx];
+ if (entry->dPC &&
+ !entry->u.info.isMethodEntry &&
+ entry->codeAddress &&
+ (entry->codeAddress != dvmCompilerGetInterpretTemplate())) {
+ char *base = getTraceBase(entry);
+ findClassPointersSingleTrace(base, callback);
+ }
+ }
+ dvmUnlockMutex(&gDvmJit.tableLock);
+ }
+ UPDATE_CODE_CACHE_PATCHES();
+
+ PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
+}
+
+/*
+ * Provide the final touch on the class object pointer pool to install the
+ * actual pointers. The thread has to be in the running state.
+ */
+void dvmJitInstallClassObjectPointers(CompilationUnit *cUnit, char *codeAddress)
+{
+ char *base = codeAddress - cUnit->headerSize -
+ (cUnit->instructionSet == DALVIK_JIT_ARM ? 0 : 1);
+
+ /* Scan the class pointer pool */
+ JitTraceDescription *desc = getTraceDescriptionPointer(base);
+ int descSize = getTraceDescriptionSize(desc);
+ intptr_t *classPointerP = (int *) ((char *) desc + descSize);
+ int numClassPointers = *(int *)classPointerP++;
+ intptr_t *startClassPointerP = classPointerP;
+
+ UNPROTECT_CODE_CACHE(startClassPointerP,
+ numClassPointers * sizeof(intptr_t));
+ /*
+ * Change the thread state to VM_RUNNING so that GC won't be happening
+ * when the assembler looks up the class pointers.
+ */
+ dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING);
+#if defined(WITH_JIT_TUNING)
+ u8 startTime = dvmGetRelativeTimeUsec();
+#endif
+ for (;numClassPointers; numClassPointers--) {
+ CallsiteInfo *callsiteInfo = (CallsiteInfo *) *classPointerP;
+ ClassObject *clazz = dvmFindClassNoInit(
+ callsiteInfo->classDescriptor, callsiteInfo->classLoader);
+ assert(!strcmp(clazz->descriptor, callsiteInfo->classDescriptor));
+ *classPointerP++ = (intptr_t) clazz;
+ }
+
+ /*
+ * Register the base address so that if GC kicks in after the thread state
+ * has been changed to VMWAIT and before the compiled code is registered
+ * in the JIT table, its content can be patched if class objects are
+ * moved.
+ */
+ gDvmJit.inflightBaseAddr = base;
+
+#if defined(WITH_JIT_TUNING)
+ u8 blockTime = dvmGetRelativeTimeUsec() - startTime;
+ gDvmJit.compilerThreadBlockGCTime += blockTime;
+ if (blockTime > gDvmJit.maxCompilerThreadBlockGCTime)
+ gDvmJit.maxCompilerThreadBlockGCTime = blockTime;
+ gDvmJit.numCompilerThreadBlockGC++;
+#endif
+ /* Change the thread state back to VMWAIT */
+ dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT);
+
+ UPDATE_CODE_CACHE_PATCHES();
+
+ PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t));
+}
+
#if defined(WITH_SELF_VERIFICATION)
/*
* The following are used to keep compiled loads and stores from modifying
diff --git a/vm/compiler/codegen/arm/CodegenCommon.c b/vm/compiler/codegen/arm/CodegenCommon.c
index 2555a8dbc..ae41fe9af 100644
--- a/vm/compiler/codegen/arm/CodegenCommon.c
+++ b/vm/compiler/codegen/arm/CodegenCommon.c
@@ -357,10 +357,8 @@ static RegLocation inlinedTarget(CompilationUnit *cUnit, MIR *mir,
* Search the existing constants in the literal pool for an exact or close match
* within specified delta (greater or equal to 0).
*/
-static ArmLIR *scanLiteralPool(CompilationUnit *cUnit, int value,
- unsigned int delta)
+static ArmLIR *scanLiteralPool(LIR *dataTarget, int value, unsigned int delta)
{
- LIR *dataTarget = cUnit->wordList;
while (dataTarget) {
if (((unsigned) (value - ((ArmLIR *) dataTarget)->operands[0])) <=
delta)
@@ -376,14 +374,15 @@ static ArmLIR *scanLiteralPool(CompilationUnit *cUnit, int value,
*/
/* Add a 32-bit constant either in the constant pool or mixed with code */
-static ArmLIR *addWordData(CompilationUnit *cUnit, int value, bool inPlace)
+static ArmLIR *addWordData(CompilationUnit *cUnit, LIR **constantListP,
+ int value)
{
/* Add the constant to the literal pool */
- if (!inPlace) {
+ if (constantListP) {
ArmLIR *newValue = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
newValue->operands[0] = value;
- newValue->generic.next = cUnit->wordList;
- cUnit->wordList = (LIR *) newValue;
+ newValue->generic.next = *constantListP;
+ *constantListP = (LIR *) newValue;
return newValue;
} else {
/* Add the constant in the middle of code stream */
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index cc81d1da8..55c06476f 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -1285,7 +1285,7 @@ static void genInvokeVirtualWholeMethod(CompilationUnit *cUnit,
CallsiteInfo *callsiteInfo = mir->meta.callsiteInfo;
dvmCompilerLockAllTemps(cUnit);
- loadConstant(cUnit, r1, (int) callsiteInfo->clazz);
+ loadClassPointer(cUnit, r1, (int) callsiteInfo);
loadWordDisp(cUnit, r0, offsetof(Object, clazz), r2);
/* Branch to the slow path if classes are not equal */
@@ -3741,7 +3741,7 @@ static void handleNormalChainingCell(CompilationUnit *cUnit,
offsetof(Thread,
jitToInterpEntries.dvmJitToInterpNormal) >> 2);
newLIR1(cUnit, kThumbBlxR, r0);
- addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+ addWordData(cUnit, NULL, (int) (cUnit->method->insns + offset));
}
/*
@@ -3760,7 +3760,7 @@ static void handleHotChainingCell(CompilationUnit *cUnit,
offsetof(Thread,
jitToInterpEntries.dvmJitToInterpTraceSelect) >> 2);
newLIR1(cUnit, kThumbBlxR, r0);
- addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+ addWordData(cUnit, NULL, (int) (cUnit->method->insns + offset));
}
/* Chaining cell for branches that branch back into the same basic block */
@@ -3781,7 +3781,7 @@ static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
offsetof(Thread, jitToInterpEntries.dvmJitToInterpNormal) >> 2);
#endif
newLIR1(cUnit, kThumbBlxR, r0);
- addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
+ addWordData(cUnit, NULL, (int) (cUnit->method->insns + offset));
}
/* Chaining cell for monomorphic method invocations. */
@@ -3797,7 +3797,7 @@ static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
offsetof(Thread,
jitToInterpEntries.dvmJitToInterpTraceSelect) >> 2);
newLIR1(cUnit, kThumbBlxR, r0);
- addWordData(cUnit, (int) (callee->insns), true);
+ addWordData(cUnit, NULL, (int) (callee->insns));
}
/* Chaining cell for monomorphic method invocations. */
@@ -3805,16 +3805,16 @@ static void handleInvokePredictedChainingCell(CompilationUnit *cUnit)
{
/* Should not be executed in the initial state */
- addWordData(cUnit, PREDICTED_CHAIN_BX_PAIR_INIT, true);
+ addWordData(cUnit, NULL, PREDICTED_CHAIN_BX_PAIR_INIT);
/* To be filled: class */
- addWordData(cUnit, PREDICTED_CHAIN_CLAZZ_INIT, true);
+ addWordData(cUnit, NULL, PREDICTED_CHAIN_CLAZZ_INIT);
/* To be filled: method */
- addWordData(cUnit, PREDICTED_CHAIN_METHOD_INIT, true);
+ addWordData(cUnit, NULL, PREDICTED_CHAIN_METHOD_INIT);
/*
* Rechain count. The initial value of 0 here will trigger chaining upon
* the first invocation of this callsite.
*/
- addWordData(cUnit, PREDICTED_CHAIN_COUNTER_INIT, true);
+ addWordData(cUnit, NULL, PREDICTED_CHAIN_COUNTER_INIT);
}
/* Load the Dalvik PC into r0 and jump to the specified target */
@@ -4042,7 +4042,7 @@ static void genValidationForPredictedInline(CompilationUnit *cUnit, MIR *mir)
rlThis = loadValue(cUnit, rlThis, kCoreReg);
int regPredictedClass = dvmCompilerAllocTemp(cUnit);
- loadConstant(cUnit, regPredictedClass, (int) callsiteInfo->clazz);
+ loadClassPointer(cUnit, regPredictedClass, (int) callsiteInfo);
genNullCheck(cUnit, rlThis.sRegLow, rlThis.lowReg, mir->offset,
NULL);/* null object? */
int regActualClass = dvmCompilerAllocTemp(cUnit);
diff --git a/vm/compiler/codegen/arm/Thumb/Factory.c b/vm/compiler/codegen/arm/Thumb/Factory.c
index bd84a2896..7b51df160 100644
--- a/vm/compiler/codegen/arm/Thumb/Factory.c
+++ b/vm/compiler/codegen/arm/Thumb/Factory.c
@@ -69,9 +69,9 @@ static ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
return res;
}
/* No shortcut - go ahead and use literal pool */
- ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 255);
+ ArmLIR *dataTarget = scanLiteralPool(cUnit->literalList, value, 255);
if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, value, false);
+ dataTarget = addWordData(cUnit, &cUnit->literalList, value);
}
ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
loadPcRel->opcode = kThumbLdrPcRel;
diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.c b/vm/compiler/codegen/arm/Thumb2/Factory.c
index e5adcadaa..80454508f 100644
--- a/vm/compiler/codegen/arm/Thumb2/Factory.c
+++ b/vm/compiler/codegen/arm/Thumb2/Factory.c
@@ -56,9 +56,9 @@ static ArmLIR *loadFPConstantValue(CompilationUnit *cUnit, int rDest,
if (encodedImm >= 0) {
return newLIR2(cUnit, kThumb2Vmovs_IMM8, rDest, encodedImm);
}
- ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 0);
+ ArmLIR *dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, value, false);
+ dataTarget = addWordData(cUnit, &cUnit->literalList, value);
}
ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
loadPcRel->opcode = kThumb2Vldrs;
@@ -164,9 +164,9 @@ static ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest,
return res;
}
/* No shortcut - go ahead and use literal pool */
- ArmLIR *dataTarget = scanLiteralPool(cUnit, value, 0);
+ ArmLIR *dataTarget = scanLiteralPool(cUnit->literalList, value, 0);
if (dataTarget == NULL) {
- dataTarget = addWordData(cUnit, value, false);
+ dataTarget = addWordData(cUnit, &cUnit->literalList, value);
}
ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true);
loadPcRel->opcode = kThumb2LdrPcRel12;
diff --git a/vm/compiler/codegen/x86/Assemble.c b/vm/compiler/codegen/x86/Assemble.c
index d583001e9..03edbf109 100644
--- a/vm/compiler/codegen/x86/Assemble.c
+++ b/vm/compiler/codegen/x86/Assemble.c
@@ -142,3 +142,7 @@ JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
void dvmCompilerSortAndPrintTraceProfiles()
{
}
+
+void dvmJitScanAllClassPointers(void (*callback)(void *))
+{
+}