Include move-parameter instructions for the 'this' parameter if it exists.
diff --git a/src/main/java/com/google/dexmaker/Code.java b/src/main/java/com/google/dexmaker/Code.java
index 99a1cd4..c393625 100644
--- a/src/main/java/com/google/dexmaker/Code.java
+++ b/src/main/java/com/google/dexmaker/Code.java
@@ -61,6 +61,11 @@
private boolean localsInitialized;
private final Local<?> thisLocal;
+
+ /**
+ * The parameters on this method. If this is non-static, the first parameter
+ * is 'thisLocal' and we have to offset the user's indices by one.
+ */
private final List<Local<?>> parameters = new ArrayList<Local<?>>();
private final List<Local<?>> locals = new ArrayList<Local<?>>();
private SourcePosition sourcePosition = SourcePosition.NO_INFO;
@@ -70,9 +75,12 @@
Code(DexGenerator.MethodDeclaration methodDeclaration) {
this.method = methodDeclaration.method;
- this.thisLocal = methodDeclaration.isStatic()
- ? null
- : Local.get(this, method.declaringType);
+ if (methodDeclaration.isStatic()) {
+ thisLocal = null;
+ } else {
+ thisLocal = Local.get(this, method.declaringType);
+ parameters.add(thisLocal);
+ }
for (Type<?> parameter : method.parameters.types) {
parameters.add(Local.get(this, parameter));
}
@@ -90,6 +98,9 @@
}
public <T> Local<T> getParameter(int index, Type<T> type) {
+ if (thisLocal != null) {
+ index++; // adjust for the hidden 'this' parameter
+ }
return coerce(parameters.get(index), type);
}
@@ -130,11 +141,7 @@
for (Local<?> local : locals) {
reg += local.initialize(reg);
}
- if (thisLocal != null) {
- reg += thisLocal.initialize(reg);
- }
int firstParamReg = reg;
-
List<Insn> moveParameterInstructions = new ArrayList<Insn>();
for (Local<?> local : parameters) {
CstInteger paramConstant = CstInteger.make(reg - firstParamReg);
@@ -145,6 +152,10 @@
labels.get(0).instructions.addAll(0, moveParameterInstructions);
}
+ /**
+ * Returns the number of registers to hold the parameters. This includes the
+ * 'this' parameter if it exists.
+ */
int paramSize() {
int result = 0;
for (Local<?> local : parameters) {
diff --git a/src/main/java/com/google/dexmaker/Local.java b/src/main/java/com/google/dexmaker/Local.java
index 696f884..05f5a25 100644
--- a/src/main/java/com/google/dexmaker/Local.java
+++ b/src/main/java/com/google/dexmaker/Local.java
@@ -41,12 +41,15 @@
*
* @return the number of registers required.
*/
- int initialize(int reg) {
- this.reg = reg;
- this.spec = RegisterSpec.make(reg, type.ropType);
+ int initialize(int nextAvailableRegister) {
+ this.reg = nextAvailableRegister;
+ this.spec = RegisterSpec.make(nextAvailableRegister, type.ropType);
return size();
}
+ /**
+ * Returns the number of registered required to hold this local.
+ */
int size() {
return type.ropType.getCategory();
}
diff --git a/src/test/java/com/google/dexmaker/DexGeneratorTest.java b/src/test/java/com/google/dexmaker/DexGeneratorTest.java
index 8483e78..4befab5 100644
--- a/src/test/java/com/google/dexmaker/DexGeneratorTest.java
+++ b/src/test/java/com/google/dexmaker/DexGeneratorTest.java
@@ -108,7 +108,7 @@
addDefaultConstructor();
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Object instance = generatedClass.newInstance();
Method method = generatedClass.getMethod("call");
method.invoke(instance);
@@ -148,7 +148,7 @@
addDefaultConstructor();
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Object instance = generatedClass.newInstance();
Method method = generatedClass.getMethod("call", int.class);
method.invoke(instance, 0);
@@ -213,7 +213,7 @@
addDefaultConstructor();
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Object instance = generatedClass.newInstance();
Method method = generatedClass.getMethod("call", generatedClass);
assertEquals(5, method.invoke(null, instance));
@@ -246,17 +246,12 @@
addDefaultConstructor();
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Object instance = generatedClass.newInstance();
Method method = generatedClass.getMethod("superHashCode");
assertEquals(System.identityHashCode(instance), method.invoke(instance));
}
- @SuppressWarnings("unused") // called by generated code
- public int superMethod(int a) {
- return a + 4;
- }
-
public void testInvokeInterface() throws Exception {
/*
* public static Object call(Callable c) {
@@ -344,7 +339,7 @@
*/
generator.declare(GENERATED.getField(Type.INT, "a"), PUBLIC | STATIC, 3);
generator.declare(GENERATED.getField(Type.OBJECT, "b"), PROTECTED | STATIC, null);
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Field a = generatedClass.getField("a");
assertEquals(int.class, a.getType());
@@ -368,7 +363,7 @@
addDefaultConstructor();
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Object instance = generatedClass.newInstance();
Field a = generatedClass.getField("a");
@@ -405,7 +400,7 @@
code.iput(fieldId, thisRef, parameter);
code.returnVoid();
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Field a = generatedClass.getField("a");
Object instance = generatedClass.getConstructor(int.class).newInstance(0xabcd);
assertEquals(0xabcd, a.get(instance));
@@ -443,7 +438,7 @@
code.returnVoid();
}
- Class<?> generatedClass = loadAndGenerate();
+ Class<?> generatedClass = generateAndLoad();
Method method = generatedClass.getMethod("call");
assertEquals(javaType, method.getReturnType());
assertEquals(value, method.invoke(null));
@@ -1650,7 +1645,7 @@
* Returns the generated method.
*/
private Method getMethod() throws Exception {
- Class<?> generated = loadAndGenerate();
+ Class<?> generated = generateAndLoad();
for (Method method : generated.getMethods()) {
if (method.getName().equals("call")) {
return method;
@@ -1666,7 +1661,7 @@
return (File) dataDirectory;
}
- private Class<?> loadAndGenerate() throws Exception {
+ private Class<?> generateAndLoad() throws Exception {
return generator.load(getClass().getClassLoader(),
getDataDirectory(), getDataDirectory()).loadClass("Generated");
}