Merge "Always pass the is-interface bit when building invoke instructions."
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
index 3eda1b7..a84b916 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvoke.java
@@ -45,6 +45,10 @@
return opcode;
}
+ public boolean isInterface() {
+ return itf;
+ }
+
@Override
public void write(MethodVisitor visitor, NamingLens lens) {
String owner = lens.lookupInternalName(method.getHolder());
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index d45fd83..f956b53 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -638,14 +638,15 @@
return builder.build();
}
- public DexEncodedMethod toForwardingMethod(DexClass holder, DexItemFactory itemFactory) {
+ public DexEncodedMethod toForwardingMethod(DexClass holder, AppInfo appInfo) {
checkIfObsolete();
// Clear the final flag, as this method is now overwritten. Do this before creating the builder
// for the forwarding method, as the forwarding method will copy the access flags from this,
// and if different forwarding methods are created in different subclasses the first could be
// final.
accessFlags.demoteFromFinal();
- DexMethod newMethod = itemFactory.createMethod(holder.type, method.proto, method.name);
+ DexMethod newMethod =
+ appInfo.dexItemFactory.createMethod(holder.type, method.proto, method.name);
Invoke.Type type = accessFlags.isStatic() ? Invoke.Type.STATIC : Invoke.Type.SUPER;
Builder builder = builder(this);
builder.setMethod(newMethod);
@@ -655,6 +656,7 @@
builder.accessFlags.setAbstract();
} else {
// Create code that forwards the call to the target.
+ DexClass target = appInfo.definitionFor(method.holder);
builder.setCode(
new SynthesizedCode(
callerPosition ->
@@ -665,7 +667,8 @@
accessFlags.isStatic() ? null : method.holder,
method,
type,
- callerPosition),
+ callerPosition,
+ target.isInterface()),
registry -> {
if (accessFlags.isStatic()) {
registry.registerInvokeStatic(method);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 8a46e1e..743f2a5 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -13,6 +13,7 @@
import com.android.tools.r8.cf.code.CfFrame;
import com.android.tools.r8.cf.code.CfFrame.FrameType;
import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.cf.code.CfTryCatch;
@@ -21,6 +22,7 @@
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCode.LocalVariableInfo;
import com.android.tools.r8.graph.DebugLocalInfo;
+import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
@@ -179,9 +181,23 @@
CodeRewriter.collapseTrivialGotos(method, code);
DexBuilder.removeRedundantDebugPositions(code);
CfCode code = buildCfCode();
+ assert verifyInvokeInterface(code, appInfo);
return code;
}
+ private static boolean verifyInvokeInterface(CfCode code, AppInfo appInfo) {
+ for (CfInstruction instruction : code.instructions) {
+ if (instruction instanceof CfInvoke) {
+ CfInvoke invoke = (CfInvoke) instruction;
+ if (invoke.getMethod().holder.isClassType()) {
+ DexClass holder = appInfo.definitionFor(invoke.getMethod().holder);
+ assert holder == null || holder.isInterface() == invoke.isInterface();
+ }
+ }
+ }
+ return true;
+ }
+
public DexField resolveField(DexField field) {
DexEncodedField resolvedField = appInfo.resolveFieldOn(field.clazz, field);
return resolvedField == null ? field : resolvedField.field;
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 31b0ec6..3f355c1 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -1405,19 +1405,6 @@
add(Invoke.create(type, item, callSiteProto, null, arguments, itf));
}
- public void addInvoke(Type type, DexItem item, DexProto callSiteProto, List<Value> arguments) {
- addInvoke(type, item, callSiteProto, arguments, false);
- }
-
- public void addInvoke(
- Type type,
- DexItem item,
- DexProto callSiteProto,
- List<ValueType> types,
- List<Integer> registers) {
- addInvoke(type, item, callSiteProto, types, registers, false);
- }
-
public void addInvoke(
Type type,
DexItem item,
@@ -1518,7 +1505,9 @@
registerIndex += constraint.requiredRegisters();
}
checkInvokeArgumentRegisters(registerIndex, argumentRegisterCount);
- addInvoke(type, method, callSiteProto, arguments);
+ // Note: We only call this register variant from DEX inputs where isInterface does not matter.
+ assert !isGeneratingClassFiles();
+ addInvoke(type, method, callSiteProto, arguments, false /* isInterface */);
}
public void addInvokeNewArray(DexType type, int argumentCount, int[] argumentRegisters) {
@@ -1538,7 +1527,7 @@
registerIndex += constraint.requiredRegisters();
}
checkInvokeArgumentRegisters(registerIndex, argumentCount);
- addInvoke(Invoke.Type.NEW_ARRAY, type, null, arguments);
+ addInvoke(Invoke.Type.NEW_ARRAY, type, null, arguments, false /* isInterface */);
}
public void addMultiNewArray(DexType type, int dest, int[] dimensions) {
@@ -1547,7 +1536,7 @@
for (int dimension : dimensions) {
arguments.add(readRegister(dimension, ValueTypeConstraint.INT));
}
- addInvoke(Invoke.Type.MULTI_NEW_ARRAY, type, null, arguments);
+ addInvoke(Invoke.Type.MULTI_NEW_ARRAY, type, null, arguments, false /* isInterface */);
addMoveResult(dest);
}
@@ -1581,7 +1570,9 @@
register += valueTypeConstraint.requiredRegisters();
}
checkInvokeArgumentRegisters(register, firstArgumentRegister + argumentCount);
- addInvoke(type, method, callSiteProto, arguments);
+ // Note: We only call this register variant from DEX inputs where isInterface does not matter.
+ assert !isGeneratingClassFiles();
+ addInvoke(type, method, callSiteProto, arguments, false /* isInterface */);
}
public void addInvokeRangeNewArray(DexType type, int argumentCount, int firstArgumentRegister) {
@@ -1597,7 +1588,9 @@
register += constraint.requiredRegisters();
}
checkInvokeArgumentRegisters(register, firstArgumentRegister + argumentCount);
- addInvoke(Invoke.Type.NEW_ARRAY, type, null, arguments);
+ // Note: We only call this register variant from DEX inputs where isInterface does not matter.
+ assert !isGeneratingClassFiles();
+ addInvoke(Invoke.Type.NEW_ARRAY, type, null, arguments, false /* isInterface */);
}
private void checkInvokeArgumentRegisters(int expected, int actual) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 1387f75..93e5355 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -2864,7 +2864,13 @@
List<ValueType> argumentTypes = Arrays.asList(valueType(CLASS_TYPE), valueType(INT_ARRAY_TYPE));
List<Integer> argumentRegisters = Arrays.asList(classDestTemp, dimensionsDestTemp);
builder.ensureBlockForThrowingInstruction();
- builder.addInvoke(Invoke.Type.STATIC, newInstance, null, argumentTypes, argumentRegisters);
+ builder.addInvoke(
+ Invoke.Type.STATIC,
+ newInstance,
+ null,
+ argumentTypes,
+ argumentRegisters,
+ false /* isInterface */);
// Pop the temporaries and push the final result.
state.pop(); // classDestTemp.
state.pop(); // dimensionsDestTemp.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
index 3554806..81f93a7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/AccessorMethodSourceCode.java
@@ -109,8 +109,17 @@
}
// Method call to the original impl-method.
- add(builder -> builder.addInvoke(inferInvokeType(),
- implMethod, implMethod.proto, argValueTypes, argRegisters));
+ // Mirroring assert in constructor, we never need accessors to interfaces.
+ assert !descriptor().implHandle.type.isInvokeInterface();
+ add(
+ builder ->
+ builder.addInvoke(
+ inferInvokeType(),
+ implMethod,
+ implMethod.proto,
+ argValueTypes,
+ argRegisters,
+ false /* isInterface */));
// Does the method have return value?
if (proto.returnType == factory().voidType) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
index d2a233b..bff3ca1 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/ClassProcessor.java
@@ -100,10 +100,10 @@
private DexEncodedMethod addForwardingMethod(DexEncodedMethod defaultMethod, DexClass clazz) {
DexMethod method = defaultMethod.method;
+ DexClass target = rewriter.findDefinitionFor(method.holder);
// NOTE: Never add a forwarding method to methods of classes unknown or coming from android.jar
// even if this results in invalid code, these classes are never desugared.
- assert rewriter.findDefinitionFor(method.holder) != null
- && !rewriter.findDefinitionFor(method.holder).isLibraryClass();
+ assert target != null && !target.isLibraryClass();
// New method will have the same name, proto, and also all the flags of the
// default method, including bridge flag.
DexMethod newMethod = rewriter.factory.createMethod(clazz.type, method.proto, method.name);
@@ -124,7 +124,8 @@
null /* static method */,
rewriter.defaultAsMethodOfCompanionClass(method),
Invoke.Type.STATIC,
- callerPosition)));
+ callerPosition,
+ target.isInterface())));
}
// For a given class `clazz` inspects all interfaces it implements directly or
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
index 955abf0..466dc83 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/CovariantReturnTypeAnnotationTransformer.java
@@ -175,7 +175,8 @@
method.method,
Invoke.Type.VIRTUAL,
callerPosition,
- true)));
+ false /* isInterface */,
+ true /* castResult */)));
// Optimize to generate DexCode instead of SynthesizedCode.
converter.optimizeSynthesizedMethod(newVirtualMethod);
return newVirtualMethod;
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
index 01b647b..fd875af 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/InterfaceProcessor.java
@@ -252,7 +252,8 @@
null,
origMethod,
Type.STATIC,
- callerPosition)));
+ callerPosition,
+ true /* isInterface */)));
newEncodedMethod.getMutableOptimizationInfo().markNeverInline();
dispatchMethods.add(newEncodedMethod);
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaBridgeMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaBridgeMethodSourceCode.java
index 7e5cd81..9507471 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaBridgeMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaBridgeMethodSourceCode.java
@@ -46,8 +46,15 @@
}
// Method call to the main functional interface method.
- add(builder -> builder.addInvoke(Invoke.Type.VIRTUAL,
- this.mainMethod, this.mainMethod.proto, argValueTypes, argRegisters));
+ add(
+ builder ->
+ builder.addInvoke(
+ Invoke.Type.VIRTUAL,
+ this.mainMethod,
+ this.mainMethod.proto,
+ argValueTypes,
+ argRegisters,
+ false /* isInterface */));
// Does the method have return value?
if (proto.returnType == factory().voidType) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClassConstructorSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClassConstructorSourceCode.java
index 2aa4630..cec70bb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaClassConstructorSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaClassConstructorSourceCode.java
@@ -24,12 +24,15 @@
// Create and initialize an instance.
int instance = nextRegister(ValueType.OBJECT);
add(builder -> builder.addNewInstance(instance, lambda.type));
- add(builder -> builder.addInvoke(
- Invoke.Type.DIRECT,
- lambda.constructor,
- lambda.constructor.proto,
- ImmutableList.of(ValueType.OBJECT),
- ImmutableList.of(instance)));
+ add(
+ builder ->
+ builder.addInvoke(
+ Invoke.Type.DIRECT,
+ lambda.constructor,
+ lambda.constructor.proto,
+ ImmutableList.of(ValueType.OBJECT),
+ ImmutableList.of(instance),
+ false /* isInterface */));
// Assign to a field.
add(builder -> builder.addStaticPut(instance, lambda.instanceField));
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java
index 7f2acc3..b2b9486 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaConstructorSourceCode.java
@@ -23,8 +23,14 @@
protected void prepareInstructions() {
// Super constructor call (always java.lang.Object.<init>()).
DexMethod objectInitMethod = lambda.rewriter.objectInitMethod;
- add(builder -> builder.addInvoke(Invoke.Type.DIRECT, objectInitMethod,
- objectInitMethod.proto, Collections.singletonList(getReceiverValue())));
+ add(
+ builder ->
+ builder.addInvoke(
+ Invoke.Type.DIRECT,
+ objectInitMethod,
+ objectInitMethod.proto,
+ Collections.singletonList(getReceiverValue()),
+ false /* isInterface */));
// Assign capture fields.
DexType[] capturedTypes = captures();
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java
index fb06f31..99112d7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaMainMethodSourceCode.java
@@ -224,8 +224,15 @@
}
// Method call to the method implementing lambda or method-ref.
- add(builder -> builder.addInvoke(target.invokeType,
- methodToCall, methodToCall.proto, argValueTypes, argRegisters));
+ add(
+ builder ->
+ builder.addInvoke(
+ target.invokeType,
+ methodToCall,
+ methodToCall.proto,
+ argValueTypes,
+ argRegisters,
+ false /* isInterface */));
// Does the method have return value?
if (enforcedReturnType.isVoidType()) {
@@ -446,8 +453,15 @@
List<ValueType> argValueTypes = ImmutableList.of(ValueType.OBJECT);
List<Integer> argRegisters = Collections.singletonList(register);
- add(builder -> builder.addInvoke(Invoke.Type.VIRTUAL,
- method, method.proto, argValueTypes, argRegisters));
+ add(
+ builder ->
+ builder.addInvoke(
+ Invoke.Type.VIRTUAL,
+ method,
+ method.proto,
+ argValueTypes,
+ argRegisters,
+ false /* isInterface */));
ValueType valueType = ValueType.fromDexType(primitiveType);
int result = nextRegister(valueType);
@@ -469,8 +483,15 @@
ValueType valueType = ValueType.fromDexType(primitiveType);
List<ValueType> argValueTypes = ImmutableList.of(valueType);
List<Integer> argRegisters = Collections.singletonList(register);
- add(builder -> builder.addInvoke(Invoke.Type.STATIC,
- method, method.proto, argValueTypes, argRegisters));
+ add(
+ builder ->
+ builder.addInvoke(
+ Invoke.Type.STATIC,
+ method,
+ method.proto,
+ argValueTypes,
+ argRegisters,
+ false /* isInterface */));
int result = nextRegister(ValueType.OBJECT);
add(builder -> builder.addMoveResult(result));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java
index 5177e4a..c6aecbb 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/ClassInitializerSourceCode.java
@@ -41,18 +41,27 @@
List<ValueType> argTypes = Lists.newArrayList(ValueType.OBJECT, ValueType.INT);
List<Integer> argRegisters = Lists.newArrayList(instance, lambdaId);
- group.forEachLambda(info -> {
- DexType lambda = info.clazz.type;
- if (group.isSingletonLambda(lambda)) {
- int id = group.lambdaId(lambda);
- add(builder -> builder.addNewInstance(instance, groupClassType));
- add(builder -> builder.addConst(TypeLatticeElement.INT, lambdaId, id));
- add(builder -> builder.addInvoke(Type.DIRECT,
- lambdaConstructorMethod, lambdaConstructorMethod.proto, argTypes, argRegisters));
- add(builder -> builder.addStaticPut(
- instance, group.getSingletonInstanceField(factory, id)));
- }
- });
+ group.forEachLambda(
+ info -> {
+ DexType lambda = info.clazz.type;
+ if (group.isSingletonLambda(lambda)) {
+ int id = group.lambdaId(lambda);
+ add(builder -> builder.addNewInstance(instance, groupClassType));
+ add(builder -> builder.addConst(TypeLatticeElement.INT, lambdaId, id));
+ add(
+ builder ->
+ builder.addInvoke(
+ Type.DIRECT,
+ lambdaConstructorMethod,
+ lambdaConstructorMethod.proto,
+ argTypes,
+ argRegisters,
+ false /* isInterface*/));
+ add(
+ builder ->
+ builder.addStaticPut(instance, group.getSingletonInstanceField(factory, id)));
+ }
+ });
assert this.nextInstructionIndex() > 0 : "no single field initialized";
add(IRBuilder::addReturn);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
index e8fcd40..2bdc441 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/JStyleLambdaGroup.java
@@ -215,8 +215,15 @@
@Override
void prepareSuperConstructorCall(int receiverRegister) {
- add(builder -> builder.addInvoke(Type.DIRECT, objectInitializer, objectInitializer.proto,
- Lists.newArrayList(ValueType.OBJECT), Lists.newArrayList(receiverRegister)));
+ add(
+ builder ->
+ builder.addInvoke(
+ Type.DIRECT,
+ objectInitializer,
+ objectInitializer.proto,
+ Lists.newArrayList(ValueType.OBJECT),
+ Lists.newArrayList(receiverRegister),
+ false /* isInterface */));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
index f677b46..ee0b800 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KStyleLambdaGroup.java
@@ -233,9 +233,15 @@
void prepareSuperConstructorCall(int receiverRegister) {
int arityRegister = nextRegister(ValueType.INT);
add(builder -> builder.addConst(TypeLatticeElement.INT, arityRegister, arity));
- add(builder -> builder.addInvoke(Type.DIRECT, lambdaInitializer, lambdaInitializer.proto,
- Lists.newArrayList(ValueType.OBJECT, ValueType.INT),
- Lists.newArrayList(receiverRegister, arityRegister)));
+ add(
+ builder ->
+ builder.addInvoke(
+ Type.DIRECT,
+ lambdaInitializer,
+ lambdaInitializer.proto,
+ Lists.newArrayList(ValueType.OBJECT, ValueType.INT),
+ Lists.newArrayList(receiverRegister, arityRegister),
+ false /* isInterface */));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaVirtualMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaVirtualMethodSourceCode.java
index 82acf49..bcd0a75 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaVirtualMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/lambda/kotlin/KotlinLambdaVirtualMethodSourceCode.java
@@ -85,16 +85,18 @@
offsets[i] = nextInstructionIndex();
// Emit fake call on `this` receiver.
- add(builder -> {
- if (arguments.isEmpty()) {
- // Late initialization of argument list.
- arguments.add(getReceiverValue());
- for (int index = 0; index < paramCount; index++) {
- arguments.add(getParamValue(index));
- }
- }
- builder.addInvoke(Type.VIRTUAL, impl.method, impl.method.proto, arguments);
- });
+ add(
+ builder -> {
+ if (arguments.isEmpty()) {
+ // Late initialization of argument list.
+ arguments.add(getReceiverValue());
+ for (int index = 0; index < paramCount; index++) {
+ arguments.add(getParamValue(index));
+ }
+ }
+ builder.addInvoke(
+ Type.VIRTUAL, impl.method, impl.method.proto, arguments, false /* isInterface */);
+ });
// Handle return value if needed.
if (returnsValue) {
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java b/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java
index 37341fb..76dba16 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodSourceCode.java
@@ -23,6 +23,7 @@
private final DexMethod target;
private final Invoke.Type invokeType;
private final boolean castResult;
+ private final boolean isInterface;
public ForwardMethodSourceCode(
DexType receiver,
@@ -31,7 +32,8 @@
DexType targetReceiver,
DexMethod target,
Type invokeType,
- Position callerPosition) {
+ Position callerPosition,
+ boolean isInterface) {
this(
receiver,
method,
@@ -40,6 +42,7 @@
target,
invokeType,
callerPosition,
+ isInterface,
false);
}
@@ -51,6 +54,7 @@
DexMethod target,
Type invokeType,
Position callerPosition,
+ boolean isInterface,
boolean castResult) {
super(receiver, method, callerPosition, originalMethod);
assert (targetReceiver == null) == (invokeType == Invoke.Type.STATIC);
@@ -58,6 +62,7 @@
this.target = target;
this.targetReceiver = targetReceiver;
this.invokeType = invokeType;
+ this.isInterface = isInterface;
this.castResult = castResult;
assert checkSignatures();
@@ -119,8 +124,15 @@
}
// Method call to the target method.
- add(builder -> builder.addInvoke(this.invokeType,
- this.target, this.target.proto, argValueTypes, argRegisters));
+ add(
+ builder ->
+ builder.addInvoke(
+ this.invokeType,
+ this.target,
+ this.target.proto,
+ argValueTypes,
+ argRegisters,
+ this.isInterface));
// Does the method return value?
if (proto.returnType.isVoidType()) {
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index 608f915..3ff88b9 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -191,7 +191,7 @@
findHolderForInterfaceMethodBridge(originalClass, targetClass.type);
assert bridgeHolder != null;
assert bridgeHolder != targetClass;
- DexEncodedMethod bridgeMethod = target.toForwardingMethod(bridgeHolder, appInfo.dexItemFactory);
+ DexEncodedMethod bridgeMethod = target.toForwardingMethod(bridgeHolder, appInfo);
bridgeHolder.addMethod(bridgeMethod);
assert lookupTarget.apply(method) == bridgeMethod;
return bridgeMethod;
@@ -242,8 +242,7 @@
DexProgramClass bridgeHolder =
findHolderForVisibilityBridge(originalClass, targetClass, packageDescriptor);
assert bridgeHolder != null;
- DexEncodedMethod bridgeMethod =
- target.toForwardingMethod(bridgeHolder, appInfo.dexItemFactory);
+ DexEncodedMethod bridgeMethod = target.toForwardingMethod(bridgeHolder, appInfo);
bridgeHolder.addMethod(bridgeMethod);
assert lookupTarget.apply(method) == bridgeMethod;
return bridgeMethod;
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index fe10045..03be595 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1191,7 +1191,8 @@
newMethod,
graphLense.getOriginalMethodSignature(method.method),
invocationTarget.method,
- invocationTarget.isPrivateMethod() ? DIRECT : STATIC);
+ invocationTarget.isPrivateMethod() ? DIRECT : STATIC,
+ target.isInterface());
// Add the bridge to the list of synthesized bridges such that the method signatures will
// be updated by the end of vertical class merging.
@@ -1873,13 +1874,19 @@
private DexMethod originalMethod;
private DexMethod invocationTarget;
private Type type;
+ private final boolean isInterface;
public SynthesizedBridgeCode(
- DexMethod method, DexMethod originalMethod, DexMethod invocationTarget, Type type) {
+ DexMethod method,
+ DexMethod originalMethod,
+ DexMethod invocationTarget,
+ Type type,
+ boolean isInterface) {
this.method = method;
this.originalMethod = originalMethod;
this.invocationTarget = invocationTarget;
this.type = type;
+ this.isInterface = isInterface;
}
// By the time the synthesized code object is created, vertical class merging still has not
@@ -1908,7 +1915,8 @@
type == DIRECT ? method.holder : null,
invocationTarget,
type,
- callerPosition);
+ callerPosition,
+ isInterface);
}
@Override