diff options
Diffstat (limited to 'src/compiler/codegen')
| -rw-r--r-- | src/compiler/codegen/Ralloc.h | 1 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArchFactory.cc | 81 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArchUtility.cc | 3 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArmLIR.h | 12 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/ArmRallocUtil.cc | 1 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Assemble.cc | 19 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/CodegenCommon.cc | 64 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/MethodCodegenDriver.cc | 98 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 66 |
9 files changed, 169 insertions, 176 deletions
diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h index 67ed6ee9a5..82ce23eb82 100644 --- a/src/compiler/codegen/Ralloc.h +++ b/src/compiler/codegen/Ralloc.h @@ -165,7 +165,6 @@ extern void oatResetDefTracking(CompilationUnit* cUnit); extern void oatKillNullCheckedLoc(CompilationUnit* cUnit, RegLocation loc); -//FIXME - this needs to also check the preserved pool. extern RegisterInfo *oatIsLive(CompilationUnit* cUnit, int reg); /* To be used when explicitly managing register use */ diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc index 574bb57018..66eaf5494f 100644 --- a/src/compiler/codegen/arm/ArchFactory.cc +++ b/src/compiler/codegen/arm/ArchFactory.cc @@ -22,6 +22,10 @@ * */ +static ArmLIR* genUnconditionalBranch(CompilationUnit*, ArmLIR*); +static ArmLIR* genConditionalBranch(CompilationUnit*, ArmConditionCode, + ArmLIR*); + /* * Utiltiy to load the current Method*. Broken out * to allow easy change between placing the current Method* in a @@ -47,26 +51,23 @@ static int loadCurrMethod(CompilationUnit *cUnit) #endif } -/* - * Perform a "reg cmp imm" operation and jump to the PCR region if condition - * satisfies. - */ -static TGT_LIR* genRegImmCheck(CompilationUnit* cUnit, - ArmConditionCode cond, int reg, - int checkValue, int dOffset, - TGT_LIR* pcrLabel) +static ArmLIR* genImmedCheck(CompilationUnit* cUnit, ArmConditionCode cCode, + int reg, int immVal, MIR* mir, ArmThrowKind kind) { - TGT_LIR* branch = genCmpImmBranch(cUnit, cond, reg, checkValue); - BasicBlock* bb = cUnit->curBlock; - if (bb->taken) { - ArmLIR *exceptionLabel = (ArmLIR* ) cUnit->blockLabelList; - exceptionLabel += bb->taken->id; - branch->generic.target = (LIR* ) exceptionLabel; - return exceptionLabel; + ArmLIR* tgt = (ArmLIR*)oatNew(sizeof(ArmLIR), true); + tgt->opcode = kArmPseudoThrowTarget; + tgt->operands[0] = kind; + tgt->operands[1] = mir->offset; + ArmLIR* branch; + if (cCode == kArmCondAl) { + branch = genUnconditionalBranch(cUnit, tgt); } else { - LOG(FATAL) << "Catch blocks not handled yet"; - return NULL; // quiet gcc + branch = genCmpImmBranch(cUnit, kArmCondEq, reg, 0); + branch->generic.target = (LIR*)tgt; } + // Remember branch target - will process later + oatInsertGrowableList(&cUnit->throwLaunchpads, (intptr_t)tgt); + return branch; } /* @@ -74,42 +75,30 @@ static TGT_LIR* genRegImmCheck(CompilationUnit* cUnit, * and mReg is the machine register holding the actual value. If internal state * indicates that sReg has been checked before the check request is ignored. */ -static TGT_LIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, - int dOffset, TGT_LIR* pcrLabel) +static ArmLIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, + MIR* mir) { - /* This particular Dalvik register has been null-checked */ -#if 0 - // Yes, I know. Please be quiet. - UNIMPLEMENTED(WARNING) << "Need null check & throw support"; -#endif - return pcrLabel; if (oatIsBitSet(cUnit->regPool->nullCheckedRegs, sReg)) { - return pcrLabel; + /* This particular Dalvik register has been null-checked */ + return NULL; } oatSetBit(cUnit->regPool->nullCheckedRegs, sReg); - return genRegImmCheck(cUnit, kArmCondEq, mReg, 0, dOffset, pcrLabel); -} - -/* - * Perform a "reg cmp reg" operation and jump to the PCR region if condition - * satisfies. - */ -static TGT_LIR* genRegRegCheck(CompilationUnit* cUnit, - ArmConditionCode cond, - int reg1, int reg2, int dOffset, - TGT_LIR* pcrLabel) -{ - TGT_LIR* res; - res = opRegReg(cUnit, kOpCmp, reg1, reg2); - TGT_LIR* branch = opCondBranch(cUnit, cond); - genCheckCommon(cUnit, dOffset, branch, pcrLabel); - return res; + return genImmedCheck(cUnit, kArmCondEq, mReg, 0, mir, kArmThrowNullPointer); } /* Perform bound check on two registers */ static TGT_LIR* genBoundsCheck(CompilationUnit* cUnit, int rIndex, - int rBound, int dOffset, TGT_LIR* pcrLabel) + int rBound, MIR* mir, ArmThrowKind kind) { - return genRegRegCheck(cUnit, kArmCondCs, rIndex, rBound, dOffset, - pcrLabel); + ArmLIR* tgt = (ArmLIR*)oatNew(sizeof(ArmLIR), true); + tgt->opcode = kArmPseudoThrowTarget; + tgt->operands[0] = kind; + tgt->operands[1] = mir->offset; + tgt->operands[2] = rIndex; + tgt->operands[3] = rBound; + opRegReg(cUnit, kOpCmp, rIndex, rBound); + ArmLIR* branch = genConditionalBranch(cUnit, kArmCondCs, tgt); + // Remember branch target - will process later + oatInsertGrowableList(&cUnit->throwLaunchpads, (intptr_t)tgt); + return branch; } diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc index e51774e7b2..6f435e77fd 100644 --- a/src/compiler/codegen/arm/ArchUtility.cc +++ b/src/compiler/codegen/arm/ArchUtility.cc @@ -351,6 +351,9 @@ void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) case kArmPseudoNormalBlockLabel: LOG(INFO) << "L" << (intptr_t)lir << ":"; break; + case kArmPseudoThrowTarget: + LOG(INFO) << "LT" << (intptr_t)lir << ":"; + break; case kArmPseudoCaseLabel: LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" << std::hex << lir->operands[0] << "|" << std::dec << diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h index 9d22c4ffae..b35f39f90b 100644 --- a/src/compiler/codegen/arm/ArmLIR.h +++ b/src/compiler/codegen/arm/ArmLIR.h @@ -347,6 +347,17 @@ typedef enum ArmConditionCode { kArmCondNv = 0xf, /* 1111 */ } ArmConditionCode; +typedef enum ArmThrowKind { + kArmThrowNullPointer, + kArmThrowDivZero, + kArmThrowArrayBounds, + kArmThrowVerificationError, + kArmThrowNegArraySize, + kArmThrowInternalError, + kArmThrowRuntimeException, + kArmThrowNoSuchMethod, +} ArmThrowKind; + #define isPseudoOpcode(opcode) ((int)(opcode) < 0) /* @@ -355,6 +366,7 @@ typedef enum ArmConditionCode { * Assemble.c. */ typedef enum ArmOpcode { + kArmPseudoThrowTarget = -14, kArmPseudoCaseLabel = -13, kArmPseudoMethodEntry = -12, kArmPseudoMethodExit = -11, diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc index bea85ea8e8..030131f41c 100644 --- a/src/compiler/codegen/arm/ArmRallocUtil.cc +++ b/src/compiler/codegen/arm/ArmRallocUtil.cc @@ -178,7 +178,6 @@ extern void oatDoPromotion(CompilationUnit* cUnit) qsort(coreRegs, numRegs, sizeof(RefCounts), sortCounts); qsort(fpRegs, numRegs, sizeof(RefCounts), sortCounts); - // TODO: temp for debugging, too verbose. Remove when unneeded if (cUnit->printMeVerbose) { dumpCounts(coreRegs, numRegs, "coreRegs"); dumpCounts(fpRegs, numRegs, "fpRegs"); diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc index 2004d46106..475f096c01 100644 --- a/src/compiler/codegen/arm/Assemble.cc +++ b/src/compiler/codegen/arm/Assemble.cc @@ -1195,17 +1195,14 @@ static AssemblerStatus assembleInstructions(CompilationUnit* cUnit, lir->opcode == kThumb2BCond) { ArmLIR *targetLIR = (ArmLIR *) lir->generic.target; int delta = 0; - if (targetLIR == NULL) { - UNIMPLEMENTED(WARNING) << "Throw targets unimplemented"; - } else { - intptr_t pc = lir->generic.offset + 4; - intptr_t target = targetLIR->generic.offset; - delta = target - pc; - if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) { - lir->opcode = kThumb2BCond; - oatSetupResourceMasks(lir); - res = kRetryAll; - } + assert(targetLIR); + intptr_t pc = lir->generic.offset + 4; + intptr_t target = targetLIR->generic.offset; + delta = target - pc; + if ((lir->opcode == kThumbBCond) && (delta > 254 || delta < -256)) { + lir->opcode = kThumb2BCond; + oatSetupResourceMasks(lir); + res = kRetryAll; } lir->operands[0] = delta >> 1; } else if (lir->opcode == kThumb2BUncond) { diff --git a/src/compiler/codegen/arm/CodegenCommon.cc b/src/compiler/codegen/arm/CodegenCommon.cc index 1aba82c746..208eecf1b4 100644 --- a/src/compiler/codegen/arm/CodegenCommon.cc +++ b/src/compiler/codegen/arm/CodegenCommon.cc @@ -226,37 +226,6 @@ static void setupResourceMasks(ArmLIR* lir) } /* - * Set up the accurate resource mask for branch instructions - */ -static void relaxBranchMasks(ArmLIR* lir) -{ - int flags = EncodingMap[lir->opcode].flags; - - /* Make sure only branch instructions are passed here */ - assert(flags & IS_BRANCH); - - lir->useMask = lir->defMask = ENCODE_REG_PC; - - if (flags & REG_DEF_LR) { - lir->defMask |= ENCODE_REG_LR; - } - - if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) { - int i; - - for (i = 0; i < 4; i++) { - if (flags & (1 << (kRegUse0 + i))) { - setupRegMask(&lir->useMask, lir->operands[i]); - } - } - } - - if (flags & USES_CCODES) { - lir->useMask |= ENCODE_CCODE; - } -} - -/* * The following are building blocks to construct low-level IRs with 0 - 4 * operands. */ @@ -383,36 +352,3 @@ static void genBarrier(CompilationUnit* cUnit) /* Mark all resources as being clobbered */ barrier->defMask = -1; } - -/* Create the PC reconstruction slot if not already done */ -static ArmLIR* genCheckCommon(CompilationUnit* cUnit, int dOffset, - ArmLIR* branch, - ArmLIR* pcrLabel) -{ - //FIXME - won't be rolling back, need to throw now. - UNIMPLEMENTED(WARNING); -#if 0 - - /* Forget all def info (because we might rollback here. Bug #2367397 */ - oatResetDefTracking(cUnit); - - /* Set up the place holder to reconstruct this Dalvik PC */ - if (pcrLabel == NULL) { - int dPC = (int) (cUnit->insns + dOffset); - pcrLabel = (ArmLIR* ) oatNew(sizeof(ArmLIR), true); - pcrLabel->opcode = kArmPseudoPCReconstructionCell; - pcrLabel->operands[0] = dPC; - pcrLabel->operands[1] = dOffset; - /* Insert the place holder to the growable list */ - oatInsertGrowableList(&cUnit->pcReconstructionList, - (intptr_t) pcrLabel); - } -#endif - /* Branch to the PC reconstruction code */ - branch->generic.target = (LIR*) pcrLabel; - - /* Clear the conservative flags for branches that punt to the interpreter */ - relaxBranchMasks(branch); - - return pcrLabel; -} diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc index c7c15cfdd2..a9d77ec4e1 100644 --- a/src/compiler/codegen/arm/MethodCodegenDriver.cc +++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc @@ -438,7 +438,7 @@ static int nextVCallInsn(CompilationUnit* cUnit, MIR* mir, loadValueDirectFixed(cUnit, rlArg, r1); break; case 1: // Is "this" null? [use r1] - genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir->offset, NULL); + genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); // get this->klass_ [use r1, set rLR] loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), rLR); break; @@ -507,7 +507,7 @@ static int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir, break; case 4: // Is "this" null? [use r1] - genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir->offset, NULL); + genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); // get this->clazz [use r1, set rLR] loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), rLR); break; @@ -601,8 +601,7 @@ static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(), rLR); // Is "this" null? [use r1] - genNullCheck(cUnit, oatSSASrc(mir,0), r1, - mir->offset, NULL); + genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); break; case 1: // Get method->declaring_class_->super_class [usr rLR, set rLR] loadWordDisp(cUnit, rLR, Class::SuperClassOffset().Int32Value(), @@ -676,7 +675,7 @@ static int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(), r0); // Null this? - genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir->offset, NULL); + genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); // Get method->declaring_class_->super_class [usr r0, set r0] loadWordDisp(cUnit, r0, Class::SuperClassOffset().Int32Value(), r0); break; @@ -687,7 +686,7 @@ static int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir, tReg = oatAllocTemp(cUnit); loadWordDisp(cUnit, r0, art::Array::LengthOffset().Int32Value(), tReg); - genBoundsCheck(cUnit, tReg, rLR, mir->offset, NULL); + genBoundsCheck(cUnit, tReg, rLR, mir, kArmThrowNoSuchMethod); oatFreeTemp(cUnit, tReg); } // Adjust vtable_ base past object header @@ -761,8 +760,7 @@ static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, //TODO: better to move this into CallInsn lists // Load direct & need a "this" null check? if (pcrLabel) { - *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, - mir->offset, NULL); + *pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir); } return callState; } @@ -1215,12 +1213,19 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, genThrow(cUnit, mir, rlSrc[0]); break; + case OP_THROW_VERIFICATION_ERROR: + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode), rLR); + loadConstant(cUnit, r0, mir->dalvikInsn.vA); + loadConstant(cUnit, r1, mir->dalvikInsn.vB); + opReg(cUnit, kOpBlx, rLR); + break; + case OP_ARRAY_LENGTH: int lenOffset; lenOffset = Array::LengthOffset().Int32Value(); rlSrc[0] = loadValue(cUnit, rlSrc[0], kCoreReg); - genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, - mir->offset, NULL); + genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir); rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); loadWordDisp(cUnit, rlSrc[0].lowReg, lenOffset, rlResult.lowReg); @@ -1986,6 +1991,77 @@ void removeRedundantBranches(CompilationUnit* cUnit) } } +static void handleThrowLaunchpads(CompilationUnit *cUnit) +{ + ArmLIR** throwLabel = + (ArmLIR **) cUnit->throwLaunchpads.elemList; + int numElems = cUnit->throwLaunchpads.numUsed; + int i; + + for (i = 0; i < numElems; i++) { + ArmLIR* lab = throwLabel[i]; + cUnit->currentDalvikOffset = lab->operands[1]; + oatAppendLIR(cUnit, (LIR *)lab); + int funcOffset = 0; + int v1 = lab->operands[2]; + int v2 = lab->operands[3]; + switch(lab->operands[0]) { + case kArmThrowNullPointer: + funcOffset = OFFSETOF_MEMBER(Thread, pThrowNullPointerFromCode); + break; + case kArmThrowArrayBounds: + if (v2 != r0) { + genRegCopy(cUnit, r0, v1); + genRegCopy(cUnit, r1, v2); + } else { + if (v1 == r1) { + genRegCopy(cUnit, r12, v1); + genRegCopy(cUnit, r1, v2); + genRegCopy(cUnit, r0, r12); + } else { + genRegCopy(cUnit, r1, v2); + genRegCopy(cUnit, r0, v1); + } + } + funcOffset = OFFSETOF_MEMBER(Thread, pThrowArrayBoundsFromCode); + break; + case kArmThrowDivZero: + funcOffset = OFFSETOF_MEMBER(Thread, pThrowDivZeroFromCode); + break; + case kArmThrowVerificationError: + loadConstant(cUnit, r0, v1); + loadConstant(cUnit, r1, v2); + funcOffset = + OFFSETOF_MEMBER(Thread, pThrowVerificationErrorFromCode); + break; + case kArmThrowNegArraySize: + genRegCopy(cUnit, r0, v1); + funcOffset = + OFFSETOF_MEMBER(Thread, pThrowNegArraySizeFromCode); + break; + case kArmThrowInternalError: + genRegCopy(cUnit, r0, v1); + funcOffset = + OFFSETOF_MEMBER(Thread, pThrowInternalErrorFromCode); + break; + case kArmThrowRuntimeException: + genRegCopy(cUnit, r0, v1); + funcOffset = + OFFSETOF_MEMBER(Thread, pThrowRuntimeExceptionFromCode); + break; + case kArmThrowNoSuchMethod: + genRegCopy(cUnit, r0, v1); + funcOffset = + OFFSETOF_MEMBER(Thread, pThrowNoSuchMethodFromCode); + break; + default: + LOG(FATAL) << "Unexpected throw kind: " << lab->operands[0]; + } + loadWordDisp(cUnit, rSELF, funcOffset, rLR); + opReg(cUnit, kOpBlx, rLR); + } +} + void oatMethodMIR2LIR(CompilationUnit* cUnit) { /* Used to hold the labels of each block */ @@ -1995,6 +2071,8 @@ void oatMethodMIR2LIR(CompilationUnit* cUnit) oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen, kPreOrderDFSTraversal, false /* Iterative */); removeRedundantBranches(cUnit); + + handleThrowLaunchpads(cUnit); } /* Common initialization routine for an architecture family */ diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index 89911fea2a..0db63f9363 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -445,8 +445,7 @@ static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size, // Field offset in r0 rlObj = loadValue(cUnit, rlObj, kCoreReg); rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */ loadBaseIndexed(cUnit, rlObj.lowReg, r0, rlResult.lowReg, 0, size); oatGenMemBarrier(cUnit, kSY); storeValue(cUnit, rlDest, rlResult); @@ -459,8 +458,7 @@ static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size, int fieldOffset = fieldPtr->GetOffset().Int32Value(); rlObj = loadValue(cUnit, rlObj, kCoreReg); rlResult = oatEvalLoc(cUnit, rlDest, regClass, true); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */ loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg, size, rlObj.sRegLow); if (isVolatile) { @@ -481,8 +479,7 @@ static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size, // Field offset in r0 rlObj = loadValue(cUnit, rlObj, kCoreReg); rlSrc = loadValue(cUnit, rlSrc, regClass); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null object? */ oatGenMemBarrier(cUnit, kSY); storeBaseIndexed(cUnit, rlObj.lowReg, r0, rlSrc.lowReg, 0, size); } else { @@ -494,8 +491,7 @@ static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size, int fieldOffset = fieldPtr->GetOffset().Int32Value(); rlObj = loadValue(cUnit, rlObj, kCoreReg); rlSrc = loadValue(cUnit, rlSrc, regClass); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */ if (isVolatile) { oatGenMemBarrier(cUnit, kSY); @@ -519,8 +515,7 @@ static void genIGetWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, // Field offset in r0 rlObj = loadValue(cUnit, rlObj, kCoreReg); rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */ opRegReg(cUnit, kOpAdd, r0, rlObj.lowReg); loadPair(cUnit, r0, rlResult.lowReg, rlResult.highReg); oatGenMemBarrier(cUnit, kSY); @@ -537,8 +532,7 @@ static void genIGetWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, assert(rlDest.wide); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */ opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset); rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); @@ -563,8 +557,7 @@ static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, // Field offset in r0 rlObj = loadValue(cUnit, rlObj, kCoreReg); rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */ opRegReg(cUnit, kOpAdd, r0, rlObj.lowReg); oatGenMemBarrier(cUnit, kSY); storePair(cUnit, r0, rlSrc.lowReg, rlSrc.highReg); @@ -579,8 +572,7 @@ static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, rlObj = loadValue(cUnit, rlObj, kCoreReg); int regPtr; rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg); - genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset, - NULL);/* null object? */ + genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir);/* null obj? */ regPtr = oatAllocTemp(cUnit); opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset); @@ -919,7 +911,7 @@ static void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, assert(art::Monitor::kLwShapeThin == 0); loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj oatLockCallTemps(cUnit); // Prepare for explicit register usage - genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); + genNullCheck(cUnit, rlSrc.sRegLow, r1, mir); loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3); newLIR3(cUnit, kThumb2Ldrex, r2, r1, Object::MonitorOffset().Int32Value() >> 2); // Get object->lock @@ -970,7 +962,7 @@ static void genMonitorExit(CompilationUnit* cUnit, MIR* mir, oatFlushAllRegs(cUnit); loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj oatLockCallTemps(cUnit); // Prepare for explicit register usage - genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); + genNullCheck(cUnit, rlSrc.sRegLow, r1, mir); loadWordDisp(cUnit, r1, Object::MonitorOffset().Int32Value(), r2); // Get lock loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3); // Is lock unheld on lock or held by us (==threadId) on unlock? @@ -1241,14 +1233,6 @@ static ArmLIR* genConditionalBranch(CompilationUnit* cUnit, return branch; } -/* Generate a unconditional branch to go to the interpreter */ -static inline ArmLIR* genTrap(CompilationUnit* cUnit, int dOffset, - ArmLIR* pcrLabel) -{ - ArmLIR* branch = opNone(cUnit, kOpUncondBr); - return genCheckCommon(cUnit, dOffset, branch, pcrLabel); -} - /* * Generate array store * @@ -1269,8 +1253,7 @@ static void genArrayObjPut(CompilationUnit* cUnit, MIR* mir, ArmLIR* pcrLabel = NULL; if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) { - pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, r1, - mir->offset, NULL); + pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, r1, mir); } loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pCanPutArrayElementFromCode), rLR); @@ -1302,8 +1285,8 @@ static void genArrayObjPut(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); /* regPtr -> array data */ opRegImm(cUnit, kOpAdd, regPtr, dataOffset); - genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset, - pcrLabel); + genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir, + kArmThrowArrayBounds); oatFreeTemp(cUnit, regLen); } else { /* regPtr -> array data */ @@ -1334,8 +1317,7 @@ static void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size, ArmLIR* pcrLabel = NULL; if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) { - pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, - rlArray.lowReg, mir->offset, NULL); + pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir); } regPtr = oatAllocTemp(cUnit); @@ -1346,8 +1328,8 @@ static void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size, loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); /* regPtr -> array data */ opRegRegImm(cUnit, kOpAdd, regPtr, rlArray.lowReg, dataOffset); - genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset, - pcrLabel); + genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir, + kArmThrowArrayBounds); oatFreeTemp(cUnit, regLen); } else { /* regPtr -> array data */ @@ -1409,8 +1391,7 @@ static void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size, ArmLIR* pcrLabel = NULL; if (!(mir->OptimizationFlags & MIR_IGNORE_NULL_CHECK)) { - pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, - mir->offset, NULL); + pcrLabel = genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir); } if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) { @@ -1420,8 +1401,8 @@ static void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size, loadWordDisp(cUnit, rlArray.lowReg, lenOffset, regLen); /* regPtr -> array data */ opRegImm(cUnit, kOpAdd, regPtr, dataOffset); - genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir->offset, - pcrLabel); + genBoundsCheck(cUnit, rlIndex.lowReg, regLen, mir, + kArmThrowArrayBounds); oatFreeTemp(cUnit, regLen); } else { /* regPtr -> array data */ @@ -1429,7 +1410,7 @@ static void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size, } /* at this point, regPtr points to array, 2 live temps */ if ((size == kLong) || (size == kDouble)) { - //TODO: need specific wide routine that can handle fp regs + //TUNING: specific wide routine that can handle fp regs if (scale) { int rNewIndex = oatAllocTemp(cUnit); opRegRegImm(cUnit, kOpLsl, rNewIndex, rlIndex.lowReg, scale); @@ -1693,7 +1674,7 @@ static bool genArithOpInt(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, rSELF, funcOffset, rLR); loadValueDirectFixed(cUnit, rlSrc1, r0); if (checkZero) { - genNullCheck(cUnit, rlSrc2.sRegLow, r1, mir->offset, NULL); + genImmedCheck(cUnit, kArmCondEq, r1, 0, mir, kArmThrowDivZero); } opReg(cUnit, kOpBlx, rLR); oatClobberCallRegs(cUnit); @@ -1844,7 +1825,7 @@ static bool handleEasyMultiply(CompilationUnit* cUnit, } else { // Reverse subtract: (src << (shift + 1)) - src. assert(powerOfTwoMinusOne); - // TODO: rsb dst, src, src lsl#lowestSetBit(lit + 1) + // TUNING: rsb dst, src, src lsl#lowestSetBit(lit + 1) int tReg = oatAllocTemp(cUnit); opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lowestSetBit(lit + 1)); opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg); @@ -1925,8 +1906,7 @@ static bool genArithOpIntLit(CompilationUnit* cUnit, MIR* mir, case OP_REM_INT_LIT8: case OP_REM_INT_LIT16: if (lit == 0) { - UNIMPLEMENTED(FATAL); - // FIXME: generate an explicit throw here + genImmedCheck(cUnit, kArmCondAl, 0, 0, mir, kArmThrowDivZero); return false; } if (handleEasyDivide(cUnit, dalvikOpcode, rlSrc, rlDest, lit)) { |