Fix for argument passing bug
The code was using r1 as a temp when it was live.
Change-Id: I79f42203eced2aff49980241c890629ecc3ff09a
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 72d42d1..aa9b719 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -167,4 +167,5 @@
StaticLeafMethods \
Statics \
SystemMethods \
+ Invoke \
XandY
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 78a9767..96f5423 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -716,7 +716,6 @@
if (dInsn->vA == 0)
return callState;
- oatLockCallTemps(cUnit);
callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
/*
@@ -729,8 +728,9 @@
if (rlArg.location == kLocPhysReg) {
reg = rlArg.lowReg;
} else {
- reg = r1;
- loadValueDirectFixed(cUnit, rlArg, r1);
+ // r3 is the last arg register loaded, so can safely be used here
+ reg = r3;
+ loadValueDirectFixed(cUnit, rlArg, reg);
callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
}
storeBaseDisp(cUnit, rSP, (i + 1) * 4, reg, kWord);
@@ -859,9 +859,6 @@
callState = loadArgRegs(cUnit, mir, dInsn, callState, registerArgs,
nextCallInsn, rollback);
- // Finally, deal with the register arguments
- // We'll be using fixed registers here
- oatLockCallTemps(cUnit);
callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback);
return callState;
}
@@ -873,9 +870,11 @@
int callState = 0;
ArmLIR* nullCk;
ArmLIR** pNullCk = direct ? &nullCk : NULL;
-
NextCallInsn nextCallInsn = nextSDCallInsn;
+ // Explicit register usage
+ oatLockCallTemps(cUnit);
+
if (range) {
callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk,
nextCallInsn, NULL, false);
@@ -899,6 +898,9 @@
DecodedInstruction* dInsn = &mir->dalvikInsn;
int callState = 0;
ArmLIR* nullCk;
+
+ // Explicit register usage
+ oatLockCallTemps(cUnit);
/* Note: must call nextInterfaceCallInsn() prior to 1st argument load */
callState = nextInterfaceCallInsn(cUnit, mir, dInsn, callState, NULL);
if (mir->dalvikInsn.opcode == OP_INVOKE_INTERFACE)
@@ -925,6 +927,9 @@
Get(dInsn->vB);
NextCallInsn nextCallInsn;
bool fastPath = true;
+
+ // Explicit register usage
+ oatLockCallTemps(cUnit);
if (FORCE_SLOW || baseMethod == NULL) {
fastPath = false;
} else {
@@ -971,6 +976,8 @@
Get(dInsn->vB);
NextCallInsn nextCallInsn;
+ // Explicit register usage
+ oatLockCallTemps(cUnit);
if (FORCE_SLOW || method == NULL) {
// Slow path
nextCallInsn = nextVCallInsnSP;
diff --git a/src/compiler_test.cc b/src/compiler_test.cc
index acfd5e5..a1aadc8 100644
--- a/src/compiler_test.cc
+++ b/src/compiler_test.cc
@@ -270,6 +270,26 @@
111);
}
+TEST_F(CompilerTest, InvokeTest) {
+ CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
+ const ClassLoader* class_loader = LoadDex("Invoke");
+ CompileDirectMethod(class_loader, "Invoke", "<init>", "()V");
+ CompileVirtualMethod(class_loader, "Invoke", "virI_I", "(I)I");
+ CompileVirtualMethod(class_loader, "Invoke", "virI_II", "(II)I");
+ CompileVirtualMethod(class_loader, "Invoke", "virI_III", "(III)I");
+ CompileVirtualMethod(class_loader, "Invoke", "virI_IIII", "(IIII)I");
+ CompileVirtualMethod(class_loader, "Invoke", "virI_IIIII", "(IIIII)I");
+ CompileVirtualMethod(class_loader, "Invoke", "virI_IIIIII", "(IIIIII)I");
+ CompileDirectMethod(class_loader, "Invoke", "statI_I", "(I)I");
+ CompileDirectMethod(class_loader, "Invoke", "statI_II", "(II)I");
+ CompileDirectMethod(class_loader, "Invoke", "statI_III", "(III)I");
+ CompileDirectMethod(class_loader, "Invoke", "statI_IIII", "(IIII)I");
+ CompileDirectMethod(class_loader, "Invoke", "statI_IIIII", "(IIIII)I");
+ CompileDirectMethod(class_loader, "Invoke", "statI_IIIIII", "(IIIIII)I");
+ AssertStaticIntMethod(class_loader, "Invoke", "test0", "(I)I", 20664,
+ 912);
+}
+
TEST_F(CompilerTest, SystemMethodsTest) {
CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
diff --git a/test/Invoke/Invoke.java b/test/Invoke/Invoke.java
new file mode 100644
index 0000000..8bb03d3
--- /dev/null
+++ b/test/Invoke/Invoke.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Invoke {
+
+ int virI_I(int a) {
+ return a + 123;
+ }
+
+ int virI_II(int a, int b) {
+ return a + b + 321;
+ }
+
+ int virI_III(int a, int b, int c) {
+ return a + b + c + 432;
+ }
+
+ int virI_IIII(int a, int b, int c, int d) {
+ return a + b + c + d + 919;
+ }
+
+ int virI_IIIII(int a, int b, int c, int d, int e) {
+ return a + b + c + d + e + 1010;
+ }
+
+ int virI_IIIIII(int a, int b, int c, int d, int e, int f) {
+ return a + b + c + d + e + f + 2020;
+ }
+
+ static int statI_I(int a) {
+ return a + 123;
+ }
+
+ static int statI_II(int a, int b) {
+ return a + b + 321;
+ }
+
+ static int statI_III(int a, int b, int c) {
+ return a + b + c + 432;
+ }
+
+ static int statI_IIII(int a, int b, int c, int d) {
+ return a + b + c + d + 919;
+ }
+
+ static int statI_IIIII(int a, int b, int c, int d, int e) {
+ return a + b + c + d + e + 1010;
+ }
+
+ static int statI_IIIIII(int a, int b, int c, int d, int e, int f) {
+ return a + b + c + d + e + f + 2020;
+ }
+
+ static int test0(int a) {
+ Invoke foo = new Invoke();
+
+ return foo.virI_I(a) +
+ foo.virI_II(a, 1) +
+ foo.virI_III(a, 1, 2) +
+ foo.virI_IIII(a, 1, 2, 3) +
+ foo.virI_IIIII(a, 1, 2, 3, 4) +
+ foo.virI_IIIIII(a, 1, 2, 3, 4, 5) +
+ statI_I(a) +
+ statI_II(a, 1) +
+ statI_III(a, 1, 2) +
+ statI_IIII(a, 1, 2, 3) +
+ statI_IIIII(a, 1, 2, 3, 4) +
+ statI_IIIIII(a, 1, 2, 3, 4, 5);
+ }
+
+ public static void main(String[] args) {
+ int res = test0(912);
+ if (res == 20664) {
+ System.out.println("test0 PASSED");
+ } else {
+ System.out.println("test0 FAILED: " + res);
+ }
+ }
+}