Introduce LIR after open/closed interfaces analysis
Change-Id: I0920048e14bfe1eaa45ba7063781533fdd073c53
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 797a842..81b1687 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -467,6 +467,9 @@
new CfOpenClosedInterfacesAnalysis(appViewWithLiveness).run(executorService);
+ // TODO(b/225838009): Move higher up.
+ LirConverter.enterLirSupportedPhase(appView, executorService);
+
assert verifyNoJarApplicationReaders(appView.appInfo().classes());
assert appView.checkForTesting(() -> allReferencesAssignedApiLevel(appViewWithLiveness));
// Build conservative main dex content after first round of tree shaking. This is used
@@ -497,9 +500,6 @@
.setMustRetargetInvokesToTargetMethod()
.run(executorService, timing);
- // TODO(b/225838009): Move higher up.
- LirConverter.enterLirSupportedPhase(appView, executorService);
-
BridgeHoistingToSharedSyntheticSuperClass.run(appViewWithLiveness, executorService, timing);
assert ArtProfileCompletenessChecker.verify(appView);
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 7c95315..1b9a92e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -1238,15 +1238,13 @@
return new ProgramMethod(holder, newMethod);
}
- public DexEncodedMethod toForwardingMethod(DexClass newHolder, AppView<?> definitions) {
- return toForwardingMethod(newHolder, definitions, ConsumerUtils.emptyConsumer());
+ public DexEncodedMethod toForwardingMethod(DexClass newHolder, AppView<?> appView) {
+ return toForwardingMethod(newHolder, appView, ConsumerUtils.emptyConsumer());
}
public DexEncodedMethod toForwardingMethod(
- DexClass newHolder,
- AppView<?> definitions,
- Consumer<DexEncodedMethod.Builder> builderConsumer) {
- DexMethod newMethod = getReference().withHolder(newHolder, definitions.dexItemFactory());
+ DexClass newHolder, AppView<?> appView, Consumer<DexEncodedMethod.Builder> builderConsumer) {
+ DexMethod newMethod = getReference().withHolder(newHolder, appView.dexItemFactory());
checkIfObsolete();
// Clear the final flag, as this method is now overwritten. Do this before creating the builder
@@ -1267,8 +1265,7 @@
builder ->
builder
.setCode(
- ForwardMethodBuilder.builder(definitions.dexItemFactory())
- .setStaticSource(newMethod)
+ ForwardMethodBuilder.builder(appView.dexItemFactory())
.applyIf(
isStatic(),
codeBuilder ->
@@ -1276,18 +1273,14 @@
.setStaticSource(newMethod)
.setStaticTarget(
getReference(),
- getReference()
- .getHolderType()
- .isInterface(definitions)),
+ getReference().getHolderType().isInterface(appView)),
codeBuilder ->
codeBuilder
.setNonStaticSource(newMethod)
.setSuperTarget(
getReference(),
- getReference()
- .getHolderType()
- .isInterface(definitions)))
- .build())
+ getReference().getHolderType().isInterface(appView)))
+ .build(appView))
.modifyAccessFlags(MethodAccessFlags::setBridge))
.setIsLibraryMethodOverrideIf(
!isStatic() && !isLibraryMethodOverride().isUnknown(), isLibraryMethodOverride())
@@ -1316,7 +1309,7 @@
ForwardMethodBuilder.builder(factory)
.setNonStaticSource(newMethod)
.setStaticTarget(forwardMethod, isInterfaceMethodReference)
- .build())
+ .buildCf())
.setApiLevelForDefinition(target.getDefinition().getApiLevelForDefinition())
.setApiLevelForCode(target.getDefinition().getApiLevelForCode())
.build();
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 67ec80a..81607e3 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
@@ -47,6 +47,6 @@
default:
throw new Unreachable();
}
- return forwardMethodBuilder.build();
+ return forwardMethodBuilder.buildCf();
}
}
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 aa69f8f..f84950a 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
@@ -192,7 +192,7 @@
.keepIf(x -> !isCovariantReturnTypeAnnotation(x.annotation)))
.setParameterAnnotations(
methodDefinition.parameterAnnotationsList.keepIf(Predicates.alwaysTrue()))
- .setCode(forwardMethodBuilder.build())
+ .setCode(forwardMethodBuilder.buildCf())
.setApiLevelForDefinition(methodDefinition.getApiLevelForDefinition())
.setApiLevelForCode(methodDefinition.getApiLevelForCode())
.build();
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 ddcdc6e..6ff9258 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
@@ -19,6 +19,6 @@
.setVirtualTarget(mainMethod, false)
.setCastArguments(lambdaClass.appView.appInfoForDesugaring())
.setCastResult()
- .build();
+ .buildCf();
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
index bc82617..29259c9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/apimodel/ApiInvokeOutlinerDesugaring.java
@@ -272,12 +272,12 @@
return ForwardMethodBuilder.builder(factory)
.setVirtualTarget(method, libraryHolder.isInterface())
.setNonStaticSource(method)
- .build();
+ .buildCf();
} else {
return ForwardMethodBuilder.builder(factory)
.setStaticTarget(method, libraryHolder.isInterface())
.setStaticSource(method)
- .build();
+ .buildCf();
}
});
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
index 99b56db..04db936 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/retargeter/DesugaredLibraryRetargeterSyntheticHelper.java
@@ -56,7 +56,7 @@
.setVirtualTarget(retarget, false)
.setNonStaticSource(target)
.setCastResult()
- .build()));
+ .buildCf()));
eventConsumer.acceptCovariantRetargetMethod(method, methodProcessingContext.getMethodContext());
return method.getReference();
}
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
index 56c3342..b290ad9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/invokespecial/InvokeSpecialToSelfDesugaring.java
@@ -117,7 +117,7 @@
ForwardMethodBuilder.builder(dexItemFactory)
.setDirectTarget(bridgeReference, clazz.isInterface())
.setNonStaticSource(method.getReference())
- .build();
+ .buildCf();
// Add the newly created direct method to its holder.
clazz.addDirectMethod(newDirectMethod.getDefinition());
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
index 2ff0fe6..dd600b3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceMethodRewriter.java
@@ -456,7 +456,7 @@
ForwardMethodBuilder.builder(factory)
.setStaticTarget(invoke.getMethod(), true)
.setStaticSource(m)
- .build()));
+ .buildCf()));
synthesizedMethods.add(newProgramMethod);
eventConsumer.acceptInvokeStaticInterfaceOutliningMethod(
newProgramMethod, context1);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java
index 0b7fc43..95604c7 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/AccessBridgeFactory.java
@@ -59,7 +59,7 @@
ForwardMethodBuilder.builder(dexItemFactory)
.setNonStaticSourceWithExtraUnusedParameter(bridgeMethodReference)
.setConstructorTarget(method.getReference())
- .build())
+ .buildCf())
.setMethod(bridgeMethodReference)
.setApiLevelForDefinition(method.getDefinition().getApiLevelForDefinition())
.setApiLevelForCode(method.getDefinition().getApiLevelForCode())
@@ -90,7 +90,7 @@
method.getAccessFlags().isStatic(),
builder -> builder.setStaticTarget(method.getReference(), isInterface),
builder -> builder.setDirectTarget(method.getReference(), isInterface))
- .build())
+ .buildCf())
.setMethod(bridgeMethodReference)
.setApiLevelForDefinition(method.getDefinition().getApiLevelForDefinition())
.setApiLevelForCode(method.getDefinition().getApiLevelForDefinition())
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java b/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java
index a9dfc03..a8abce9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/api/InstanceInitializerOutliner.java
@@ -272,7 +272,7 @@
ForwardMethodBuilder.builder(appView.dexItemFactory())
.setConstructorTargetWithNewInstance(targetMethod)
.setStaticSource(m)
- .build())
+ .buildCf())
.setOptimizationInfo(
DefaultMethodOptimizationInfo.getInstance()
.toMutableOptimizationInfo()
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodBuilder.java b/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodBuilder.java
index 0718a90..b8c5959 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/ForwardMethodBuilder.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.synthetic;
+import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
+import static com.android.tools.r8.ir.analysis.type.Nullability.maybeNull;
import static com.android.tools.r8.utils.ConsumerUtils.emptyConsumer;
import com.android.tools.r8.cf.code.CfCheckCast;
@@ -14,18 +16,28 @@
import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStackInstruction.Opcode;
+import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.graph.CfCodeWithLens;
+import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.lens.GraphLens;
+import com.android.tools.r8.ir.analysis.type.TypeElement;
+import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueType;
+import com.android.tools.r8.lightir.LirBuilder;
+import com.android.tools.r8.lightir.LirCode;
+import com.android.tools.r8.lightir.LirEncodingStrategy;
+import com.android.tools.r8.lightir.LirStrategy;
import com.android.tools.r8.utils.BooleanUtils;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.Consumer;
import org.objectweb.asm.Opcodes;
@@ -159,12 +171,15 @@
return this;
}
- @SuppressWarnings({"BadImport", "ReferenceEquality"})
- public CfCode build() {
+ public Code build(AppView<?> appView) {
+ return appView.testing().isSupportedLirPhase() ? buildLir(appView) : buildCf();
+ }
+
+ public CfCode buildCf() {
assert validate();
int maxStack = 0;
int maxLocals = 0;
- Builder<CfInstruction> instructions = ImmutableList.builder();
+ ImmutableList.Builder<CfInstruction> instructions = ImmutableList.builder();
if (isConstructorDelegate) {
// A constructor delegate allocates a new instance of the type.
// It is dup'ed on the stack so it is ready to return after the invoke call.
@@ -205,9 +220,10 @@
assert !isConstructorDelegate;
instructions.add(new CfReturnVoid());
} else {
- if (!isConstructorDelegate && sourceMethod.getReturnType() != targetMethod.getReturnType()) {
+ if (!isConstructorDelegate
+ && sourceMethod.getReturnType().isNotIdenticalTo(targetMethod.getReturnType())) {
assert castResult;
- if (sourceMethod.getReturnType() != factory.objectType) {
+ if (sourceMethod.getReturnType().isNotIdenticalTo(factory.objectType)) {
instructions.add(new CfCheckCast(sourceMethod.getReturnType()));
}
}
@@ -220,9 +236,66 @@
return new CfCode(sourceMethod.holder, maxStack, maxLocals, instructions.build());
}
- @SuppressWarnings({"BadImport", "ReferenceEquality"})
+ public LirCode<Integer> buildLir(AppView<?> appView) {
+ assert validate();
+ if (castResult
+ || isConstructorDelegate
+ || sourceMethodHasExtraUnusedParameter
+ || appInfoForCastArguments != null
+ || codeLens != null) {
+ throw new Unimplemented();
+ }
+ if (invokeType != InvokeType.STATIC && invokeType != InvokeType.SPECIAL) {
+ throw new Unimplemented();
+ }
+ if (invokeType == InvokeType.SPECIAL
+ && sourceMethod.getHolderType().isIdenticalTo(targetMethod.getHolderType())) {
+ throw new Unimplemented();
+ }
+
+ boolean isD8R8Synthesized = true;
+ LirEncodingStrategy<Value, Integer> strategy =
+ LirStrategy.getDefaultStrategy().getEncodingStrategy();
+ LirBuilder<Value, Integer> lirBuilder =
+ LirCode.builder(sourceMethod, isD8R8Synthesized, strategy, appView.options());
+
+ // Add all arguments.
+ List<Value> argumentValues = new ArrayList<>();
+ int instructionIndex = 0;
+ for (; instructionIndex < sourceMethod.getNumberOfArguments(staticSource); instructionIndex++) {
+ DexType argumentType = sourceMethod.getArgumentType(instructionIndex, staticSource);
+ TypeElement argumentTypeElement =
+ argumentType.toTypeElement(
+ appView, instructionIndex == 0 && !staticSource ? definitelyNotNull() : maybeNull());
+ Value argumentValue = Value.createNoDebugLocal(instructionIndex, argumentTypeElement);
+ argumentValues.add(argumentValue);
+ strategy.defineValue(argumentValue, argumentValue.getNumber());
+ lirBuilder.addArgument(instructionIndex, argumentType.isBooleanType());
+ }
+
+ if (isStaticTarget()) {
+ lirBuilder.addInvokeStatic(targetMethod, argumentValues, isInterface);
+ } else {
+ lirBuilder.addInvokeSuper(targetMethod, argumentValues, isInterface);
+ }
+
+ if (sourceMethod.getReturnType().isVoidType()) {
+ lirBuilder.addReturnVoid();
+ } else {
+ Value returnValue =
+ Value.createNoDebugLocal(
+ instructionIndex, sourceMethod.getReturnType().toTypeElement(appView));
+ strategy.defineValue(returnValue, returnValue.getNumber());
+ lirBuilder.addReturn(returnValue);
+ }
+
+ return lirBuilder.build();
+ }
+
private void maybeInsertArgumentCast(
- int argumentIndex, DexType sourceArgumentType, Builder<CfInstruction> instructions) {
+ int argumentIndex,
+ DexType sourceArgumentType,
+ ImmutableList.Builder<CfInstruction> instructions) {
if (appInfoForCastArguments == null) {
return;
}
@@ -235,8 +308,9 @@
argumentIndex == -1
? targetMethod.holder
: targetMethod.getParameters().values[argumentIndex];
- if (sourceArgumentType != targetArgumentType
- && targetArgumentType != appInfoForCastArguments.dexItemFactory().objectType) {
+ if (sourceArgumentType.isNotIdenticalTo(targetArgumentType)
+ && targetArgumentType.isNotIdenticalTo(
+ appInfoForCastArguments.dexItemFactory().objectType)) {
assert appInfoForCastArguments.isSubtype(targetArgumentType, sourceArgumentType);
instructions.add(new CfCheckCast(targetArgumentType));
}
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 c177e50..f56f8bc 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -501,6 +501,7 @@
MemberRebindingLens memberRebindingLens = lensBuilder.build();
appView.setGraphLens(memberRebindingLens);
eventConsumer.finished(appView, memberRebindingLens);
+ appView.dexItemFactory().clearTypeElementsCache();
appView.notifyOptimizationFinishedForTesting();
}
}