Fix bug in invoke-super slow path
Also re-enabled some SystemMethods tests, now that we can compile
them.
Change-Id: Ie91aabd0eb015656d4dc546b4698c967b73c6ba8
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 13e5497..78a9767 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -667,14 +667,13 @@
// Load curMethod->declaring_class_ [uses r0, sets r0]
loadWordDisp(cUnit, r0, Method::DeclaringClassOffset().Int32Value(),
r0);
- case 4: // Get method->declaring_class_->super_class [usr r0, set r0]
+ // Null this?
+ genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir->offset, NULL);
+ // Get method->declaring_class_->super_class [usr r0, set r0]
loadWordDisp(cUnit, r0, Class::SuperClassOffset().Int32Value(), r0);
break;
- case 5: // Get ...->super_class_->vtable [u/s r0]
+ case 4: // Get ...->super_class_->vtable [u/s r0]
loadWordDisp(cUnit, r0, Class::VTableOffset().Int32Value(), r0);
- // In load shadow fold vtable_ object header size into method_index_
- opRegImm(cUnit, kOpAdd, rLR,
- art::Array::DataOffset().Int32Value() / 4);
if (!(mir->OptimizationFlags & MIR_IGNORE_RANGE_CHECK)) {
// Range check, throw NSM on failure
tReg = oatAllocTemp(cUnit);
@@ -683,10 +682,12 @@
genBoundsCheck(cUnit, tReg, rLR, mir->offset, NULL);
oatFreeTemp(cUnit, tReg);
}
+ // Adjust vtable_ base past object header
+ opRegImm(cUnit, kOpAdd, r0, art::Array::DataOffset().Int32Value());
// Get target Method*
- loadBaseIndexed(cUnit, r0, r0, rLR, 2, kWord);
+ loadBaseIndexed(cUnit, r0, rLR, r0, 2, kWord);
break;
- case 6: // Get the target compiled code address [uses r0, sets rLR]
+ case 5: // Get the target compiled code address [uses r0, sets rLR]
loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
break;
default:
@@ -711,8 +712,6 @@
RegLocation rlArg;
int registerArgs[3];
-skipThis = false;
-
/* If no arguments, just return */
if (dInsn->vA == 0)
return callState;
@@ -751,6 +750,7 @@
callState = loadArgRegs(cUnit, mir, dInsn, callState, registerArgs,
nextCallInsn, rollback);
+ //TODO: better to move this into CallInsn lists
// Load direct & need a "this" null check?
if (pcrLabel) {
*pcrLabel = genNullCheck(cUnit, oatSSASrc(mir,0), r1,
@@ -783,8 +783,6 @@
int numArgs = dInsn->vA;
int registerArgs[3];
-skipThis = false;
-
// If we can treat it as non-range (Jumbo ops will use range form)
if (numArgs <= 5)
return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel,
@@ -927,7 +925,7 @@
Get(dInsn->vB);
NextCallInsn nextCallInsn;
bool fastPath = true;
- if (baseMethod == NULL) {
+ if (FORCE_SLOW || baseMethod == NULL) {
fastPath = false;
} else {
Class* superClass = cUnit->method->GetDeclaringClass()->GetSuperClass();
@@ -958,7 +956,7 @@
nextCallInsn, rollback, true);
// Finish up any of the call sequence not interleaved in arg loading
while (callState >= 0) {
- callState = nextSuperCallInsn(cUnit, mir, dInsn, callState, NULL);
+ callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
}
newLIR1(cUnit, kThumbBlxR, rLR);
}