Extend the lens lookup API for methods to pass the rebound reference
Bug: 168282032
Change-Id: I96ba24c8703100f712b3e1d423a310a23851f8d3
diff --git a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
index f37ce58..ae54120 100644
--- a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
@@ -6,7 +6,6 @@
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
-import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.utils.MapUtils;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneMap;
import com.google.common.collect.BiMap;
@@ -138,26 +137,32 @@
}
@Override
- public DexType internalDescribeLookupClassType(DexType previous) {
- return renamedTypeNames.getOrDefault(previous, previous);
- }
-
- @Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Invoke.Type type) {
- return GraphLens.getIdentityLens().lookupMethod(method, context, type);
- }
-
- @Override
public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(DexMethod method) {
return GraphLens.getIdentityLens().lookupPrototypeChangesForMethodDefinition(method);
}
@Override
+ public DexType internalDescribeLookupClassType(DexType previous) {
+ return renamedTypeNames.getOrDefault(previous, previous);
+ }
+
+ @Override
protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
return previous;
}
@Override
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ return previous;
+ }
+
+ @Override
+ protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+ return method;
+ }
+
+ @Override
public boolean isContextFreeForMethods() {
return true;
}
diff --git a/src/main/java/com/android/tools/r8/graph/GraphLens.java b/src/main/java/com/android/tools/r8/graph/GraphLens.java
index 5f49c95..361ef09 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.horizontalclassmerging.ClassMerger;
import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.desugar.InterfaceProcessor.InterfaceProcessorNestedGraphLens;
@@ -42,25 +43,21 @@
*/
public abstract class GraphLens {
- /**
- * Intermediate result of a field lookup that stores the actual non-rebound reference and the
- * rebound reference that points to the definition of the field.
- */
- public static class FieldLookupResult {
+ abstract static class MemberLookupResult<R extends DexMember<?, R>> {
- private final DexField reference;
- private final DexField reboundReference;
+ private final R reference;
+ private final R reboundReference;
- private FieldLookupResult(DexField reference, DexField reboundReference) {
+ private MemberLookupResult(R reference, R reboundReference) {
this.reference = reference;
this.reboundReference = reboundReference;
}
- public DexField getReference() {
+ public R getReference() {
return reference;
}
- public DexField getRewrittenReference(Map<DexField, DexField> rewritings) {
+ public R getRewrittenReference(Map<R, R> rewritings) {
return rewritings.getOrDefault(reference, reference);
}
@@ -68,35 +65,57 @@
return reboundReference != null;
}
- public DexField getReboundReference() {
+ public R getReboundReference() {
return reboundReference;
}
- public DexField getRewrittenReboundReference(Map<DexField, DexField> rewritings) {
+ public R getRewrittenReboundReference(Map<R, R> rewritings) {
return rewritings.getOrDefault(reboundReference, reboundReference);
}
+ abstract static class Builder<R extends DexMember<?, R>, Self extends Builder<R, Self>> {
+
+ R reference;
+ R reboundReference;
+
+ public Self setReference(R reference) {
+ this.reference = reference;
+ return self();
+ }
+
+ public Self setReboundReference(R reboundReference) {
+ this.reboundReference = reboundReference;
+ return self();
+ }
+
+ public abstract Self self();
+ }
+ }
+
+ /**
+ * Intermediate result of a field lookup that stores the actual non-rebound reference and the
+ * rebound reference that points to the definition of the field.
+ */
+ public static class FieldLookupResult extends MemberLookupResult<DexField> {
+
+ private FieldLookupResult(DexField reference, DexField reboundReference) {
+ super(reference, reboundReference);
+ }
+
public static Builder builder(GraphLens lens) {
return new Builder(lens);
}
- public static class Builder {
+ public static class Builder extends MemberLookupResult.Builder<DexField, Builder> {
private GraphLens lens;
- private DexField reference;
- private DexField reboundReference;
private Builder(GraphLens lens) {
this.lens = lens;
}
- public Builder setReference(DexField reference) {
- this.reference = reference;
- return this;
- }
-
- public Builder setReboundReference(DexField reboundReference) {
- this.reboundReference = reboundReference;
+ @Override
+ public Builder self() {
return this;
}
@@ -114,21 +133,23 @@
* prototype changes that have been made to the target method and the corresponding required
* changes to the invoke arguments.
*/
- public static class MethodLookupResult {
+ public static class MethodLookupResult extends MemberLookupResult<DexMethod> {
- private final DexMethod method;
private final Type type;
private final RewrittenPrototypeDescription prototypeChanges;
public MethodLookupResult(
- DexMethod method, Type type, RewrittenPrototypeDescription prototypeChanges) {
- this.method = method;
+ DexMethod reference,
+ DexMethod reboundReference,
+ Type type,
+ RewrittenPrototypeDescription prototypeChanges) {
+ super(reference, reboundReference);
this.type = type;
this.prototypeChanges = prototypeChanges;
}
- public DexMethod getReference() {
- return method;
+ public static Builder builder(GraphLens lens) {
+ return new Builder(lens);
}
public Type getType() {
@@ -138,6 +159,38 @@
public RewrittenPrototypeDescription getPrototypeChanges() {
return prototypeChanges;
}
+
+ public static class Builder extends MemberLookupResult.Builder<DexMethod, Builder> {
+
+ private final GraphLens lens;
+ private RewrittenPrototypeDescription prototypeChanges = RewrittenPrototypeDescription.none();
+ private Type type;
+
+ private Builder(GraphLens lens) {
+ this.lens = lens;
+ }
+
+ public Builder setPrototypeChanges(RewrittenPrototypeDescription prototypeChanges) {
+ this.prototypeChanges = prototypeChanges;
+ return this;
+ }
+
+ public Builder setType(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ public MethodLookupResult build() {
+ assert reference != null;
+ // TODO(b/168282032): All non-identity graph lenses should set the rebound reference.
+ return new MethodLookupResult(reference, reboundReference, type, prototypeChanges);
+ }
+
+ @Override
+ public Builder self() {
+ return this;
+ }
+ }
}
public static class Builder {
@@ -268,12 +321,23 @@
public abstract DexType lookupType(DexType type);
// This overload can be used when the graph lens is known to be context insensitive.
- public DexMethod lookupMethod(DexMethod method) {
+ public final DexMethod lookupMethod(DexMethod method) {
assert verifyIsContextFreeForMethod(method);
return lookupMethod(method, null, null).getReference();
}
- public abstract MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type);
+ /** Lookup a rebound or non-rebound method reference using the current graph lens. */
+ public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
+ return internalLookupMethod(method, context, type, result -> result);
+ }
+
+ protected abstract MethodLookupResult internalLookupMethod(
+ DexMethod reference, DexMethod context, Type type, LookupMethodContinuation continuation);
+
+ interface LookupMethodContinuation {
+
+ MethodLookupResult lookupMethod(MethodLookupResult previous);
+ }
public abstract RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
DexMethod method);
@@ -562,16 +626,31 @@
}
@Override
- protected final DexField internalLookupField(
+ protected DexField internalLookupField(
DexField reference, LookupFieldContinuation continuation) {
return previousLens.internalLookupField(
reference, previous -> continuation.lookupField(internalDescribeLookupField(previous)));
}
+ @Override
+ protected MethodLookupResult internalLookupMethod(
+ DexMethod reference, DexMethod context, Type type, LookupMethodContinuation continuation) {
+ return previousLens.internalLookupMethod(
+ reference,
+ internalGetPreviousMethodSignature(context),
+ type,
+ previous -> continuation.lookupMethod(internalDescribeLookupMethod(previous, context)));
+ }
+
protected abstract FieldLookupResult internalDescribeLookupField(FieldLookupResult previous);
+ protected abstract MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context);
+
protected abstract DexType internalDescribeLookupClassType(DexType previous);
+ protected abstract DexMethod internalGetPreviousMethodSignature(DexMethod method);
+
@Override
public final boolean isIdentityLens() {
return false;
@@ -645,11 +724,6 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- return new MethodLookupResult(method, type, RewrittenPrototypeDescription.none());
- }
-
- @Override
public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
DexMethod method) {
return RewrittenPrototypeDescription.none();
@@ -665,6 +739,15 @@
}
@Override
+ protected MethodLookupResult internalLookupMethod(
+ DexMethod reference, DexMethod context, Type type, LookupMethodContinuation continuation) {
+ // Passes the method reference back to the next graph lens. The identity lens intentionally
+ // does not set the rebound method reference, since it does not know what that is.
+ return continuation.lookupMethod(
+ MethodLookupResult.builder(this).setReference(reference).setType(type).build());
+ }
+
+ @Override
public boolean isContextFreeForMethods() {
return true;
}
@@ -711,27 +794,45 @@
}
@Override
- public final DexType internalDescribeLookupClassType(DexType previous) {
- return previous;
- }
-
- @Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- return getIdentityLens().lookupMethod(method, context, type);
- }
-
- @Override
public RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
DexMethod method) {
return getIdentityLens().lookupPrototypeChangesForMethodDefinition(method);
}
@Override
- protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ public final DexType internalDescribeLookupClassType(DexType previous) {
return previous;
}
@Override
+ protected DexField internalLookupField(
+ DexField reference, LookupFieldContinuation continuation) {
+ return getIdentityLens().internalLookupField(reference, continuation);
+ }
+
+ @Override
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ throw new Unreachable();
+ }
+
+ @Override
+ protected MethodLookupResult internalLookupMethod(
+ DexMethod reference, DexMethod context, Type type, LookupMethodContinuation continuation) {
+ return getIdentityLens().internalLookupMethod(reference, context, type, continuation);
+ }
+
+ @Override
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ throw new Unreachable();
+ }
+
+ @Override
+ protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+ return method;
+ }
+
+ @Override
public boolean isContextFreeForMethods() {
return getIdentityLens().isContextFreeForMethods();
}
@@ -839,23 +940,40 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- DexMethod previousContext = internalGetPreviousMethodSignature(context);
- MethodLookupResult previousLookup = getPrevious().lookupMethod(method, previousContext, type);
- return lookupMethod(method, previousLookup);
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ if (previous.hasReboundReference()) {
+ // Rewrite the rebound reference and then "fixup" the non-rebound reference.
+ DexField rewrittenReboundReference = previous.getRewrittenReboundReference(fieldMap);
+ return FieldLookupResult.builder(this)
+ .setReboundReference(rewrittenReboundReference)
+ .setReference(
+ rewrittenReboundReference.withHolder(
+ internalDescribeLookupClassType(previous.getReference().getHolderType()),
+ dexItemFactory))
+ .build();
+ } else {
+ // TODO(b/168282032): We should always have the rebound reference, so this should become
+ // unreachable.
+ DexField rewrittenReference = previous.getRewrittenReference(fieldMap);
+ return FieldLookupResult.builder(this).setReference(rewrittenReference).build();
+ }
}
- protected MethodLookupResult lookupMethod(DexMethod method, MethodLookupResult previousLookup) {
- DexMethod newMethod = methodMap.get(previousLookup.getReference());
+ @Override
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ DexMethod newMethod = methodMap.get(previous.getReference());
if (newMethod == null) {
- return previousLookup;
+ return previous;
}
// TODO(sgjesse): Should we always do interface to virtual mapping? Is it a performance win
// that only subclasses which are known to need it actually do it?
- return new MethodLookupResult(
- newMethod,
- mapInvocationType(newMethod, method, previousLookup.getType()),
- internalDescribePrototypeChanges(previousLookup.getPrototypeChanges(), newMethod));
+ return MethodLookupResult.builder(this)
+ .setReference(newMethod)
+ .setPrototypeChanges(
+ internalDescribePrototypeChanges(previous.getPrototypeChanges(), newMethod))
+ .setType(mapInvocationType(newMethod, previous.getReference(), previous.getType()))
+ .build();
}
@Override
@@ -872,6 +990,7 @@
return prototypeChanges;
}
+ @Override
protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
return originalMethodSignatures != null
? originalMethodSignatures.getOrDefault(method, method)
@@ -927,26 +1046,6 @@
}
@Override
- protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
- if (previous.hasReboundReference()) {
- // Rewrite the rebound reference and then "fixup" the non-rebound reference.
- DexField rewrittenReboundReference = previous.getRewrittenReboundReference(fieldMap);
- return FieldLookupResult.builder(this)
- .setReboundReference(rewrittenReboundReference)
- .setReference(
- rewrittenReboundReference.withHolder(
- internalDescribeLookupClassType(previous.getReference().getHolderType()),
- dexItemFactory))
- .build();
- } else {
- // TODO(b/168282032): We should always have the rebound reference, so this should become
- // unreachable.
- DexField rewrittenReference = previous.getRewrittenReference(fieldMap);
- return FieldLookupResult.builder(this).setReference(rewrittenReference).build();
- }
- }
-
- @Override
public boolean isContextFreeForMethods() {
return getPrevious().isContextFreeForMethods();
}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
index 5cae0a2..395409f 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMergerGraphLens.java
@@ -10,8 +10,6 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
-import com.android.tools.r8.graph.RewrittenPrototypeDescription;
-import com.android.tools.r8.ir.code.Invoke.Type;
import com.android.tools.r8.ir.conversion.ExtraParameter;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
@@ -68,23 +66,18 @@
* constructor. Otherwise return the lookup on the underlying graph lens.
*/
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- DexMethod previousContext = internalGetPreviousMethodSignature(context);
- MethodLookupResult previousLookup = getPrevious().lookupMethod(method, previousContext, type);
- List<ExtraParameter> extraParameters = methodExtraParameters.get(previousLookup.getReference());
-
- MethodLookupResult lookup = super.lookupMethod(method, previousLookup);
- if (extraParameters != null) {
- DexMethod newMethod = lookup.getReference();
-
- RewrittenPrototypeDescription prototypeChanges =
- lookup.getPrototypeChanges().withExtraParameters(extraParameters);
-
- return new MethodLookupResult(
- newMethod, mapInvocationType(newMethod, method, lookup.getType()), prototypeChanges);
- } else {
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ List<ExtraParameter> extraParameters = methodExtraParameters.get(previous.getReference());
+ MethodLookupResult lookup = super.internalDescribeLookupMethod(previous, context);
+ if (extraParameters == null) {
return lookup;
}
+ return MethodLookupResult.builder(this)
+ .setReference(lookup.getReference())
+ .setPrototypeChanges(lookup.getPrototypeChanges().withExtraParameters(extraParameters))
+ .setType(lookup.getType())
+ .build();
}
public static class Builder {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index fad4980..2faa07a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -354,14 +354,20 @@
for (DexProgramClass clazz : appView.appInfo().classes()) {
EnclosingMethodAttribute enclosingMethod = clazz.getEnclosingMethodAttribute();
if (enclosingMethod != null) {
- DexMethod mappedEnclosingMethod = lens.lookupMethod(enclosingMethod.getEnclosingMethod());
- if (mappedEnclosingMethod != null
- && mappedEnclosingMethod != enclosingMethod.getEnclosingMethod()) {
- clazz.setEnclosingMethodAttribute(new EnclosingMethodAttribute(mappedEnclosingMethod));
+ if (enclosingMethod.getEnclosingMethod() != null) {
+ DexMethod mappedEnclosingMethod = lens.lookupMethod(enclosingMethod.getEnclosingMethod());
+ if (mappedEnclosingMethod != enclosingMethod.getEnclosingMethod()) {
+ clazz.setEnclosingMethodAttribute(new EnclosingMethodAttribute(mappedEnclosingMethod));
+ }
+ } else {
+ assert enclosingMethod.getEnclosingClass() != null;
+ DexType mappedEnclosingClass = lens.lookupType(enclosingMethod.getEnclosingClass());
+ if (mappedEnclosingClass != enclosingMethod.getEnclosingClass()) {
+ clazz.setEnclosingMethodAttribute(new EnclosingMethodAttribute(mappedEnclosingClass));
+ }
}
}
}
- ;
// Return lens without method map (but still retaining originalMethodSignatures), as the
// generated lambdas classes are generated with the an invoke to the new method, so no
// code rewriting is required.
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLens.java b/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLens.java
index 2dc813e..7bc5e6b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLens.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/NestedPrivateMethodLens.java
@@ -11,7 +11,7 @@
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NestedGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
-import com.android.tools.r8.ir.code.Invoke;
+import com.android.tools.r8.ir.code.Invoke.Type;
import com.google.common.collect.ImmutableMap;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -110,24 +110,28 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Invoke.Type type) {
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
assert originalMethodSignatures == null;
- MethodLookupResult lookup = getPrevious().lookupMethod(method, context, type);
- DexMethod bridge = methodMap.get(lookup.getReference());
+ DexMethod bridge = methodMap.get(previous.getReference());
if (bridge == null) {
- return lookup;
+ return previous;
}
assert context != null : "Guaranteed by isContextFreeForMethod";
if (bridge.holder == context.holder) {
- return lookup;
+ return previous;
}
+ MethodLookupResult.Builder resultBuilder =
+ MethodLookupResult.builder(this).setReference(bridge);
if (isConstructorBridge(bridge)) {
- return new MethodLookupResult(
- bridge,
- Invoke.Type.DIRECT,
- internalDescribePrototypeChanges(lookup.getPrototypeChanges(), bridge));
+ resultBuilder
+ .setPrototypeChanges(
+ internalDescribePrototypeChanges(previous.getPrototypeChanges(), bridge))
+ .setType(Type.DIRECT);
+ } else {
+ resultBuilder.setPrototypeChanges(previous.getPrototypeChanges()).setType(Type.STATIC);
}
- return new MethodLookupResult(bridge, Invoke.Type.STATIC, lookup.getPrototypeChanges());
+ return resultBuilder.build();
}
public static Builder builder() {
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
index 1a51e48..7838e5b 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.GraphLens.NonIdentityGraphLens;
import com.android.tools.r8.graph.RewrittenPrototypeDescription;
-import com.android.tools.r8.ir.code.Invoke.Type;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -52,6 +51,23 @@
}
@Override
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ assert previous.getReboundReference() == null;
+ return MethodLookupResult.builder(this)
+ .setReference(previous.getReference())
+ .setReboundReference(getReboundMethodReference(previous.getReference()))
+ .setPrototypeChanges(previous.getPrototypeChanges())
+ .setType(previous.getType())
+ .build();
+ }
+
+ private DexMethod getReboundMethodReference(DexMethod method) {
+ // TODO(b/168282032): Return the rebound method reference.
+ return method;
+ }
+
+ @Override
public DexType getOriginalType(DexType type) {
return getPrevious().getOriginalType(type);
}
@@ -82,8 +98,8 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- return getPrevious().lookupMethod(method, context, type);
+ protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+ return method;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
index 2d59762..a6a6021 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingLens.java
@@ -86,17 +86,19 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- MethodLookupResult lookup = getPrevious().lookupMethod(method, context, type);
- Map<DexMethod, DexMethod> methodMap = methodMaps.getOrDefault(type, Collections.emptyMap());
- DexMethod newMethod = methodMap.get(lookup.getReference());
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ Map<DexMethod, DexMethod> methodMap =
+ methodMaps.getOrDefault(previous.getType(), Collections.emptyMap());
+ DexMethod newMethod = methodMap.get(previous.getReference());
if (newMethod == null) {
- return lookup;
+ return previous;
}
- return new MethodLookupResult(
- newMethod,
- mapInvocationType(newMethod, method, lookup.getType()),
- lookup.getPrototypeChanges());
+ return MethodLookupResult.builder(this)
+ .setReference(newMethod)
+ .setPrototypeChanges(previous.getPrototypeChanges())
+ .setType(mapInvocationType(newMethod, previous.getReference(), previous.getType()))
+ .build();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java b/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
index 78ab924..d36cbee 100644
--- a/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/PublicizerLens.java
@@ -40,14 +40,17 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- MethodLookupResult lookup = getPrevious().lookupMethod(method, context, type);
- if (lookup.getType() == Type.DIRECT && publicizedMethods.contains(lookup.getReference())) {
- assert publicizedMethodIsPresentOnHolder(lookup.getReference(), context);
- return new MethodLookupResult(
- lookup.getReference(), Type.VIRTUAL, lookup.getPrototypeChanges());
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ if (previous.getType() == Type.DIRECT && publicizedMethods.contains(previous.getReference())) {
+ assert publicizedMethodIsPresentOnHolder(previous.getReference(), context);
+ return MethodLookupResult.builder(this)
+ .setReference(previous.getReference())
+ .setPrototypeChanges(previous.getPrototypeChanges())
+ .setType(Type.VIRTUAL)
+ .build();
}
- return lookup;
+ return previous;
}
private boolean publicizedMethodIsPresentOnHolder(DexMethod method, DexMethod context) {
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 d61fbd7..953779d 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1140,7 +1140,7 @@
// resolve to a method on an interface never hit an implementation below that interface.
deferredRenamings.mapVirtualMethodToDirectInType(
oldTarget,
- prototypeChanges -> new MethodLookupResult(newTarget, STATIC, prototypeChanges),
+ prototypeChanges -> new MethodLookupResult(newTarget, null, STATIC, prototypeChanges),
target.type);
} else {
// If we merge class B into class C, and class C contains an invocation super.m(), then it
@@ -1161,7 +1161,8 @@
if (resolutionSucceeds) {
deferredRenamings.mapVirtualMethodToDirectInType(
signatureInHolder,
- prototypeChanges -> new MethodLookupResult(newTarget, DIRECT, prototypeChanges),
+ prototypeChanges ->
+ new MethodLookupResult(newTarget, null, DIRECT, prototypeChanges),
target.type);
} else {
break;
@@ -1185,7 +1186,8 @@
if (resolutionSucceededBeforeMerge) {
deferredRenamings.mapVirtualMethodToDirectInType(
signatureInType,
- prototypeChanges -> new MethodLookupResult(newTarget, DIRECT, prototypeChanges),
+ prototypeChanges ->
+ new MethodLookupResult(newTarget, null, DIRECT, prototypeChanges),
target.type);
}
}
@@ -1735,6 +1737,11 @@
}
@Override
+ protected DexMethod internalGetPreviousMethodSignature(DexMethod method) {
+ throw new Unreachable();
+ }
+
+ @Override
public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
// First look up the method using the existing graph lens (for example, the type will have
// changed if the method was publicized by ClassAndMemberPublicizer).
@@ -1744,16 +1751,28 @@
if (newMethod == null) {
return lookup;
}
+ MethodLookupResult.Builder methodLookupResultBuilder =
+ MethodLookupResult.builder(this)
+ .setReference(newMethod)
+ .setPrototypeChanges(lookup.getPrototypeChanges())
+ .setType(lookup.getType());
if (lookup.getType() == Type.INTERFACE) {
// If an interface has been merged into a class, invoke-interface needs to be translated
// to invoke-virtual.
DexClass clazz = appInfo.definitionFor(newMethod.holder);
if (clazz != null && !clazz.accessFlags.isInterface()) {
assert appInfo.definitionFor(method.holder).accessFlags.isInterface();
- return new MethodLookupResult(newMethod, Type.VIRTUAL, lookup.getPrototypeChanges());
+ methodLookupResultBuilder.setType(Type.VIRTUAL);
}
}
- return new MethodLookupResult(newMethod, lookup.getType(), lookup.getPrototypeChanges());
+ return methodLookupResultBuilder.build();
+ }
+
+ @Override
+ protected MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ // This is unreachable since we override the implementation of lookupMethod() above.
+ throw new Unreachable();
}
@Override
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
index 8feaefe..2848d3f 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMergerGraphLens.java
@@ -98,19 +98,16 @@
}
@Override
- public MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
- assert context != null || verifyIsContextFreeForMethod(method);
- assert context == null || type != null;
- DexMethod previousContext =
- originalMethodSignaturesForBridges.containsKey(context)
- ? originalMethodSignaturesForBridges.get(context)
- : originalMethodSignatures.getOrDefault(context, context);
- MethodLookupResult lookup = getPrevious().lookupMethod(method, previousContext, type);
- if (lookup.getType() == Type.SUPER && !mergedMethods.contains(context)) {
+ public MethodLookupResult internalDescribeLookupMethod(
+ MethodLookupResult previous, DexMethod context) {
+ assert context != null || verifyIsContextFreeForMethod(previous.getReference());
+ assert context == null || previous.getType() != null;
+ if (previous.getType() == Type.SUPER && !mergedMethods.contains(context)) {
Map<DexMethod, GraphLensLookupResultProvider> virtualToDirectMethodMap =
- contextualVirtualToDirectMethodMaps.get(context.holder);
+ contextualVirtualToDirectMethodMaps.get(context.getHolderType());
if (virtualToDirectMethodMap != null) {
- GraphLensLookupResultProvider result = virtualToDirectMethodMap.get(lookup.getReference());
+ GraphLensLookupResultProvider result =
+ virtualToDirectMethodMap.get(previous.getReference());
if (result != null) {
// If the super class A of the enclosing class B (i.e., context.holder())
// has been merged into B during vertical class merging, and this invoke-super instruction
@@ -118,18 +115,20 @@
// method and moved into B, so that we need to use an invoke-direct instruction instead of
// invoke-super (or invoke-static, if the method was originally a default interface
// method).
- return result.get(lookup.getPrototypeChanges());
+ return result.get(previous.getPrototypeChanges());
}
}
}
- DexMethod newMethod = methodMap.get(lookup.getReference());
+ DexMethod newMethod = methodMap.get(previous.getReference());
if (newMethod == null) {
- return lookup;
+ return previous;
}
- return new MethodLookupResult(
- newMethod,
- mapInvocationType(newMethod, lookup.getReference(), lookup.getType()),
- internalDescribePrototypeChanges(lookup.getPrototypeChanges(), newMethod));
+ return MethodLookupResult.builder(this)
+ .setReference(newMethod)
+ .setPrototypeChanges(
+ internalDescribePrototypeChanges(previous.getPrototypeChanges(), newMethod))
+ .setType(mapInvocationType(newMethod, previous.getReference(), previous.getType()))
+ .build();
}
@Override
@@ -200,7 +199,8 @@
builder.getMethodSignatureAfterClassMerging(rewriting.getReference(), mergedClasses);
newBuilder.mapVirtualMethodToDirectInType(
from,
- prototypeChanges -> new MethodLookupResult(to, rewriting.getType(), prototypeChanges),
+ prototypeChanges ->
+ new MethodLookupResult(to, null, rewriting.getType(), prototypeChanges),
context);
}
}