Complete compiler portion of exception handling
Will still need much testing once the runtime portions are in place.
Change-Id: I90fc7c1fd89bfae89dfd19a6e422024b6b5454ec
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index 574bb57..66eaf54 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 @@
#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 @@
* 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 e51774e..6f435e7 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -351,6 +351,9 @@
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 9d22c4f..b35f39f 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -347,6 +347,17 @@
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 @@
* 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 bea85ea..030131f 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -178,7 +178,6 @@
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 2004d46..475f096 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -1195,17 +1195,14 @@
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 1aba82c..208eecf 100644
--- a/src/compiler/codegen/arm/CodegenCommon.cc
+++ b/src/compiler/codegen/arm/CodegenCommon.cc
@@ -226,37 +226,6 @@
}
/*
- * 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 @@
/* 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 c7c15cf..a9d77ec 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -438,7 +438,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
//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 @@
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 @@
}
}
+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 @@
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 89911fe..0db63f9 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -445,8 +445,7 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
/* 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 @@
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 @@
} 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 @@
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)) {