Rewrite lir with lens before first round of vertical class merging
Change-Id: I3504b9d392787c2290ace7c86a94110c21597e48
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 0559d8f..7cabfb6 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -502,6 +502,9 @@
assert ArtProfileCompletenessChecker.verify(appView);
+ LirConverter.rewriteLirWithLens(appView, timing, executorService);
+ appView.clearCodeRewritings(executorService, timing);
+
VerticalClassMerger.createForInitialClassMerging(appViewWithLiveness, timing)
.runIfNecessary(executorService, timing);
diff --git a/src/main/java/com/android/tools/r8/graph/DexType.java b/src/main/java/com/android/tools/r8/graph/DexType.java
index f597df0..108877b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexType.java
+++ b/src/main/java/com/android/tools/r8/graph/DexType.java
@@ -394,6 +394,12 @@
return definitionSupplier.definitionFor(this).isInterface();
}
+ public boolean isInterfaceOrDefault(
+ DexDefinitionSupplier definitionSupplier, boolean defaultValue) {
+ DexClass clazz = definitionSupplier.definitionFor(this);
+ return clazz != null ? clazz.isInterface() : defaultValue;
+ }
+
public DexProgramClass asProgramClass(DexDefinitionSupplier definitions) {
return asProgramClassOrNull(definitions.definitionFor(this));
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
index 25df747..8810391 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
@@ -84,7 +84,9 @@
GraphLens graphLens = appView.graphLens();
assert graphLens.isNonIdentityLens();
- assert appView.codeLens().isAppliedLens() || appView.codeLens().isClearCodeRewritingLens();
+ assert appView.codeLens().isAppliedLens()
+ || appView.codeLens().isClearCodeRewritingLens()
+ || appView.codeLens().isIdentityLens();
MemberRebindingIdentityLens memberRebindingIdentityLens =
graphLens.asNonIdentityLens().find(GraphLens::isMemberRebindingIdentityLens);
diff --git a/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java b/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
index de48365..b5ab4d1 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirLensCodeRewriter.java
@@ -10,7 +10,6 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
@@ -34,7 +33,6 @@
import com.android.tools.r8.ir.optimize.AffectedValues;
import com.android.tools.r8.ir.optimize.DeadCodeRemover;
import com.android.tools.r8.lightir.LirBuilder.NameComputationPayload;
-import com.android.tools.r8.lightir.LirBuilder.RecordFieldValuesPayload;
import com.android.tools.r8.lightir.LirCode.TryCatchTable;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ArrayUtils;
@@ -125,9 +123,10 @@
assert newMethod.getArity() == method.getArity();
if (newOpcode != opcode) {
assert type == newType
- || (type.isVirtual() && newType.isInterface())
+ || (type.isDirect() && (newType.isInterface() || newType.isVirtual()))
|| (type.isInterface() && newType.isVirtual())
|| (type.isSuper() && newType.isVirtual())
+ || (type.isVirtual() && newType.isInterface())
: type + " -> " + newType;
numberOfInvokeOpcodeChanges++;
} else {
@@ -273,6 +272,9 @@
}
private InvokeType getInvokeTypeThatMayChange(int opcode) {
+ if (codeLens.isIdentityLens() && LirOpcodeUtils.isInvokeMethod(opcode)) {
+ return LirOpcodeUtils.getInvokeType(opcode);
+ }
if (opcode == LirOpcodes.INVOKEVIRTUAL) {
return InvokeType.VIRTUAL;
}
@@ -400,8 +402,6 @@
boolean hasFieldReference = false;
boolean hasPotentialRewrittenMethod = false;
for (LirConstant constant : code.getConstantPool()) {
- // RecordFieldValuesPayload is lowered to NewArrayEmpty before lens code rewriting any LIR.
- assert !(constant instanceof RecordFieldValuesPayload);
if (constant instanceof DexType) {
onTypeReference((DexType) constant);
} else if (constant instanceof DexField) {
@@ -521,15 +521,18 @@
// TODO(b/157111832): This should be part of the graph lens lookup result.
private boolean lookupIsInterface(DexMethod method, int opcode, MethodLookupResult result) {
+ boolean wasInterface = LirOpcodeUtils.getInterfaceBitFromInvokeOpcode(opcode);
+ // Update interface bit after member rebinding.
+ if (codeLens.isIdentityLens() && method.isNotIdenticalTo(result.getReference())) {
+ return result.getReference().getHolderType().isInterfaceOrDefault(appView, wasInterface);
+ }
+ // Update interface bit after vertical class merging.
VerticalClassMergerGraphLens verticalClassMergerLens = graphLens.asVerticalClassMergerLens();
if (verticalClassMergerLens != null
&& verticalClassMergerLens.hasInterfaceBeenMergedIntoClass(method.getHolderType())) {
- DexClass clazz = appView.definitionFor(result.getReference().getHolderType());
- if (clazz != null) {
- return clazz.isInterface();
- }
+ return result.getReference().getHolderType().isInterfaceOrDefault(appView, wasInterface);
}
- return LirOpcodeUtils.getInterfaceBitFromInvokeOpcode(opcode);
+ return wasInterface;
}
private LirCode<EV> rewriteTryCatchTable(LirCode<EV> code) {
diff --git a/src/main/java/com/android/tools/r8/lightir/LirOpcodeUtils.java b/src/main/java/com/android/tools/r8/lightir/LirOpcodeUtils.java
index ec71974..7b110eb 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirOpcodeUtils.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirOpcodeUtils.java
@@ -12,6 +12,9 @@
import static com.android.tools.r8.lightir.LirOpcodes.INVOKESUPER_ITF;
import static com.android.tools.r8.lightir.LirOpcodes.INVOKEVIRTUAL;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.InvokeType;
+
public class LirOpcodeUtils {
public static boolean getInterfaceBitFromInvokeOpcode(int opcode) {
@@ -30,6 +33,27 @@
}
}
+ public static InvokeType getInvokeType(int opcode) {
+ assert isInvokeMethod(opcode);
+ switch (opcode) {
+ case INVOKEDIRECT:
+ case INVOKEDIRECT_ITF:
+ return InvokeType.DIRECT;
+ case INVOKEINTERFACE:
+ return InvokeType.INTERFACE;
+ case INVOKESTATIC:
+ case INVOKESTATIC_ITF:
+ return InvokeType.STATIC;
+ case INVOKESUPER:
+ case INVOKESUPER_ITF:
+ return InvokeType.SUPER;
+ case INVOKEVIRTUAL:
+ return InvokeType.VIRTUAL;
+ default:
+ throw new Unreachable();
+ }
+ }
+
public static boolean isInvokeMethod(int opcode) {
switch (opcode) {
case INVOKEDIRECT: