diff options
Diffstat (limited to 'vm/compiler/codegen/arm')
-rw-r--r-- | vm/compiler/codegen/arm/ArchUtility.c | 8 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/ArmLIR.h | 6 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 118 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/CodegenCommon.c | 17 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/CodegenDriver.c | 313 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/LocalOptimizations.c | 6 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Thumb/Factory.c | 4 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Thumb/Gen.c | 66 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Thumb2/Factory.c | 8 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Thumb2/Gen.c | 65 |
10 files changed, 381 insertions, 230 deletions
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c index 0b76eb58b..95b96c496 100644 --- a/vm/compiler/codegen/arm/ArchUtility.c +++ b/vm/compiler/codegen/arm/ArchUtility.c @@ -375,7 +375,7 @@ void dvmCompilerCodegenDump(CompilationUnit *cUnit) LOGD("installed code is at %p\n", cUnit->baseAddr); LOGD("total size is %d bytes\n", cUnit->totalSize); for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { - dvmDumpLIRInsn(lirInsn, cUnit->baseAddr); + dvmDumpLIRInsn(lirInsn, (unsigned char *) cUnit->baseAddr); } for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) { armLIR = (ArmLIR *) lirInsn; @@ -385,3 +385,9 @@ void dvmCompilerCodegenDump(CompilationUnit *cUnit) armLIR->operands[0]); } } + +/* Target-specific cache flushing */ +int dvmCompilerCacheFlush(long start, long end, long flags) +{ + return cacheflush(start, end, flags); +} diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h index 213344cd8..437c2ed96 100644 --- a/vm/compiler/codegen/arm/ArmLIR.h +++ b/vm/compiler/codegen/arm/ArmLIR.h @@ -119,10 +119,6 @@ typedef struct RegisterPool { int numFPTemps; RegisterInfo *FPTemps; int nextFPTemp; - int numCoreRegs; - RegisterInfo *coreRegs; - int numFPRegs; - RegisterInfo *FPRegs; } RegisterPool; typedef enum ResourceEncodingPos { @@ -623,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 a1f47acf1..e52c26c8c 100644 --- a/vm/compiler/codegen/arm/Assemble.c +++ b/vm/compiler/codegen/arm/Assemble.c @@ -20,7 +20,6 @@ #include "../../CompilerInternals.h" #include "ArmLIR.h" #include "Codegen.h" -#include <unistd.h> /* for cacheflush */ #include <sys/mman.h> /* for protection change */ #define MAX_ASSEMBLER_RETRIES 10 @@ -877,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), }; /* @@ -973,7 +977,8 @@ static AssemblerStatus assembleInstructions(CompilationUnit *cUnit, int delta = target - pc; if (delta > 126 || delta < 0) { /* Convert to cmp rx,#0 / b[eq/ne] tgt pair */ - ArmLIR *newInst = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *newInst = + (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true); /* Make new branch instruction and insert after */ newInst->opcode = kThumbBCond; newInst->operands[0] = 0; @@ -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; @@ -1280,7 +1282,7 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) } /* Allocate enough space for the code block */ - cUnit->codeBuffer = dvmCompilerNew(chainCellOffset, true); + cUnit->codeBuffer = (unsigned char *)dvmCompilerNew(chainCellOffset, true); if (cUnit->codeBuffer == NULL) { LOGE("Code buffer allocation failure\n"); cUnit->baseAddr = NULL; @@ -1352,8 +1354,8 @@ void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info) installDataContent(cUnit); /* Flush dcache and invalidate the icache to maintain coherence */ - cacheflush((long)cUnit->baseAddr, - (long)((char *) cUnit->baseAddr + offset), 0); + dvmCompilerCacheFlush((long)cUnit->baseAddr, + (long)((char *) cUnit->baseAddr + offset), 0); UPDATE_CODE_CACHE_PATCHES(); PROTECT_CODE_CACHE(cUnit->baseAddr, offset); @@ -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; } /* @@ -1448,7 +1452,7 @@ void* dvmJitChain(void* tgtAddr, u4* branchAddr) UNPROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr)); *branchAddr = newInst; - cacheflush((long)branchAddr, (long)branchAddr + 4, 0); + dvmCompilerCacheFlush((long)branchAddr, (long)branchAddr + 4, 0); UPDATE_CODE_CACHE_PATCHES(); PROTECT_CODE_CACHE(branchAddr, sizeof(*branchAddr)); @@ -1487,8 +1491,8 @@ static void inlineCachePatchEnqueue(PredictedChainingCell *cellAddr, * will bring the uninitialized chaining cell to life. */ android_atomic_release_store((int32_t)newContent->clazz, - (void*) &cellAddr->clazz); - cacheflush((intptr_t) cellAddr, (intptr_t) (cellAddr+1), 0); + (volatile int32_t *)(void *)&cellAddr->clazz); + dvmCompilerCacheFlush((intptr_t) cellAddr, (intptr_t) (cellAddr+1), 0); UPDATE_CODE_CACHE_PATCHES(); PROTECT_CODE_CACHE(cellAddr, sizeof(*cellAddr)); @@ -1579,7 +1583,7 @@ const Method *dvmJitToPatchPredictedChain(const Method *method, * trigger immediate patching and will continue to fail to match with * a real clazz pointer. */ - cell->clazz = (void *) PREDICTED_CHAIN_FAKE_CLAZZ; + cell->clazz = (ClassObject *) PREDICTED_CHAIN_FAKE_CLAZZ; UPDATE_CODE_CACHE_PATCHES(); PROTECT_CODE_CACHE(cell, sizeof(*cell)); @@ -1676,7 +1680,7 @@ void dvmCompilerPatchInlineCache(void) } /* Then synchronize the I/D cache */ - cacheflush((long) minAddr, (long) (maxAddr+1), 0); + dvmCompilerCacheFlush((long) minAddr, (long) (maxAddr+1), 0); UPDATE_CODE_CACHE_PATCHES(); PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); @@ -1797,7 +1801,7 @@ void dvmJitUnchainAll() highAddress = lastAddress; } } - cacheflush((long)lowAddress, (long)highAddress, 0); + dvmCompilerCacheFlush((long)lowAddress, (long)highAddress, 0); UPDATE_CODE_CACHE_PATCHES(); PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed); @@ -1832,14 +1836,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; @@ -1857,14 +1884,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); @@ -1889,8 +1914,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, @@ -1908,14 +1933,14 @@ static int dumpTraceProfile(JitEntry *p, bool silent, bool reset, * be a meta info field (only used by callsite info for now). */ if (!desc->trace[idx].frag.isCode) { - const Method *method = desc->trace[idx+1].meta; + const Method *method = (const Method *)desc->trace[idx+1].meta; char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype); /* Print the callee info in the trace */ LOGD(" -> %s%s;%s", method->clazz->descriptor, method->name, methodDesc); } - return executionCount; + return count; } /* Create a copy of the trace descriptor of an existing compilation */ @@ -1944,27 +1969,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 = entry1; - const JitEntry *jitEntry2 = 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); } @@ -1980,7 +1992,7 @@ void dvmCompilerSortAndPrintTraceProfiles() dvmLockMutex(&gDvmJit.tableLock); /* Sort the entries by descending order */ - sortedEntries = malloc(sizeof(JitEntry) * gDvmJit.jitTableSize); + sortedEntries = (JitEntry *)malloc(sizeof(JitEntry) * gDvmJit.jitTableSize); if (sortedEntries == NULL) goto done; memcpy(sortedEntries, gDvmJit.pJitEntryTable, diff --git a/vm/compiler/codegen/arm/CodegenCommon.c b/vm/compiler/codegen/arm/CodegenCommon.c index 4a2057976..c29efa640 100644 --- a/vm/compiler/codegen/arm/CodegenCommon.c +++ b/vm/compiler/codegen/arm/CodegenCommon.c @@ -204,7 +204,7 @@ static void setupResourceMasks(ArmLIR *lir) */ static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpcode opcode) { - ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND)); insn->opcode = opcode; setupResourceMasks(insn); @@ -215,7 +215,7 @@ static ArmLIR *newLIR0(CompilationUnit *cUnit, ArmOpcode opcode) static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpcode opcode, int dest) { - ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP)); insn->opcode = opcode; insn->operands[0] = dest; @@ -227,7 +227,7 @@ static ArmLIR *newLIR1(CompilationUnit *cUnit, ArmOpcode opcode, static ArmLIR *newLIR2(CompilationUnit *cUnit, ArmOpcode opcode, int dest, int src1) { - ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP)); insn->opcode = opcode; @@ -241,7 +241,7 @@ static ArmLIR *newLIR2(CompilationUnit *cUnit, ArmOpcode opcode, static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpcode opcode, int dest, int src1, int src2) { - ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); if (!(EncodingMap[opcode].flags & IS_TERTIARY_OP)) { LOGE("Bad LIR3: %s[%d]",EncodingMap[opcode].name,opcode); } @@ -260,7 +260,7 @@ static ArmLIR *newLIR3(CompilationUnit *cUnit, ArmOpcode opcode, static ArmLIR *newLIR4(CompilationUnit *cUnit, ArmOpcode opcode, int dest, int src1, int src2, int info) { - ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); assert(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP)); insn->opcode = opcode; @@ -321,7 +321,7 @@ static ArmLIR *addWordData(CompilationUnit *cUnit, int value, bool inPlace) { /* Add the constant to the literal pool */ if (!inPlace) { - ArmLIR *newValue = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *newValue = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); newValue->operands[0] = value; newValue->generic.next = cUnit->wordList; cUnit->wordList = (LIR *) newValue; @@ -371,12 +371,13 @@ static ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset, /* Set up the place holder to reconstruct this Dalvik PC */ if (pcrLabel == NULL) { int dPC = (int) (cUnit->method->insns + dOffset); - pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true); + pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); pcrLabel->opcode = kArmPseudoPCReconstructionCell; pcrLabel->operands[0] = dPC; pcrLabel->operands[1] = dOffset; /* Insert the place holder to the growable list */ - dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel); + dvmInsertGrowableList(&cUnit->pcReconstructionList, + (intptr_t) pcrLabel); } /* Branch to the PC reconstruction code */ branch->generic.target = (LIR *) pcrLabel; diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c index 061ffb825..236482f39 100644 --- a/vm/compiler/codegen/arm/CodegenDriver.c +++ b/vm/compiler/codegen/arm/CodegenDriver.c @@ -205,7 +205,7 @@ static bool genConversionPortable(CompilationUnit *cUnit, MIR *mir) static void selfVerificationBranchInsert(LIR *currentLIR, ArmOpcode opcode, int dest, int src1) { - ArmLIR *insn = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *insn = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); insn->opcode = opcode; insn->operands[0] = dest; insn->operands[1] = src1; @@ -912,12 +912,12 @@ static void genReturnCommon(CompilationUnit *cUnit, MIR *mir) /* Insert branch, but defer setting of target */ ArmLIR *branch = genUnconditionalBranch(cUnit, NULL); /* Set up the place holder to reconstruct this Dalvik PC */ - ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); pcrLabel->opcode = kArmPseudoPCReconstructionCell; pcrLabel->operands[0] = dPC; pcrLabel->operands[1] = mir->offset; /* Insert the place holder to the growable list */ - dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel); + dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel); /* Branch to the PC reconstruction code */ branch->generic.target = (LIR *) pcrLabel; } @@ -982,8 +982,11 @@ static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir, /* * Protect the loadMultiple instruction from being reordered with other * Dalvik stack accesses. + * + * This code is also shared by the invoke jumbo instructions, and this + * does not need to be done if the invoke jumbo has no arguments. */ - loadMultiple(cUnit, r4PC, regMask); + if (numArgs != 0) loadMultiple(cUnit, r4PC, regMask); opRegRegImm(cUnit, kOpSub, r7, rFP, sizeof(StackSaveArea) + (numArgs << 2)); @@ -1024,7 +1027,7 @@ static void genProcessArgsRange(CompilationUnit *cUnit, MIR *mir, } /* Save the last batch of loaded values */ - storeMultiple(cUnit, r7, regMask); + if (numArgs != 0) storeMultiple(cUnit, r7, regMask); /* Generate the loop epilogue - don't use r0 */ if ((numArgs > 4) && (numArgs % 4)) { @@ -1156,12 +1159,13 @@ static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir, */ if (pcrLabel == NULL) { int dPC = (int) (cUnit->method->insns + mir->offset); - pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true); + pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); pcrLabel->opcode = kArmPseudoPCReconstructionCell; pcrLabel->operands[0] = dPC; pcrLabel->operands[1] = mir->offset; /* Insert the place holder to the growable list */ - dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel); + dvmInsertGrowableList(&cUnit->pcReconstructionList, + (intptr_t) pcrLabel); } /* return through lr+2 - punt to the interpreter */ @@ -1412,14 +1416,14 @@ static bool handleFmt21h(CompilationUnit *cUnit, MIR *mir) return false; } -static bool handleFmt20bc(CompilationUnit *cUnit, MIR *mir) +static bool handleFmt20bc_Fmt40sc(CompilationUnit *cUnit, MIR *mir) { - /* For OP_THROW_VERIFICATION_ERROR */ + /* For OP_THROW_VERIFICATION_ERROR & OP_THROW_VERIFICATION_ERROR_JUMBO */ genInterpSingleStep(cUnit, mir); return false; } -static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) +static bool handleFmt21c_Fmt31c_Fmt41c(CompilationUnit *cUnit, MIR *mir) { RegLocation rlResult; RegLocation rlDest; @@ -1442,7 +1446,8 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) storeValue(cUnit, rlDest, rlResult); break; } - case OP_CONST_CLASS: { + case OP_CONST_CLASS: + case OP_CONST_CLASS_JUMBO: { void *classPtr = (void*) (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]); @@ -1457,14 +1462,20 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) storeValue(cUnit, rlDest, rlResult); break; } + case OP_SGET: case OP_SGET_VOLATILE: - case OP_SGET_OBJECT_VOLATILE: + case OP_SGET_JUMBO: case OP_SGET_OBJECT: + case OP_SGET_OBJECT_VOLATILE: + case OP_SGET_OBJECT_JUMBO: case OP_SGET_BOOLEAN: + case OP_SGET_BOOLEAN_JUMBO: case OP_SGET_CHAR: + case OP_SGET_CHAR_JUMBO: case OP_SGET_BYTE: + case OP_SGET_BYTE_JUMBO: case OP_SGET_SHORT: - case OP_SGET: { + case OP_SGET_SHORT_JUMBO: { int valOffset = offsetof(StaticField, value); int tReg = dvmCompilerAllocTemp(cUnit); bool isVolatile; @@ -1480,7 +1491,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) isVolatile = (mir->dalvikInsn.opcode == OP_SGET_VOLATILE) || (mir->dalvikInsn.opcode == OP_SGET_OBJECT_VOLATILE) || - dvmIsVolatileField(fieldPtr); + dvmIsVolatileField((Field *) fieldPtr); rlDest = dvmCompilerGetDest(cUnit, mir, 0); rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true); @@ -1496,7 +1507,8 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) storeValue(cUnit, rlDest, rlResult); break; } - case OP_SGET_WIDE: { + case OP_SGET_WIDE: + case OP_SGET_WIDE_JUMBO: { int valOffset = offsetof(StaticField, value); const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? mir->meta.calleeMethod : cUnit->method; @@ -1520,14 +1532,20 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) storeValueWide(cUnit, rlDest, rlResult); break; } + case OP_SPUT: + case OP_SPUT_VOLATILE: + case OP_SPUT_JUMBO: case OP_SPUT_OBJECT: case OP_SPUT_OBJECT_VOLATILE: - case OP_SPUT_VOLATILE: + case OP_SPUT_OBJECT_JUMBO: case OP_SPUT_BOOLEAN: + case OP_SPUT_BOOLEAN_JUMBO: case OP_SPUT_CHAR: + case OP_SPUT_CHAR_JUMBO: case OP_SPUT_BYTE: + case OP_SPUT_BYTE_JUMBO: case OP_SPUT_SHORT: - case OP_SPUT: { + case OP_SPUT_SHORT_JUMBO: { int valOffset = offsetof(StaticField, value); int tReg = dvmCompilerAllocTemp(cUnit); int objHead; @@ -1540,9 +1558,10 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) isVolatile = (mir->dalvikInsn.opcode == OP_SPUT_VOLATILE) || (mir->dalvikInsn.opcode == OP_SPUT_OBJECT_VOLATILE) || - dvmIsVolatileField(fieldPtr); + dvmIsVolatileField((Field *) fieldPtr); isSputObject = (mir->dalvikInsn.opcode == OP_SPUT_OBJECT) || + (mir->dalvikInsn.opcode == OP_SPUT_OBJECT_JUMBO) || (mir->dalvikInsn.opcode == OP_SPUT_OBJECT_VOLATILE); if (fieldPtr == NULL) { @@ -1572,7 +1591,8 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) break; } - case OP_SPUT_WIDE: { + case OP_SPUT_WIDE: + case OP_SPUT_WIDE_JUMBO: { int tReg = dvmCompilerAllocTemp(cUnit); int valOffset = offsetof(StaticField, value); const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? @@ -1594,12 +1614,13 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) HEAP_ACCESS_SHADOW(false); break; } - case OP_NEW_INSTANCE: { + case OP_NEW_INSTANCE: + case OP_NEW_INSTANCE_JUMBO: { /* * Obey the calling convention and don't mess with the register * usage. */ - ClassObject *classPtr = (void*) + ClassObject *classPtr = (ClassObject *) (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]); if (classPtr == NULL) { @@ -1637,7 +1658,8 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir) storeValue(cUnit, rlDest, rlResult); break; } - case OP_CHECK_CAST: { + case OP_CHECK_CAST: + case OP_CHECK_CAST_JUMBO: { /* * Obey the calling convention and don't mess with the register * usage. @@ -2192,7 +2214,7 @@ static bool handleFmt22b_Fmt22s(CompilationUnit *cUnit, MIR *mir) return false; } -static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) +static bool handleFmt22c_Fmt52c(CompilationUnit *cUnit, MIR *mir) { Opcode dalvikOpcode = mir->dalvikInsn.opcode; int fieldOffset = -1; @@ -2206,22 +2228,36 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) */ case OP_IGET: case OP_IGET_VOLATILE: + case OP_IGET_JUMBO: case OP_IGET_WIDE: + case OP_IGET_WIDE_JUMBO: case OP_IGET_OBJECT: case OP_IGET_OBJECT_VOLATILE: + case OP_IGET_OBJECT_JUMBO: case OP_IGET_BOOLEAN: + case OP_IGET_BOOLEAN_JUMBO: case OP_IGET_BYTE: + case OP_IGET_BYTE_JUMBO: case OP_IGET_CHAR: + case OP_IGET_CHAR_JUMBO: case OP_IGET_SHORT: + case OP_IGET_SHORT_JUMBO: case OP_IPUT: case OP_IPUT_VOLATILE: + case OP_IPUT_JUMBO: case OP_IPUT_WIDE: + case OP_IPUT_WIDE_JUMBO: case OP_IPUT_OBJECT: case OP_IPUT_OBJECT_VOLATILE: + case OP_IPUT_OBJECT_JUMBO: case OP_IPUT_BOOLEAN: + case OP_IPUT_BOOLEAN_JUMBO: case OP_IPUT_BYTE: + case OP_IPUT_BYTE_JUMBO: case OP_IPUT_CHAR: - case OP_IPUT_SHORT: { + case OP_IPUT_CHAR_JUMBO: + case OP_IPUT_SHORT: + case OP_IPUT_SHORT_JUMBO: { const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? mir->meta.calleeMethod : cUnit->method; Field *fieldPtr = @@ -2240,7 +2276,8 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) } switch (dalvikOpcode) { - case OP_NEW_ARRAY: { + case OP_NEW_ARRAY: + case OP_NEW_ARRAY_JUMBO: { // Generates a call - use explicit registers RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0); @@ -2283,7 +2320,8 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) storeValue(cUnit, rlDest, rlResult); break; } - case OP_INSTANCE_OF: { + case OP_INSTANCE_OF: + case OP_INSTANCE_OF_JUMBO: { // May generate a call - use explicit registers RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0); RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0); @@ -2329,6 +2367,7 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) break; } case OP_IGET_WIDE: + case OP_IGET_WIDE_JUMBO: genIGetWide(cUnit, mir, fieldOffset); break; case OP_IGET_VOLATILE: @@ -2336,21 +2375,33 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) isVolatile = true; // NOTE: intentional fallthrough case OP_IGET: + case OP_IGET_JUMBO: case OP_IGET_OBJECT: + case OP_IGET_OBJECT_JUMBO: case OP_IGET_BOOLEAN: + case OP_IGET_BOOLEAN_JUMBO: case OP_IGET_BYTE: + case OP_IGET_BYTE_JUMBO: case OP_IGET_CHAR: + case OP_IGET_CHAR_JUMBO: case OP_IGET_SHORT: + case OP_IGET_SHORT_JUMBO: genIGet(cUnit, mir, kWord, fieldOffset, isVolatile); break; case OP_IPUT_WIDE: + case OP_IPUT_WIDE_JUMBO: genIPutWide(cUnit, mir, fieldOffset); break; case OP_IPUT: - case OP_IPUT_SHORT: - case OP_IPUT_CHAR: - case OP_IPUT_BYTE: + case OP_IPUT_JUMBO: case OP_IPUT_BOOLEAN: + case OP_IPUT_BOOLEAN_JUMBO: + case OP_IPUT_BYTE: + case OP_IPUT_BYTE_JUMBO: + case OP_IPUT_CHAR: + case OP_IPUT_CHAR_JUMBO: + case OP_IPUT_SHORT: + case OP_IPUT_SHORT_JUMBO: genIPut(cUnit, mir, kWord, fieldOffset, false, isVolatile); break; case OP_IPUT_VOLATILE: @@ -2358,6 +2409,7 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir) isVolatile = true; // NOTE: intentional fallthrough case OP_IPUT_OBJECT: + case OP_IPUT_OBJECT_JUMBO: genIPut(cUnit, mir, kWord, fieldOffset, true, isVolatile); break; case OP_IGET_WIDE_VOLATILE: @@ -2778,8 +2830,8 @@ static void genLandingPadForMispredictedCallee(CompilationUnit *cUnit, MIR *mir, mir->meta.callsiteInfo->misPredBranchOver->target = (LIR *) target; } -static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, - ArmLIR *labelList) +static bool handleFmt35c_3rc_5rc(CompilationUnit *cUnit, MIR *mir, + BasicBlock *bb, ArmLIR *labelList) { ArmLIR *retChainingCell = NULL; ArmLIR *pcrLabel = NULL; @@ -2799,7 +2851,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, * ] */ case OP_INVOKE_VIRTUAL: - case OP_INVOKE_VIRTUAL_RANGE: { + case OP_INVOKE_VIRTUAL_RANGE: + case OP_INVOKE_VIRTUAL_JUMBO: { ArmLIR *predChainingCell = &labelList[bb->taken->id]; int methodIndex = cUnit->method->clazz->pDvmDex->pResMethods[dInsn->vB]-> @@ -2830,7 +2883,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, * ->pResMethods[BBBB]->methodIndex] */ case OP_INVOKE_SUPER: - case OP_INVOKE_SUPER_RANGE: { + case OP_INVOKE_SUPER_RANGE: + case OP_INVOKE_SUPER_JUMBO: { /* Grab the method ptr directly from what the interpreter sees */ const Method *calleeMethod = mir->meta.callsiteInfo->method; assert(calleeMethod == cUnit->method->clazz->super->vtable[ @@ -2851,7 +2905,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, } /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */ case OP_INVOKE_DIRECT: - case OP_INVOKE_DIRECT_RANGE: { + case OP_INVOKE_DIRECT_RANGE: + case OP_INVOKE_DIRECT_JUMBO: { /* Grab the method ptr directly from what the interpreter sees */ const Method *calleeMethod = mir->meta.callsiteInfo->method; assert(calleeMethod == @@ -2871,7 +2926,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, } /* calleeMethod = method->clazz->pDvmDex->pResMethods[BBBB] */ case OP_INVOKE_STATIC: - case OP_INVOKE_STATIC_RANGE: { + case OP_INVOKE_STATIC_RANGE: + case OP_INVOKE_STATIC_JUMBO: { /* Grab the method ptr directly from what the interpreter sees */ const Method *calleeMethod = mir->meta.callsiteInfo->method; assert(calleeMethod == @@ -2963,7 +3019,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, * 0x47357ebc : .word (0x425719dc) */ case OP_INVOKE_INTERFACE: - case OP_INVOKE_INTERFACE_RANGE: { + case OP_INVOKE_INTERFACE_RANGE: + case OP_INVOKE_INTERFACE_JUMBO: { ArmLIR *predChainingCell = &labelList[bb->taken->id]; /* @@ -3007,12 +3064,13 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, */ if (pcrLabel == NULL) { int dPC = (int) (cUnit->method->insns + mir->offset); - pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true); + pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); pcrLabel->opcode = kArmPseudoPCReconstructionCell; pcrLabel->operands[0] = dPC; pcrLabel->operands[1] = mir->offset; /* Insert the place holder to the growable list */ - dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel); + dvmInsertGrowableList(&cUnit->pcReconstructionList, + (intptr_t) pcrLabel); } /* return through lr+2 - punt to the interpreter */ @@ -3111,7 +3169,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb, return false; } case OP_FILLED_NEW_ARRAY: - case OP_FILLED_NEW_ARRAY_RANGE: { + case OP_FILLED_NEW_ARRAY_RANGE: + case OP_FILLED_NEW_ARRAY_JUMBO: { /* Just let the interpreter deal with these */ genInterpSingleStep(cUnit, mir); break; @@ -3532,7 +3591,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) @@ -3554,7 +3612,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) @@ -3830,8 +3887,8 @@ static void genValidationForPredictedInline(CompilationUnit *cUnit, MIR *mir) static void handleExtendedMIR(CompilationUnit *cUnit, MIR *mir) { int opOffset = mir->dalvikInsn.opcode - kMirOpFirst; - char *msg = dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1, - false); + char *msg = (char *)dvmCompilerNew(strlen(extendedMIROpNames[opOffset]) + 1, + false); strcpy(msg, extendedMIROpNames[opOffset]); newLIR1(cUnit, kArmPseudoExtended, (int) msg); @@ -3878,25 +3935,25 @@ static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry, ArmLIR *bodyLabel) { /* Set up the place holder to reconstruct this Dalvik PC */ - ArmLIR *pcrLabel = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *pcrLabel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); pcrLabel->opcode = kArmPseudoPCReconstructionCell; pcrLabel->operands[0] = (int) (cUnit->method->insns + entry->startOffset); pcrLabel->operands[1] = entry->startOffset; /* Insert the place holder to the growable list */ - dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel); + dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel); /* * Next, create two branches - one branch over to the loop body and the * other branch to the PCR cell to punt. */ - ArmLIR *branchToBody = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *branchToBody = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); branchToBody->opcode = kThumbBUncond; branchToBody->generic.target = (LIR *) bodyLabel; setupResourceMasks(branchToBody); cUnit->loopAnalysis->branchToBody = (LIR *) branchToBody; - ArmLIR *branchToPCR = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *branchToPCR = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); branchToPCR->opcode = kThumbBUncond; branchToPCR->generic.target = (LIR *) pcrLabel; setupResourceMasks(branchToPCR); @@ -3926,7 +3983,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) { /* Used to hold the labels of each block */ ArmLIR *labelList = - dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true); + (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR) * cUnit->numBlocks, true); GrowableList chainingListByType[kChainingCellGap]; int i; @@ -3937,51 +3994,22 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) dvmInitGrowableList(&chainingListByType[i], 2); } - BasicBlock **blockList = cUnit->blockList; + 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 < cUnit->numBlocks; i++) { - blockList[i]->visited = true; + for (i = 0; ; i++) { MIR *mir; + BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator); + if (bb == NULL) break; - labelList[i].operands[0] = blockList[i]->startOffset; + labelList[i].operands[0] = bb->startOffset; - if (blockList[i]->blockType >= kChainingCellGap) { - if (blockList[i]->isFallThroughFromInvoke == true) { + if (bb->blockType >= kChainingCellGap) { + if (bb->isFallThroughFromInvoke == true) { /* Align this block first since it is a return chaining cell */ newLIR0(cUnit, kArmPseudoPseudoAlign4); } @@ -3992,56 +4020,53 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]); } - if (blockList[i]->blockType == kTraceEntryBlock) { + if (bb->blockType == kTraceEntryBlock) { labelList[i].opcode = kArmPseudoEntryBlock; - if (blockList[i]->firstMIRInsn == NULL) { + if (bb->firstMIRInsn == NULL) { continue; } else { - setupLoopEntryBlock(cUnit, blockList[i], - &labelList[blockList[i]->fallThrough->id]); + setupLoopEntryBlock(cUnit, bb, + &labelList[bb->fallThrough->id]); } - } else if (blockList[i]->blockType == kTraceExitBlock) { + } else if (bb->blockType == kTraceExitBlock) { labelList[i].opcode = kArmPseudoExitBlock; goto gen_fallthrough; - } else if (blockList[i]->blockType == kDalvikByteCode) { + } else if (bb->blockType == kDalvikByteCode) { labelList[i].opcode = kArmPseudoNormalBlockLabel; /* Reset the register state */ dvmCompilerResetRegPool(cUnit); dvmCompilerClobberAllRegs(cUnit); dvmCompilerResetNullCheck(cUnit); } else { - switch (blockList[i]->blockType) { + switch (bb->blockType) { case kChainingCellNormal: labelList[i].opcode = kArmPseudoChainingCellNormal; /* handle the codegen later */ dvmInsertGrowableList( - &chainingListByType[kChainingCellNormal], (void *) i); + &chainingListByType[kChainingCellNormal], i); break; case kChainingCellInvokeSingleton: labelList[i].opcode = kArmPseudoChainingCellInvokeSingleton; labelList[i].operands[0] = - (int) blockList[i]->containingMethod; + (int) bb->containingMethod; /* handle the codegen later */ dvmInsertGrowableList( - &chainingListByType[kChainingCellInvokeSingleton], - (void *) i); + &chainingListByType[kChainingCellInvokeSingleton], i); break; case kChainingCellInvokePredicted: labelList[i].opcode = kArmPseudoChainingCellInvokePredicted; /* handle the codegen later */ dvmInsertGrowableList( - &chainingListByType[kChainingCellInvokePredicted], - (void *) i); + &chainingListByType[kChainingCellInvokePredicted], i); break; case kChainingCellHot: labelList[i].opcode = kArmPseudoChainingCellHot; /* handle the codegen later */ dvmInsertGrowableList( - &chainingListByType[kChainingCellHot], - (void *) i); + &chainingListByType[kChainingCellHot], i); break; case kPCReconstruction: /* Make sure exception handling block is next */ @@ -4059,16 +4084,14 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) opReg(cUnit, kOpBlx, r1); } break; -#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING) case kChainingCellBackwardBranch: labelList[i].opcode = kArmPseudoChainingCellBackwardBranch; /* handle the codegen later */ dvmInsertGrowableList( &chainingListByType[kChainingCellBackwardBranch], - (void *) i); + i); break; -#endif default: break; } @@ -4077,7 +4100,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) ArmLIR *headLIR = NULL; - for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) { + for (mir = bb->firstMIRInsn; mir; mir = mir->next) { dvmCompilerResetRegPool(cUnit); if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) { @@ -4154,7 +4177,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) case kFmt20t: case kFmt30t: notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit, - mir, blockList[i], labelList); + mir, bb, labelList); break; case kFmt10x: notHandled = handleFmt10x(cUnit, mir); @@ -4170,11 +4193,13 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) notHandled = handleFmt12x(cUnit, mir); break; case kFmt20bc: - notHandled = handleFmt20bc(cUnit, mir); + case kFmt40sc: + notHandled = handleFmt20bc_Fmt40sc(cUnit, mir); break; case kFmt21c: case kFmt31c: - notHandled = handleFmt21c_Fmt31c(cUnit, mir); + case kFmt41c: + notHandled = handleFmt21c_Fmt31c_Fmt41c(cUnit, mir); break; case kFmt21h: notHandled = handleFmt21h(cUnit, mir); @@ -4183,22 +4208,21 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) notHandled = handleFmt21s(cUnit, mir); break; case kFmt21t: - notHandled = handleFmt21t(cUnit, mir, blockList[i], - labelList); + notHandled = handleFmt21t(cUnit, mir, bb, labelList); break; case kFmt22b: case kFmt22s: notHandled = handleFmt22b_Fmt22s(cUnit, mir); break; case kFmt22c: - notHandled = handleFmt22c(cUnit, mir); + case kFmt52c: + notHandled = handleFmt22c_Fmt52c(cUnit, mir); break; case kFmt22cs: notHandled = handleFmt22cs(cUnit, mir); break; case kFmt22t: - notHandled = handleFmt22t(cUnit, mir, blockList[i], - labelList); + notHandled = handleFmt22t(cUnit, mir, bb, labelList); break; case kFmt22x: case kFmt32x: @@ -4212,12 +4236,13 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) break; case kFmt3rc: case kFmt35c: - notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i], + case kFmt5rc: + notHandled = handleFmt35c_3rc_5rc(cUnit, mir, bb, labelList); break; case kFmt3rms: case kFmt35ms: - notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i], + notHandled = handleFmt35ms_3rms(cUnit, mir, bb, labelList); break; case kFmt35mi: @@ -4242,7 +4267,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit) } } - if (blockList[i]->blockType == kTraceEntryBlock) { + if (bb->blockType == kTraceEntryBlock) { dvmCompilerAppendLIR(cUnit, (LIR *) cUnit->loopAnalysis->branchToBody); dvmCompilerAppendLIR(cUnit, @@ -4263,9 +4288,9 @@ gen_fallthrough: * Check if the block is terminated due to trace length constraint - * insert an unconditional branch to the chaining cell. */ - if (blockList[i]->needFallThroughBranch) { + if (bb->needFallThroughBranch) { genUnconditionalBranch(cUnit, - &labelList[blockList[i]->fallThrough->id]); + &labelList[bb->fallThrough->id]); } } @@ -4286,6 +4311,9 @@ gen_fallthrough: for (j = 0; j < chainingListByType[i].numUsed; j++) { int blockId = blockIdList[j]; + BasicBlock *chainingBlock = + (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, + blockId); /* Align this chaining cell first */ newLIR0(cUnit, kArmPseudoPseudoAlign4); @@ -4294,30 +4322,26 @@ gen_fallthrough: dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]); - switch (blockList[blockId]->blockType) { + switch (chainingBlock->blockType) { case kChainingCellNormal: - handleNormalChainingCell(cUnit, - blockList[blockId]->startOffset); + handleNormalChainingCell(cUnit, chainingBlock->startOffset); break; case kChainingCellInvokeSingleton: handleInvokeSingletonChainingCell(cUnit, - blockList[blockId]->containingMethod); + chainingBlock->containingMethod); break; case kChainingCellInvokePredicted: handleInvokePredictedChainingCell(cUnit); break; case kChainingCellHot: - handleHotChainingCell(cUnit, - blockList[blockId]->startOffset); + handleHotChainingCell(cUnit, chainingBlock->startOffset); break; -#if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING) case kChainingCellBackwardBranch: handleBackwardBranchChainingCell(cUnit, - blockList[blockId]->startOffset); + chainingBlock->startOffset); break; -#endif default: - LOGE("Bad blocktype %d", blockList[blockId]->blockType); + LOGE("Bad blocktype %d", chainingBlock->blockType); dvmCompilerAbort(cUnit); } } @@ -4349,10 +4373,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) { - bool res; + JitTraceDescription *desc; + bool isCompile; + bool success = true; if (gDvmJit.codeCacheFull) { return false; @@ -4360,25 +4389,35 @@ bool dvmCompilerDoWork(CompilerWorkOrder *work) switch (work->kind) { case kWorkOrderTrace: + isCompile = true; /* Start compilation with maximally allowed trace length */ - res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result, - work->bailPtr, 0 /* no hints */); + desc = (JitTraceDescription *)work->info; + 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 */ - res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result, - work->bailPtr, 0 /* no hints */); + desc = (JitTraceDescription *)work->info; + 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/LocalOptimizations.c b/vm/compiler/codegen/arm/LocalOptimizations.c index 33e1e4188..d91734fcf 100644 --- a/vm/compiler/codegen/arm/LocalOptimizations.c +++ b/vm/compiler/codegen/arm/LocalOptimizations.c @@ -147,7 +147,7 @@ static void applyLoadStoreElimination(CompilationUnit *cUnit, /* The store can be sunk for at least one cycle */ if (sinkDistance != 0) { ArmLIR *newStoreLIR = - dvmCompilerNew(sizeof(ArmLIR), true); + (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true); *newStoreLIR = *thisLIR; newStoreLIR->age = cUnit->optRound; /* @@ -369,7 +369,7 @@ static void applyLoadHoisting(CompilationUnit *cUnit, /* The load can be hoisted for at least one cycle */ if (hoistDistance != 0) { ArmLIR *newLoadLIR = - dvmCompilerNew(sizeof(ArmLIR), true); + (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true); *newLoadLIR = *thisLIR; newLoadLIR->age = cUnit->optRound; /* @@ -473,7 +473,7 @@ static void applyLoadHoisting(CompilationUnit *cUnit, /* The store can be hoisted for at least one cycle */ if (hoistDistance != 0) { ArmLIR *newLoadLIR = - dvmCompilerNew(sizeof(ArmLIR), true); + (ArmLIR *)dvmCompilerNew(sizeof(ArmLIR), true); *newLoadLIR = *thisLIR; newLoadLIR->age = cUnit->optRound; /* diff --git a/vm/compiler/codegen/arm/Thumb/Factory.c b/vm/compiler/codegen/arm/Thumb/Factory.c index af255a939..53dc2ce55 100644 --- a/vm/compiler/codegen/arm/Thumb/Factory.c +++ b/vm/compiler/codegen/arm/Thumb/Factory.c @@ -73,7 +73,7 @@ static ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, if (dataTarget == NULL) { dataTarget = addWordData(cUnit, value, false); } - ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); loadPcRel->opcode = kThumbLdrPcRel; loadPcRel->generic.target = (LIR *) dataTarget; loadPcRel->operands[0] = tDest; @@ -819,7 +819,7 @@ static ArmLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc) { ArmLIR* res; ArmOpcode opcode; - res = dvmCompilerNew(sizeof(ArmLIR), true); + res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); if (LOWREG(rDest) && LOWREG(rSrc)) opcode = kThumbMovRR; else if (!LOWREG(rDest) && !LOWREG(rSrc)) diff --git a/vm/compiler/codegen/arm/Thumb/Gen.c b/vm/compiler/codegen/arm/Thumb/Gen.c index 37cc18d97..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. */ @@ -113,21 +169,15 @@ static void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp, void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit) { int numTemps = sizeof(coreTemps)/sizeof(int); - RegisterPool *pool = dvmCompilerNew(sizeof(*pool), true); + RegisterPool *pool = (RegisterPool *) dvmCompilerNew(sizeof(*pool), true); cUnit->regPool = pool; pool->numCoreTemps = numTemps; - pool->coreTemps = + pool->coreTemps = (RegisterInfo *) dvmCompilerNew(numTemps * sizeof(*pool->coreTemps), true); pool->numFPTemps = 0; pool->FPTemps = NULL; - pool->numCoreRegs = 0; - pool->coreRegs = NULL; - pool->numFPRegs = 0; - pool->FPRegs = NULL; dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps); dvmCompilerInitPool(pool->FPTemps, NULL, 0); - dvmCompilerInitPool(pool->coreRegs, NULL, 0); - dvmCompilerInitPool(pool->FPRegs, NULL, 0); pool->nullCheckedRegs = dvmCompilerAllocBitVector(cUnit->numSSARegs, false); } diff --git a/vm/compiler/codegen/arm/Thumb2/Factory.c b/vm/compiler/codegen/arm/Thumb2/Factory.c index 141c925fa..f50edfe32 100644 --- a/vm/compiler/codegen/arm/Thumb2/Factory.c +++ b/vm/compiler/codegen/arm/Thumb2/Factory.c @@ -60,7 +60,7 @@ static ArmLIR *loadFPConstantValue(CompilationUnit *cUnit, int rDest, if (dataTarget == NULL) { dataTarget = addWordData(cUnit, value, false); } - ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); loadPcRel->opcode = kThumb2Vldrs; loadPcRel->generic.target = (LIR *) dataTarget; loadPcRel->operands[0] = rDest; @@ -170,7 +170,7 @@ static ArmLIR *loadConstantNoClobber(CompilationUnit *cUnit, int rDest, if (dataTarget == NULL) { dataTarget = addWordData(cUnit, value, false); } - ArmLIR *loadPcRel = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR *loadPcRel = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); loadPcRel->opcode = kThumb2LdrPcRel12; loadPcRel->generic.target = (LIR *) dataTarget; loadPcRel->operands[0] = rDest; @@ -1121,7 +1121,7 @@ static ArmLIR *genCmpImmBranch(CompilationUnit *cUnit, static ArmLIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc) { - ArmLIR* res = dvmCompilerNew(sizeof(ArmLIR), true); + ArmLIR* res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); res->operands[0] = rDest; res->operands[1] = rSrc; if (rDest == rSrc) { @@ -1151,7 +1151,7 @@ static ArmLIR* genRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc) ArmOpcode opcode; if (FPREG(rDest) || FPREG(rSrc)) return fpRegCopy(cUnit, rDest, rSrc); - res = dvmCompilerNew(sizeof(ArmLIR), true); + res = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR), true); if (LOWREG(rDest) && LOWREG(rSrc)) opcode = kThumbMovRR; else if (!LOWREG(rDest) && !LOWREG(rSrc)) diff --git a/vm/compiler/codegen/arm/Thumb2/Gen.c b/vm/compiler/codegen/arm/Thumb2/Gen.c index 825b271a7..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) { @@ -89,22 +140,16 @@ void dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit) { int numTemps = sizeof(coreTemps)/sizeof(int); int numFPTemps = sizeof(fpTemps)/sizeof(int); - RegisterPool *pool = dvmCompilerNew(sizeof(*pool), true); + RegisterPool *pool = (RegisterPool *)dvmCompilerNew(sizeof(*pool), true); cUnit->regPool = pool; pool->numCoreTemps = numTemps; - pool->coreTemps = + pool->coreTemps = (RegisterInfo *) dvmCompilerNew(numTemps * sizeof(*cUnit->regPool->coreTemps), true); pool->numFPTemps = numFPTemps; - pool->FPTemps = + pool->FPTemps = (RegisterInfo *) dvmCompilerNew(numFPTemps * sizeof(*cUnit->regPool->FPTemps), true); - pool->numCoreRegs = 0; - pool->coreRegs = NULL; - pool->numFPRegs = 0; - pool->FPRegs = NULL; dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps); dvmCompilerInitPool(pool->FPTemps, fpTemps, pool->numFPTemps); - dvmCompilerInitPool(pool->coreRegs, NULL, 0); - dvmCompilerInitPool(pool->FPRegs, NULL, 0); pool->nullCheckedRegs = dvmCompilerAllocBitVector(cUnit->numSSARegs, false); } |