Extend the lens lookup API for fields to pass the rebound reference
Bug: 168282032
Change-Id: Icb015fd05dbd91df0806660d327569421001d0f6
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 0c43ae8..0a03d50 100644
--- a/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/AppliedGraphLens.java
@@ -134,8 +134,8 @@
}
@Override
- public DexField lookupField(DexField field) {
- return field;
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ return previous;
}
@Override
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 8180a8b..84443a0 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -42,6 +42,64 @@
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 {
+
+ private final DexField reference;
+ private final DexField reboundReference;
+
+ private FieldLookupResult(DexField reference, DexField reboundReference) {
+ this.reference = reference;
+ this.reboundReference = reboundReference;
+ }
+
+ public DexField getReference() {
+ return reference;
+ }
+
+ public DexField getRewrittenReference(Map<DexField, DexField> rewritings) {
+ return rewritings.getOrDefault(reference, reference);
+ }
+
+ public DexField getReboundReference() {
+ return reboundReference;
+ }
+
+ public static Builder builder(GraphLens lens) {
+ return new Builder(lens);
+ }
+
+ public static class 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;
+ return this;
+ }
+
+ public FieldLookupResult build() {
+ // All non-identity graph lenses should set the rebound reference.
+ assert lens.isIdentityLens() || reboundReference != null;
+ return new FieldLookupResult(reference, reboundReference);
+ }
+ }
+ }
+
+ /**
* Result of a method lookup in a GraphLens.
*
* <p>This provides the new target and invoke type to use, along with a description of the
@@ -215,7 +273,20 @@
public abstract RewrittenPrototypeDescription lookupPrototypeChangesForMethodDefinition(
DexMethod method);
- public abstract DexField lookupField(DexField field);
+ /** Lookup a rebound or non-rebound field reference using the current graph lens. */
+ public DexField lookupField(DexField field) {
+ // Lookup the field using the graph lens and return the (non-rebound) reference from the lookup
+ // result.
+ return internalLookupField(field, FieldLookupResult::getReference);
+ }
+
+ protected abstract DexField internalLookupField(
+ DexField reference, LookupFieldContinuation continuation);
+
+ interface LookupFieldContinuation {
+
+ DexField lookupField(FieldLookupResult previous);
+ }
public DexMethod lookupGetFieldForMethod(DexField field, DexMethod context) {
return null;
@@ -455,6 +526,14 @@
}
@Override
+ protected final DexField internalLookupField(
+ DexField reference, LookupFieldContinuation continuation) {
+ return previousLens.internalLookupField(
+ reference, previous -> continuation.lookupField(internalDescribeLookupField(previous)));
+ }
+
+ protected abstract FieldLookupResult internalDescribeLookupField(FieldLookupResult previous);
+
public final boolean isIdentityLens() {
return false;
}
@@ -532,8 +611,12 @@
}
@Override
- public DexField lookupField(DexField field) {
- return field;
+ protected DexField internalLookupField(
+ DexField reference, LookupFieldContinuation continuation) {
+ // Passes the field reference back to the next graph lens. The identity lens intentionally
+ // does not set the rebound field reference, since it does not know what that is.
+ return continuation.lookupField(
+ FieldLookupResult.builder(this).setReference(reference).build());
}
@Override
@@ -599,8 +682,8 @@
}
@Override
- public DexField lookupField(DexField field) {
- return getIdentityLens().lookupField(field);
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ return previous;
}
@Override
@@ -810,9 +893,13 @@
}
@Override
- public DexField lookupField(DexField field) {
- DexField previous = getPrevious().lookupField(field);
- return fieldMap.getOrDefault(previous, previous);
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ DexField rewrittenReference = previous.getRewrittenReference(fieldMap);
+ return FieldLookupResult.builder(this)
+ .setReference(rewrittenReference)
+ // TODO(b/168282032): This should set the rebound reference.
+ .setReboundReference(rewrittenReference)
+ .build();
}
@Override
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 8dc0d84..729a1d8 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -1769,6 +1769,12 @@
}
@Override
+ protected FieldLookupResult internalDescribeLookupField(FieldLookupResult previous) {
+ // This is unreachable since we override the implementation of lookupField() above.
+ throw new Unreachable();
+ }
+
+ @Override
public boolean isContextFreeForMethods() {
return true;
}