Enable virtual invokes, use new alloc, misc
Make use of the new alloc routines. Extended the filter to allow
simple virtual invoke test to get through. Fixed a register allocation
problem.
Note that the invoke sequeces are still the verbose & long path.
Will start using the new CodeandDirectMethods mechanism in upcoming CL
Change-Id: I8ff79f6392ff3da14d7679dcf65029ae48f18eba
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index cf606a3..c8c7e34 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -23,6 +23,20 @@
*/
/*
+ * Utiltiy to load the current Method*. Broken out
+ * to allow easy change between placing the current Method* in a
+ * dedicated register or its home location in the frame.
+ */
+static void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
+{
+#if defined(METHOD_IN_REG)
+ genRegCopy(cUnit, rTgt, rMETHOD);
+#else
+ loadWordDisp(cUnit, rSP, 0, rTgt);
+#endif
+}
+
+/*
* Perform a "reg cmp imm" operation and jump to the PCR region if condition
* satisfies.
*/
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index 21ed8aa..d643a90 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -316,7 +316,7 @@
switch(lir->opcode) {
case kArmPseudoMethodEntry:
LOG(INFO) << "-------- method entry " <<
- art::PrettyMethod(cUnit->method, true);
+ art::PrettyMethod(cUnit->method);
break;
case kArmPseudoMethodExit:
LOG(INFO) << "-------- Method_Exit";
@@ -390,8 +390,7 @@
{
const Method *method = cUnit->method;
LOG(INFO) << "/*";
- LOG(INFO) << "Dumping LIR insns for " <<
- art::PrettyMethod(cUnit->method, true);
+ LOG(INFO) << "Dumping LIR insns for " << art::PrettyMethod(cUnit->method);
LIR* lirInsn;
ArmLIR* armLIR;
int insnsSize = cUnit->insnsSize;
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 400fff6..b2217d0 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -248,12 +248,12 @@
if (base->fpLocation == kLocPhysReg) {
if (curr->wide) {
/* TUNING: consider alignment during allocation */
- if (base->fpLowReg & 1) {
- // Pair must start on even reg - don't promote
- continue;
- }
- /* Make sure upper half is also in reg or skip */
- if (baseNext->fpLocation != kLocPhysReg) {
+ if ((base->fpLowReg & 1) ||
+ (baseNext->fpLocation != kLocPhysReg)) {
+ /* Half-promoted or bad alignment - demote */
+ curr->location = kLocDalvikFrame;
+ curr->lowReg = INVALID_REG;
+ curr->highReg = INVALID_REG;
continue;
}
curr->highReg = baseNext->fpLowReg;
@@ -268,6 +268,10 @@
if (curr->wide) {
/* Make sure upper half is also in reg or skip */
if (baseNext->location != kLocPhysReg) {
+ /* Only half promoted; demote to frame */
+ curr->location = kLocDalvikFrame;
+ curr->lowReg = INVALID_REG;
+ curr->highReg = INVALID_REG;
continue;
}
curr->highReg = baseNext->lowReg;
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 4106e1d..c83a2a4 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -21,30 +21,24 @@
static const RegLocation retLoc = LOC_DALVIK_RETURN_VAL;
static const RegLocation retLocWide = LOC_DALVIK_RETURN_VAL_WIDE;
+/*
+ * Let helper function take care of everything. Will call
+ * Array::AllocFromCode(type_idx, method, count);
+ * Note: AllocFromCode will handle checks for errNegativeArraySize.
+ */
static void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
RegLocation rlSrc)
{
- oatFlushAllRegs(cUnit); /* All temps to home location */
- UNIMPLEMENTED(WARNING) << "Need to handle unresolved";
- /*
- * Need new routine that passes Method*, type index, length.
- * This is unconditional - always go this way.
- */
- Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
- GetResolvedType(mir->dalvikInsn.vC);
- if (classPtr == NULL) {
- LOG(FATAL) << "Unexpected null classPtr";
- } else {
- loadValueDirectFixed(cUnit, rlSrc, r1); /* get Len */
- loadConstant(cUnit, r0, (int)classPtr);
- }
- UNIMPLEMENTED(WARNING) << "Support for throwing errNegativeArraySize";
- genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL);
- loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocArrayByClass),
- rLR);
- UNIMPLEMENTED(WARNING) << "Need NoThrow wrapper";
- newLIR1(cUnit, kThumbBlxR, rLR); // (arrayClass, length, allocFlags)
- storeValue(cUnit, rlDest, retLoc);
+ oatFlushAllRegs(cUnit); /* Everything to home location */
+ loadWordDisp(cUnit, rSELF,
+ OFFSETOF_MEMBER(Thread, pAllocFromCode), rLR);
+ loadCurrMethodDirect(cUnit, r1); // arg1 <- Method*
+ loadConstant(cUnit, r0, mir->dalvikInsn.vC); // arg0 <- type_id
+ loadValueDirectFixed(cUnit, rlSrc, r2); // arg2 <- count
+ opReg(cUnit, kOpBlx, rLR);
+ oatClobberCallRegs(cUnit);
+ RegLocation rlResult = oatGetReturn(cUnit);
+ storeValue(cUnit, rlDest, rlResult);
}
/*
@@ -57,36 +51,32 @@
{
DecodedInstruction* dInsn = &mir->dalvikInsn;
int elems;
- int typeIndex;
+ int typeId;
if (isRange) {
elems = dInsn->vA;
- typeIndex = dInsn->vB;
+ typeId = dInsn->vB;
} else {
elems = dInsn->vB;
- typeIndex = dInsn->vC;
+ typeId = dInsn->vC;
}
- oatFlushAllRegs(cUnit); /* All temps to home location */
- Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
- GetResolvedType(typeIndex);
- if (classPtr == NULL) {
- LOG(FATAL) << "Unexpected null classPtr";
- } else {
- loadConstant(cUnit, r0, (int)classPtr);
- loadConstant(cUnit, r1, elems);
- }
- if (elems < 0) {
- LOG(FATAL) << "Unexpected empty array";
- }
+ oatFlushAllRegs(cUnit); /* Everything to home location */
+ // TODO: Alloc variant that checks types (see header comment) */
+ UNIMPLEMENTED(WARNING) << "Need AllocFromCode variant w/ extra checks";
+ loadWordDisp(cUnit, rSELF,
+ OFFSETOF_MEMBER(Thread, pAllocFromCode), rLR);
+ loadCurrMethodDirect(cUnit, r1); // arg1 <- Method*
+ loadConstant(cUnit, r0, typeId); // arg0 <- type_id
+ loadConstant(cUnit, r2, elems); // arg2 <- count
+ opReg(cUnit, kOpBlx, rLR);
/*
- * FIXME: Need a new NoThrow allocator that checks for and handles
- * the above mentioned bad cases of 'D', 'J' or !('L' | '[' | 'I').
- * That will keep us from wasting space generating an inline check here.
+ * NOTE: the implicit target for OP_FILLED_NEW_ARRAY is the
+ * return region. Because AllocFromCode placed the new array
+ * in r0, we'll just lock it into place. When debugger support is
+ * added, it may be necessary to additionally copy all return
+ * values to a home location in thread-local storage
*/
- loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocArrayByClass),
- rLR);
- newLIR1(cUnit, kThumbBlxR, rLR); // (arrayClass, length, allocFlags)
- // Reserve ret0 (r0) - we'll use it in place.
oatLockTemp(cUnit, r0);
+
// Having a range of 0 is legal
if (isRange && (dInsn->vA > 0)) {
/*
@@ -313,7 +303,7 @@
#if 0
switch(state) {
case 0: // Get the current Method* [sets r0]
- loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+ loadCurrMethodDirect(cUnit, r0);
break;
case 1: // Get the pResMethods pointer [uses r0, sets r0]
UNIMPLEMENTED(FATAL) << "Update with new cache";
@@ -342,7 +332,7 @@
{
switch(state) {
case 0: // Get the current Method* [sets r0]
- loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+ loadCurrMethodDirect(cUnit, r0);
break;
case 1: // Get the current Method->DeclaringClass() [sets r0]
loadBaseDisp(cUnit, mir, r0,
@@ -391,7 +381,7 @@
RegLocation rlArg;
switch(state) {
case 0: // Get the current Method* [set r0]
- loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+ loadCurrMethodDirect(cUnit, r0);
// Load "this" [set r1]
rlArg = oatGetSrc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlArg, r1);
@@ -440,7 +430,7 @@
RegLocation rlArg;
switch(state) {
case 0: // Get the current Method* [sets r0]
- loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+ loadCurrMethodDirect(cUnit, r0);
break;
case 1: // Get the current Method->DeclaringClass() [uses/sets r0]
loadBaseDisp(cUnit, mir, r0,
@@ -530,7 +520,7 @@
rlArg = oatGetSrc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlArg, r12);
// Get the current Method* [set arg2]
- loadBaseDisp(cUnit, mir, rSP, 0, r2, kWord, INVALID_SREG);
+ loadCurrMethodDirect(cUnit, r2);
// Is "this" null? [use r12]
genNullCheck(cUnit, oatSSASrc(mir,0), r12,
mir->offset, NULL);
@@ -576,7 +566,7 @@
switch(state) {
case 0:
// Get the current Method* [set r0]
- loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG);
+ loadCurrMethodDirect(cUnit, r0);
// Load "this" [set r1]
rlArg = oatGetSrc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlArg, r1);
@@ -1554,7 +1544,8 @@
/* If there are any ins passed in registers that have not been promoted
* to a callee-save register, flush them to the frame.
- * Note: at this pointCopy any ins that are passed in register to their home location */
+ * Note: at this pointCopy any ins that are passed in register to their
+ * home location */
static void flushIns(CompilationUnit* cUnit)
{
if (cUnit->method->num_ins_ == 0)
@@ -1564,11 +1555,10 @@
int startLoc = cUnit->method->num_registers_ - cUnit->method->num_ins_;
for (int i = 0; i < inRegs; i++) {
RegLocation loc = cUnit->regLocation[startLoc + i];
+ //TUNING: be smarter about flushing ins to frame
+ storeBaseDisp(cUnit, rSP, loc.spOffset, startReg + i, kWord);
if (loc.location == kLocPhysReg) {
genRegCopy(cUnit, loc.lowReg, startReg + i);
- } else {
- assert(loc.location == kLocDalvikFrame);
- storeBaseDisp(cUnit, rSP, loc.spOffset, startReg + i, kWord);
}
}
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 2bdeee6..eb136b8 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -550,29 +550,18 @@
storeValue(cUnit, rlDest, rlResult);
}
+/*
+ * Let helper function take care of everything. Will
+ * call Class::NewInstanceFromCode(type_idx, method);
+ */
static void genNewInstance(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest)
{
- Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()->
- GetResolvedType(mir->dalvikInsn.vB);
-
- /*
- * Need new routine that passes Method*, type index.
- * Call unconditionally.
- */
- if (classPtr == NULL) {
- /* Shouldn't happen */
- LOG(FATAL) << "Unexpected null class pointer";
- }
-
- // Verifier should have already rejected abstract/interface
- assert((classPtr->access_flags_ &
- (art::kAccInterface|art::kAccAbstract)) == 0);
- oatFlushAllRegs(cUnit); /* Everything to home location */
+ oatFlushAllRegs(cUnit); /* Everything to home location */
loadWordDisp(cUnit, rSELF,
- OFFSETOF_MEMBER(Thread, pArtAllocObjectNoThrow), rLR);
- loadConstant(cUnit, r0, (int) classPtr);
- UNIMPLEMENTED(WARNING) << "Need NewWorld dvmAllocObject";
+ OFFSETOF_MEMBER(Thread, pNewInstanceFromCode), rLR);
+ loadCurrMethodDirect(cUnit, r1); // arg1 <= Method*
+ loadConstant(cUnit, r0, mir->dalvikInsn.vB); // arg0 <- type_id
opReg(cUnit, kOpBlx, rLR);
oatClobberCallRegs(cUnit);
RegLocation rlResult = oatGetReturn(cUnit);