Merge commit '65918686c5697b32d3d8cbb9f3624d4b55e50f15' into dev-release
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
index 9b48471..558386a 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_alternative_3.json
@@ -1,5 +1,5 @@
{
- "identifier": "com.tools.android:desugar_jdk_libs_alternative_3:1.0.12",
+ "identifier": "com.tools.android:desugar_jdk_libs_alternative_3:2.0.0",
"configuration_format_version": 100,
"required_compilation_api_level": 30,
"synthesized_library_classes_package_prefix": "j$.",
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 885ada8..d479e46 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -70,7 +70,6 @@
import com.android.tools.r8.naming.signature.GenericSignatureRewriter;
import com.android.tools.r8.optimize.ClassAndMemberPublicizer;
import com.android.tools.r8.optimize.MemberRebindingAnalysis;
-import com.android.tools.r8.optimize.MemberRebindingIdentityLens;
import com.android.tools.r8.optimize.MemberRebindingIdentityLensFactory;
import com.android.tools.r8.optimize.VisibilityBridgeRemover;
import com.android.tools.r8.optimize.bridgehoisting.BridgeHoisting;
@@ -290,7 +289,6 @@
DirectMappedDexApplication application = applicationReader.read(executorService).toDirect();
options.loadMachineDesugaredLibrarySpecification(timing, application);
MainDexInfo mainDexInfo = applicationReader.readMainDexClassesForR8(application);
-
// Now that the dex-application is fully loaded, close any internal archive providers.
inputApp.closeInternalArchiveProviders();
@@ -712,9 +710,15 @@
assert !options.isShrinking();
}
- MemberRebindingIdentityLens memberRebindingLens =
- MemberRebindingIdentityLensFactory.create(appView, executorService);
- appView.setGraphLens(memberRebindingLens);
+ // Insert a member rebinding oracle in the graph to ensure that all subsequent rewritings of
+ // the application has an applied oracle for looking up non-rebound references.
+ appView.setGraphLens(MemberRebindingIdentityLensFactory.create(appView, executorService));
+
+ if (appView.appInfo().hasLiveness()) {
+ SyntheticFinalization.finalizeWithLiveness(appView.withLiveness(), executorService);
+ } else {
+ SyntheticFinalization.finalizeWithClassHierarchy(appView, executorService);
+ }
// Read any -applymapping input to allow for repackaging to not relocate the classes.
timing.begin("read -applymapping file");
@@ -728,24 +732,13 @@
RepackagingLens lens =
new Repackaging(appView.withLiveness()).run(appBuilder, executorService, timing);
if (lens != null) {
- // Specify to use the member rebinding lens as the parent lens during the rewriting. This
- // is needed to ensure that the rebound references are available during lens lookups.
- // TODO(b/168282032): This call-site should not have to think about the parent lens that
- // is used for the rewriting. Once the new member rebinding lens replaces the old member
- // rebinding analysis it should be possible to clean this up.
- appView.rewriteWithLensAndApplication(
- lens, appBuilder.build(), memberRebindingLens.getPrevious());
+ appView.rewriteWithLensAndApplication(lens, appBuilder.build());
}
}
if (appView.appInfo().hasLiveness()) {
assert Repackaging.verifyIdentityRepackaging(appView.withLiveness());
}
- if (appView.appInfo().hasLiveness()) {
- SyntheticFinalization.finalizeWithLiveness(appView.withLiveness(), executorService);
- } else {
- SyntheticFinalization.finalizeWithClassHierarchy(appView, executorService);
- }
// Clear the reference type lattice element cache. This is required since class merging may
// need to build IR.
diff --git a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
index 6a2d78d..5725955 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -21,7 +21,6 @@
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.CommittedItems;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
@@ -156,7 +155,7 @@
public void processClass(DexProgramClass clazz) {
if (appView
.getSyntheticItems()
- .isSyntheticOfKind(clazz.getType(), SyntheticKind.API_MODEL_OUTLINE)) {
+ .isSyntheticOfKind(clazz.getType(), kinds -> kinds.API_MODEL_OUTLINE)) {
return;
}
findReferencedLibraryClasses(clazz.type);
@@ -235,7 +234,7 @@
.appInfo()
.getSyntheticItems()
.ensureFixedClassFromType(
- SyntheticKind.API_MODEL_STUB,
+ kinds -> kinds.API_MODEL_STUB,
libraryClass.getType(),
appView,
classBuilder -> {
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index b740f3d..db99838 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -795,6 +795,7 @@
while (firstUnappliedLens.getPrevious() != appliedLens) {
GraphLens previousLens = firstUnappliedLens.getPrevious();
assert previousLens.isNonIdentityLens();
+ assert previousLens != appView.codeLens();
firstUnappliedLens = previousLens.asNonIdentityLens();
}
@@ -802,22 +803,24 @@
// TODO(b/182129249): Once the member rebinding phase has been removed, the MemberRebindingLens
// should be removed and all uses of FieldRebindingIdentityLens should be replaced by
// MemberRebindingIdentityLens.
- NonIdentityGraphLens appliedMemberRebindingLens =
- firstUnappliedLens.findPrevious(
- previous ->
- previous.isMemberRebindingLens() || previous.isMemberRebindingIdentityLens());
- GraphLens newMemberRebindingLens;
- if (appliedMemberRebindingLens != null) {
- newMemberRebindingLens =
- appliedMemberRebindingLens.isMemberRebindingLens()
- ? appliedMemberRebindingLens
- .asMemberRebindingLens()
- .toRewrittenFieldRebindingLens(appView, appliedLens)
- : appliedMemberRebindingLens
- .asMemberRebindingIdentityLens()
- .toRewrittenMemberRebindingIdentityLens(appView, appliedLens);
- } else {
- newMemberRebindingLens = GraphLens.getIdentityLens();
+ GraphLens newMemberRebindingLens = GraphLens.getIdentityLens();
+ if (!firstUnappliedLens.isMemberRebindingLens()
+ && !firstUnappliedLens.isMemberRebindingIdentityLens()) {
+ NonIdentityGraphLens appliedMemberRebindingLens =
+ firstUnappliedLens.findPreviousUntil(
+ previous ->
+ previous.isMemberRebindingLens() || previous.isMemberRebindingIdentityLens(),
+ previous -> previous == appView.codeLens());
+ if (appliedMemberRebindingLens != null) {
+ newMemberRebindingLens =
+ appliedMemberRebindingLens.isMemberRebindingLens()
+ ? appliedMemberRebindingLens
+ .asMemberRebindingLens()
+ .toRewrittenFieldRebindingLens(appView, appliedLens)
+ : appliedMemberRebindingLens
+ .asMemberRebindingIdentityLens()
+ .toRewrittenMemberRebindingIdentityLens(appView, appliedLens);
+ }
}
firstUnappliedLens.withAlternativeParentLens(
diff --git a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
index 366ad9c..5a2bffc 100644
--- a/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
+++ b/src/main/java/com/android/tools/r8/graph/DexAnnotation.java
@@ -13,7 +13,7 @@
import com.android.tools.r8.graph.DexValue.DexValueString;
import com.android.tools.r8.graph.DexValue.DexValueType;
import com.android.tools.r8.ir.desugar.CovariantReturnTypeAnnotationTransformer;
-import com.android.tools.r8.synthesis.SyntheticNaming;
+import com.android.tools.r8.synthesis.SyntheticItems;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Pair;
@@ -391,9 +391,7 @@
public static DexAnnotation createAnnotationSynthesizedClass(
SyntheticKind kind, DexItemFactory dexItemFactory) {
DexAnnotationElement kindElement =
- new DexAnnotationElement(
- dexItemFactory.kindString,
- new DexValueString(dexItemFactory.createString(kind.descriptor)));
+ new DexAnnotationElement(dexItemFactory.kindString, DexValueInt.create(kind.getId()));
DexAnnotationElement[] elements = new DexAnnotationElement[] {kindElement};
return new DexAnnotation(
VISIBILITY_BUILD,
@@ -401,12 +399,12 @@
}
public static boolean hasSynthesizedClassAnnotation(
- DexAnnotationSet annotations, DexItemFactory factory) {
- return getSynthesizedClassAnnotationInfo(annotations, factory) != null;
+ DexAnnotationSet annotations, DexItemFactory factory, SyntheticItems synthetics) {
+ return getSynthesizedClassAnnotationInfo(annotations, factory, synthetics) != null;
}
public static SyntheticKind getSynthesizedClassAnnotationInfo(
- DexAnnotationSet annotations, DexItemFactory factory) {
+ DexAnnotationSet annotations, DexItemFactory factory, SyntheticItems synthetics) {
if (annotations.size() != 1) {
return null;
}
@@ -423,12 +421,11 @@
if (kindElement.name != factory.kindString) {
return null;
}
- if (!kindElement.value.isDexValueString()) {
+ if (!kindElement.value.isDexValueInt()) {
return null;
}
SyntheticKind kind =
- SyntheticNaming.SyntheticKind.fromDescriptor(
- kindElement.value.asDexValueString().getValue().toString());
+ synthetics.getNaming().fromId(kindElement.value.asDexValueInt().getValue());
return kind;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index 34e4809..6259d4c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -35,6 +35,7 @@
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.Int2StructuralItemArrayMap;
@@ -682,6 +683,12 @@
public final StringConcatFactoryMembers stringConcatFactoryMembers =
new StringConcatFactoryMembers();
+ private final SyntheticNaming syntheticNaming = new SyntheticNaming();
+
+ public SyntheticNaming getSyntheticNaming() {
+ return syntheticNaming;
+ }
+
public final BiMap<DexType, DexType> primitiveToBoxed = HashBiMap.create(
ImmutableMap.<DexType, DexType>builder()
.put(booleanType, boxedBooleanType)
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 952c31d..188211d 100644
--- a/src/main/java/com/android/tools/r8/graph/GraphLens.java
+++ b/src/main/java/com/android/tools/r8/graph/GraphLens.java
@@ -400,7 +400,7 @@
public abstract DexType lookupType(DexType type, GraphLens applied);
- // This overload can be used when the graph lens is known to be context insensitive.
+ @Deprecated
public final DexMethod lookupMethod(DexMethod method) {
assert verifyIsContextFreeForMethod(method);
return lookupMethod(method, null, null).getReference();
@@ -410,22 +410,47 @@
return lookupMethod(method, context.getReference(), Type.DIRECT);
}
+ public final MethodLookupResult lookupInvokeDirect(
+ DexMethod method, ProgramMethod context, GraphLens codeLens) {
+ return lookupMethod(method, context.getReference(), Type.DIRECT, codeLens);
+ }
+
public final MethodLookupResult lookupInvokeInterface(DexMethod method, ProgramMethod context) {
return lookupMethod(method, context.getReference(), Type.INTERFACE);
}
+ public final MethodLookupResult lookupInvokeInterface(
+ DexMethod method, ProgramMethod context, GraphLens codeLens) {
+ return lookupMethod(method, context.getReference(), Type.INTERFACE, codeLens);
+ }
+
public final MethodLookupResult lookupInvokeStatic(DexMethod method, ProgramMethod context) {
return lookupMethod(method, context.getReference(), Type.STATIC);
}
+ public final MethodLookupResult lookupInvokeStatic(
+ DexMethod method, ProgramMethod context, GraphLens codeLens) {
+ return lookupMethod(method, context.getReference(), Type.STATIC, codeLens);
+ }
+
public final MethodLookupResult lookupInvokeSuper(DexMethod method, ProgramMethod context) {
return lookupMethod(method, context.getReference(), Type.SUPER);
}
+ public final MethodLookupResult lookupInvokeSuper(
+ DexMethod method, ProgramMethod context, GraphLens codeLens) {
+ return lookupMethod(method, context.getReference(), Type.SUPER, codeLens);
+ }
+
public final MethodLookupResult lookupInvokeVirtual(DexMethod method, ProgramMethod context) {
return lookupMethod(method, context.getReference(), Type.VIRTUAL);
}
+ public final MethodLookupResult lookupInvokeVirtual(
+ DexMethod method, ProgramMethod context, GraphLens codeLens) {
+ return lookupMethod(method, context.getReference(), Type.VIRTUAL, codeLens);
+ }
+
public final MethodLookupResult lookupMethod(DexMethod method, DexMethod context, Type type) {
return lookupMethod(method, context, type, null);
}
@@ -816,6 +841,13 @@
return previous.isNonIdentityLens() ? previous.asNonIdentityLens().find(predicate) : null;
}
+ public final <T extends NonIdentityGraphLens> T findPreviousUntil(
+ Predicate<NonIdentityGraphLens> predicate,
+ Predicate<NonIdentityGraphLens> stoppingCriterion) {
+ T found = findPrevious(predicate.or(stoppingCriterion));
+ return (found == null || stoppingCriterion.test(found)) ? null : found;
+ }
+
public final void withAlternativeParentLens(GraphLens lens, Action action) {
GraphLens oldParent = getPrevious();
previousLens = lens;
diff --git a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
index ee7bc18..afbda8d 100644
--- a/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
+++ b/src/main/java/com/android/tools/r8/graph/JarClassFileReader.java
@@ -124,7 +124,9 @@
}
reader.accept(
new CreateDexClassVisitor<>(origin, classKind, reader.b, application, classConsumer),
- new Attribute[] {SyntheticMarker.getMarkerAttributePrototype()},
+ new Attribute[] {
+ SyntheticMarker.getMarkerAttributePrototype(application.getFactory().getSyntheticNaming())
+ },
parsingOptions);
// Read marker.
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
index 88a4755..ec19e83 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/SyntheticArgumentClass.java
@@ -8,7 +8,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -50,21 +50,22 @@
this.appView = appView;
}
- private DexProgramClass synthesizeClass(DexProgramClass context, SyntheticKind syntheticKind) {
+ private DexProgramClass synthesizeClass(
+ DexProgramClass context, SyntheticKindSelector syntheticKindSelector) {
return appView
.getSyntheticItems()
- .createFixedClass(syntheticKind, context, appView, builder -> {});
+ .createFixedClass(syntheticKindSelector, context, appView, builder -> {});
}
public SyntheticArgumentClass build(Collection<MergeGroup> mergeGroups) {
DexProgramClass context = getDeterministicContext(mergeGroups);
List<DexType> syntheticArgumentTypes = new ArrayList<>();
syntheticArgumentTypes.add(
- synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_1).getType());
+ synthesizeClass(context, kinds -> kinds.HORIZONTAL_INIT_TYPE_ARGUMENT_1).getType());
syntheticArgumentTypes.add(
- synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_2).getType());
+ synthesizeClass(context, kinds -> kinds.HORIZONTAL_INIT_TYPE_ARGUMENT_2).getType());
syntheticArgumentTypes.add(
- synthesizeClass(context, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_3).getType());
+ synthesizeClass(context, kinds -> kinds.HORIZONTAL_INIT_TYPE_ARGUMENT_3).getType());
return new SyntheticArgumentClass(syntheticArgumentTypes);
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 9cf8f31..3da2a7e 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1313,7 +1313,7 @@
codeRewriter.rewriteKnownArrayLengthCalls(code);
timing.end();
timing.begin("Natural Int Loop Remover");
- naturalIntLoopRemover.run(code);
+ naturalIntLoopRemover.run(appView, code);
timing.end();
timing.begin("Rewrite AssertionError");
codeRewriter.rewriteAssertionErrorTwoArgumentConstructor(code, options);
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
index b799580b..eb5a30b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/BackportedMethodRewriter.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.ir.desugar;
+import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.contexts.CompilationContext.MethodProcessingContext;
@@ -40,6 +41,7 @@
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
@@ -94,7 +96,7 @@
&& getMethodProviderOrNull(instruction.asInvoke().getMethod()) != null
&& !appView
.getSyntheticItems()
- .isSyntheticOfKind(context.getContextType(), SyntheticKind.BACKPORT_WITH_FORWARDING);
+ .isSyntheticOfKind(context.getContextType(), kinds -> kinds.BACKPORT_WITH_FORWARDING);
}
public static List<DexMethod> generateListOfBackportedMethods(
@@ -148,6 +150,8 @@
private static final class RewritableMethods {
+ private final Map<DexType, AndroidApiLevel> typeMinApi;
+
private final AppView<?> appView;
// Map backported method to a provider for creating the actual target method (with code).
@@ -155,7 +159,7 @@
RewritableMethods(InternalOptions options, AppView<?> appView) {
this.appView = appView;
-
+ this.typeMinApi = initializeTypeMinApi(appView.dexItemFactory());
if (!options.shouldBackportMethods()) {
return;
}
@@ -164,65 +168,125 @@
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.K)) {
initializeAndroidKMethodProviders(factory);
+ if (typeIsAbsentOrPresentWithoutBackportsFrom(factory.objectsType, AndroidApiLevel.K)) {
+ initializeAndroidKObjectsMethodProviders(factory);
+ }
}
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.N)) {
initializeAndroidNMethodProviders(factory);
+ if (typeIsAbsentOrPresentWithoutBackportsFrom(factory.objectsType, AndroidApiLevel.N)) {
+ initializeAndroidNObjectsMethodProviders(factory);
+ if (typeIsPresent(factory.supplierType)) {
+ initializeAndroidNObjectsMethodProviderWithSupplier(factory);
+ }
+ }
}
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.O)) {
initializeAndroidOMethodProviders(factory);
}
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.R)) {
- initializeAndroidRMethodProviders(factory);
+ if (typeIsPresentWithoutBackportsFrom(factory.setType, AndroidApiLevel.R)) {
+ initializeAndroidRSetListMapMethodProviders(factory);
+ }
+ if (typeIsAbsentOrPresentWithoutBackportsFrom(factory.objectsType, AndroidApiLevel.R)) {
+ initializeAndroidRObjectsMethodProviders(factory);
+ if (typeIsPresent(factory.supplierType)) {
+ initializeAndroidRObjectsMethodProviderWithSupplier(factory);
+ }
+ }
}
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.S)) {
initializeAndroidSMethodProviders(factory);
+ if (typeIsPresentWithoutBackportsFrom(factory.setType, AndroidApiLevel.S)) {
+ initializeAndroidSSetListMapMethodProviders(factory);
+ }
}
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.Sv2)) {
initializeAndroidSv2MethodProviders(factory);
}
if (options.getMinApiLevel().isLessThan(AndroidApiLevel.T)) {
initializeAndroidTMethodProviders(factory);
- }
-
- // The following providers are implemented at API level T. For backporting they require
- // the java.util.Optional class to be present, either through library desugaring or natively.
- // If the java.util.Optional class is not present, we do not backport to avoid confusion in
- // error messages.
- if (appView.typeRewriter.hasRewrittenType(factory.optionalType, appView)
- || options.getMinApiLevel().betweenBothIncluded(AndroidApiLevel.N, AndroidApiLevel.Sv2)) {
- initializeAndroidOptionalTMethodProviders(factory);
- }
-
- // The following providers are currently not implemented at any API level in Android. For
- // backporting they require the java.util.stream.Stream class to be present, either through
- // library desugaring or natively. If the class is not present, we do not desugar to avoid
- // confusion in error messages.
- if (appView.typeRewriter.hasRewrittenType(factory.streamType, appView)
- || options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)) {
- initializeStreamMethodProviders(factory);
- }
-
- // The following providers are currently not implemented at any API level in Android. For
- // backporting they require the java.util.function.Predicate class to be present, either
- // through library desugaring or natively. If the class is not present, we do not desugar to
- // avoid confusion in error messages.
- if (appView.typeRewriter.hasRewrittenType(factory.predicateType, appView)
- || options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)) {
- initializePredicateMethodProviders(factory);
- }
-
- if (appView.typeRewriter.hasRewrittenType(factory.supplierType, appView)) {
- // TODO(b/191188594): Consider adding the Objects method from R here, or instead
- // rely on desugared library to support them.
- initializeObjectsMethodProviders(factory);
+ if (typeIsPresentWithoutBackportsFrom(factory.optionalType, AndroidApiLevel.T)) {
+ initializeAndroidOptionalTMethodProviders(factory);
+ }
}
// These are currently not implemented at any API level in Android.
+ if (typeIsPresentWithoutNeverIntroducedBackports(factory.streamType)) {
+ initializeStreamMethodProviders(factory);
+ }
+ if (typeIsPresentWithoutNeverIntroducedBackports(factory.predicateType)) {
+ initializePredicateMethodProviders(factory);
+ }
initializeJava9MethodProviders(factory);
initializeJava10MethodProviders(factory);
initializeJava11MethodProviders(factory);
}
+ private Map<DexType, AndroidApiLevel> initializeTypeMinApi(DexItemFactory factory) {
+ ImmutableMap.Builder<DexType, AndroidApiLevel> builder = ImmutableMap.builder();
+ builder.put(factory.objectsType, AndroidApiLevel.K);
+ builder.put(factory.optionalType, AndroidApiLevel.N);
+ builder.put(factory.predicateType, AndroidApiLevel.N);
+ builder.put(factory.setType, AndroidApiLevel.B);
+ builder.put(factory.streamType, AndroidApiLevel.N);
+ builder.put(factory.supplierType, AndroidApiLevel.N);
+ ImmutableMap<DexType, AndroidApiLevel> typeMinApi = builder.build();
+ assert minApiMatchDatabaseMinApi(typeMinApi);
+ return typeMinApi;
+ }
+
+ private boolean minApiMatchDatabaseMinApi(ImmutableMap<DexType, AndroidApiLevel> typeMinApi) {
+ // TODO(b/224954240): Remove the assertion and always use the apiDatabase.
+ typeMinApi.forEach(
+ (type, api) -> {
+ ComputedApiLevel apiLevel =
+ appView
+ .apiLevelCompute()
+ .computeApiLevelForLibraryReference(type, ComputedApiLevel.unknown());
+ if (!apiLevel.isKnownApiLevel()) {
+ // API database is missing.
+ return;
+ }
+ AndroidApiLevel theApi = apiLevel.asKnownApiLevel().getApiLevel();
+ if (appView.typeRewriter.hasRewrittenType(type, appView)) {
+ assert theApi.equals(appView.options().getMinApiLevel());
+ return;
+ }
+ assert theApi.equals(api.max(appView.options().getMinApiLevel()));
+ });
+ return true;
+ }
+
+ private boolean typeIsAbsentOrPresentWithoutBackportsFrom(
+ DexType type, AndroidApiLevel apiLevel) {
+ return !typeIsPresent(type) || typeIsPresentWithoutBackportsFrom(type, apiLevel);
+ }
+
+ private boolean typeIsPresentWithoutNeverIntroducedBackports(DexType type) {
+ return typeIsPresentWithoutBackportsFrom(type, AndroidApiLevel.ANDROID_PLATFORM);
+ }
+
+ private boolean typeIsPresentWithoutBackportsFrom(DexType type, AndroidApiLevel methodsMinAPI) {
+ if (appView.typeRewriter.hasRewrittenType(type, appView)) {
+ // Desugared library is enabled, the methods are present if desugared library specifies it.
+ return methodsMinAPI.isGreaterThan(AndroidApiLevel.N)
+ && !appView.options().machineDesugaredLibrarySpecification.includesJDK11Methods();
+ }
+ // TODO(b/224954240): Always use the apiDatabase when always available.
+ if (!appView.options().getMinApiLevel().isGreaterThanOrEqualTo(typeMinApi.get(type))) {
+ // If the class is not present, we do not backport to avoid confusion in error messages.
+ return false;
+ }
+ return appView.options().getMinApiLevel().isLessThan(methodsMinAPI);
+ }
+
+ private boolean typeIsPresent(DexType type) {
+ // TODO(b/224954240): Always use the apiDatabase when always available.
+ return appView.options().getMinApiLevel().isGreaterThanOrEqualTo(typeMinApi.get(type))
+ || appView.typeRewriter.hasRewrittenType(type, appView);
+ }
+
boolean isEmpty() {
return rewritable.isEmpty();
}
@@ -231,54 +295,11 @@
rewritable.keySet().forEach(consumer);
}
- private void initializeAndroidKMethodProviders(DexItemFactory factory) {
- // Byte
- DexType type = factory.boxedByteType;
- // int Byte.compare(byte a, byte b)
- DexString name = factory.createString("compare");
- DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
- DexMethod method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::ByteMethods_compare));
-
- // Short
- type = factory.boxedShortType;
- // int Short.compare(short a, short b)
- name = factory.createString("compare");
- proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::ShortMethods_compare));
-
- // Integer
- type = factory.boxedIntType;
- // int Integer.compare(int a, int b)
- name = factory.createString("compare");
- proto = factory.createProto(factory.intType, factory.intType, factory.intType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::IntegerMethods_compare));
-
- // Long
- type = factory.boxedLongType;
- // int Long.compare(long a, long b)
- name = factory.createString("compare");
- proto = factory.createProto(factory.intType, factory.longType, factory.longType);
- method = factory.createMethod(type, proto, name);
- addProvider(new InvokeRewriter(method, LongMethodRewrites.rewriteCompare()));
-
- // Boolean
- type = factory.boxedBooleanType;
- // int Boolean.compare(boolean a, boolean b)
- name = factory.createString("compare");
- proto = factory.createProto(factory.intType, factory.booleanType, factory.booleanType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::BooleanMethods_compare));
-
- // Character
- type = factory.boxedCharType;
- // int Character.compare(char a, char b)
- name = factory.createString("compare");
- proto = factory.createProto(factory.intType, factory.charType, factory.charType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::CharacterMethods_compare));
+ private void initializeAndroidKObjectsMethodProviders(DexItemFactory factory) {
+ DexType type;
+ DexString name;
+ DexProto proto;
+ DexMethod method;
// Objects
type = factory.objectsType;
@@ -342,6 +363,56 @@
addProvider(
new MethodGenerator(
method, BackportedMethods::ObjectsMethods_toStringDefault, "toStringDefault"));
+ }
+
+ private void initializeAndroidKMethodProviders(DexItemFactory factory) {
+ // Byte
+ DexType type = factory.boxedByteType;
+ // int Byte.compare(byte a, byte b)
+ DexString name = factory.createString("compare");
+ DexProto proto = factory.createProto(factory.intType, factory.byteType, factory.byteType);
+ DexMethod method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::ByteMethods_compare));
+
+ // Short
+ type = factory.boxedShortType;
+ // int Short.compare(short a, short b)
+ name = factory.createString("compare");
+ proto = factory.createProto(factory.intType, factory.shortType, factory.shortType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::ShortMethods_compare));
+
+ // Integer
+ type = factory.boxedIntType;
+ // int Integer.compare(int a, int b)
+ name = factory.createString("compare");
+ proto = factory.createProto(factory.intType, factory.intType, factory.intType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::IntegerMethods_compare));
+
+ // Long
+ type = factory.boxedLongType;
+ // int Long.compare(long a, long b)
+ name = factory.createString("compare");
+ proto = factory.createProto(factory.intType, factory.longType, factory.longType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new InvokeRewriter(method, LongMethodRewrites.rewriteCompare()));
+
+ // Boolean
+ type = factory.boxedBooleanType;
+ // int Boolean.compare(boolean a, boolean b)
+ name = factory.createString("compare");
+ proto = factory.createProto(factory.intType, factory.booleanType, factory.booleanType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::BooleanMethods_compare));
+
+ // Character
+ type = factory.boxedCharType;
+ // int Character.compare(char a, char b)
+ name = factory.createString("compare");
+ proto = factory.createProto(factory.intType, factory.charType, factory.charType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::CharacterMethods_compare));
// Collections
type = factory.collectionsType;
@@ -367,6 +438,27 @@
new MethodGenerator(method, BackportedMethods::CollectionsMethods_emptyListIterator));
}
+ private void initializeAndroidNObjectsMethodProviders(DexItemFactory factory) {
+ DexString name;
+ DexProto proto;
+ DexMethod method;
+
+ // Objects
+ DexType type = factory.objectsType;
+
+ // boolean Objects.isNull(Object o)
+ name = factory.createString("isNull");
+ proto = factory.createProto(factory.booleanType, factory.objectType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::ObjectsMethods_isNull));
+
+ // boolean Objects.nonNull(Object a)
+ name = factory.createString("nonNull");
+ proto = factory.createProto(factory.booleanType, factory.objectType);
+ method = factory.createMethod(type, proto, name);
+ addProvider(new MethodGenerator(method, BackportedMethods::ObjectsMethods_nonNull));
+ }
+
private void initializeAndroidNMethodProviders(DexItemFactory factory) {
// Byte
DexType type = factory.boxedByteType;
@@ -540,21 +632,6 @@
method = factory.createMethod(type, proto, name);
addProvider(new InvokeRewriter(method, NumericMethodRewrites.rewriteAsIdentity()));
- // Objects
- type = factory.objectsType;
-
- // boolean Objects.isNull(Object o)
- name = factory.createString("isNull");
- proto = factory.createProto(factory.booleanType, factory.objectType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::ObjectsMethods_isNull));
-
- // boolean Objects.nonNull(Object a)
- name = factory.createString("nonNull");
- proto = factory.createProto(factory.booleanType, factory.objectType);
- method = factory.createMethod(type, proto, name);
- addProvider(new MethodGenerator(method, BackportedMethods::ObjectsMethods_nonNull));
-
// Math & StrictMath, which have some symmetric, binary-compatible APIs
DexType[] mathTypes = {factory.mathType, factory.strictMathType};
for (DexType mathType : mathTypes) {
@@ -876,7 +953,20 @@
method, BackportedMethods::StringMethods_joinIterable, "joinIterable"));
}
- private void initializeAndroidRMethodProviders(DexItemFactory factory) {
+ private void initializeAndroidRObjectsMethodProviderWithSupplier(DexItemFactory factory) {
+ // Objects
+ DexType type = factory.objectsType;
+
+ // T Objects.requireNonNullElseGet(T, Supplier<? extends T>)
+ DexString name = factory.createString("requireNonNullElseGet");
+ DexProto proto =
+ factory.createProto(factory.objectType, factory.objectType, factory.supplierType);
+ DexMethod method = factory.createMethod(type, proto, name);
+ addProvider(
+ new MethodGenerator(method, BackportedMethods::ObjectsMethods_requireNonNullElseGet));
+ }
+
+ private void initializeAndroidRObjectsMethodProviders(DexItemFactory factory) {
DexType type;
DexString name;
DexProto proto;
@@ -892,13 +982,6 @@
addProvider(
new MethodGenerator(method, BackportedMethods::ObjectsMethods_requireNonNullElse));
- // T Objects.requireNonNullElseGet(T, Supplier<? extends T>)
- name = factory.createString("requireNonNullElseGet");
- proto = factory.createProto(factory.objectType, factory.objectType, factory.supplierType);
- method = factory.createMethod(type, proto, name);
- addProvider(
- new MethodGenerator(method, BackportedMethods::ObjectsMethods_requireNonNullElseGet));
-
// int Objects.checkIndex(int, int)
name = factory.createString("checkIndex");
proto = factory.createProto(factory.intType, factory.intType, factory.intType);
@@ -919,6 +1002,13 @@
method = factory.createMethod(type, proto, name);
addProvider(
new MethodGenerator(method, BackportedMethods::ObjectsMethods_checkFromIndexSize));
+ }
+
+ private void initializeAndroidRSetListMapMethodProviders(DexItemFactory factory) {
+ DexType type;
+ DexString name;
+ DexProto proto;
+ DexMethod method;
// List<E> List.of(<args>) for 0 to 10 arguments and List.of(E[])
type = factory.listType;
@@ -989,7 +1079,7 @@
addProvider(new MethodGenerator(method, BackportedMethods::CollectionMethods_mapEntry));
}
- private void initializeAndroidSMethodProviders(DexItemFactory factory) {
+ private void initializeAndroidSSetListMapMethodProviders(DexItemFactory factory) {
DexType type;
DexString name;
DexProto proto;
@@ -1027,6 +1117,13 @@
addProvider(
new MethodGenerator(
method, BackportedMethods::CollectionsMethods_copyOfMap, "copyOfMap"));
+ }
+
+ private void initializeAndroidSMethodProviders(DexItemFactory factory) {
+ DexType type;
+ DexString name;
+ DexProto proto;
+ DexMethod method;
// Byte
type = factory.boxedByteType;
@@ -1481,7 +1578,7 @@
addProvider(new MethodGenerator(method, BackportedMethods::PredicateMethods_not, "not"));
}
- private void initializeObjectsMethodProviders(DexItemFactory factory) {
+ private void initializeAndroidNObjectsMethodProviderWithSupplier(DexItemFactory factory) {
// Objects
DexType type = factory.objectsType;
@@ -1495,26 +1592,6 @@
}
private void addProvider(MethodProvider generator) {
- if (appView.options().machineDesugaredLibrarySpecification.isSupported(generator.method)) {
- // TODO(b/174453232): Remove this after the configuration file format has bee updated
- // with the "rewrite_method" section.
- if (generator.method.getHolderType() == appView.dexItemFactory().objectsType) {
- // Still backport the new API level 30 methods and Objects.requireNonNull taking
- // one argument.
- String methodName = generator.method.getName().toString();
- if (!methodName.equals("requireNonNull")
- && !methodName.equals("requireNonNullElse")
- && !methodName.equals("requireNonNullElseGet")
- && !methodName.equals("checkIndex")
- && !methodName.equals("checkFromToIndex")
- && !methodName.equals("checkFromIndexSize")) {
- return;
- }
- if (methodName.equals("requireNonNull") && generator.method.getArity() != 1) {
- return;
- }
- }
- }
MethodProvider replaced = rewritable.put(generator.method, generator);
assert replaced == null;
}
@@ -1575,8 +1652,8 @@
this.methodName = methodName;
}
- protected SyntheticKind getSyntheticKind() {
- return SyntheticNaming.SyntheticKind.BACKPORT;
+ protected SyntheticKind getSyntheticKind(SyntheticNaming naming) {
+ return naming.BACKPORT;
}
@Override
@@ -1596,7 +1673,7 @@
return appView
.getSyntheticItems()
.createMethod(
- getSyntheticKind(),
+ this::getSyntheticKind,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
@@ -1644,8 +1721,8 @@
}
@Override
- protected SyntheticKind getSyntheticKind() {
- return SyntheticKind.BACKPORT_WITH_FORWARDING;
+ protected SyntheticKind getSyntheticKind(SyntheticNaming naming) {
+ return naming.BACKPORT_WITH_FORWARDING;
}
}
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 aa2ecfa..e642655 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
@@ -28,7 +28,6 @@
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.collect.ImmutableList;
@@ -171,7 +170,7 @@
return appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.API_MODEL_OUTLINE,
+ kinds -> kinds.API_MODEL_OUTLINE,
context,
appView,
syntheticMethodBuilder -> {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java
index 1d55e7e..8853e8b 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/constantdynamic/ConstantDynamicInstructionDesugaring.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.Box;
import java.util.Collection;
import java.util.HashMap;
@@ -117,7 +116,7 @@
appView
.getSyntheticItems()
.createClass(
- SyntheticKind.CONST_DYNAMIC,
+ kinds -> kinds.CONST_DYNAMIC,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
index 520b5ea..f041fe3 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryAPIConverter.java
@@ -36,7 +36,6 @@
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.desugar.desugaredlibrary.apiconversion.DesugaredLibraryWrapperSynthesizerEventConsumer.DesugaredLibraryClasspathWrapperSynthesizeEventConsumer;
import com.android.tools.r8.ir.synthetic.DesugaredLibraryAPIConversionCfCodeProvider.APIConversionCfCodeProvider;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.Iterables;
@@ -126,7 +125,7 @@
static boolean isAPIConversionSyntheticType(
DexType type, DesugaredLibraryWrapperSynthesizer wrapperSynthesizor, AppView<?> appView) {
return wrapperSynthesizor.isSyntheticWrapper(type)
- || appView.getSyntheticItems().isSyntheticOfKind(type, SyntheticKind.API_CONVERSION);
+ || appView.getSyntheticItems().isSyntheticOfKind(type, kinds -> kinds.API_CONVERSION);
}
public static boolean isVivifiedType(DexType type) {
@@ -429,7 +428,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.API_CONVERSION_PARAMETERS,
+ kinds -> kinds.API_CONVERSION_PARAMETERS,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
@@ -534,7 +533,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.API_CONVERSION,
+ kinds -> kinds.API_CONVERSION,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryEnumConversionSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryEnumConversionSynthesizer.java
index 60a2281..d69a158 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryEnumConversionSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryEnumConversionSynthesizer.java
@@ -21,7 +21,6 @@
import com.android.tools.r8.synthesis.SyntheticClasspathClassBuilder;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder.SyntheticCodeGenerator;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.synthesis.SyntheticProgramClassBuilder;
import com.google.common.collect.Iterables;
@@ -116,7 +115,7 @@
DexProgramClass enumConversion =
appView
.getSyntheticItems()
- .getExistingFixedClass(SyntheticKind.ENUM_CONVERSION, clazz, appView);
+ .getExistingFixedClass(kinds -> kinds.ENUM_CONVERSION, clazz, appView);
DexMethod method =
factory.createMethod(
enumConversion.type, factory.createProto(destType, srcType), factory.convertMethodName);
@@ -137,7 +136,7 @@
return appView
.getSyntheticItems()
.ensureFixedClass(
- SyntheticKind.ENUM_CONVERSION,
+ kinds -> kinds.ENUM_CONVERSION,
programContext,
appView,
builder -> buildEnumMethodsWithCode(builder, enumFields, type, vivifiedType),
@@ -150,14 +149,14 @@
if (context.isProgramClass()) {
return appView
.getSyntheticItems()
- .getExistingFixedClass(SyntheticKind.ENUM_CONVERSION, context, appView);
+ .getExistingFixedClass(kinds -> kinds.ENUM_CONVERSION, context, appView);
}
DexType type = context.type;
DexType vivifiedType = vivifiedTypeFor(context.type, appView);
return appView
.getSyntheticItems()
.ensureFixedClasspathClass(
- SyntheticKind.ENUM_CONVERSION,
+ kinds -> kinds.ENUM_CONVERSION,
context.asClasspathOrLibraryClass(),
appView,
builder -> buildEnumMethodsWithoutCode(builder, type, vivifiedType),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
index e1fbb96..79f1ff2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/apiconversion/DesugaredLibraryWrapperSynthesizer.java
@@ -40,8 +40,8 @@
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.synthesis.SyntheticClassBuilder;
+import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.StringDiagnostic;
import java.util.ArrayList;
import java.util.Collection;
@@ -108,8 +108,8 @@
}
public boolean isSyntheticWrapper(DexType type) {
- return appView.getSyntheticItems().isSyntheticOfKind(type, SyntheticKind.WRAPPER)
- || appView.getSyntheticItems().isSyntheticOfKind(type, SyntheticKind.VIVIFIED_WRAPPER);
+ return appView.getSyntheticItems().isSyntheticOfKind(type, kinds -> kinds.WRAPPER)
+ || appView.getSyntheticItems().isSyntheticOfKind(type, kinds -> kinds.VIVIFIED_WRAPPER);
}
public boolean shouldConvert(DexType type, DexMethod method) {
@@ -202,7 +202,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.ARRAY_CONVERSION,
+ kinds -> kinds.ARRAY_CONVERSION,
contextSupplier.get(),
appView,
builder ->
@@ -351,7 +351,7 @@
DexType vivifiedType = vivifiedTypeFor(type);
DexClass wrapper =
ensureClasspathWrapper(
- SyntheticKind.WRAPPER,
+ kinds -> kinds.WRAPPER,
vivifiedType,
type,
classpathOrLibraryContext,
@@ -363,7 +363,7 @@
DesugaredLibraryWrapperSynthesizer::codeForClasspathMethod));
DexClass vivifiedWrapper =
ensureClasspathWrapper(
- SyntheticKind.VIVIFIED_WRAPPER,
+ kinds -> kinds.VIVIFIED_WRAPPER,
type,
vivifiedType,
classpathOrLibraryContext,
@@ -382,8 +382,8 @@
DexClass vivifiedWrapper;
DexClass wrapper;
assert appView.options().isDesugaredLibraryCompilation();
- wrapper = getExistingProgramWrapper(context, SyntheticKind.WRAPPER);
- vivifiedWrapper = getExistingProgramWrapper(context, SyntheticKind.VIVIFIED_WRAPPER);
+ wrapper = getExistingProgramWrapper(context, kinds -> kinds.WRAPPER);
+ vivifiedWrapper = getExistingProgramWrapper(context, kinds -> kinds.VIVIFIED_WRAPPER);
DexField wrapperField = getWrapperUniqueField(wrapper);
DexField vivifiedWrapperField = getWrapperUniqueField(vivifiedWrapper);
return new WrapperConversions(
@@ -391,8 +391,9 @@
getConversion(vivifiedWrapper, wrapperField.type, vivifiedWrapperField.type));
}
- private DexProgramClass getExistingProgramWrapper(DexClass context, SyntheticKind kind) {
- return appView.getSyntheticItems().getExistingFixedClass(kind, context, appView);
+ private DexProgramClass getExistingProgramWrapper(
+ DexClass context, SyntheticKindSelector kindSelector) {
+ return appView.getSyntheticItems().getExistingFixedClass(kindSelector, context, appView);
}
private DexMethod getConversion(DexClass wrapper, DexType returnType, DexType argType) {
@@ -412,7 +413,7 @@
}
private DexProgramClass ensureProgramWrapper(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexType wrappingType,
DexType wrappedType,
DexProgramClass programContext,
@@ -422,7 +423,7 @@
return appView
.getSyntheticItems()
.ensureFixedClass(
- kind,
+ kindSelector,
programContext,
appView,
builder -> buildWrapper(wrappingType, wrappedType, programContext, builder),
@@ -432,7 +433,7 @@
}
private DexClasspathClass ensureClasspathWrapper(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexType wrappingType,
DexType wrappedType,
ClasspathOrLibraryClass classpathOrLibraryContext,
@@ -442,7 +443,7 @@
return appView
.getSyntheticItems()
.ensureFixedClasspathClass(
- kind,
+ kindSelector,
classpathOrLibraryContext,
appView,
builder -> {
@@ -459,7 +460,10 @@
}
private void getExistingProgramConversionMethod(
- SyntheticKind kind, DexProgramClass context, DexClass wrapper, DexClass reverseWrapper) {
+ SyntheticKindSelector kindSelector,
+ DexProgramClass context,
+ DexClass wrapper,
+ DexClass reverseWrapper) {
DexField wrapperField = getWrapperUniqueField(wrapper);
DexField reverseWrapperField = getWrapperUniqueField(reverseWrapper);
DexProto proto = factory.createProto(reverseWrapperField.type, wrapperField.type);
@@ -468,7 +472,7 @@
.ensureFixedClassMethod(
factory.convertMethodName,
proto,
- kind,
+ kindSelector,
context,
appView,
ignored -> {},
@@ -694,18 +698,18 @@
DexProgramClass programContext = context.asProgramClass();
DexClass wrapper =
ensureProgramWrapper(
- SyntheticKind.WRAPPER, vivifiedTypeFor(type), type, programContext, eventConsumer);
+ kinds -> kinds.WRAPPER, vivifiedTypeFor(type), type, programContext, eventConsumer);
DexClass vivifiedWrapper =
ensureProgramWrapper(
- SyntheticKind.VIVIFIED_WRAPPER,
+ kinds -> kinds.VIVIFIED_WRAPPER,
type,
vivifiedTypeFor(type),
programContext,
eventConsumer);
getExistingProgramConversionMethod(
- SyntheticKind.WRAPPER, programContext, wrapper, vivifiedWrapper);
+ kinds -> kinds.WRAPPER, programContext, wrapper, vivifiedWrapper);
getExistingProgramConversionMethod(
- SyntheticKind.VIVIFIED_WRAPPER, programContext, vivifiedWrapper, wrapper);
+ kinds -> kinds.VIVIFIED_WRAPPER, programContext, vivifiedWrapper, wrapper);
}
private void ensureProgramWrappersVirtualMethods(
@@ -713,7 +717,7 @@
Iterable<DexMethod> methods,
CfClassSynthesizerDesugaringEventConsumer eventConsumer,
ClassSynthesisDesugaringContext processingContext) {
- DexProgramClass wrapper = getExistingProgramWrapper(context, SyntheticKind.WRAPPER);
+ DexProgramClass wrapper = getExistingProgramWrapper(context, kinds -> kinds.WRAPPER);
DexEncodedField wrapperField = getWrapperUniqueEncodedField(wrapper);
wrapper.addVirtualMethods(
synthesizeVirtualMethodsForTypeWrapper(
@@ -726,7 +730,7 @@
eventConsumer,
() -> processingContext.createUniqueContext(wrapper))));
DexProgramClass vivifiedWrapper =
- getExistingProgramWrapper(context, SyntheticKind.VIVIFIED_WRAPPER);
+ getExistingProgramWrapper(context, kinds -> kinds.VIVIFIED_WRAPPER);
DexEncodedField vivifiedWrapperField = getWrapperUniqueEncodedField(vivifiedWrapper);
vivifiedWrapper.addVirtualMethods(
synthesizeVirtualMethodsForVivifiedTypeWrapper(
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
index d578eed..1f52b3d 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/machinespecification/MachineDesugaredLibrarySpecification.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.SemanticVersion;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -20,6 +21,8 @@
private final MachineTopLevelFlags topLevelFlags;
private final MachineRewritingFlags rewritingFlags;
+ private int leadingVersionNumberCache = -1;
+
public static MachineDesugaredLibrarySpecification empty() {
return new MachineDesugaredLibrarySpecification(
false, MachineTopLevelFlags.empty(), MachineRewritingFlags.builder().build()) {
@@ -175,4 +178,16 @@
public AndroidApiLevel getRequiredCompilationApiLevel() {
return topLevelFlags.getRequiredCompilationAPILevel();
}
+
+ private int getLeadingVersionNumber() {
+ if (leadingVersionNumberCache != -1) {
+ return leadingVersionNumberCache;
+ }
+ String[] split = topLevelFlags.getIdentifier().split(":");
+ return leadingVersionNumberCache = SemanticVersion.parse(split[split.length - 1]).getMajor();
+ }
+
+ public boolean includesJDK11Methods() {
+ return getLeadingVersionNumber() >= 2;
+ }
}
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 6102e1a..1fa4b75 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
@@ -19,6 +19,7 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.retargeter.DesugaredLibraryRetargeterSynthesizerEventConsumer.DesugaredLibraryRetargeterL8SynthesizerEventConsumer;
import com.android.tools.r8.ir.synthetic.EmulateDispatchSyntheticCfCodeProvider;
import com.android.tools.r8.synthesis.SyntheticClassBuilder;
+import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import java.util.LinkedHashMap;
@@ -46,7 +47,7 @@
.ensureFixedClasspathMethodFromType(
retarget.getName(),
retarget.getProto(),
- SyntheticKind.RETARGET_STUB,
+ kinds -> kinds.RETARGET_STUB,
retarget.getHolderType(),
appView,
ignored -> {},
@@ -70,14 +71,20 @@
return ensureRetargetMethod(forwardingMethod(descriptor), eventConsumer);
}
+ private boolean verifyKind(DerivedMethod method, SyntheticKindSelector kindSelector) {
+ SyntheticKind kind = kindSelector.select(appView.getSyntheticItems().getNaming());
+ assert method.getHolderKind().equals(kind);
+ return true;
+ }
+
private DexMethod emulatedHolderDispatchMethod(DexType holder, DerivedMethod method) {
- assert method.getHolderKind() == SyntheticKind.RETARGET_CLASS;
+ assert verifyKind(method, kinds -> kinds.RETARGET_CLASS);
DexProto newProto = appView.dexItemFactory().prependHolderToProto(method.getMethod());
return appView.dexItemFactory().createMethod(holder, newProto, method.getName());
}
DexMethod emulatedInterfaceDispatchMethod(DexType holder, DerivedMethod method) {
- assert method.getHolderKind() == SyntheticKind.RETARGET_INTERFACE;
+ assert verifyKind(method, kinds -> kinds.RETARGET_INTERFACE);
return appView.dexItemFactory().createMethod(holder, method.getProto(), method.getName());
}
@@ -102,7 +109,7 @@
appView
.getSyntheticItems()
.getExistingFixedClass(
- emulatedDispatchMethod.getHolderKind(), holderContext, appView);
+ ignored -> emulatedDispatchMethod.getHolderKind(), holderContext, appView);
DexMethod dispatchMethod =
emulatedHolderDispatchMethod(syntheticClass.type, emulatedDispatchMethod);
assert syntheticClass.lookupMethod(dispatchMethod) != null;
@@ -115,7 +122,7 @@
appView
.getSyntheticItems()
.ensureFixedClasspathClass(
- SyntheticKind.RETARGET_CLASS,
+ kinds -> kinds.RETARGET_CLASS,
context,
appView,
classBuilder ->
@@ -140,7 +147,7 @@
appView
.getSyntheticItems()
.ensureFixedClass(
- emulatedDispatchMethod.getHolderKind(),
+ ignored -> emulatedDispatchMethod.getHolderKind(),
holderContext,
appView,
classBuilder -> buildHolderDispatchMethod(classBuilder, itfClass, descriptor, null),
@@ -156,14 +163,14 @@
if (appView.options().isDesugaredLibraryCompilation()) {
return appView
.getSyntheticItems()
- .getExistingFixedClass(itfMethod.getHolderKind(), itfContext, appView);
+ .getExistingFixedClass(ignored -> itfMethod.getHolderKind(), itfContext, appView);
}
ClasspathOrLibraryClass context = itfContext.asClasspathOrLibraryClass();
assert context != null;
return appView
.getSyntheticItems()
.ensureFixedClasspathClass(
- SyntheticKind.RETARGET_INTERFACE,
+ kinds -> kinds.RETARGET_INTERFACE,
context,
appView,
classBuilder -> buildInterfaceDispatchMethod(classBuilder, descriptor),
@@ -180,7 +187,7 @@
return appView
.getSyntheticItems()
.ensureFixedClass(
- itfMethod.getHolderKind(),
+ ignore -> itfMethod.getHolderKind(),
itfContext,
appView,
classBuilder -> buildInterfaceDispatchMethod(classBuilder, descriptor),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
index 182202b..5f385c5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineEmulatedInterfaceConverter.java
@@ -16,7 +16,7 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedInterfaceDescriptor;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.Sets;
import java.util.ArrayList;
@@ -68,7 +68,8 @@
private EmulatedDispatchMethodDescriptor computeEmulatedDispatchDescriptor(
DexMethod method, HumanRewritingFlags rewritingFlags, AppInfoWithClassHierarchy appInfo) {
- DerivedMethod forwardingMethod = new DerivedMethod(method, SyntheticKind.COMPANION_CLASS);
+ SyntheticNaming syntheticNaming = appInfo.getSyntheticItems().getNaming();
+ DerivedMethod forwardingMethod = new DerivedMethod(method, syntheticNaming.COMPANION_CLASS);
DexMethod itfDexMethod =
appInfo
.dexItemFactory()
@@ -78,7 +79,7 @@
method.getName());
DerivedMethod interfaceMethod = new DerivedMethod(itfDexMethod);
DerivedMethod dispatchMethod =
- new DerivedMethod(method, SyntheticKind.EMULATED_INTERFACE_CLASS);
+ new DerivedMethod(method, syntheticNaming.EMULATED_INTERFACE_CLASS);
LinkedHashMap<DexType, DerivedMethod> dispatchCases = getDispatchCases(rewritingFlags, method);
return new EmulatedDispatchMethodDescriptor(
interfaceMethod, dispatchMethod, forwardingMethod, dispatchCases);
@@ -109,6 +110,7 @@
}
}
if (subInterfaces != null) {
+ SyntheticNaming syntheticNaming = appInfo.getSyntheticItems().getNaming();
for (int i = subInterfaces.size() - 1; i >= 0; i--) {
DexClass subInterfaceClass = appInfo.definitionFor(subInterfaces.get(i));
assert subInterfaceClass != null;
@@ -119,7 +121,8 @@
assert result.isDefaultMethod();
DexMethod reference = result.getReference();
extraDispatchCases.put(
- subInterfaceClass.type, new DerivedMethod(reference, SyntheticKind.COMPANION_CLASS));
+ subInterfaceClass.type,
+ new DerivedMethod(reference, syntheticNaming.COMPANION_CLASS));
}
}
} else {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
index 6db6518..f64a3d0 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/specificationconversion/HumanToMachineRetargetConverter.java
@@ -15,7 +15,7 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.DerivedMethod;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedDispatchMethodDescriptor;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineRewritingFlags;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.TraversalContinuation;
import com.google.common.collect.Sets;
import java.util.LinkedHashMap;
@@ -123,11 +123,12 @@
return;
}
// TODO(b/184026720): Implement library boundaries.
+ SyntheticNaming syntheticNaming = appInfo.getSyntheticItems().getNaming();
DerivedMethod forwardingMethod = new DerivedMethod(forwardingDexMethod);
DerivedMethod interfaceMethod =
- new DerivedMethod(src.getReference(), SyntheticKind.RETARGET_INTERFACE);
+ new DerivedMethod(src.getReference(), syntheticNaming.RETARGET_INTERFACE);
DerivedMethod dispatchMethod =
- new DerivedMethod(src.getReference(), SyntheticKind.RETARGET_CLASS);
+ new DerivedMethod(src.getReference(), syntheticNaming.RETARGET_CLASS);
LinkedHashMap<DexType, DerivedMethod> dispatchCases = new LinkedHashMap<>();
builder.putEmulatedVirtualRetarget(
src.getReference(),
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java
index 6636e1e..65379b5 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringForTesting.java
@@ -4,12 +4,12 @@
package com.android.tools.r8.ir.desugar.itf;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
-
public class InterfaceDesugaringForTesting {
+ public static final String EMULATED_INTERFACE_CLASS_SUFFIX = "$-EL";
+
public static String getEmulateLibraryClassNameSuffix() {
- return SyntheticKind.EMULATED_INTERFACE_CLASS.descriptor;
+ return EMULATED_INTERFACE_CLASS_SUFFIX;
}
public static String getCompanionClassNameSuffix() {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
index 5d00719..dc739bb 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceDesugaringSyntheticHelper.java
@@ -41,6 +41,7 @@
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.EmulatedInterfaceDescriptor;
import com.android.tools.r8.ir.desugar.itf.EmulatedInterfaceSynthesizerEventConsumer.ClasspathEmulatedInterfaceSynthesizerEventConsumer;
import com.android.tools.r8.synthesis.SyntheticClassBuilder;
+import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.InternalOptions;
@@ -120,8 +121,14 @@
return true;
}
+ public boolean verifyKind(DerivedMethod method, SyntheticKindSelector kindSelector) {
+ SyntheticKind kind = kindSelector.select(appView.getSyntheticItems().getNaming());
+ assert method.getHolderKind().equals(kind);
+ return true;
+ }
+
DexMethod emulatedInterfaceDispatchMethod(DerivedMethod method, DexType holder) {
- assert method.getHolderKind() == SyntheticKind.EMULATED_INTERFACE_CLASS;
+ assert verifyKind(method, kinds -> kinds.EMULATED_INTERFACE_CLASS);
DexProto newProto = appView.dexItemFactory().prependHolderToProto(method.getMethod());
return appView.dexItemFactory().createMethod(holder, newProto, method.getName());
}
@@ -168,7 +175,7 @@
return appView
.getSyntheticItems()
.ensureFixedClasspathClassFromType(
- SyntheticKind.EMULATED_INTERFACE_MARKER_CLASS,
+ kinds -> kinds.EMULATED_INTERFACE_MARKER_CLASS,
type,
appView,
SyntheticClassBuilder::setInterface,
@@ -247,7 +254,7 @@
if (method.getHolderKind() == null) {
return method.getMethod();
}
- assert method.getHolderKind() == SyntheticKind.COMPANION_CLASS;
+ assert verifyKind(method, kinds -> kinds.COMPANION_CLASS);
DexClassAndMethod resolvedMethod =
appView.appInfoForDesugaring().resolveMethod(method.getMethod(), true).getResolutionPair();
return ensureDefaultAsMethodOfCompanionClassStub(resolvedMethod).getReference();
@@ -256,20 +263,20 @@
DexClassAndMethod ensureEmulatedInterfaceDispatchMethod(
DerivedMethod emulatedDispatchMethod,
ClasspathEmulatedInterfaceSynthesizerEventConsumer eventConsumer) {
- assert emulatedDispatchMethod.getHolderKind() == SyntheticKind.EMULATED_INTERFACE_CLASS;
+ assert verifyKind(emulatedDispatchMethod, kinds -> kinds.EMULATED_INTERFACE_CLASS);
DexClassAndMethod method =
appView
.appInfoForDesugaring()
.resolveMethod(emulatedDispatchMethod.getMethod(), true)
.getResolutionPair();
- assert emulatedDispatchMethod.getHolderKind() == SyntheticKind.EMULATED_INTERFACE_CLASS;
+ assert verifyKind(emulatedDispatchMethod, kinds -> kinds.EMULATED_INTERFACE_CLASS);
if (method.isProgramMethod()) {
assert appView.options().isDesugaredLibraryCompilation();
DexProgramClass emulatedInterface =
appView
.getSyntheticItems()
.getExistingFixedClass(
- SyntheticKind.EMULATED_INTERFACE_CLASS,
+ kinds -> kinds.EMULATED_INTERFACE_CLASS,
method.asProgramMethod().getHolder(),
appView);
DexMethod emulatedInterfaceMethod =
@@ -286,7 +293,7 @@
.ensureFixedClasspathClassMethod(
emulatedInterfaceMethod.getName(),
emulatedInterfaceMethod.getProto(),
- SyntheticKind.EMULATED_INTERFACE_CLASS,
+ kinds -> kinds.EMULATED_INTERFACE_CLASS,
method.getHolder().asClasspathOrLibraryClass(),
appView,
classBuilder -> {},
@@ -420,7 +427,7 @@
.ensureFixedClasspathClassMethod(
companionMethodReference.getName(),
companionMethodReference.getProto(),
- SyntheticKind.COMPANION_CLASS,
+ kinds -> kinds.COMPANION_CLASS,
context,
appView,
classBuilder -> {},
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 85efd2b..2ae7d7d 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
@@ -43,7 +43,6 @@
import com.android.tools.r8.ir.synthetic.ForwardMethodBuilder;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
-import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.structural.Ordered;
@@ -382,7 +381,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticNaming.SyntheticKind.STATIC_INTERFACE_CALL,
+ kind -> kind.STATIC_INTERFACE_CALL,
methodProcessingContext.createUniqueContext(),
appView,
syntheticMethodBuilder ->
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
index 06f2d76..5d14741 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/InterfaceProcessor.java
@@ -26,7 +26,6 @@
import com.android.tools.r8.graph.NestedGraphLens;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.collections.BidirectionalManyToManyRepresentativeMap;
import com.android.tools.r8.utils.collections.BidirectionalManyToOneRepresentativeMap;
@@ -96,7 +95,7 @@
.ensureFixedClassMethod(
methodName,
methodProto,
- SyntheticKind.COMPANION_CLASS,
+ kinds -> kinds.COMPANION_CLASS,
iface,
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java b/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
index 8d14980..b8b50d9 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/itf/ProgramEmulatedInterfaceSynthesizer.java
@@ -18,7 +18,6 @@
import com.android.tools.r8.ir.desugar.itf.EmulatedInterfaceSynthesizerEventConsumer.L8ProgramEmulatedInterfaceSynthesizerEventConsumer;
import com.android.tools.r8.ir.synthetic.EmulateDispatchSyntheticCfCodeProvider;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder;
-import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.synthesis.SyntheticProgramClassBuilder;
import com.android.tools.r8.utils.StringDiagnostic;
import java.util.LinkedHashMap;
@@ -48,7 +47,7 @@
return appView
.getSyntheticItems()
.ensureFixedClass(
- SyntheticNaming.SyntheticKind.EMULATED_INTERFACE_CLASS,
+ kinds -> kinds.EMULATED_INTERFACE_CLASS,
emulatedInterface,
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
index f7e8d1a..d336a16 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/lambda/LambdaInstructionDesugaring.java
@@ -30,7 +30,6 @@
import com.android.tools.r8.ir.desugar.LambdaClass;
import com.android.tools.r8.ir.desugar.LambdaDescriptor;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
-import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.Box;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
@@ -165,7 +164,7 @@
appView
.getSyntheticItems()
.createClass(
- SyntheticNaming.SyntheticKind.LAMBDA,
+ kinds -> kinds.LAMBDA,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
index 8f658a3..4da9973 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/nest/NestBasedAccessDesugaring.java
@@ -36,7 +36,6 @@
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.desugar.ProgramAdditions;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.BooleanUtils;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@@ -444,7 +443,7 @@
return appView
.getSyntheticItems()
.createFixedClass(
- SyntheticKind.INIT_TYPE_ARGUMENT,
+ kinds -> kinds.INIT_TYPE_ARGUMENT,
method.asProgramMethod().getHolder(),
appView,
builder -> {})
@@ -454,7 +453,7 @@
return appView
.getSyntheticItems()
.ensureFixedClasspathClass(
- SyntheticKind.INIT_TYPE_ARGUMENT,
+ kinds -> kinds.INIT_TYPE_ARGUMENT,
method.asClasspathMethod().getHolder(),
appView,
ignored -> {},
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
index a6fcf97..3f17800 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
@@ -51,7 +51,6 @@
import com.android.tools.r8.ir.synthetic.RecordCfCodeProvider.RecordEqualsCfCodeProvider;
import com.android.tools.r8.ir.synthetic.RecordCfCodeProvider.RecordGetFieldsAsObjectsCfCodeProvider;
import com.android.tools.r8.ir.synthetic.SyntheticCfCodeProvider;
-import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -285,7 +284,7 @@
return appView
.getSyntheticItems()
.createMethod(
- SyntheticNaming.SyntheticKind.RECORD_HELPER,
+ kinds -> kinds.RECORD_HELPER,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
@@ -374,7 +373,7 @@
appView
.getSyntheticItems()
.ensureFixedClassFromType(
- SyntheticNaming.SyntheticKind.RECORD_TAG,
+ kinds -> kinds.RECORD_TAG,
factory.recordType,
appView,
builder -> {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
index 476859a..017ba89 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/twr/TwrInstructionDesugaring.java
@@ -22,7 +22,7 @@
import com.android.tools.r8.ir.desugar.FreshLocalProvider;
import com.android.tools.r8.ir.desugar.LocalStackAllocator;
import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
+import com.android.tools.r8.synthesis.SyntheticItems.SyntheticKindSelector;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import java.util.Collection;
@@ -82,7 +82,7 @@
DexProto proto =
factory.createProto(factory.voidType, factory.throwableType, factory.throwableType);
return createAndCallSyntheticMethod(
- SyntheticKind.BACKPORT,
+ kinds -> kinds.BACKPORT,
proto,
BackportedMethods::ThrowableMethods_addSuppressed,
methodProcessingContext,
@@ -98,7 +98,7 @@
factory.createProto(
factory.createArrayType(1, factory.throwableType), factory.throwableType);
return createAndCallSyntheticMethod(
- SyntheticKind.BACKPORT,
+ kinds -> kinds.BACKPORT,
proto,
BackportedMethods::ThrowableMethods_getSuppressed,
methodProcessingContext,
@@ -111,7 +111,7 @@
MethodProcessingContext methodProcessingContext) {
// Synthesize a new method.
return createAndCallSyntheticMethod(
- SyntheticKind.TWR_CLOSE_RESOURCE,
+ kinds -> kinds.TWR_CLOSE_RESOURCE,
twrCloseResourceProto,
BackportedMethods::CloseResourceMethod_closeResourceImpl,
methodProcessingContext,
@@ -120,7 +120,7 @@
}
private ImmutableList<CfInstruction> createAndCallSyntheticMethod(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexProto proto,
BiFunction<InternalOptions, DexMethod, CfCode> generator,
MethodProcessingContext methodProcessingContext,
@@ -130,7 +130,7 @@
appView
.getSyntheticItems()
.createMethod(
- kind,
+ kindSelector,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java
index 9e0908a..0951ff9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/NaturalIntLoopRemover.java
@@ -5,6 +5,7 @@
package com.android.tools.r8.ir.optimize;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.Goto;
import com.android.tools.r8.ir.code.IRCode;
@@ -28,7 +29,10 @@
*/
public class NaturalIntLoopRemover {
- public void run(IRCode code) {
+ public void run(AppView<?> appView, IRCode code) {
+ if (!appView.testing().enableExperimentalLoopUnrolling) {
+ return;
+ }
boolean loopRemoved = false;
for (BasicBlock comparisonBlockCandidate : code.blocks) {
if (isComparisonBlock(comparisonBlockCandidate)) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java b/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
index 3edb51f..f04e328 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/OutlinerImpl.java
@@ -68,7 +68,6 @@
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.InternalOptions.OutlineOptions;
import com.android.tools.r8.utils.ListUtils;
@@ -1525,7 +1524,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.OUTLINE,
+ kinds -> kinds.OUTLINE,
methodProcessingContext.createUniqueContext(),
appView,
builder -> {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
index 260a5a3..1288379 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ServiceLoaderRewriter.java
@@ -24,7 +24,6 @@
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.desugar.ServiceLoaderSourceCode;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
@@ -198,7 +197,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.SERVICE_LOADER,
+ kinds -> kinds.SERVICE_LOADER,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
index 5639925..257fd7d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/UtilityMethodsForCodeOptimizations.java
@@ -17,7 +17,6 @@
import com.android.tools.r8.ir.conversion.MethodProcessor;
import com.android.tools.r8.ir.optimize.templates.CfUtilityMethodsForCodeOptimizations;
import com.android.tools.r8.synthesis.SyntheticItems;
-import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.InternalOptions;
public class UtilityMethodsForCodeOptimizations {
@@ -36,7 +35,7 @@
SyntheticItems syntheticItems = appView.getSyntheticItems();
ProgramMethod syntheticMethod =
syntheticItems.createMethod(
- SyntheticNaming.SyntheticKind.TO_STRING_IF_NOT_NULL,
+ kinds -> kinds.TO_STRING_IF_NOT_NULL,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
@@ -65,7 +64,7 @@
UniqueContext positionContext = methodProcessingContext.createUniqueContext();
ProgramMethod syntheticMethod =
syntheticItems.createMethod(
- SyntheticNaming.SyntheticKind.THROW_CCE_IF_NOT_NULL,
+ kinds -> kinds.THROW_CCE_IF_NOT_NULL,
positionContext,
appView,
builder ->
@@ -95,7 +94,7 @@
SyntheticItems syntheticItems = appView.getSyntheticItems();
ProgramMethod syntheticMethod =
syntheticItems.createMethod(
- SyntheticNaming.SyntheticKind.THROW_IAE,
+ kinds -> kinds.THROW_IAE,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
@@ -123,7 +122,7 @@
SyntheticItems syntheticItems = appView.getSyntheticItems();
ProgramMethod syntheticMethod =
syntheticItems.createMethod(
- SyntheticNaming.SyntheticKind.THROW_ICCE,
+ kinds -> kinds.THROW_ICCE,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
@@ -153,7 +152,7 @@
SyntheticItems syntheticItems = appView.getSyntheticItems();
ProgramMethod syntheticMethod =
syntheticItems.createMethod(
- SyntheticNaming.SyntheticKind.THROW_NSME,
+ kinds -> kinds.THROW_NSME,
methodProcessingContext.createUniqueContext(),
appView,
builder ->
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
index 3c8bdbc..e19e0b6 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingTreeFixer.java
@@ -48,7 +48,6 @@
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.ImmutableArrayUtils;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.SetUtils;
@@ -178,7 +177,7 @@
appView
.getSyntheticItems()
.createMethod(
- SyntheticKind.ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD,
+ kinds -> kinds.ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD,
// Use the context of the checkNotNull() method to ensure the method is placed
// in the same feature split.
processorContext
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java
index ed8958d..6741924 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/LocalEnumUnboxingUtilityClass.java
@@ -22,7 +22,6 @@
import com.android.tools.r8.ir.synthetic.EnumUnboxingCfCodeProvider;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder.SyntheticCodeGenerator;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
public class LocalEnumUnboxingUtilityClass extends EnumUnboxingUtilityClass {
@@ -123,7 +122,7 @@
.ensureFixedClassMethod(
methodName,
methodProto,
- SyntheticKind.ENUM_UNBOXING_LOCAL_UTILITY_CLASS,
+ kinds -> kinds.ENUM_UNBOXING_LOCAL_UTILITY_CLASS,
getSynthesizingContext(),
appView,
emptyConsumer(),
@@ -174,7 +173,7 @@
appView
.getSyntheticItems()
.createFixedClass(
- SyntheticKind.ENUM_UNBOXING_LOCAL_UTILITY_CLASS,
+ kinds -> kinds.ENUM_UNBOXING_LOCAL_UTILITY_CLASS,
enumToUnbox,
appView,
builder -> builder.setUseSortedMethodBacking(true));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
index 096c2cf..55d5c50 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/SharedEnumUnboxingUtilityClass.java
@@ -36,7 +36,6 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.FieldAccessInfoCollectionModifier;
import com.android.tools.r8.synthesis.SyntheticMethodBuilder.SyntheticCodeGenerator;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.ConsumerUtils;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -139,7 +138,7 @@
.ensureFixedClassMethod(
methodName,
methodProto,
- SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS,
+ kinds -> kinds.ENUM_UNBOXING_SHARED_UTILITY_CLASS,
getSynthesizingContext(),
appView,
ConsumerUtils.emptyConsumer(),
@@ -202,7 +201,7 @@
appView
.getSyntheticItems()
.createFixedClass(
- SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS,
+ kinds -> kinds.ENUM_UNBOXING_SHARED_UTILITY_CLASS,
synthesizingContext,
appView,
classBuilder -> {
diff --git a/src/main/java/com/android/tools/r8/naming/Minifier.java b/src/main/java/com/android/tools/r8/naming/Minifier.java
index 3bc7392..1ba7556 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -5,7 +5,7 @@
import static com.android.tools.r8.graph.DexApplication.classesWithDeterministicOrder;
import static com.android.tools.r8.utils.StringUtils.EMPTY_CHAR_ARRAY;
-import static com.android.tools.r8.utils.SymbolGenerationUtils.PRIMITIVE_TYPE_NAMES;
+import static com.android.tools.r8.utils.SymbolGenerationUtils.RESERVED_NAMES;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.AppView;
@@ -132,7 +132,7 @@
SymbolGenerationUtils.numberToIdentifier(state.incrementNameIndex(), mixedCasing);
} while (obfuscationDictionaryForLookup.contains(nextString));
}
- } while (PRIMITIVE_TYPE_NAMES.contains(nextString));
+ } while (RESERVED_NAMES.contains(nextString));
nextName.append(nextString);
return nextName.toString();
}
diff --git a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
index 4599085..1ab29eb 100644
--- a/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
+++ b/src/main/java/com/android/tools/r8/optimize/argumentpropagation/ArgumentPropagatorProgramOptimizer.java
@@ -39,7 +39,6 @@
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.KeepFieldInfo;
import com.android.tools.r8.shaking.KeepMethodInfo;
-import com.android.tools.r8.synthesis.SyntheticNaming.SyntheticKind;
import com.android.tools.r8.utils.AccessUtils;
import com.android.tools.r8.utils.BooleanBox;
import com.android.tools.r8.utils.IntBox;
@@ -812,7 +811,7 @@
appView
.getSyntheticItems()
.createClass(
- SyntheticKind.NON_FIXED_INIT_TYPE_ARGUMENT,
+ kinds -> kinds.NON_FIXED_INIT_TYPE_ARGUMENT,
processorContext.createMethodProcessingContext(method).createUniqueContext(),
appView)
.getType();
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingAnnotationTracer.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingAnnotationTracer.java
index f52b8b7..d119f1c 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingAnnotationTracer.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingAnnotationTracer.java
@@ -13,16 +13,19 @@
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexValue;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.ParameterAnnotationsList;
public class RepackagingAnnotationTracer {
private final AppInfoWithClassHierarchy appInfo;
+ private final GraphLens graphLens;
private final RepackagingUseRegistry registry;
public RepackagingAnnotationTracer(
AppView<? extends AppInfoWithClassHierarchy> appView, RepackagingUseRegistry registry) {
this.appInfo = appView.appInfo();
+ this.graphLens = appView.graphLens();
this.registry = registry;
}
@@ -39,7 +42,7 @@
}
private void traceEncodedAnnotation(DexEncodedAnnotation annotation) {
- registry.registerTypeReference(annotation.type);
+ registry.registerTypeReference(annotation.type, graphLens);
annotation.forEachElement(this::traceAnnotationElement);
}
@@ -94,11 +97,14 @@
break;
case METHOD_TYPE:
- value.asDexValueMethodType().getValue().forEachType(registry::registerTypeReference);
+ value
+ .asDexValueMethodType()
+ .getValue()
+ .forEachType(type -> registry.registerTypeReference(type, graphLens));
break;
case TYPE:
- registry.registerTypeReference(value.asDexValueType().getValue());
+ registry.registerTypeReference(value.asDexValueType().getValue(), graphLens);
break;
default:
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
index 9854d69..e17be11 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingConstraintGraph.java
@@ -105,8 +105,8 @@
new RepackagingUseRegistry(appView, this, clazz, libraryBoundaryNode);
// Trace the references to the immediate super types.
- registry.registerTypeReference(clazz.getSuperType());
- clazz.interfaces.forEach(registry::registerTypeReference);
+ registry.registerTypeReference(clazz.getSuperType(), appView.graphLens());
+ clazz.interfaces.forEach(type -> registry.registerTypeReference(type, appView.graphLens()));
// Trace the references from the class annotations.
new RepackagingAnnotationTracer(appView, registry).trace(clazz.annotations());
@@ -114,10 +114,10 @@
// Trace the references in the nest host and/or members.
if (clazz.isInANest()) {
if (clazz.isNestHost()) {
- clazz.forEachNestMember(registry::registerTypeReference);
+ clazz.forEachNestMember(type -> registry.registerTypeReference(type, appView.graphLens()));
} else {
assert clazz.isNestMember();
- registry.registerTypeReference(clazz.getNestHost());
+ registry.registerTypeReference(clazz.getNestHost(), appView.graphLens());
}
}
@@ -139,7 +139,7 @@
new RepackagingUseRegistry(appView, this, field, libraryBoundaryNode);
// Trace the type of the field.
- registry.registerTypeReference(field.getReference().getType());
+ registry.registerTypeReference(field.getReference().getType(), appView.graphLens());
// Trace the references in the field annotations.
new RepackagingAnnotationTracer(appView, registry).trace(field.getDefinition().annotations());
@@ -151,7 +151,9 @@
new RepackagingUseRegistry(appView, this, method, libraryBoundaryNode);
// Trace the type references in the method signature.
- definition.getProto().forEachType(registry::registerTypeReference);
+ definition
+ .getProto()
+ .forEachType(type -> registry.registerTypeReference(type, appView.graphLens()));
// Check if this overrides a package-private method.
DexClass superClass =
diff --git a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
index 5c5a857..1339cbf 100644
--- a/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/repackaging/RepackagingUseRegistry.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClassAccessFlags;
+import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMember;
import com.android.tools.r8.graph.DexField;
@@ -16,6 +17,7 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.EnclosingMethodAttribute;
+import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.InitClassLens;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.graph.MemberResolutionResult;
@@ -36,10 +38,13 @@
private final AppInfoWithLiveness appInfo;
private final InternalOptions options;
+ private final GraphLens graphLens;
private final RepackagingConstraintGraph constraintGraph;
private final InitClassLens initClassLens;
private final RepackagingConstraintGraph.Node node;
private final RepackagingConstraintGraph.Node missingTypeNode;
+ private final GraphLens codeLens;
+ private final ProgramMethod methodContext;
public RepackagingUseRegistry(
AppView<AppInfoWithLiveness> appView,
@@ -51,8 +56,18 @@
this.options = appView.options();
this.constraintGraph = constraintGraph;
this.initClassLens = appView.initClassLens();
+ this.graphLens = appView.graphLens();
this.node = constraintGraph.getNode(context.getDefinition());
this.missingTypeNode = missingTypeNode;
+ GraphLens codeLens = appView.graphLens();
+ if (context.isMethod()) {
+ Code code = context.asMethod().getDefinition().getCode();
+ if (code != null) {
+ codeLens = code.getCodeLens(appView);
+ }
+ }
+ this.codeLens = codeLens;
+ methodContext = context.isMethod() ? context.asMethod() : null;
}
private boolean isOnlyAccessibleFromSamePackage(DexClass referencedClass) {
@@ -60,11 +75,8 @@
if (accessFlags.isPackagePrivate()) {
return true;
}
- if (accessFlags.isProtected()
- && !appInfo.isSubtype(getContext().getContextType(), referencedClass.getType())) {
- return true;
- }
- return false;
+ return accessFlags.isProtected()
+ && !appInfo.isSubtype(getContext().getContextType(), referencedClass.getType());
}
private boolean isOnlyAccessibleFromSamePackage(
@@ -92,7 +104,7 @@
}
public void registerFieldAccess(DexField field) {
- registerMemberAccess(appInfo.resolveField(field), false);
+ registerMemberAccess(appInfo.resolveField(graphLens.lookupField(field)), false);
}
public ProgramMethod registerMethodReference(DexMethod method) {
@@ -189,32 +201,46 @@
@Override
public void registerInitClass(DexType type) {
- registerFieldAccess(initClassLens.getInitClassField(type));
+ registerMemberAccess(
+ appInfo.resolveField(initClassLens.getInitClassField(graphLens.lookupClassType(type))),
+ false);
}
@Override
public void registerInvokeVirtual(DexMethod invokedMethod) {
- registerMemberAccessForInvoke(appInfo.resolveMethod(invokedMethod, false));
+ registerMemberAccessForInvoke(
+ appInfo.resolveMethod(
+ graphLens.lookupInvokeVirtual(invokedMethod, methodContext, codeLens).getReference(),
+ false));
}
@Override
public void registerInvokeDirect(DexMethod invokedMethod) {
- registerMemberAccessForInvoke(appInfo.unsafeResolveMethodDueToDexFormat(invokedMethod));
+ registerMemberAccessForInvoke(
+ appInfo.unsafeResolveMethodDueToDexFormat(
+ graphLens.lookupInvokeDirect(invokedMethod, methodContext, codeLens).getReference()));
}
@Override
public void registerInvokeStatic(DexMethod invokedMethod) {
- registerMemberAccessForInvoke(appInfo.unsafeResolveMethodDueToDexFormat(invokedMethod));
+ registerMemberAccessForInvoke(
+ appInfo.unsafeResolveMethodDueToDexFormat(
+ graphLens.lookupInvokeStatic(invokedMethod, methodContext, codeLens).getReference()));
}
@Override
public void registerInvokeInterface(DexMethod invokedMethod) {
- registerMemberAccessForInvoke(appInfo.resolveMethod(invokedMethod, true));
+ registerMemberAccessForInvoke(
+ appInfo.resolveMethod(
+ graphLens.lookupInvokeInterface(invokedMethod, methodContext, codeLens).getReference(),
+ true));
}
@Override
public void registerInvokeSuper(DexMethod invokedMethod) {
- registerMemberAccessForInvoke(appInfo.unsafeResolveMethodDueToDexFormat(invokedMethod));
+ registerMemberAccessForInvoke(
+ appInfo.unsafeResolveMethodDueToDexFormat(
+ graphLens.lookupInvokeSuper(invokedMethod, methodContext, codeLens).getReference()));
}
@Override
@@ -229,7 +255,7 @@
@Override
public void registerNewInstance(DexType type) {
- registerTypeAccess(type);
+ registerTypeAccess(graphLens.lookupClassType(type));
}
@Override
@@ -244,12 +270,16 @@
@Override
public void registerTypeReference(DexType type) {
- registerTypeAccess(type);
+ registerTypeReference(type, codeLens);
+ }
+
+ public void registerTypeReference(DexType type, GraphLens applied) {
+ registerTypeAccess(graphLens.lookupType(type, applied));
}
@Override
public void registerInstanceOf(DexType type) {
- registerTypeAccess(type);
+ registerTypeAccess(graphLens.lookupType(type));
}
public void registerEnclosingMethodAttribute(EnclosingMethodAttribute enclosingMethodAttribute) {
diff --git a/src/main/java/com/android/tools/r8/retrace/MappingProvider.java b/src/main/java/com/android/tools/r8/retrace/MappingProvider.java
new file mode 100644
index 0000000..18bf9ee
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/MappingProvider.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.Keep;
+import com.android.tools.r8.retrace.internal.MappingProviderInternal;
+
+@Keep
+public abstract class MappingProvider extends MappingProviderInternal {}
diff --git a/src/main/java/com/android/tools/r8/retrace/MappingProviderBuilder.java b/src/main/java/com/android/tools/r8/retrace/MappingProviderBuilder.java
new file mode 100644
index 0000000..f9dbd492
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/MappingProviderBuilder.java
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.Keep;
+
+@Keep
+public abstract class MappingProviderBuilder<
+ P extends MappingProvider, T extends MappingProviderBuilder<P, T>> {
+
+ public abstract T self();
+
+ public abstract T setAllowExperimental(boolean allowExperimental);
+
+ public abstract T setDiagnosticsHandler(DiagnosticsHandler diagnosticsHandler);
+
+ public abstract P build();
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/ProguardMappingProvider.java b/src/main/java/com/android/tools/r8/retrace/ProguardMappingProvider.java
new file mode 100644
index 0000000..6e8d4fc
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/ProguardMappingProvider.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.Keep;
+import com.android.tools.r8.retrace.internal.ProguardMappingProviderBuilderImpl;
+
+@Keep
+public abstract class ProguardMappingProvider extends MappingProvider {
+
+ public static Builder builder() {
+ return new ProguardMappingProviderBuilderImpl();
+ }
+
+ @Keep
+ public abstract static class Builder
+ extends MappingProviderBuilder<ProguardMappingProvider, Builder> {
+
+ public abstract Builder setProguardMapProducer(ProguardMapProducer proguardMapProducer);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/Retrace.java b/src/main/java/com/android/tools/r8/retrace/Retrace.java
index b4467ea..61ba441 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retrace.java
@@ -314,11 +314,17 @@
// The setup of a retracer should likely also follow a builder pattern instead of having
// static create methods. That would avoid the need to method overload the construction here
// and the default create would become the default build of a retracer.
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(options.getProguardMapProducer())
+ .setDiagnosticsHandler(diagnosticsHandler)
+ .setAllowExperimental(allowExperimentalMapping)
+ .build();
RetracerImpl retracer =
- RetracerImpl.create(
- options.getProguardMapProducer(),
- options.getDiagnosticsHandler(),
- allowExperimentalMapping);
+ RetracerImpl.builder()
+ .setMappingProvider(mappingProvider)
+ .setDiagnosticsHandler(diagnosticsHandler)
+ .build();
retracer
.getMapVersions()
.forEach(
diff --git a/src/main/java/com/android/tools/r8/retrace/Retracer.java b/src/main/java/com/android/tools/r8/retrace/Retracer.java
index 2cbe2a9..9a4eadf 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retracer.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retracer.java
@@ -72,11 +72,22 @@
static Retracer createDefault(
ProguardMapProducer proguardMapProducer, DiagnosticsHandler diagnosticsHandler) {
- return RetracerImpl.create(proguardMapProducer, diagnosticsHandler, false);
+ try {
+ ProguardMappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(proguardMapProducer)
+ .setDiagnosticsHandler(diagnosticsHandler)
+ .build();
+ return Retracer.builder()
+ .setMappingProvider(mappingProvider)
+ .setDiagnosticsHandler(diagnosticsHandler)
+ .build();
+ } catch (Exception e) {
+ throw new InvalidMappingFileException(e);
+ }
}
- static Retracer createExperimental(
- ProguardMapProducer proguardMapProducer, DiagnosticsHandler diagnosticsHandler) {
- return RetracerImpl.create(proguardMapProducer, diagnosticsHandler, true);
+ static RetracerBuilder builder() {
+ return RetracerImpl.builder();
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetracerBuilder.java b/src/main/java/com/android/tools/r8/retrace/RetracerBuilder.java
new file mode 100644
index 0000000..efd56ce
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/RetracerBuilder.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.Keep;
+
+@Keep
+public interface RetracerBuilder {
+
+ RetracerBuilder setMappingProvider(MappingProvider mappingProvider);
+
+ RetracerBuilder setDiagnosticsHandler(DiagnosticsHandler diagnosticsHandler);
+
+ Retracer build();
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/DirectClassNameMapperProguardMapProducer.java b/src/main/java/com/android/tools/r8/retrace/internal/DirectClassNameMapperProguardMapProducer.java
deleted file mode 100644
index b243ff5..0000000
--- a/src/main/java/com/android/tools/r8/retrace/internal/DirectClassNameMapperProguardMapProducer.java
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-package com.android.tools.r8.retrace.internal;
-
-import com.android.tools.r8.naming.ClassNameMapper;
-import com.android.tools.r8.retrace.ProguardMapProducer;
-import java.io.BufferedReader;
-
-public interface DirectClassNameMapperProguardMapProducer extends ProguardMapProducer {
-
- ClassNameMapper getClassNameMapper();
-
- @Override
- default BufferedReader get() {
- throw new RuntimeException("Should not be called for DirectClassNameMapperProguardMapProducer");
- }
-}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/MappingProviderInternal.java b/src/main/java/com/android/tools/r8/retrace/internal/MappingProviderInternal.java
new file mode 100644
index 0000000..c0739c0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/internal/MappingProviderInternal.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.internal;
+
+import com.android.tools.r8.naming.ClassNameMapper;
+
+public abstract class MappingProviderInternal {
+
+ abstract ClassNameMapper getClassNameMapper();
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/ProguardMappingProviderBuilderImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/ProguardMappingProviderBuilderImpl.java
new file mode 100644
index 0000000..8162f5c
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/internal/ProguardMappingProviderBuilderImpl.java
@@ -0,0 +1,58 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.internal;
+
+import com.android.tools.r8.DiagnosticsHandler;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.retrace.InvalidMappingFileException;
+import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
+import java.io.BufferedReader;
+
+public class ProguardMappingProviderBuilderImpl extends ProguardMappingProvider.Builder {
+
+ private ProguardMapProducer proguardMapProducer;
+ private boolean allowExperimental = false;
+ private DiagnosticsHandler diagnosticsHandler = new DiagnosticsHandler() {};
+
+ @Override
+ public ProguardMappingProvider.Builder self() {
+ return this;
+ }
+
+ @Override
+ public ProguardMappingProvider.Builder setAllowExperimental(boolean allowExperimental) {
+ this.allowExperimental = allowExperimental;
+ return self();
+ }
+
+ @Override
+ public ProguardMappingProvider.Builder setDiagnosticsHandler(
+ DiagnosticsHandler diagnosticsHandler) {
+ this.diagnosticsHandler = diagnosticsHandler;
+ return self();
+ }
+
+ @Override
+ public ProguardMappingProvider.Builder setProguardMapProducer(
+ ProguardMapProducer proguardMapProducer) {
+ this.proguardMapProducer = proguardMapProducer;
+ return self();
+ }
+
+ @Override
+ public ProguardMappingProvider build() {
+ try {
+ return new ProguardMappingProviderImpl(
+ ClassNameMapper.mapperFromBufferedReader(
+ new BufferedReader(proguardMapProducer.get()),
+ diagnosticsHandler,
+ true,
+ allowExperimental));
+ } catch (Exception e) {
+ throw new InvalidMappingFileException(e);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/ProguardMappingProviderImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/ProguardMappingProviderImpl.java
new file mode 100644
index 0000000..8ea72fa
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/internal/ProguardMappingProviderImpl.java
@@ -0,0 +1,26 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace.internal;
+
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
+
+/**
+ * IntelliJ highlights the class as being invalid because it cannot see getClassNameMapper is
+ * defined on the class for some reason.
+ */
+public class ProguardMappingProviderImpl extends ProguardMappingProvider {
+
+ private final ClassNameMapper classNameMapper;
+
+ public ProguardMappingProviderImpl(ClassNameMapper classNameMapper) {
+ this.classNameMapper = classNameMapper;
+ }
+
+ @Override
+ ClassNameMapper getClassNameMapper() {
+ return classNameMapper;
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
index 6cac8dd..b01aa7f 100644
--- a/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
+++ b/src/main/java/com/android/tools/r8/retrace/internal/RetracerImpl.java
@@ -11,12 +11,11 @@
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.TypeReference;
-import com.android.tools.r8.retrace.InvalidMappingFileException;
-import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.RetraceFrameResult;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.Retracer;
-import java.io.BufferedReader;
+import com.android.tools.r8.retrace.RetracerBuilder;
import java.util.OptionalInt;
import java.util.Set;
@@ -26,34 +25,12 @@
private final ClassNameMapper classNameMapper;
private final DiagnosticsHandler diagnosticsHandler;
- public RetracerImpl(ClassNameMapper classNameMapper, DiagnosticsHandler diagnosticsHandler) {
+ private RetracerImpl(ClassNameMapper classNameMapper, DiagnosticsHandler diagnosticsHandler) {
this.classNameMapper = classNameMapper;
this.diagnosticsHandler = diagnosticsHandler;
assert classNameMapper != null;
}
- public static RetracerImpl create(
- ProguardMapProducer proguardMapProducer,
- DiagnosticsHandler diagnosticsHandler,
- boolean allowExperimentalMapping) {
- if (proguardMapProducer instanceof DirectClassNameMapperProguardMapProducer) {
- return new RetracerImpl(
- ((DirectClassNameMapperProguardMapProducer) proguardMapProducer).getClassNameMapper(),
- diagnosticsHandler);
- }
- try {
- ClassNameMapper classNameMapper =
- ClassNameMapper.mapperFromBufferedReader(
- new BufferedReader(proguardMapProducer.get()),
- diagnosticsHandler,
- true,
- allowExperimentalMapping);
- return new RetracerImpl(classNameMapper, diagnosticsHandler);
- } catch (Throwable throwable) {
- throw new InvalidMappingFileException(throwable);
- }
- }
-
public DiagnosticsHandler getDiagnosticsHandler() {
return diagnosticsHandler;
}
@@ -109,4 +86,34 @@
public Set<MapVersionMappingInformation> getMapVersions() {
return classNameMapper.getMapVersions();
}
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static class Builder implements RetracerBuilder {
+
+ private MappingProvider mappingProvider;
+ private DiagnosticsHandler diagnosticsHandler = new DiagnosticsHandler() {};
+
+ private Builder() {}
+
+ @Override
+ public Builder setMappingProvider(MappingProvider mappingProvider) {
+ this.mappingProvider = mappingProvider;
+ return this;
+ }
+
+ @Override
+ public Builder setDiagnosticsHandler(DiagnosticsHandler diagnosticsHandler) {
+ this.diagnosticsHandler = diagnosticsHandler;
+ return this;
+ }
+
+ @Override
+ public RetracerImpl build() {
+ return new RetracerImpl(
+ ((MappingProviderInternal) mappingProvider).getClassNameMapper(), diagnosticsHandler);
+ }
+ }
}
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index 1125b65..c3950c4 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -155,7 +155,6 @@
import com.google.common.collect.Sets.SetView;
import it.unimi.dsi.fastutil.objects.Object2BooleanArrayMap;
import it.unimi.dsi.fastutil.objects.Object2BooleanMap;
-import java.lang.reflect.InvocationHandler;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
@@ -246,7 +245,7 @@
// Don't hold a direct pointer to app info (use appView).
private AppInfoWithClassHierarchy appInfo;
private final AppView<AppInfoWithClassHierarchy> appView;
- private final DexItemFactory dexItemFactory;
+ private final EnqueuerDeferredTracing deferredTracing;
private final ExecutorService executorService;
private SubtypingInfo subtypingInfo;
private final InternalOptions options;
@@ -462,7 +461,7 @@
InternalOptions options = appView.options();
this.appInfo = appView.appInfo();
this.appView = appView.withClassHierarchy();
- this.dexItemFactory = appView.dexItemFactory();
+ this.deferredTracing = new EnqueuerDeferredTracing();
this.executorService = executorService;
this.subtypingInfo = subtypingInfo;
this.forceProguardCompatibility = options.forceProguardCompatibility;
@@ -1460,282 +1459,339 @@
}
void traceInstanceFieldRead(DexField field, ProgramMethod currentMethod) {
- traceInstanceFieldRead(field, currentMethod, FieldReadType.READ);
+ traceInstanceFieldRead(field, currentMethod, FieldAccessMetadata.DEFAULT);
}
void traceInstanceFieldReadFromMethodHandle(DexField field, ProgramMethod currentMethod) {
- traceInstanceFieldRead(field, currentMethod, FieldReadType.READ_FROM_METHOD_HANDLE);
+ traceInstanceFieldRead(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE);
}
void traceInstanceFieldReadFromRecordMethodHandle(DexField field, ProgramMethod currentMethod) {
- traceInstanceFieldRead(field, currentMethod, FieldReadType.READ_FROM_RECORD_METHOD_HANDLE);
+ traceInstanceFieldRead(field, currentMethod, FieldAccessMetadata.FROM_RECORD_METHOD_HANDLE);
}
- private enum FieldReadType {
- READ,
- READ_FROM_METHOD_HANDLE,
- READ_FROM_RECORD_METHOD_HANDLE
+ enum FieldAccessKind {
+ INSTANCE_READ,
+ INSTANCE_WRITE,
+ STATIC_READ,
+ STATIC_WRITE;
+
+ boolean isRead() {
+ return this == INSTANCE_READ || this == STATIC_READ;
+ }
+
+ boolean isStatic() {
+ return this == STATIC_READ || this == STATIC_WRITE;
+ }
+
+ boolean isWrite() {
+ return !isRead();
+ }
+ }
+
+ static class FieldAccessMetadata {
+
+ private static int FROM_METHOD_HANDLE_MASK = 1;
+ private static int FROM_RECORD_METHOD_HANDLE_MASK = 2;
+
+ static FieldAccessMetadata DEFAULT = new FieldAccessMetadata(0);
+ static FieldAccessMetadata FROM_METHOD_HANDLE =
+ new FieldAccessMetadata(FROM_METHOD_HANDLE_MASK);
+ static FieldAccessMetadata FROM_RECORD_METHOD_HANDLE =
+ new FieldAccessMetadata(FROM_RECORD_METHOD_HANDLE_MASK);
+
+ private final int flags;
+
+ FieldAccessMetadata(int flags) {
+ this.flags = flags;
+ }
+
+ boolean isFromMethodHandle() {
+ return (flags & FROM_METHOD_HANDLE_MASK) != 0;
+ }
+
+ boolean isFromRecordMethodHandle() {
+ return (flags & FROM_RECORD_METHOD_HANDLE_MASK) != 0;
+ }
}
private void traceInstanceFieldRead(
- DexField fieldReference, ProgramMethod currentMethod, FieldReadType readType) {
+ DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) {
if (!registerFieldRead(fieldReference, currentMethod)) {
return;
}
- resolveField(fieldReference, currentMethod)
- .visitFieldResolutionResults(
- resolutionResult -> {
- fieldAccessAnalyses.forEach(
- analysis ->
- analysis.traceInstanceFieldRead(
- fieldReference, resolutionResult, currentMethod, workList));
+ FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod);
+ if (deferredTracing.deferTracingOfFieldAccess(
+ fieldReference, resolutionResult, currentMethod, FieldAccessKind.INSTANCE_READ, metadata)) {
+ return;
+ }
- ProgramField field = resolutionResult.getProgramField();
- if (field == null) {
- // No need to trace into the non-program code.
- return;
- }
+ resolutionResult.visitFieldResolutionResults(
+ singleResolutionResult -> {
+ fieldAccessAnalyses.forEach(
+ analysis ->
+ analysis.traceInstanceFieldRead(
+ fieldReference, singleResolutionResult, currentMethod, workList));
- assert !mode.isFinalTreeShaking()
- || !field.getDefinition().getOptimizationInfo().isDead()
- : "Unexpected reference in `"
- + currentMethod.toSourceString()
- + "` to field marked dead: "
- + field.getReference().toSourceString();
+ ProgramField field = singleResolutionResult.getProgramField();
+ if (field == null) {
+ // No need to trace into the non-program code.
+ return;
+ }
- if (readType == FieldReadType.READ_FROM_METHOD_HANDLE) {
- fieldAccessInfoCollection.get(field.getReference()).setReadFromMethodHandle();
- } else if (readType == FieldReadType.READ_FROM_RECORD_METHOD_HANDLE) {
- fieldAccessInfoCollection
- .get(field.getReference())
- .setReadFromRecordInvokeDynamic();
- }
+ assert !mode.isFinalTreeShaking() || !field.getDefinition().getOptimizationInfo().isDead()
+ : "Unexpected reference in `"
+ + currentMethod.toSourceString()
+ + "` to field marked dead: "
+ + field.getReference().toSourceString();
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Iget `%s`.", fieldReference);
- }
+ if (metadata.isFromMethodHandle()) {
+ fieldAccessInfoCollection.get(field.getReference()).setReadFromMethodHandle();
+ } else if (metadata.isFromRecordMethodHandle()) {
+ fieldAccessInfoCollection.get(field.getReference()).setReadFromRecordInvokeDynamic();
+ }
- if (field.getReference() != fieldReference) {
- // Mark the initial resolution holder as live.
- markTypeAsLive(resolutionResult.getInitialResolutionHolder(), currentMethod);
- }
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Register Iget `%s`.", fieldReference);
+ }
- workList.enqueueMarkFieldAsReachableAction(
- field, currentMethod, KeepReason.fieldReferencedIn(currentMethod));
- },
- failedResolution -> {
- // Must trace the types from the field reference even if it does not exist.
- traceFieldReference(fieldReference, failedResolution, currentMethod);
- noClassMerging.add(fieldReference.getHolderType());
- });
+ if (field.getReference() != fieldReference) {
+ // Mark the initial resolution holder as live.
+ markTypeAsLive(singleResolutionResult.getInitialResolutionHolder(), currentMethod);
+ }
+
+ workList.enqueueMarkFieldAsReachableAction(
+ field, currentMethod, KeepReason.fieldReferencedIn(currentMethod));
+ },
+ failedResolution -> {
+ // Must trace the types from the field reference even if it does not exist.
+ traceFieldReference(fieldReference, failedResolution, currentMethod);
+ noClassMerging.add(fieldReference.getHolderType());
+ });
}
void traceInstanceFieldWrite(DexField field, ProgramMethod currentMethod) {
- traceInstanceFieldWrite(field, currentMethod, false);
+ traceInstanceFieldWrite(field, currentMethod, FieldAccessMetadata.DEFAULT);
}
void traceInstanceFieldWriteFromMethodHandle(DexField field, ProgramMethod currentMethod) {
- traceInstanceFieldWrite(field, currentMethod, true);
+ traceInstanceFieldWrite(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE);
}
private void traceInstanceFieldWrite(
- DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) {
if (!registerFieldWrite(fieldReference, currentMethod)) {
return;
}
- resolveField(fieldReference, currentMethod)
- .visitFieldResolutionResults(
- resolutionResult -> {
- fieldAccessAnalyses.forEach(
- analysis ->
- analysis.traceInstanceFieldWrite(
- fieldReference, resolutionResult, currentMethod, workList));
+ FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod);
+ if (deferredTracing.deferTracingOfFieldAccess(
+ fieldReference,
+ resolutionResult,
+ currentMethod,
+ FieldAccessKind.INSTANCE_WRITE,
+ metadata)) {
+ return;
+ }
- ProgramField field = resolutionResult.getProgramField();
- if (field == null) {
- // No need to trace into the non-program code.
- return;
- }
+ resolutionResult.visitFieldResolutionResults(
+ singleResolutionResult -> {
+ fieldAccessAnalyses.forEach(
+ analysis ->
+ analysis.traceInstanceFieldWrite(
+ fieldReference, singleResolutionResult, currentMethod, workList));
- assert !mode.isFinalTreeShaking()
- || !field.getDefinition().getOptimizationInfo().isDead()
- : "Unexpected reference in `"
- + currentMethod.toSourceString()
- + "` to field marked dead: "
- + field.getReference().toSourceString();
+ ProgramField field = singleResolutionResult.getProgramField();
+ if (field == null) {
+ // No need to trace into the non-program code.
+ return;
+ }
- if (fromMethodHandle) {
- fieldAccessInfoCollection.get(field.getReference()).setWrittenFromMethodHandle();
- }
+ assert !mode.isFinalTreeShaking() || !field.getDefinition().getOptimizationInfo().isDead()
+ : "Unexpected reference in `"
+ + currentMethod.toSourceString()
+ + "` to field marked dead: "
+ + field.getReference().toSourceString();
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Iput `%s`.", fieldReference);
- }
+ if (metadata.isFromMethodHandle()) {
+ fieldAccessInfoCollection.get(field.getReference()).setWrittenFromMethodHandle();
+ }
- if (field.getReference() != fieldReference) {
- // Mark the initial resolution holder as live.
- markTypeAsLive(resolutionResult.getInitialResolutionHolder(), currentMethod);
- }
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Register Iput `%s`.", fieldReference);
+ }
- KeepReason reason = KeepReason.fieldReferencedIn(currentMethod);
- workList.enqueueMarkFieldAsReachableAction(field, currentMethod, reason);
- },
- failedResolution -> {
- // Must trace the types from the field reference even if it does not exist.
- traceFieldReference(fieldReference, failedResolution, currentMethod);
- noClassMerging.add(fieldReference.getHolderType());
- });
+ if (field.getReference() != fieldReference) {
+ // Mark the initial resolution holder as live.
+ markTypeAsLive(singleResolutionResult.getInitialResolutionHolder(), currentMethod);
+ }
+
+ KeepReason reason = KeepReason.fieldReferencedIn(currentMethod);
+ workList.enqueueMarkFieldAsReachableAction(field, currentMethod, reason);
+ },
+ failedResolution -> {
+ // Must trace the types from the field reference even if it does not exist.
+ traceFieldReference(fieldReference, failedResolution, currentMethod);
+ noClassMerging.add(fieldReference.getHolderType());
+ });
}
void traceStaticFieldRead(DexField field, ProgramMethod currentMethod) {
- traceStaticFieldRead(field, currentMethod, false);
+ traceStaticFieldRead(field, currentMethod, FieldAccessMetadata.DEFAULT);
}
void traceStaticFieldReadFromMethodHandle(DexField field, ProgramMethod currentMethod) {
- traceStaticFieldRead(field, currentMethod, true);
+ traceStaticFieldRead(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE);
}
private void traceStaticFieldRead(
- DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) {
if (!registerFieldRead(fieldReference, currentMethod)) {
return;
}
- resolveField(fieldReference, currentMethod)
- .visitFieldResolutionResults(
- resolutionResult -> {
- fieldAccessAnalyses.forEach(
- analysis ->
- analysis.traceStaticFieldRead(
- fieldReference, resolutionResult, currentMethod, workList));
+ FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod);
+ if (deferredTracing.deferTracingOfFieldAccess(
+ fieldReference, resolutionResult, currentMethod, FieldAccessKind.STATIC_READ, metadata)) {
+ return;
+ }
- ProgramField field = resolutionResult.getProgramField();
- if (field == null) {
- // No need to trace into the non-program code.
- return;
- }
+ resolutionResult.visitFieldResolutionResults(
+ singleResolutionResult -> {
+ fieldAccessAnalyses.forEach(
+ analysis ->
+ analysis.traceStaticFieldRead(
+ fieldReference, singleResolutionResult, currentMethod, workList));
- assert !mode.isFinalTreeShaking()
- || !field.getDefinition().getOptimizationInfo().isDead()
- : "Unexpected reference in `"
- + currentMethod.toSourceString()
- + "` to field marked dead: "
- + field.getReference().toSourceString();
+ ProgramField field = singleResolutionResult.getProgramField();
+ if (field == null) {
+ // No need to trace into the non-program code.
+ return;
+ }
- if (fromMethodHandle) {
- fieldAccessInfoCollection.get(field.getReference()).setReadFromMethodHandle();
- }
+ assert !mode.isFinalTreeShaking() || !field.getDefinition().getOptimizationInfo().isDead()
+ : "Unexpected reference in `"
+ + currentMethod.toSourceString()
+ + "` to field marked dead: "
+ + field.getReference().toSourceString();
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Sget `%s`.", fieldReference);
- }
+ if (metadata.isFromMethodHandle()) {
+ fieldAccessInfoCollection.get(field.getReference()).setReadFromMethodHandle();
+ }
- // If it is a dead proto extension field, don't trace onwards.
- boolean skipTracing =
- appView.withGeneratedExtensionRegistryShrinker(
- shrinker ->
- shrinker.isDeadProtoExtensionField(
- field, fieldAccessInfoCollection, keepInfo),
- false);
- if (skipTracing) {
- addDeadProtoTypeCandidate(field.getHolder());
- return;
- }
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Register Sget `%s`.", fieldReference);
+ }
- if (field.getReference() != fieldReference) {
- // Mark the initial resolution holder as live. Note that this should only be done if
- // the field
- // is not a dead proto field (in which case we bail-out above).
- markTypeAsLive(resolutionResult.getInitialResolutionHolder(), currentMethod);
- }
-
- markFieldAsLive(field, currentMethod);
- },
- failedResolution -> {
- // Must trace the types from the field reference even if it does not exist.
- traceFieldReference(fieldReference, failedResolution, currentMethod);
- noClassMerging.add(fieldReference.getHolderType());
- // Record field reference for generated extension registry shrinking.
+ // If it is a dead proto extension field, don't trace onwards.
+ boolean skipTracing =
appView.withGeneratedExtensionRegistryShrinker(
shrinker ->
- shrinker.handleFailedOrUnknownFieldResolution(
- fieldReference, currentMethod, mode));
- });
+ shrinker.isDeadProtoExtensionField(
+ field, fieldAccessInfoCollection, keepInfo),
+ false);
+ if (skipTracing) {
+ addDeadProtoTypeCandidate(field.getHolder());
+ return;
+ }
+
+ if (field.getReference() != fieldReference) {
+ // Mark the initial resolution holder as live. Note that this should only be done if
+ // the field
+ // is not a dead proto field (in which case we bail-out above).
+ markTypeAsLive(singleResolutionResult.getInitialResolutionHolder(), currentMethod);
+ }
+
+ markFieldAsLive(field, currentMethod);
+ },
+ failedResolution -> {
+ // Must trace the types from the field reference even if it does not exist.
+ traceFieldReference(fieldReference, failedResolution, currentMethod);
+ noClassMerging.add(fieldReference.getHolderType());
+ // Record field reference for generated extension registry shrinking.
+ appView.withGeneratedExtensionRegistryShrinker(
+ shrinker ->
+ shrinker.handleFailedOrUnknownFieldResolution(
+ fieldReference, currentMethod, mode));
+ });
}
void traceStaticFieldWrite(DexField field, ProgramMethod currentMethod) {
- traceStaticFieldWrite(field, currentMethod, false);
+ traceStaticFieldWrite(field, currentMethod, FieldAccessMetadata.DEFAULT);
}
void traceStaticFieldWriteFromMethodHandle(DexField field, ProgramMethod currentMethod) {
- traceStaticFieldWrite(field, currentMethod, true);
+ traceStaticFieldWrite(field, currentMethod, FieldAccessMetadata.FROM_METHOD_HANDLE);
}
private void traceStaticFieldWrite(
- DexField fieldReference, ProgramMethod currentMethod, boolean fromMethodHandle) {
+ DexField fieldReference, ProgramMethod currentMethod, FieldAccessMetadata metadata) {
if (!registerFieldWrite(fieldReference, currentMethod)) {
return;
}
- resolveField(fieldReference, currentMethod)
- .visitFieldResolutionResults(
- resolutionResult -> {
- fieldAccessAnalyses.forEach(
- analysis ->
- analysis.traceStaticFieldWrite(
- fieldReference, resolutionResult, currentMethod, workList));
+ FieldResolutionResult resolutionResult = resolveField(fieldReference, currentMethod);
+ if (deferredTracing.deferTracingOfFieldAccess(
+ fieldReference, resolutionResult, currentMethod, FieldAccessKind.STATIC_WRITE, metadata)) {
+ return;
+ }
- ProgramField field = resolutionResult.getProgramField();
- if (field == null) {
- // No need to trace into the non-program code.
- return;
- }
+ resolutionResult.visitFieldResolutionResults(
+ singleResolutionResult -> {
+ fieldAccessAnalyses.forEach(
+ analysis ->
+ analysis.traceStaticFieldWrite(
+ fieldReference, singleResolutionResult, currentMethod, workList));
- assert !mode.isFinalTreeShaking()
- || !field.getDefinition().getOptimizationInfo().isDead()
- : "Unexpected reference in `"
- + currentMethod.toSourceString()
- + "` to field marked dead: "
- + field.getReference().toSourceString();
+ ProgramField field = singleResolutionResult.getProgramField();
+ if (field == null) {
+ // No need to trace into the non-program code.
+ return;
+ }
- if (fromMethodHandle) {
- fieldAccessInfoCollection.get(field.getReference()).setWrittenFromMethodHandle();
- }
+ assert !mode.isFinalTreeShaking() || !field.getDefinition().getOptimizationInfo().isDead()
+ : "Unexpected reference in `"
+ + currentMethod.toSourceString()
+ + "` to field marked dead: "
+ + field.getReference().toSourceString();
- if (Log.ENABLED) {
- Log.verbose(getClass(), "Register Sput `%s`.", fieldReference);
- }
+ if (metadata.isFromMethodHandle()) {
+ fieldAccessInfoCollection.get(field.getReference()).setWrittenFromMethodHandle();
+ }
- if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) {
- // If it is a dead proto extension field, don't trace onwards.
- boolean skipTracing =
- appView.withGeneratedExtensionRegistryShrinker(
- shrinker ->
- shrinker.isDeadProtoExtensionField(
- field, fieldAccessInfoCollection, keepInfo),
- false);
- if (skipTracing) {
- addDeadProtoTypeCandidate(field.getHolder());
- return;
- }
- }
+ if (Log.ENABLED) {
+ Log.verbose(getClass(), "Register Sput `%s`.", fieldReference);
+ }
- if (field.getReference() != fieldReference) {
- // Mark the initial resolution holder as live. Note that this should only be done if
- // the field
- // is not a dead proto field (in which case we bail-out above).
- markTypeAsLive(resolutionResult.getInitialResolutionHolder(), currentMethod);
- }
+ if (appView.options().protoShrinking().enableGeneratedExtensionRegistryShrinking) {
+ // If it is a dead proto extension field, don't trace onwards.
+ boolean skipTracing =
+ appView.withGeneratedExtensionRegistryShrinker(
+ shrinker ->
+ shrinker.isDeadProtoExtensionField(
+ field, fieldAccessInfoCollection, keepInfo),
+ false);
+ if (skipTracing) {
+ addDeadProtoTypeCandidate(field.getHolder());
+ return;
+ }
+ }
- markFieldAsLive(field, currentMethod);
- },
- failedResolution -> {
- // Must trace the types from the field reference even if it does not exist.
- traceFieldReference(fieldReference, failedResolution, currentMethod);
- noClassMerging.add(fieldReference.getHolderType());
- });
+ if (field.getReference() != fieldReference) {
+ // Mark the initial resolution holder as live. Note that this should only be done if
+ // the field
+ // is not a dead proto field (in which case we bail-out above).
+ markTypeAsLive(singleResolutionResult.getInitialResolutionHolder(), currentMethod);
+ }
+
+ markFieldAsLive(field, currentMethod);
+ },
+ failedResolution -> {
+ // Must trace the types from the field reference even if it does not exist.
+ traceFieldReference(fieldReference, failedResolution, currentMethod);
+ noClassMerging.add(fieldReference.getHolderType());
+ });
}
private DexMethod getInvokeSuperTarget(DexMethod method, ProgramMethod currentMethod) {
@@ -3760,7 +3816,8 @@
return true;
}
- private EnqueuerResult createEnqueuerResult(AppInfoWithClassHierarchy appInfo) {
+ private EnqueuerResult createEnqueuerResult(AppInfoWithClassHierarchy appInfo)
+ throws ExecutionException {
// Compute the set of dead proto types.
deadProtoTypeCandidates.removeIf(this::isTypeLive);
Set<DexType> deadProtoTypes =
@@ -3828,6 +3885,7 @@
: ImmutableSet.of(syntheticClass.getType());
};
amendKeepInfoWithCompanionMethods();
+ deferredTracing.rewriteApplication(executorService);
AppInfoWithLiveness appInfoWithLiveness =
new AppInfoWithLiveness(
appInfo.getSyntheticItems().commit(app),
@@ -4052,6 +4110,12 @@
continue;
}
+ // Allow deferred tracing to enqueue worklist items.
+ if (deferredTracing.enqueueWorklistActions(workList)) {
+ assert !workList.isEmpty();
+ continue;
+ }
+
// Notify each analysis that a fixpoint has been reached, and give each analysis an
// opportunity to add items to the worklist.
analyses.forEach(analysis -> analysis.notifyFixpoint(this, workList, timing));
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java
new file mode 100644
index 0000000..a09a358
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerDeferredTracing.java
@@ -0,0 +1,48 @@
+// Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.shaking;
+
+import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.FieldResolutionResult;
+import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.shaking.Enqueuer.FieldAccessKind;
+import com.android.tools.r8.shaking.Enqueuer.FieldAccessMetadata;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+public class EnqueuerDeferredTracing {
+
+ /**
+ * Returns true if the {@link Enqueuer} should not trace the given field reference.
+ *
+ * <p>If for some reason the field reference should be traced after all, a worklist item can be
+ * enqueued upon reaching a (preliminary) fixpoint in {@link
+ * #enqueueWorklistActions(EnqueuerWorklist)}, which will cause tracing to continue.
+ */
+ public boolean deferTracingOfFieldAccess(
+ DexField fieldReference,
+ FieldResolutionResult resolutionResult,
+ ProgramMethod context,
+ FieldAccessKind kind,
+ FieldAccessMetadata metadata) {
+ return false;
+ }
+
+ /**
+ * Called when the {@link EnqueuerWorklist} is empty, to allow additional tracing before ending
+ * tree shaking.
+ */
+ public boolean enqueueWorklistActions(EnqueuerWorklist worklist) {
+ return false;
+ }
+
+ /**
+ * Called when tree shaking has ended, to allow rewriting the application according to the tracing
+ * that has not been performed (e.g., rewriting of dead field instructions).
+ */
+ public void rewriteApplication(ExecutorService executorService) throws ExecutionException {
+ // Intentionally empty.
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
index 91efed4..06ceb79 100644
--- a/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
+++ b/src/main/java/com/android/tools/r8/shaking/MainDexDirectReferenceTracer.java
@@ -48,7 +48,7 @@
consumer.accept(type);
// Super and interfaces are live, no need to add them.
if (!DexAnnotation.hasSynthesizedClassAnnotation(
- clazz.annotations(), appView.dexItemFactory())) {
+ clazz.annotations(), appView.dexItemFactory(), appView.getSyntheticItems())) {
traceAnnotationsDirectDependencies(clazz.annotations());
}
clazz.forEachField(field -> consumer.accept(field.getReference().type));
diff --git a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
index ef9ae30..177fde7 100644
--- a/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
+++ b/src/main/java/com/android/tools/r8/synthesis/CommittedSyntheticsCollection.java
@@ -107,7 +107,7 @@
ImmutableSet<DexType> allSyntheticInputs =
newSyntheticInputs == null ? parent.syntheticInputs : newSyntheticInputs.build();
return new CommittedSyntheticsCollection(
- allNonLegacyMethods, allNonLegacyClasses, allSyntheticInputs);
+ parent.naming, allNonLegacyMethods, allNonLegacyClasses, allSyntheticInputs);
}
}
@@ -122,8 +122,7 @@
return ImmutableMap.copyOf(newSynthetics);
}
- private static final CommittedSyntheticsCollection EMPTY =
- new CommittedSyntheticsCollection(ImmutableMap.of(), ImmutableMap.of(), ImmutableSet.of());
+ private final SyntheticNaming naming;
/** Mapping from synthetic type to its synthetic method item description. */
private final ImmutableMap<DexType, List<SyntheticMethodReference>> nonLegacyMethods;
@@ -135,15 +134,21 @@
public final ImmutableSet<DexType> syntheticInputs;
public CommittedSyntheticsCollection(
+ SyntheticNaming naming,
ImmutableMap<DexType, List<SyntheticMethodReference>> nonLegacyMethods,
ImmutableMap<DexType, List<SyntheticProgramClassReference>> nonLegacyClasses,
ImmutableSet<DexType> syntheticInputs) {
+ this.naming = naming;
this.nonLegacyMethods = nonLegacyMethods;
this.nonLegacyClasses = nonLegacyClasses;
this.syntheticInputs = syntheticInputs;
assert verifySyntheticInputsSubsetOfSynthetics();
}
+ SyntheticNaming getNaming() {
+ return naming;
+ }
+
private boolean verifySyntheticInputsSubsetOfSynthetics() {
Set<DexType> synthetics =
ImmutableSet.<DexType>builder()
@@ -158,8 +163,9 @@
return true;
}
- public static CommittedSyntheticsCollection empty() {
- return EMPTY;
+ public static CommittedSyntheticsCollection empty(SyntheticNaming naming) {
+ return new CommittedSyntheticsCollection(
+ naming, ImmutableMap.of(), ImmutableMap.of(), ImmutableSet.of());
}
Builder builder() {
@@ -234,7 +240,7 @@
if (removed.isEmpty()) {
return this;
}
- Builder builder = CommittedSyntheticsCollection.empty().builder();
+ Builder builder = CommittedSyntheticsCollection.empty(naming).builder();
boolean changed = false;
for (SyntheticMethodReference reference : IterableUtils.flatten(nonLegacyMethods.values())) {
if (removed.contains(reference.getHolder())) {
@@ -264,6 +270,7 @@
CommittedSyntheticsCollection rewriteWithLens(NonIdentityGraphLens lens) {
ImmutableSet.Builder<DexType> syntheticInputsBuilder = ImmutableSet.builder();
return new CommittedSyntheticsCollection(
+ naming,
rewriteItems(nonLegacyMethods, lens, syntheticInputsBuilder),
rewriteItems(nonLegacyClasses, lens, syntheticInputsBuilder),
syntheticInputsBuilder.build());
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
index 574f518..097df5d 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticDefinition.java
@@ -70,9 +70,9 @@
ClassToFeatureSplitMap classToFeatureSplitMap,
SyntheticItems syntheticItems) {
HasherWrapper hasher = HasherWrapper.murmur3128Hasher();
- hasher.putInt(kind.id);
- if (getKind().isFixedSuffixSynthetic) {
- // Fixed synthetics are non-shareable. Its unique type is used as the hash key.
+ hasher.putInt(kind.getId());
+ if (!getKind().isShareable()) {
+ // Non-shareable synthetics should use its assumed unique type as the hash.
getHolder().getType().hash(hasher);
return hasher.hash();
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
index fdaaaee..07f65be 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticFinalization.java
@@ -270,7 +270,8 @@
new CommittedItems(
SyntheticItems.INVALID_ID_AFTER_SYNTHETIC_FINALIZATION,
application,
- new CommittedSyntheticsCollection(finalMethods, finalClasses, finalInputSynthetics),
+ new CommittedSyntheticsCollection(
+ synthetics.getNaming(), finalMethods, finalClasses, finalInputSynthetics),
ImmutableList.of()),
syntheticFinalizationGraphLens,
PrunedItems.builder().setPrunedApp(application).addRemovedClasses(prunedSynthetics).build(),
@@ -717,7 +718,7 @@
AppView<?> appView,
Predicate<DexType> reserved) {
DexItemFactory factory = appView.dexItemFactory();
- if (kind.isFixedSuffixSynthetic) {
+ if (kind.isFixedSuffixSynthetic()) {
return SyntheticNaming.createExternalType(kind, externalSyntheticTypePrefix, "", factory);
}
NumberGenerator generator =
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
index 7740805..48ff52a 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticItems.java
@@ -55,9 +55,15 @@
static final int INVALID_ID_AFTER_SYNTHETIC_FINALIZATION = -1;
+ private final SyntheticNaming naming;
+
/** Globally incremented id for the next internal synthetic class. */
private int nextSyntheticId;
+ public SyntheticNaming getNaming() {
+ return naming;
+ }
+
/** Collection of pending items. */
private static class PendingSynthetics {
@@ -100,13 +106,16 @@
// Empty collection for use only in tests and utilities.
public static SyntheticItems empty() {
- return new SyntheticItems(-1, CommittedSyntheticsCollection.empty());
+ return new SyntheticItems(-1, CommittedSyntheticsCollection.empty(null));
}
// Only for use from initial AppInfo/AppInfoWithClassHierarchy create functions. */
public static CommittedItems createInitialSyntheticItems(DexApplication application) {
return new CommittedItems(
- 0, application, CommittedSyntheticsCollection.empty(), ImmutableList.of());
+ 0,
+ application,
+ CommittedSyntheticsCollection.empty(application.dexItemFactory().getSyntheticNaming()),
+ ImmutableList.of());
}
// Only for conversion to a mutable synthetic items collection.
@@ -117,6 +126,7 @@
private SyntheticItems(int nextSyntheticId, CommittedSyntheticsCollection committed) {
this.nextSyntheticId = nextSyntheticId;
this.committed = committed;
+ this.naming = committed.getNaming();
}
public static void collectSyntheticInputs(AppView<?> appView) {
@@ -190,7 +200,7 @@
if (clazz != null) {
assert kind != null;
assert !baseDefinitionFor.apply(type).hasClassResolutionResult()
- || kind.mayOverridesNonProgramType
+ || kind.isMayOverridesNonProgramType()
: "Pending synthetic definition also present in the active program: " + type;
return clazz;
}
@@ -245,11 +255,11 @@
Iterable<SyntheticReference<?, ?, ?>> references = committed.getNonLegacyItems(clazz.getType());
if (!Iterables.isEmpty(references)) {
assert Iterables.size(references) == 1;
- return references.iterator().next().getKind() == SyntheticKind.LAMBDA;
+ return references.iterator().next().getKind() == naming.LAMBDA;
}
SyntheticDefinition<?, ?, ?> definition = pending.nonLegacyDefinitions.get(clazz.getType());
if (definition != null) {
- return definition.getKind() == SyntheticKind.LAMBDA;
+ return definition.getKind() == naming.LAMBDA;
}
assert false;
return false;
@@ -268,7 +278,8 @@
return isSyntheticClass(clazz.type);
}
- public boolean isSyntheticOfKind(DexType type, SyntheticKind kind) {
+ public boolean isSyntheticOfKind(DexType type, SyntheticKindSelector kindSelector) {
+ SyntheticKind kind = kindSelector.select(naming);
return pending.containsTypeOfKind(type, kind) || committed.containsTypeOfKind(type, kind);
}
@@ -278,7 +289,7 @@
public FeatureSplit getContextualFeatureSplit(
DexType type, ClassToFeatureSplitMap classToFeatureSplitMap) {
- if (isSyntheticOfKind(type, SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS)) {
+ if (isSyntheticOfKind(type, kinds -> kinds.ENUM_UNBOXING_SHARED_UTILITY_CLASS)) {
// Use the startup base if there is one, such that we don't merge non-startup classes with the
// shared utility class in case it is used during startup. The use of base startup allows for
// merging startup classes with the shared utility class, however, which could be bad for
@@ -341,14 +352,14 @@
committed
.getNonLegacyMethods()
.getOrDefault(method.getHolderType(), Collections.emptyList())) {
- if (reference.getKind() == SyntheticKind.STATIC_INTERFACE_CALL) {
+ if (reference.getKind().equals(naming.STATIC_INTERFACE_CALL)) {
return true;
}
}
SyntheticDefinition<?, ?, ?> definition =
pending.nonLegacyDefinitions.get(method.getHolderType());
if (definition != null) {
- return definition.getKind() == SyntheticKind.STATIC_INTERFACE_CALL;
+ return definition.getKind().equals(naming.STATIC_INTERFACE_CALL);
}
return false;
}
@@ -364,7 +375,7 @@
if (definition != null) {
references = Iterables.concat(references, IterableUtils.singleton(definition.toReference()));
}
- if (Iterables.any(references, reference -> reference.getKind() == SyntheticKind.LAMBDA)) {
+ if (Iterables.any(references, reference -> reference.getKind().equals(naming.LAMBDA))) {
assert ifIsLambda.test(clazz);
} else {
assert ifNotLambda.test(clazz);
@@ -489,15 +500,16 @@
}
public DexProgramClass createClass(
- SyntheticKind kind, UniqueContext context, AppView<?> appView) {
- return createClass(kind, context, appView, ConsumerUtils.emptyConsumer());
+ SyntheticKindSelector kindSelector, UniqueContext context, AppView<?> appView) {
+ return createClass(kindSelector, context, appView, ConsumerUtils.emptyConsumer());
}
public DexProgramClass createClass(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
UniqueContext context,
AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> fn) {
+ SyntheticKind kind = kindSelector.select(naming);
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
SynthesizingContext outerContext = getSynthesizingContext(context.getClassContext(), appView);
@@ -511,10 +523,11 @@
// TODO(b/172194101): Make this take a unique context.
public DexProgramClass createFixedClass(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexProgramClass context,
AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> fn) {
+ SyntheticKind kind = kindSelector.select(naming);
SynthesizingContext outerContext = internalGetOuterContext(context, appView);
Function<SynthesizingContext, DexType> contextToType =
c -> SyntheticNaming.createFixedType(kind, c, appView.dexItemFactory());
@@ -523,8 +536,9 @@
}
public DexProgramClass getExistingFixedClass(
- SyntheticKind kind, DexClass context, AppView<?> appView) {
- assert kind.isFixedSuffixSynthetic;
+ SyntheticKindSelector kindSelector, DexClass context, AppView<?> appView) {
+ SyntheticKind kind = kindSelector.select(naming);
+ assert kind.isFixedSuffixSynthetic();
SynthesizingContext outerContext = internalGetOuterContext(context, appView);
DexType type = SyntheticNaming.createFixedType(kind, outerContext, appView.dexItemFactory());
DexClass clazz = appView.definitionFor(type);
@@ -542,18 +556,24 @@
: SynthesizingContext.fromNonSyntheticInputContext(context.asClasspathOrLibraryClass());
}
+ @FunctionalInterface
+ public interface SyntheticKindSelector {
+ SyntheticKind select(SyntheticNaming naming);
+ }
+
/**
* Ensure that a fixed synthetic class exists.
*
* <p>This method is thread safe and will synchronize based on the context of the fixed synthetic.
*/
public DexProgramClass ensureFixedClass(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexClass context,
AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> fn,
Consumer<DexProgramClass> onCreationConsumer) {
- assert kind.isFixedSuffixSynthetic;
+ SyntheticKind kind = kindSelector.select(naming);
+ assert kind.isFixedSuffixSynthetic();
SynthesizingContext outerContext = internalGetOuterContext(context, appView);
return internalEnsureFixedProgramClass(kind, fn, onCreationConsumer, outerContext, appView);
}
@@ -561,7 +581,7 @@
public ProgramMethod ensureFixedClassMethod(
DexString name,
DexProto proto,
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
ProgramDefinition context,
AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> buildClassCallback,
@@ -569,7 +589,7 @@
return ensureFixedClassMethod(
name,
proto,
- kind,
+ kindSelector,
context,
appView,
buildClassCallback,
@@ -580,15 +600,16 @@
public ProgramMethod ensureFixedClassMethod(
DexString name,
DexProto proto,
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
ProgramDefinition context,
AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> buildClassCallback,
Consumer<SyntheticMethodBuilder> buildMethodCallback,
Consumer<ProgramMethod> newMethodCallback) {
+ SyntheticKind kind = kindSelector.select(naming);
DexProgramClass clazz =
ensureFixedClass(
- kind, context.getContextClass(), appView, buildClassCallback, emptyConsumer());
+ kindSelector, context.getContextClass(), appView, buildClassCallback, emptyConsumer());
DexMethod methodReference = appView.dexItemFactory().createMethod(clazz.getType(), proto, name);
DexEncodedMethod methodDefinition =
internalEnsureMethod(
@@ -642,18 +663,19 @@
}
public DexClasspathClass ensureFixedClasspathClassFromType(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexType contextType,
AppView<?> appView,
Consumer<SyntheticClasspathClassBuilder> classConsumer,
Consumer<DexClasspathClass> onCreationConsumer) {
+ SyntheticKind kind = kindSelector.select(naming);
SynthesizingContext outerContext = SynthesizingContext.fromType(contextType);
return internalEnsureFixedClasspathClass(
kind, classConsumer, onCreationConsumer, outerContext, appView);
}
public DexClasspathClass ensureFixedClasspathClass(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
ClasspathOrLibraryClass context,
AppView<?> appView,
Consumer<SyntheticClasspathClassBuilder> classConsumer,
@@ -662,13 +684,13 @@
// This is to ensure a flat input-type -> synthetic-item mapping.
SynthesizingContext outerContext = SynthesizingContext.fromNonSyntheticInputContext(context);
return internalEnsureFixedClasspathClass(
- kind, classConsumer, onCreationConsumer, outerContext, appView);
+ kindSelector.select(naming), classConsumer, onCreationConsumer, outerContext, appView);
}
public ClasspathMethod ensureFixedClasspathMethodFromType(
DexString methodName,
DexProto methodProto,
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexType contextType,
AppView<?> appView,
Consumer<SyntheticClasspathClassBuilder> classConsumer,
@@ -676,15 +698,15 @@
Consumer<SyntheticMethodBuilder> buildMethodCallback) {
DexClasspathClass clazz =
ensureFixedClasspathClassFromType(
- kind, contextType, appView, classConsumer, onCreationConsumer);
+ kindSelector, contextType, appView, classConsumer, onCreationConsumer);
return internalEnsureFixedClasspathMethod(
- methodName, methodProto, kind, appView, buildMethodCallback, clazz);
+ methodName, methodProto, kindSelector.select(naming), appView, buildMethodCallback, clazz);
}
public ClasspathMethod ensureFixedClasspathClassMethod(
DexString methodName,
DexProto methodProto,
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
ClasspathOrLibraryClass context,
AppView<?> appView,
Consumer<SyntheticClasspathClassBuilder> buildClassCallback,
@@ -692,9 +714,9 @@
Consumer<SyntheticMethodBuilder> buildMethodCallback) {
DexClasspathClass clazz =
ensureFixedClasspathClass(
- kind, context, appView, buildClassCallback, onClassCreationCallback);
+ kindSelector, context, appView, buildClassCallback, onClassCreationCallback);
return internalEnsureFixedClasspathMethod(
- methodName, methodProto, kind, appView, buildMethodCallback, clazz);
+ methodName, methodProto, kindSelector.select(naming), appView, buildMethodCallback, clazz);
}
private ClasspathMethod internalEnsureFixedClasspathMethod(
@@ -748,26 +770,28 @@
}
public DexProgramClass ensureFixedClassFromType(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
DexType contextType,
AppView<?> appView,
Consumer<SyntheticProgramClassBuilder> fn,
Consumer<DexProgramClass> onCreationConsumer) {
+ SyntheticKind kind = kindSelector.select(naming);
SynthesizingContext outerContext = SynthesizingContext.fromType(contextType);
return internalEnsureFixedProgramClass(kind, fn, onCreationConsumer, outerContext, appView);
}
/** Create a single synthetic method item. */
public ProgramMethod createMethod(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
UniqueContext context,
AppView<?> appView,
Consumer<SyntheticMethodBuilder> fn) {
- return createMethod(kind, context.getClassContext(), appView, fn, context::getSyntheticSuffix);
+ return createMethod(
+ kindSelector, context.getClassContext(), appView, fn, context::getSyntheticSuffix);
}
private ProgramMethod createMethod(
- SyntheticKind kind,
+ SyntheticKindSelector kindSelector,
ProgramDefinition context,
AppView<?> appView,
Consumer<SyntheticMethodBuilder> fn,
@@ -776,6 +800,7 @@
// Obtain the outer synthesizing context in the case the context itself is synthetic.
// This is to ensure a flat input-type -> synthetic-item mapping.
SynthesizingContext outerContext = getSynthesizingContext(context, appView);
+ SyntheticKind kind = kindSelector.select(naming);
DexType type =
SyntheticNaming.createInternalType(
kind, outerContext, syntheticIdSupplier.get(), appView.dexItemFactory());
@@ -832,7 +857,7 @@
if (!removedClasses.contains(definition.getHolder().getType())) {
if (definition.isProgramDefinition()) {
committedProgramTypesBuilder.add(definition.getHolder().getType());
- if (definition.getKind().mayOverridesNonProgramType) {
+ if (definition.getKind().isMayOverridesNonProgramType()) {
appBuilder.addProgramClassPotentiallyOverridingNonProgramClass(
definition.asProgramDefinition().getHolder());
} else {
@@ -868,7 +893,7 @@
// single kind of a synthetic which is required for marking synthetics. This check could be
// relaxed to ensure that all kinds are equivalent if merging is possible.
assert !it.hasNext();
- SyntheticMarker.writeMarkerAttribute(writer, kind);
+ SyntheticMarker.writeMarkerAttribute(writer, kind, appView.getSyntheticItems());
}
}
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
index d660753..c21954b 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMarker.java
@@ -25,12 +25,13 @@
private static final String SYNTHETIC_MARKER_ATTRIBUTE_TYPE_NAME =
"com.android.tools.r8.SynthesizedClass";
- public static Attribute getMarkerAttributePrototype() {
- return MarkerAttribute.PROTOTYPE;
+ public static Attribute getMarkerAttributePrototype(SyntheticNaming syntheticNaming) {
+ return new MarkerAttribute(null, syntheticNaming);
}
- public static void writeMarkerAttribute(ClassWriter writer, SyntheticKind kind) {
- writer.visitAttribute(new MarkerAttribute(kind));
+ public static void writeMarkerAttribute(
+ ClassWriter writer, SyntheticKind kind, SyntheticItems syntheticItems) {
+ writer.visitAttribute(new MarkerAttribute(kind, syntheticItems.getNaming()));
}
public static SyntheticMarker readMarkerAttribute(Attribute attribute) {
@@ -43,13 +44,13 @@
private static class MarkerAttribute extends Attribute {
- private static final MarkerAttribute PROTOTYPE = new MarkerAttribute(null);
-
private SyntheticKind kind;
+ private final SyntheticNaming syntheticNaming;
- public MarkerAttribute(SyntheticKind kind) {
+ public MarkerAttribute(SyntheticKind kind, SyntheticNaming syntheticNaming) {
super(SYNTHETIC_MARKER_ATTRIBUTE_TYPE_NAME);
this.kind = kind;
+ this.syntheticNaming = syntheticNaming;
}
@Override
@@ -62,16 +63,16 @@
Label[] labels) {
short id = classReader.readShort(offset);
assert id >= 0;
- SyntheticKind kind = SyntheticKind.fromId(id);
- return new MarkerAttribute(kind);
+ SyntheticKind kind = syntheticNaming.fromId(id);
+ return new MarkerAttribute(kind, syntheticNaming);
}
@Override
protected ByteVector write(
ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
ByteVector byteVector = new ByteVector();
- assert 0 <= kind.id && kind.id <= Short.MAX_VALUE;
- byteVector.putShort(kind.id);
+ assert 0 <= kind.getId() && kind.getId() <= Short.MAX_VALUE;
+ byteVector.putShort(kind.getId());
return byteVector;
}
}
@@ -103,7 +104,7 @@
SyntheticMarker marker = internalStripMarkerFromClass(clazz, appView);
assert marker != NO_MARKER
|| !DexAnnotation.hasSynthesizedClassAnnotation(
- clazz.annotations(), appView.dexItemFactory());
+ clazz.annotations(), appView.dexItemFactory(), appView.getSyntheticItems());
return marker;
}
@@ -117,12 +118,12 @@
}
SyntheticKind kind =
DexAnnotation.getSynthesizedClassAnnotationInfo(
- clazz.annotations(), appView.dexItemFactory());
+ clazz.annotations(), appView.dexItemFactory(), appView.getSyntheticItems());
if (kind == null) {
return NO_MARKER;
}
assert clazz.annotations().size() == 1;
- if (kind.isSingleSyntheticMethod) {
+ if (kind.isSingleSyntheticMethod()) {
if (!clazz.interfaces.isEmpty()) {
return NO_MARKER;
}
@@ -161,11 +162,11 @@
}
public boolean isSyntheticMethods() {
- return kind != null && kind.isSingleSyntheticMethod;
+ return kind != null && kind.isSingleSyntheticMethod();
}
public boolean isSyntheticClass() {
- return kind != null && !kind.isSingleSyntheticMethod;
+ return kind != null && !kind.isSingleSyntheticMethod();
}
public SyntheticKind getKind() {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
index ec8a010..d2daa6c 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodBuilder.java
@@ -145,22 +145,21 @@
.setOptimizationInfo(optimizationInfo)
.applyIf(!checkAndroidApiLevels, DexEncodedMethod.Builder::disableAndroidApiLevelCheck)
.build();
- assert isValidSyntheticMethod(method, syntheticKind);
+ assert !syntheticKind.isSingleSyntheticMethod()
+ || isValidSingleSyntheticMethod(method, syntheticKind);
return method;
}
/**
- * Predicate for what is a "supported" synthetic method.
+ * Predicate for what is a "supported" single synthetic method.
*
- * <p>This method is used when identifying synthetic methods in the program input and should be as
- * narrow as possible.
- *
- * <p>Methods in fixed suffix synthetics are identified differently (through the class name) and
- * can have different properties.
+ * <p>This method is used when identifying single synthetic methods in the program input and
+ * should be as narrow as possible.
*/
- public static boolean isValidSyntheticMethod(
+ public static boolean isValidSingleSyntheticMethod(
DexEncodedMethod method, SyntheticKind syntheticKind) {
- return isValidSingleSyntheticMethod(method) || syntheticKind.isFixedSuffixSynthetic;
+ assert syntheticKind.isSingleSyntheticMethod();
+ return isValidSingleSyntheticMethod(method);
}
public static boolean isValidSingleSyntheticMethod(DexEncodedMethod method) {
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java
index d00eb21..2129b9d 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticMethodDefinition.java
@@ -11,7 +11,7 @@
import java.util.function.Consumer;
/**
- * Definition of a synthetic method item.
+ * Definition of a single synthetic method item.
*
* <p>This class is internal to the synthetic items collection, thus package-protected.
*/
@@ -24,6 +24,7 @@
SyntheticMethodDefinition(SyntheticKind kind, SynthesizingContext context, ProgramMethod method) {
super(kind, context);
+ assert kind.isSingleSyntheticMethod();
this.method = method;
}
@@ -70,7 +71,7 @@
@Override
public boolean isValid() {
- return SyntheticMethodBuilder.isValidSyntheticMethod(method.getDefinition(), getKind());
+ return SyntheticMethodBuilder.isValidSingleSyntheticMethod(method.getDefinition(), getKind());
}
@Override
diff --git a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
index 657f7d5..e95c6a1 100644
--- a/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
+++ b/src/main/java/com/android/tools/r8/synthesis/SyntheticNaming.java
@@ -6,14 +6,140 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringForTesting;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.DescriptorUtils;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
+import com.android.tools.r8.utils.structural.Equatable;
+import com.android.tools.r8.utils.structural.Ordered;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
public class SyntheticNaming {
+ public SyntheticNaming() {}
+
+ private KindGenerator generator = new KindGenerator();
+
+ // Global synthetics.
+ public final SyntheticKind RECORD_TAG = generator.forGlobalClass();
+ public final SyntheticKind API_MODEL_STUB = generator.forGlobalClass();
+
+ // Classpath only synthetics in the global type namespace.
+ public final SyntheticKind RETARGET_STUB = generator.forGlobalClasspathClass();
+ public final SyntheticKind EMULATED_INTERFACE_MARKER_CLASS = generator.forGlobalClasspathClass();
+
+ // Fixed suffix synthetics. Each has a hygienic prefix type.
+ public final SyntheticKind ENUM_UNBOXING_LOCAL_UTILITY_CLASS =
+ generator.forFixedClass("$EnumUnboxingLocalUtility");
+ public final SyntheticKind ENUM_UNBOXING_SHARED_UTILITY_CLASS =
+ generator.forFixedClass("$EnumUnboxingSharedUtility");
+ public final SyntheticKind COMPANION_CLASS = generator.forFixedClass("$-CC");
+ public final SyntheticKind EMULATED_INTERFACE_CLASS =
+ generator.forFixedClass(InterfaceDesugaringForTesting.EMULATED_INTERFACE_CLASS_SUFFIX);
+ public final SyntheticKind RETARGET_CLASS = generator.forFixedClass("RetargetClass");
+ public final SyntheticKind RETARGET_INTERFACE = generator.forFixedClass("RetargetInterface");
+ public final SyntheticKind WRAPPER = generator.forFixedClass("$Wrapper");
+ public final SyntheticKind VIVIFIED_WRAPPER = generator.forFixedClass("$VivifiedWrapper");
+ public final SyntheticKind INIT_TYPE_ARGUMENT = generator.forFixedClass("-IA");
+ public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_1 =
+ generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$1");
+ public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_2 =
+ generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$2");
+ public final SyntheticKind HORIZONTAL_INIT_TYPE_ARGUMENT_3 =
+ generator.forFixedClass(SYNTHETIC_CLASS_SEPARATOR + "IA$3");
+ public final SyntheticKind ENUM_CONVERSION = generator.forFixedClass("$EnumConversion");
+
+ // Locally generated synthetic classes.
+ public final SyntheticKind LAMBDA = generator.forInstanceClass("Lambda");
+
+ // TODO(b/214901256): Sharing of synthetic classes may lead to duplicate method errors.
+ public final SyntheticKind NON_FIXED_INIT_TYPE_ARGUMENT =
+ generator.forNonSharableInstanceClass("$IA");
+ public final SyntheticKind CONST_DYNAMIC = generator.forInstanceClass("$Condy");
+
+ // Method synthetics.
+ public final SyntheticKind ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD =
+ generator.forSingleMethod("CheckNotZero");
+ public final SyntheticKind RECORD_HELPER = generator.forSingleMethod("Record");
+ public final SyntheticKind BACKPORT = generator.forSingleMethod("Backport");
+ public final SyntheticKind BACKPORT_WITH_FORWARDING =
+ generator.forSingleMethod("BackportWithForwarding");
+ public final SyntheticKind STATIC_INTERFACE_CALL =
+ generator.forSingleMethod("StaticInterfaceCall");
+ public final SyntheticKind TO_STRING_IF_NOT_NULL = generator.forSingleMethod("ToStringIfNotNull");
+ public final SyntheticKind THROW_CCE_IF_NOT_NULL = generator.forSingleMethod("ThrowCCEIfNotNull");
+ public final SyntheticKind THROW_IAE = generator.forSingleMethod("ThrowIAE");
+ public final SyntheticKind THROW_ICCE = generator.forSingleMethod("ThrowICCE");
+ public final SyntheticKind THROW_NSME = generator.forSingleMethod("ThrowNSME");
+ public final SyntheticKind TWR_CLOSE_RESOURCE = generator.forSingleMethod("TwrCloseResource");
+ public final SyntheticKind SERVICE_LOADER = generator.forSingleMethod("ServiceLoad");
+ public final SyntheticKind OUTLINE = generator.forSingleMethod("Outline");
+ public final SyntheticKind API_CONVERSION = generator.forSingleMethod("APIConversion");
+ public final SyntheticKind API_CONVERSION_PARAMETERS =
+ generator.forSingleMethod("APIConversionParameters");
+ public final SyntheticKind ARRAY_CONVERSION = generator.forSingleMethod("$ArrayConversion");
+ public final SyntheticKind API_MODEL_OUTLINE = generator.forSingleMethod("ApiModelOutline");
+
+ private final List<SyntheticKind> ALL_KINDS = generator.getAllKinds();
+
+ public Collection<SyntheticKind> kinds() {
+ return ALL_KINDS;
+ }
+
+ public SyntheticKind fromId(int id) {
+ if (0 < id && id <= ALL_KINDS.size()) {
+ return ALL_KINDS.get(id - 1);
+ }
+ return null;
+ }
+
+ private static class KindGenerator {
+ private int nextId = 1;
+ private List<SyntheticKind> kinds = new ArrayList<>();
+
+ private int getNextId() {
+ return nextId++;
+ }
+
+ private SyntheticKind register(SyntheticKind kind) {
+ kinds.add(kind);
+ return kind;
+ }
+
+ SyntheticKind forSingleMethod(String descriptor) {
+ return register(new SyntheticMethodKind(getNextId(), descriptor));
+ }
+
+ // TODO(b/214901256): Remove once fixed.
+ SyntheticKind forNonSharableInstanceClass(String descriptor) {
+ return register(new SyntheticClassKind(getNextId(), descriptor, false));
+ }
+
+ SyntheticKind forInstanceClass(String descriptor) {
+ return register(new SyntheticClassKind(getNextId(), descriptor, true));
+ }
+
+ SyntheticKind forFixedClass(String descriptor) {
+ return register(new SyntheticFixedClassKind(getNextId(), descriptor, false, false));
+ }
+
+ SyntheticKind forGlobalClass() {
+ return register(new SyntheticFixedClassKind(getNextId(), "", true, true));
+ }
+
+ SyntheticKind forGlobalClasspathClass() {
+ return register(new SyntheticFixedClassKind(getNextId(), "", false, false));
+ }
+
+ List<SyntheticKind> getAllKinds() {
+ List<SyntheticKind> kinds = this.kinds;
+ this.kinds = null;
+ return kinds;
+ }
+ }
+
/**
* Enumeration of all kinds of synthetic items.
*
@@ -23,129 +149,169 @@
* will be put into any non-minified synthetic name and thus the kind "descriptor" must be a
* distinct for each kind.
*/
- public enum SyntheticKind {
- // Class synthetics.
- ENUM_UNBOXING_LOCAL_UTILITY_CLASS("$EnumUnboxingLocalUtility", 24, false, true),
- ENUM_UNBOXING_SHARED_UTILITY_CLASS("$EnumUnboxingSharedUtility", 25, false, true),
- RECORD_TAG("", 1, false, true, true),
- COMPANION_CLASS("$-CC", 2, false, true),
- EMULATED_INTERFACE_CLASS("$-EL", 3, false, true),
- RETARGET_CLASS("RetargetClass", 20, false, true),
- RETARGET_STUB("", 36, false, true),
- RETARGET_INTERFACE("RetargetInterface", 21, false, true),
- WRAPPER("$Wrapper", 22, false, true),
- VIVIFIED_WRAPPER("$VivifiedWrapper", 23, false, true),
- LAMBDA("Lambda", 4, false),
- INIT_TYPE_ARGUMENT("-IA", 5, false, true),
- HORIZONTAL_INIT_TYPE_ARGUMENT_1(SYNTHETIC_CLASS_SEPARATOR + "IA$1", 6, false, true),
- HORIZONTAL_INIT_TYPE_ARGUMENT_2(SYNTHETIC_CLASS_SEPARATOR + "IA$2", 7, false, true),
- HORIZONTAL_INIT_TYPE_ARGUMENT_3(SYNTHETIC_CLASS_SEPARATOR + "IA$3", 8, false, true),
- NON_FIXED_INIT_TYPE_ARGUMENT("$IA", 35, false),
- // Method synthetics.
- ENUM_UNBOXING_CHECK_NOT_ZERO_METHOD("CheckNotZero", 27, true),
- RECORD_HELPER("Record", 9, true),
- BACKPORT("Backport", 10, true),
- BACKPORT_WITH_FORWARDING("BackportWithForwarding", 34, true),
- STATIC_INTERFACE_CALL("StaticInterfaceCall", 11, true),
- TO_STRING_IF_NOT_NULL("ToStringIfNotNull", 12, true),
- THROW_CCE_IF_NOT_NULL("ThrowCCEIfNotNull", 13, true),
- THROW_IAE("ThrowIAE", 14, true),
- THROW_ICCE("ThrowICCE", 15, true),
- THROW_NSME("ThrowNSME", 16, true),
- TWR_CLOSE_RESOURCE("TwrCloseResource", 17, true),
- SERVICE_LOADER("ServiceLoad", 18, true),
- OUTLINE("Outline", 19, true),
- API_CONVERSION("APIConversion", 26, true),
- API_CONVERSION_PARAMETERS("APIConversionParameters", 28, true),
- EMULATED_INTERFACE_MARKER_CLASS("", 29, false, true, true),
- CONST_DYNAMIC("$Condy", 30, false),
- ENUM_CONVERSION("$EnumConversion", 31, false, true),
- ARRAY_CONVERSION("$ArrayConversion", 37, true, false),
- API_MODEL_OUTLINE("ApiModelOutline", 32, true, false, false),
- API_MODEL_STUB("", 33, false, true, true);
+ public abstract static class SyntheticKind implements Ordered<SyntheticKind> {
- static {
- assert verifyNoOverlappingIds();
- }
+ private final int id;
+ private final String descriptor;
- public final String descriptor;
- public final int id;
- public final boolean isSingleSyntheticMethod;
- public final boolean isFixedSuffixSynthetic;
- public final boolean mayOverridesNonProgramType;
-
- SyntheticKind(String descriptor, int id, boolean isSingleSyntheticMethod) {
- this(descriptor, id, isSingleSyntheticMethod, false);
- }
-
- SyntheticKind(
- String descriptor,
- int id,
- boolean isSingleSyntheticMethod,
- boolean isFixedSuffixSynthetic) {
- this(descriptor, id, isSingleSyntheticMethod, isFixedSuffixSynthetic, false);
- }
-
- SyntheticKind(
- String descriptor,
- int id,
- boolean isSingleSyntheticMethod,
- boolean isFixedSuffixSynthetic,
- boolean mayOverridesNonProgramType) {
- this.descriptor = descriptor;
+ SyntheticKind(int id, String descriptor) {
this.id = id;
- this.isSingleSyntheticMethod = isSingleSyntheticMethod;
- this.isFixedSuffixSynthetic = isFixedSuffixSynthetic;
- this.mayOverridesNonProgramType = mayOverridesNonProgramType;
+ this.descriptor = descriptor;
}
- public boolean allowSyntheticContext() {
- return this == RECORD_TAG;
+ @Override
+ public int compareTo(SyntheticKind other) {
+ return Integer.compare(id, other.getId());
}
- public boolean isGlobal() {
- return isFixedSuffixSynthetic && descriptor.isEmpty();
+ @Override
+ public int hashCode() {
+ return id;
}
+ @Override
+ public boolean equals(Object o) {
+ return Equatable.equalsImpl(this, o);
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getDescriptor() {
+ return descriptor;
+ }
+
+ public abstract boolean isShareable();
+
+ public abstract boolean isSingleSyntheticMethod();
+
+ public abstract boolean isFixedSuffixSynthetic();
+
+ public abstract boolean isGlobal();
+
+ public abstract boolean isMayOverridesNonProgramType();
+
+ public abstract boolean allowSyntheticContext();
+ }
+
+ private static class SyntheticMethodKind extends SyntheticKind {
+
+ public SyntheticMethodKind(int id, String descriptor) {
+ super(id, descriptor);
+ }
+
+ @Override
public boolean isShareable() {
- if (isFixedSuffixSynthetic) {
- // Fixed synthetics are non-shareable. Ordered by their unique type.
- return false;
- }
- if (this == NON_FIXED_INIT_TYPE_ARGUMENT) {
- // TODO(b/214901256): Sharing of synthetic classes may lead to duplicate method errors.
- return false;
- }
+ // Single methods may always be shared.
return true;
}
- public static SyntheticKind fromDescriptor(String descriptor) {
- for (SyntheticKind kind : values()) {
- if (kind.descriptor.equals(descriptor)) {
- return kind;
- }
- }
- return null;
- }
-
- public static SyntheticKind fromId(int id) {
- for (SyntheticKind kind : values()) {
- if (kind.id == id) {
- return kind;
- }
- }
- return null;
- }
-
- private static boolean verifyNoOverlappingIds() {
- Int2ReferenceMap<SyntheticKind> idToKind = new Int2ReferenceOpenHashMap<>();
- for (SyntheticKind kind : values()) {
- SyntheticKind kindWithSameId = idToKind.put(kind.id, kind);
- assert kindWithSameId == null
- : "Synthetic kind " + idToKind + " has same id as " + kindWithSameId;
- }
+ @Override
+ public boolean isSingleSyntheticMethod() {
return true;
}
+
+ @Override
+ public boolean isFixedSuffixSynthetic() {
+ return false;
+ }
+
+ @Override
+ public boolean isGlobal() {
+ return false;
+ }
+
+ @Override
+ public boolean isMayOverridesNonProgramType() {
+ return false;
+ }
+
+ @Override
+ public boolean allowSyntheticContext() {
+ return false;
+ }
+ }
+
+ private static class SyntheticClassKind extends SyntheticKind {
+
+ // TODO(b/214901256): Remove once fixed.
+ private final boolean sharable;
+
+ public SyntheticClassKind(int id, String descriptor, boolean sharable) {
+ super(id, descriptor);
+ this.sharable = sharable;
+ }
+
+ @Override
+ public boolean isShareable() {
+ return sharable;
+ }
+
+ @Override
+ public final boolean isSingleSyntheticMethod() {
+ return false;
+ }
+
+ @Override
+ public boolean isFixedSuffixSynthetic() {
+ return false;
+ }
+
+ @Override
+ public boolean isGlobal() {
+ return false;
+ }
+
+ @Override
+ public boolean isMayOverridesNonProgramType() {
+ return false;
+ }
+
+ @Override
+ public boolean allowSyntheticContext() {
+ return false;
+ }
+ }
+
+ private static class SyntheticFixedClassKind extends SyntheticClassKind {
+ private final boolean mayOverridesNonProgramType;
+ private final boolean allowSyntheticContext;
+
+ private SyntheticFixedClassKind(
+ int id,
+ String descriptor,
+ boolean mayOverridesNonProgramType,
+ boolean allowSyntheticContext) {
+ super(id, descriptor, false);
+ this.mayOverridesNonProgramType = mayOverridesNonProgramType;
+ this.allowSyntheticContext = allowSyntheticContext;
+ }
+
+ @Override
+ public boolean isShareable() {
+ return false;
+ }
+
+ @Override
+ public boolean isFixedSuffixSynthetic() {
+ return true;
+ }
+
+ @Override
+ public boolean isGlobal() {
+ return getDescriptor().isEmpty();
+ }
+
+ @Override
+ public boolean isMayOverridesNonProgramType() {
+ return mayOverridesNonProgramType;
+ }
+
+ @Override
+ public boolean allowSyntheticContext() {
+ return allowSyntheticContext;
+ }
}
private static final String SYNTHETIC_CLASS_SEPARATOR = "$$";
@@ -169,22 +335,22 @@
String binaryName = type.toBinaryName();
int index =
binaryName.lastIndexOf(
- kind.isFixedSuffixSynthetic ? kind.descriptor : SYNTHETIC_CLASS_SEPARATOR);
+ kind.isFixedSuffixSynthetic() ? kind.descriptor : SYNTHETIC_CLASS_SEPARATOR);
if (index < 0) {
throw new Unreachable("Unexpected failure to compute an synthetic prefix");
}
return binaryName.substring(0, index);
}
- public static DexType createFixedType(
+ static DexType createFixedType(
SyntheticKind kind, SynthesizingContext context, DexItemFactory factory) {
- assert kind.isFixedSuffixSynthetic;
+ assert kind.isFixedSuffixSynthetic();
return createType("", kind, context.getSynthesizingContextType(), "", factory);
}
static DexType createInternalType(
SyntheticKind kind, SynthesizingContext context, String id, DexItemFactory factory) {
- assert !kind.isFixedSuffixSynthetic;
+ assert !kind.isFixedSuffixSynthetic();
return createType(
INTERNAL_SYNTHETIC_CLASS_SEPARATOR,
kind,
@@ -195,9 +361,9 @@
static DexType createExternalType(
SyntheticKind kind, String externalSyntheticTypePrefix, String id, DexItemFactory factory) {
- assert kind.isFixedSuffixSynthetic == id.isEmpty();
+ assert kind.isFixedSuffixSynthetic() == id.isEmpty();
return createType(
- kind.isFixedSuffixSynthetic ? "" : EXTERNAL_SYNTHETIC_CLASS_SEPARATOR,
+ kind.isFixedSuffixSynthetic() ? "" : EXTERNAL_SYNTHETIC_CLASS_SEPARATOR,
kind,
externalSyntheticTypePrefix,
id,
@@ -257,14 +423,9 @@
createDescriptor(EXTERNAL_SYNTHETIC_CLASS_SEPARATOR, kind, context.getBinaryName(), id));
}
- public static boolean isInternalStaticInterfaceCall(ClassReference reference) {
- return SyntheticNaming.isSynthetic(
- reference, Phase.INTERNAL, SyntheticKind.STATIC_INTERFACE_CALL);
- }
-
static boolean isSynthetic(ClassReference clazz, Phase phase, SyntheticKind kind) {
String typeName = clazz.getTypeName();
- if (kind.isFixedSuffixSynthetic) {
+ if (kind.isFixedSuffixSynthetic()) {
assert phase == null;
return clazz.getBinaryName().endsWith(kind.descriptor);
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalArchiveClassFileProvider.java b/src/main/java/com/android/tools/r8/utils/InternalArchiveClassFileProvider.java
index a231b0f..e5557d9 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalArchiveClassFileProvider.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalArchiveClassFileProvider.java
@@ -8,10 +8,12 @@
import com.android.tools.r8.ClassFileResourceProvider;
import com.android.tools.r8.ProgramResource;
-import com.android.tools.r8.ResourceException;
+import com.android.tools.r8.ProgramResource.Kind;
+import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.origin.ArchiveEntryOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
+import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@@ -81,36 +83,18 @@
if (!descriptors.contains(descriptor)) {
return null;
}
- return new ProgramResource() {
-
- private final Origin entryOrigin =
- new ArchiveEntryOrigin(getZipEntryNameFromDescriptor(descriptor), origin);
-
- @Override
- public Origin getOrigin() {
- return entryOrigin;
+ try {
+ ZipEntry zipEntry = getZipEntryFromDescriptor(descriptor);
+ try (InputStream inputStream = getOpenZipFile().getInputStream(zipEntry)) {
+ return ProgramResource.fromBytes(
+ new ArchiveEntryOrigin(zipEntry.getName(), origin),
+ Kind.CF,
+ ByteStreams.toByteArray(inputStream),
+ Collections.singleton(descriptor));
}
-
- @Override
- public Kind getKind() {
- return Kind.CF;
- }
-
- @Override
- public Set<String> getClassDescriptors() {
- return Collections.singleton(descriptor);
- }
-
- @Override
- public InputStream getByteStream() throws ResourceException {
- try {
- ZipEntry zipEntry = getZipEntryFromDescriptor(descriptor);
- return getOpenZipFile().getInputStream(zipEntry);
- } catch (IOException e) {
- throw new ResourceException(getOrigin(), "Failed to read '" + descriptor + "'");
- }
- }
- };
+ } catch (IOException e) {
+ throw new CompilationError("Failed to read '" + descriptor, origin);
+ }
}
private ZipFile getOpenZipFile() throws IOException {
@@ -134,11 +118,8 @@
openedZipFile = null;
}
- private static String getZipEntryNameFromDescriptor(String descriptor) {
- return descriptor.substring(1, descriptor.length() - 1) + CLASS_EXTENSION;
- }
-
private ZipEntry getZipEntryFromDescriptor(String descriptor) throws IOException {
- return getOpenZipFile().getEntry(getZipEntryNameFromDescriptor(descriptor));
+ return getOpenZipFile()
+ .getEntry(descriptor.substring(1, descriptor.length() - 1) + CLASS_EXTENSION);
}
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index e359381..dcf8dbd 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1764,6 +1764,7 @@
public boolean enableEnumUnboxingDebugLogs = false;
public boolean forceRedundantConstNumberRemoval = false;
public boolean enableExperimentalDesugaredLibraryKeepRuleGenerator = false;
+ public boolean enableExperimentalLoopUnrolling = false;
public boolean invertConditionals = false;
public boolean placeExceptionalBlocksLast = false;
public boolean dontCreateMarkerInD8 = false;
diff --git a/src/main/java/com/android/tools/r8/utils/SymbolGenerationUtils.java b/src/main/java/com/android/tools/r8/utils/SymbolGenerationUtils.java
index 3729ead..ea895e9 100644
--- a/src/main/java/com/android/tools/r8/utils/SymbolGenerationUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/SymbolGenerationUtils.java
@@ -17,9 +17,9 @@
DONT_USE_MIXED_CASE
}
- public static Set<String> PRIMITIVE_TYPE_NAMES =
+ public static Set<String> RESERVED_NAMES =
Sets.newHashSet(
- "boolean", "byte", "char", "double", "float", "int", "long", "short", "void", "it");
+ "boolean", "byte", "char", "double", "float", "int", "long", "short", "void", "it", "by");
// These letters are used not creating fresh names to output and not for parsing dex/class files.
private static final char[] IDENTIFIER_CHARACTERS =
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
index 527d2c0..f926a22 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ObjectsBackportJava9Test.java
@@ -36,12 +36,12 @@
public ObjectsBackportJava9Test(TestParameters parameters) {
super(parameters, Objects.class, TEST_JAR, TEST_CLASS);
- // Note: None of the methods in this test exist in the latest android.jar. If/when they ship in
- // an actual API level, migrate these tests to ObjectsBackportTest.
-
// Objects.checkFromIndexSize, Objects.checkFromToIndex, Objects.checkIndex,
// Objects.requireNonNullElse and Objects.requireNonNullElseGet added in API 30.
registerTarget(AndroidApiLevel.R, 28);
+ registerTarget(AndroidApiLevel.N, 0);
+ // Objects.requireNonNullElseGet is not desugared if Supplier is absent.
+ registerTarget(AndroidApiLevel.B, 4);
}
@Test
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
index 3209290..ef978a7 100644
--- a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/ObjectsTest.java
@@ -245,7 +245,7 @@
onlyIf(invokeJavaUtilObjects, invokesObjectsRequireNonNull("java.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNull"),
- onlyIf(parameters.getApiLevel().isLessThan(AndroidApiLevel.K), invokesClassGetClass()));
+ onlyIf(invokeJDollarUtilObjects, invokesObjectsRequireNonNull("j$.util.Objects")));
assertThat(
testClass.uniqueMethodWithName("objectsRequireNonNullWithMessage"),
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java b/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java
index dc3ca19..6bbfb60 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/loops/LoopWith1Iterations.java
@@ -33,6 +33,7 @@
.setMinApi(parameters.getApiLevel())
.addProgramClasses(Main.class)
.addKeepMainRule(Main.class)
+ .addOptionsModification(options -> options.testing.enableExperimentalLoopUnrolling = true)
.enableInliningAnnotations()
.noMinification()
.compile()
diff --git a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLambdaRepackageTest.java b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLambdaRepackageTest.java
index c85c55b..6c799bd 100644
--- a/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLambdaRepackageTest.java
+++ b/src/test/java/com/android/tools/r8/naming/applymapping/ApplyMappingLambdaRepackageTest.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.naming.applymapping;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertEquals;
import com.android.tools.r8.NeverClassInline;
import com.android.tools.r8.NeverInline;
@@ -50,14 +50,8 @@
.addApplyMapping(firstRunResult.proguardMap())
.compile()
.run(parameters.getRuntime(), Main.class);
- if (parameters.isDexRuntime()) {
- // TODO(b/218793832): Should be the same map.
- assertNotEquals(firstRunResult.proguardMap(), secondRunResult.proguardMap());
- }
- secondRunResult
- .assertSuccessWithOutputLinesIf(parameters.isCfRuntime(), "Hello World")
- // TODO(b/218793832): Should not fail with an error.
- .assertFailureWithErrorThatThrowsIf(parameters.isDexRuntime(), IllegalAccessError.class);
+ assertEquals(firstRunResult.proguardMap(), secondRunResult.proguardMap());
+ secondRunResult.assertSuccessWithOutputLines("Hello World");
}
@NeverClassInline
diff --git a/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java b/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java
index 1a3bfca..7611b1c 100644
--- a/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java
+++ b/src/test/java/com/android/tools/r8/repackage/RepackageWithSyntheticItemTest.java
@@ -64,11 +64,7 @@
.filter(item -> item.getFinalName().startsWith("foo"))
.collect(Collectors.toList());
assertEquals(1, classesStartingWithfoo.size());
- // TODO(b/172014416): We should not be able to look this up through the repackage name
- String expectedOriginalNamePrefix =
- isFlattenPackageHierarchy()
- ? "foo.a.RepackageWithSyntheticItemTest$A"
- : "foo.RepackageWithSyntheticItemTest$A";
+ String expectedOriginalNamePrefix = typeName(A.class) + "$$ExternalSyntheticLambda0";
assertThat(
classesStartingWithfoo.get(0).getOriginalName(),
containsString(expectedOriginalNamePrefix));
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiInlineInOutlineTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiInlineInOutlineTest.java
index d67f6ee..4e8d81e 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiInlineInOutlineTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiInlineInOutlineTest.java
@@ -6,11 +6,12 @@
import static org.junit.Assert.assertEquals;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetracedMethodReference;
@@ -62,9 +63,11 @@
@Test
public void test() {
- Retracer retracer =
- Retracer.createExperimental(
- ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(mapping))
+ .build();
+ Retracer retracer = Retracer.builder().setMappingProvider(mappingProvider).build();
List<RetraceFrameElement> outlineRetraced =
retracer
.retraceFrame(
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInOutlineStackTrace.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInOutlineStackTrace.java
index 94824c5..ca3bb00 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInOutlineStackTrace.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInOutlineStackTrace.java
@@ -6,12 +6,13 @@
import static org.junit.Assert.assertEquals;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetracedMethodReference;
@@ -70,9 +71,11 @@
@Test
public void test() {
- Retracer retracer =
- Retracer.createExperimental(
- ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(mapping))
+ .build();
+ Retracer retracer = Retracer.builder().setMappingProvider(mappingProvider).build();
// Retrace the first outline.
RetraceStackTraceContext outlineContext =
retraceOutline(
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInlineTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInlineTest.java
index 6aaa0fa..4401dfa 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInlineTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineInlineTest.java
@@ -6,11 +6,12 @@
import static org.junit.Assert.assertEquals;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetracedMethodReference;
@@ -61,9 +62,11 @@
@Test
public void test() {
- Retracer retracer =
- Retracer.createExperimental(
- ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(mapping))
+ .build();
+ Retracer retracer = Retracer.builder().setMappingProvider(mappingProvider).build();
List<RetraceFrameElement> outlineRetraced =
retracer
.retraceFrame(
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineNoInlineTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineNoInlineTest.java
index e4ef644..5ed27fae 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineNoInlineTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiOutlineNoInlineTest.java
@@ -7,11 +7,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetracedMethodReference;
@@ -61,9 +62,11 @@
@Test
public void test() {
- Retracer retracer =
- Retracer.createExperimental(
- ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(mapping))
+ .build();
+ Retracer retracer = Retracer.builder().setMappingProvider(mappingProvider).build();
List<RetraceFrameElement> outlineRetraced =
retracer
.retraceFrame(
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeResidualTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeResidualTest.java
index 5175ecb..9cd18f5 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeResidualTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeResidualTest.java
@@ -7,11 +7,12 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetraceThrownExceptionElement;
@@ -79,9 +80,11 @@
@Test
public void testUsingObfuscatedName() {
- Retracer retracer =
- Retracer.createExperimental(
- ProguardMapProducer.fromString(mapping), new DiagnosticsHandler() {});
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(mapping))
+ .build();
+ Retracer retracer = Retracer.builder().setMappingProvider(mappingProvider).build();
List<RetraceThrownExceptionElement> npeRetraced =
retracer.retraceThrownException(renamedException).stream().collect(Collectors.toList());
assertEquals(1, npeRetraced.size());
diff --git a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeTest.java b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeTest.java
index 66bdc03..61ddca6 100644
--- a/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/api/RetraceApiRewriteFrameInlineNpeTest.java
@@ -11,7 +11,9 @@
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.MappingProvider;
import com.android.tools.r8.retrace.ProguardMapProducer;
+import com.android.tools.r8.retrace.ProguardMappingProvider;
import com.android.tools.r8.retrace.RetraceFrameElement;
import com.android.tools.r8.retrace.RetraceStackTraceContext;
import com.android.tools.r8.retrace.RetraceThrownExceptionElement;
@@ -58,9 +60,16 @@
@Test
public void testFirstStackLineIsRemoved() {
TestDiagnosticsHandler testDiagnosticsHandler = new TestDiagnosticsHandler();
+ MappingProvider mappingProvider =
+ ProguardMappingProvider.builder()
+ .setProguardMapProducer(ProguardMapProducer.fromString(mapping))
+ .setDiagnosticsHandler(testDiagnosticsHandler)
+ .build();
Retracer retracer =
- Retracer.createExperimental(
- ProguardMapProducer.fromString(mapping), testDiagnosticsHandler);
+ Retracer.builder()
+ .setMappingProvider(mappingProvider)
+ .setDiagnosticsHandler(testDiagnosticsHandler)
+ .build();
List<RetraceThrownExceptionElement> npeRetraced =
retracer.retraceThrownException(Reference.classFromDescriptor(npeDescriptor)).stream()
diff --git a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
index f85290d..369d584 100644
--- a/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
+++ b/src/test/java/com/android/tools/r8/shaking/KeepAnnotatedMemberTest.java
@@ -10,7 +10,6 @@
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import com.android.tools.r8.R8;
@@ -292,8 +291,7 @@
.apply(this::configureHorizontalClassMerging)
.compile()
.graphInspector();
- assertRetainedClassesEqual(
- referenceInspector, ifHasMemberThenKeepClassInspector, true, true, true, true);
+ assertRetainedClassesEqual(referenceInspector, ifHasMemberThenKeepClassInspector);
}
private void configureHorizontalClassMerging(R8FullTestBuilder testBuilder) {
@@ -313,58 +311,27 @@
private void assertRetainedClassesEqual(
GraphInspector referenceResult, GraphInspector conditionalResult) {
- assertRetainedClassesEqual(referenceResult, conditionalResult, false, false, false, false);
- }
-
- private void assertRetainedClassesEqual(
- GraphInspector referenceResult,
- GraphInspector conditionalResult,
- boolean expectReferenceIsLarger,
- boolean expectReferenceIsLargerOnlyBySynthetics,
- boolean expectConditionalIsLarger,
- boolean expectConditionalIsLargerOnlyBySynthetics) {
Set<String> referenceClasses =
new TreeSet<>(
referenceResult.codeInspector().allClasses().stream()
.map(FoundClassSubject::getOriginalName)
.collect(Collectors.toSet()));
-
Set<String> conditionalClasses =
conditionalResult.codeInspector().allClasses().stream()
.map(FoundClassSubject::getOriginalName)
.collect(Collectors.toSet());
- {
- Set<String> notInReference =
- new TreeSet<>(Sets.difference(conditionalClasses, referenceClasses));
- if (expectConditionalIsLarger) {
- assertFalse("Expected classes in -if rule to retain more.", notInReference.isEmpty());
- if (expectConditionalIsLargerOnlyBySynthetics) {
- assertAllClassesAreSynthetics(notInReference);
- }
- } else {
- assertEquals(
- "Classes in -if rule that are not in -keepclassmembers rule",
- Collections.emptySet(),
- notInReference);
- }
- }
- {
- Set<String> notInConditional =
- new TreeSet<>(Sets.difference(referenceClasses, conditionalClasses));
- if (expectReferenceIsLarger) {
- assertFalse(
- "Expected classes in -keepclassmembers rule to retain more.",
- notInConditional.isEmpty());
- if (expectReferenceIsLargerOnlyBySynthetics) {
- assertAllClassesAreSynthetics(notInConditional);
- }
- } else {
- assertEquals(
- "Classes in -keepclassmembers rule that are not in -if rule",
- Collections.emptySet(),
- notInConditional);
- }
- }
+ Set<String> notInReference =
+ new TreeSet<>(Sets.difference(conditionalClasses, referenceClasses));
+ assertEquals(
+ "Classes in -if rule that are not in -keepclassmembers rule",
+ Collections.emptySet(),
+ notInReference);
+ Set<String> notInConditional =
+ new TreeSet<>(Sets.difference(referenceClasses, conditionalClasses));
+ assertEquals(
+ "Classes in -keepclassmembers rule that are not in -if rule",
+ Collections.emptySet(),
+ notInConditional);
}
private void assertAllClassesAreSynthetics(Set<String> classNames) {
diff --git a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
index 5977b9a..b53f301 100644
--- a/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
+++ b/src/test/java/com/android/tools/r8/synthesis/SyntheticItemsTestUtils.java
@@ -16,6 +16,10 @@
public class SyntheticItemsTestUtils {
+ // Private copy of the synthetic namings. This is not the compiler instance, but checking on the
+ // id/descriptor content is safe.
+ private static final SyntheticNaming naming = new SyntheticNaming();
+
public static String syntheticMethodName() {
return SyntheticNaming.INTERNAL_SYNTHETIC_METHOD_NAME;
}
@@ -38,8 +42,7 @@
}
public static MethodReference syntheticBackportMethod(Class<?> clazz, int id, Method method) {
- ClassReference syntheticHolder =
- syntheticClass(clazz, SyntheticNaming.SyntheticKind.BACKPORT, id);
+ ClassReference syntheticHolder = syntheticClass(clazz, naming.BACKPORT, id);
MethodReference originalMethod = Reference.methodFromMethod(method);
return Reference.methodFromDescriptor(
syntheticHolder.getDescriptor(),
@@ -48,15 +51,15 @@
}
public static ClassReference syntheticOutlineClass(Class<?> clazz, int id) {
- return syntheticClass(clazz, SyntheticKind.OUTLINE, id);
+ return syntheticClass(clazz, naming.OUTLINE, id);
}
public static ClassReference syntheticOutlineClass(ClassReference clazz, int id) {
- return syntheticClass(clazz, SyntheticKind.OUTLINE, id);
+ return syntheticClass(clazz, naming.OUTLINE, id);
}
public static ClassReference syntheticLambdaClass(Class<?> clazz, int id) {
- return syntheticClass(clazz, SyntheticNaming.SyntheticKind.LAMBDA, id);
+ return syntheticClass(clazz, naming.LAMBDA, id);
}
public static MethodReference syntheticLambdaMethod(Class<?> clazz, int id, Method method) {
@@ -69,16 +72,15 @@
}
public static boolean isEnumUnboxingSharedUtilityClass(ClassReference reference) {
- return SyntheticNaming.isSynthetic(
- reference, null, SyntheticKind.ENUM_UNBOXING_SHARED_UTILITY_CLASS);
+ return SyntheticNaming.isSynthetic(reference, null, naming.ENUM_UNBOXING_SHARED_UTILITY_CLASS);
}
public static boolean isExternalSynthetic(ClassReference reference) {
- for (SyntheticKind kind : SyntheticKind.values()) {
+ for (SyntheticKind kind : naming.kinds()) {
if (kind.isGlobal()) {
continue;
}
- if (kind.isFixedSuffixSynthetic) {
+ if (kind.isFixedSuffixSynthetic()) {
if (SyntheticNaming.isSynthetic(reference, null, kind)) {
return true;
}
@@ -92,52 +94,48 @@
}
public static boolean isInternalLambda(ClassReference reference) {
- return SyntheticNaming.isSynthetic(reference, Phase.INTERNAL, SyntheticKind.LAMBDA);
+ return SyntheticNaming.isSynthetic(reference, Phase.INTERNAL, naming.LAMBDA);
}
public static boolean isExternalLambda(ClassReference reference) {
- return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.LAMBDA);
+ return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, naming.LAMBDA);
}
public static boolean isExternalStaticInterfaceCall(ClassReference reference) {
- return SyntheticNaming.isSynthetic(
- reference, Phase.EXTERNAL, SyntheticKind.STATIC_INTERFACE_CALL);
+ return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, naming.STATIC_INTERFACE_CALL);
}
public static boolean isExternalTwrCloseMethod(ClassReference reference) {
- return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.TWR_CLOSE_RESOURCE);
+ return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, naming.TWR_CLOSE_RESOURCE);
}
public static boolean isMaybeExternalSuppressedExceptionMethod(ClassReference reference) {
// The suppressed exception methods are grouped with the backports.
- return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.BACKPORT);
+ return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, naming.BACKPORT);
}
public static boolean isExternalOutlineClass(ClassReference reference) {
- return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, SyntheticKind.OUTLINE);
+ return SyntheticNaming.isSynthetic(reference, Phase.EXTERNAL, naming.OUTLINE);
}
public static boolean isInitializerTypeArgument(ClassReference reference) {
- return SyntheticNaming.isSynthetic(reference, null, SyntheticKind.INIT_TYPE_ARGUMENT);
+ return SyntheticNaming.isSynthetic(reference, null, naming.INIT_TYPE_ARGUMENT);
}
public static boolean isExternalNonFixedInitializerTypeArgument(ClassReference reference) {
return SyntheticNaming.isSynthetic(
- reference, Phase.EXTERNAL, SyntheticKind.NON_FIXED_INIT_TYPE_ARGUMENT);
+ reference, Phase.EXTERNAL, naming.NON_FIXED_INIT_TYPE_ARGUMENT);
}
public static boolean isHorizontalInitializerTypeArgument(ClassReference reference) {
- return SyntheticNaming.isSynthetic(
- reference, null, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_1)
- || SyntheticNaming.isSynthetic(
- reference, null, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_2)
- || SyntheticNaming.isSynthetic(
- reference, null, SyntheticKind.HORIZONTAL_INIT_TYPE_ARGUMENT_3);
+ return SyntheticNaming.isSynthetic(reference, null, naming.HORIZONTAL_INIT_TYPE_ARGUMENT_1)
+ || SyntheticNaming.isSynthetic(reference, null, naming.HORIZONTAL_INIT_TYPE_ARGUMENT_2)
+ || SyntheticNaming.isSynthetic(reference, null, naming.HORIZONTAL_INIT_TYPE_ARGUMENT_3);
}
public static boolean isWrapper(ClassReference reference) {
- return SyntheticNaming.isSynthetic(reference, null, SyntheticKind.WRAPPER)
- || SyntheticNaming.isSynthetic(reference, null, SyntheticKind.VIVIFIED_WRAPPER);
+ return SyntheticNaming.isSynthetic(reference, null, naming.WRAPPER)
+ || SyntheticNaming.isSynthetic(reference, null, naming.VIVIFIED_WRAPPER);
}
public static Matcher<String> containsInternalSyntheticReference() {
@@ -149,7 +147,6 @@
}
public static boolean isInternalThrowNSME(MethodReference method) {
- return SyntheticNaming.isSynthetic(
- method.getHolderClass(), Phase.INTERNAL, SyntheticKind.THROW_NSME);
+ return SyntheticNaming.isSynthetic(method.getHolderClass(), Phase.INTERNAL, naming.THROW_NSME);
}
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index d753ca5..d9869b2 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -36,8 +36,7 @@
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.retrace.Retracer;
-import com.android.tools.r8.retrace.internal.DirectClassNameMapperProguardMapProducer;
-import com.android.tools.r8.retrace.internal.RetracerImpl;
+import com.android.tools.r8.retrace.internal.ProguardMappingProviderImpl;
import com.android.tools.r8.synthesis.SyntheticItemsTestUtils;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BiMapContainer;
@@ -177,7 +176,11 @@
public Retracer getRetracer() {
if (lazyRetracer == null) {
- lazyRetracer = new RetracerImpl(mapping, new TestDiagnosticMessagesImpl());
+ lazyRetracer =
+ Retracer.builder()
+ .setMappingProvider(new ProguardMappingProviderImpl(mapping))
+ .setDiagnosticsHandler(new TestDiagnosticMessagesImpl())
+ .build();
}
return lazyRetracer;
}
@@ -525,24 +528,11 @@
}
public Retracer retrace() {
- return Retracer.createDefault(
- new InternalProguardMapProducer(
- mapping == null ? ClassNameMapper.builder().build() : mapping),
- new TestDiagnosticMessagesImpl());
- }
-
- public static class InternalProguardMapProducer
- implements DirectClassNameMapperProguardMapProducer {
-
- public final ClassNameMapper prebuiltMapper;
-
- public InternalProguardMapProducer(ClassNameMapper prebuiltMapper) {
- this.prebuiltMapper = prebuiltMapper;
- }
-
- @Override
- public ClassNameMapper getClassNameMapper() {
- return prebuiltMapper;
- }
+ return Retracer.builder()
+ .setMappingProvider(
+ new ProguardMappingProviderImpl(
+ mapping == null ? ClassNameMapper.builder().build() : mapping))
+ .setDiagnosticsHandler(new TestDiagnosticMessagesImpl())
+ .build();
}
}
diff --git a/third_party/retrace/binary_compatibility.tar.gz.sha1 b/third_party/retrace/binary_compatibility.tar.gz.sha1
index 26b5e24..431fdbe 100644
--- a/third_party/retrace/binary_compatibility.tar.gz.sha1
+++ b/third_party/retrace/binary_compatibility.tar.gz.sha1
@@ -1 +1 @@
-3238b42ace7a8e81abf0336c069645c5b97dd470
\ No newline at end of file
+2ebfdd6c7d270471cb38baa355d5d137af2f7dd1
\ No newline at end of file