Remove uses of MethodAccessInfoCollection after final tree shaking
Change-Id: Ibdedf96c0056c6eb82484c25117c69a09ea85d86
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index 81b1687..5b08837 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -78,6 +78,7 @@
import com.android.tools.r8.optimize.interfaces.analysis.CfOpenClosedInterfacesAnalysis;
import com.android.tools.r8.optimize.proto.ProtoNormalizer;
import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemover;
+import com.android.tools.r8.optimize.redundantbridgeremoval.RedundantBridgeRemover.RedundantBridgeRemoverMode;
import com.android.tools.r8.optimize.singlecaller.SingleCallerInliner;
import com.android.tools.r8.origin.CommandLineOrigin;
import com.android.tools.r8.origin.Origin;
@@ -487,7 +488,8 @@
// should therefore be run after the publicizer.
new NestReducer(appViewWithLiveness).run(executorService, timing);
- appView.setGraphLens(MemberRebindingIdentityLensFactory.create(appView, executorService));
+ appView.setGraphLens(
+ MemberRebindingIdentityLensFactory.createFromAppInfo(appViewWithLiveness));
new MemberRebindingAnalysis(appViewWithLiveness).run();
appViewWithLiveness.appInfo().notifyMemberRebindingFinished(appViewWithLiveness);
@@ -496,7 +498,7 @@
AccessModifier.run(appViewWithLiveness, executorService, timing);
- new RedundantBridgeRemover(appViewWithLiveness)
+ new RedundantBridgeRemover(appViewWithLiveness, RedundantBridgeRemoverMode.INITIAL)
.setMustRetargetInvokesToTargetMethod()
.run(executorService, timing);
@@ -683,14 +685,14 @@
// 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.
MemberRebindingIdentityLens memberRebindingIdentityLens =
- MemberRebindingIdentityLensFactory.create(appView, executorService);
+ MemberRebindingIdentityLensFactory.createFromLir(appView, executorService);
appView.setGraphLens(memberRebindingIdentityLens);
// Remove redundant bridges that have been inserted for member rebinding.
// This can only be done if we have AppInfoWithLiveness.
if (appView.appInfo().hasLiveness()) {
timing.begin("Bridge remover");
- new RedundantBridgeRemover(appView.withLiveness())
+ new RedundantBridgeRemover(appView.withLiveness(), RedundantBridgeRemoverMode.FINAL)
.run(executorService, timing, memberRebindingIdentityLens);
timing.end();
} else {
@@ -724,6 +726,7 @@
GenericSignatureContextBuilder genericContextBuilderBeforeFinalMerging = null;
if (appView.hasCfByteCodePassThroughMethods()) {
LirConverter.rewriteLirWithLens(appView, timing, executorService);
+ appView.clearCodeRewritings(executorService, timing);
} else {
// Perform repackaging.
if (appView.hasLiveness()) {
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 1b6b6f9..56670bf 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -448,7 +448,7 @@
setGraphLens(new ClearCodeRewritingGraphLens(withClassHierarchy()));
MemberRebindingIdentityLens memberRebindingIdentityLens =
- MemberRebindingIdentityLensFactory.rebuild(withClassHierarchy(), executorService);
+ MemberRebindingIdentityLensFactory.createFromLir(withClassHierarchy(), executorService);
setGraphLens(memberRebindingIdentityLens);
timing.end();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 518a40d..c09e32a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -110,6 +110,10 @@
return bootstrapArgs;
}
+ public DexMethodHandle getBootstrapMethod() {
+ return bootstrapMethod;
+ }
+
public DexProto getMethodProto() {
return methodProto;
}
diff --git a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
index 908f08f..0701401 100644
--- a/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/MethodAccessInfoCollection.java
@@ -37,6 +37,15 @@
private boolean fullyDestroyed = false;
+ private MethodAccessInfoCollection() {
+ this.directInvokes = ThrowingMap.get();
+ this.interfaceInvokes = ThrowingMap.get();
+ this.staticInvokes = ThrowingMap.get();
+ this.superInvokes = ThrowingMap.get();
+ this.virtualInvokes = ThrowingMap.get();
+ this.fullyDestroyed = true;
+ }
+
private MethodAccessInfoCollection(
Map<DexMethod, ProgramMethodSet> directInvokes,
Map<DexMethod, ProgramMethodSet> interfaceInvokes,
@@ -452,6 +461,13 @@
return new MethodAccessInfoCollection(
directInvokes, interfaceInvokes, staticInvokes, superInvokes, virtualInvokes);
}
+
+ public MethodAccessInfoCollection build(Enqueuer.Mode mode) {
+ if (mode.isInitialTreeShaking()) {
+ return build();
+ }
+ return new MethodAccessInfoCollection();
+ }
}
public static class ConcurrentBuilder
diff --git a/src/main/java/com/android/tools/r8/graph/ReferencedMembersCollector.java b/src/main/java/com/android/tools/r8/graph/ReferencedMembersCollector.java
new file mode 100644
index 0000000..c82116a
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/ReferencedMembersCollector.java
@@ -0,0 +1,112 @@
+// Copyright (c) 2024, 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.graph;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.lightir.LirCode;
+import com.android.tools.r8.lightir.LirConstant;
+import com.android.tools.r8.utils.ThreadUtils;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+
+public class ReferencedMembersCollector {
+
+ public interface ReferencedMembersConsumer {
+
+ void onFieldReference(DexField field, ProgramMethod context);
+
+ void onMethodReference(DexMethod method, ProgramMethod context);
+ }
+
+ private final AppView<? extends AppInfoWithClassHierarchy> appView;
+ private final ReferencedMembersConsumer consumer;
+
+ public ReferencedMembersCollector(
+ AppView<? extends AppInfoWithClassHierarchy> appView, ReferencedMembersConsumer consumer) {
+ this.appView = appView;
+ this.consumer = consumer;
+ }
+
+ public void run(ExecutorService executorService) throws ExecutionException {
+ ThreadUtils.processItems(
+ appView.appInfo().classes(),
+ this::processClass,
+ appView.options().getThreadingModule(),
+ executorService);
+ }
+
+ private void processClass(DexProgramClass clazz) {
+ clazz.forEachProgramMethodMatching(DexEncodedMethod::hasCode, this::processMethod);
+ }
+
+ private void processMethod(ProgramMethod method) {
+ Code code = method.getDefinition().getCode();
+ if (code.isCfCode()) {
+ assert appView.isCfByteCodePassThrough(method.getDefinition());
+ processCfCode(method, code.asCfCode());
+ } else if (code.isDefaultInstanceInitializerCode()) {
+ processDefaultInstanceInitializerCode(method);
+ } else if (code.isLirCode()) {
+ processLirCode(method, code.asLirCode());
+ } else if (code.isThrowNullCode()) {
+ // Intentionally empty.
+ } else {
+ assert false : code.getClass().getTypeName();
+ }
+ }
+
+ private void processDefaultInstanceInitializerCode(ProgramMethod method) {
+ DexMethod invokedMethod =
+ DefaultInstanceInitializerCode.getParentConstructor(method, appView.dexItemFactory());
+ consumer.onMethodReference(invokedMethod, method);
+ }
+
+ private void processCfCode(ProgramMethod method, CfCode code) {
+ for (CfInstruction instruction : code.getInstructions()) {
+ if (instruction.isFieldInstruction()) {
+ consumer.onFieldReference(instruction.asFieldInstruction().getField(), method);
+ } else if (instruction.isInvoke()) {
+ consumer.onMethodReference(instruction.asInvoke().getMethod(), method);
+ } else if (instruction.isInvokeDynamic()) {
+ processCallSite(method, instruction.asInvokeDynamic().getCallSite());
+ }
+ }
+ }
+
+ private void processLirCode(ProgramMethod method, LirCode<Integer> code) {
+ for (LirConstant constant : code.getConstantPool()) {
+ if (constant instanceof DexField) {
+ consumer.onFieldReference((DexField) constant, method);
+ } else if (constant instanceof DexCallSite) {
+ processCallSite(method, (DexCallSite) constant);
+ } else if (constant instanceof DexMethod) {
+ consumer.onMethodReference((DexMethod) constant, method);
+ } else if (constant instanceof DexMethodHandle) {
+ processMethodHandle(method, (DexMethodHandle) constant);
+ }
+ }
+ }
+
+ private void processCallSite(ProgramMethod method, DexCallSite callSite) {
+ processMethodHandle(method, callSite.getBootstrapMethod());
+ for (DexValue bootstrapArg : callSite.getBootstrapArgs()) {
+ if (bootstrapArg.isDexValueField()) {
+ consumer.onFieldReference(bootstrapArg.asDexValueField().getValue(), method);
+ } else if (bootstrapArg.isDexValueMethod()) {
+ consumer.onMethodReference(bootstrapArg.asDexValueMethod().getValue(), method);
+ } else if (bootstrapArg.isDexValueMethodHandle()) {
+ processMethodHandle(method, bootstrapArg.asDexValueMethodHandle().getValue());
+ }
+ }
+ }
+
+ private void processMethodHandle(ProgramMethod method, DexMethodHandle methodHandle) {
+ if (methodHandle.isFieldHandle()) {
+ consumer.onFieldReference(methodHandle.asField(), method);
+ } else {
+ assert methodHandle.isMethodHandle();
+ consumer.onMethodReference(methodHandle.asMethod(), method);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
index 9c774c4..80b6dc7 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/HorizontalClassMerger.java
@@ -16,10 +16,8 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.ImmediateProgramSubtypingInfo;
-import com.android.tools.r8.graph.MethodAccessInfoCollection;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.PrunedItems;
-import com.android.tools.r8.horizontalclassmerging.VirtualMethodMerger.SuperMethodReference;
import com.android.tools.r8.horizontalclassmerging.code.SyntheticInitializerConverter;
import com.android.tools.r8.ir.conversion.LirConverter;
import com.android.tools.r8.ir.conversion.MethodConversionOptions;
@@ -36,7 +34,6 @@
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.TraversalContinuation;
-import com.android.tools.r8.utils.collections.ProgramMethodMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
@@ -192,8 +189,6 @@
// sites, fields accesses, etc. are correctly transferred to the target classes.
DexApplication newApplication = getNewApplication(mergedClasses);
if (appView.enableWholeProgramOptimizations()) {
- ProgramMethodMap<DexMethod> newNonReboundMethodReferences =
- extractNonReboundMethodReferences(groups, horizontalClassMergerGraphLens);
// Finalize synthetic code.
transformIncompleteCode(groups, horizontalClassMergerGraphLens, executorService);
// Prune keep info.
@@ -212,8 +207,6 @@
appViewWithClassHierarchy.setAppInfo(
appViewWithClassHierarchy.appInfo().rebuildWithClassHierarchy(newApplication));
}
- amendMethodAccessInfoCollection(
- horizontalClassMergerGraphLens, newNonReboundMethodReferences);
appView.clearCodeRewritings(executorService, timing);
} else {
SyntheticItems syntheticItems = appView.appInfo().getSyntheticItems();
@@ -277,40 +270,6 @@
});
}
- private ProgramMethodMap<DexMethod> extractNonReboundMethodReferences(
- Collection<HorizontalMergeGroup> groups, HorizontalClassMergerGraphLens lens) {
- ProgramMethodMap<DexMethod> newNonReboundMethodReferences = ProgramMethodMap.create();
- for (HorizontalMergeGroup group : groups) {
- group
- .getTarget()
- .forEachProgramVirtualMethodMatching(
- method ->
- method.hasCode()
- && method.getCode() instanceof IncompleteVirtuallyMergedMethodCode
- && ((IncompleteVirtuallyMergedMethodCode) method.getCode()).hasSuperMethod(),
- method -> {
- SuperMethodReference superMethodReference =
- ((IncompleteVirtuallyMergedMethodCode) method.getDefinition().getCode())
- .getSuperMethod();
- newNonReboundMethodReferences.put(
- method, superMethodReference.getRewrittenReference(lens, method));
- });
- }
- return newNonReboundMethodReferences;
- }
-
- private void amendMethodAccessInfoCollection(
- HorizontalClassMergerGraphLens lens,
- ProgramMethodMap<DexMethod> newNonReboundMethodReferences) {
- MethodAccessInfoCollection.Modifier methodAccessInfoCollectionModifier =
- appView.appInfoWithLiveness().getMethodAccessInfoCollection().modifier();
- newNonReboundMethodReferences.forEach(
- (context, reference) ->
- // Reference is already lens rewritten.
- methodAccessInfoCollectionModifier.registerInvokeSuperInContext(
- reference, context.rewrittenWithLens(lens, lens.getPrevious(), appView)));
- }
-
private FieldAccessInfoCollectionModifier createFieldAccessInfoCollectionModifier(
Collection<HorizontalMergeGroup> groups) {
FieldAccessInfoCollectionModifier.Builder builder =
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 31577fc..71f0772 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
@@ -115,7 +115,6 @@
private final ClassInliner classInliner;
protected final InternalOptions options;
public final CodeRewriter codeRewriter;
- public AssertionErrorTwoArgsConstructorRewriter assertionErrorTwoArgsConstructorRewriter;
public final MemberValuePropagation<?> memberValuePropagation;
private final LensCodeRewriter lensCodeRewriter;
protected final Inliner inliner;
@@ -124,7 +123,6 @@
protected final CovariantReturnTypeAnnotationTransformer covariantReturnTypeAnnotationTransformer;
private final StringSwitchRemover stringSwitchRemover;
private final TypeChecker typeChecker;
- protected ServiceLoaderRewriter serviceLoaderRewriter;
protected EnumUnboxer enumUnboxer;
protected final NumberUnboxer numberUnboxer;
protected final RemoveVerificationErrorForUnknownReturnedValues
@@ -164,10 +162,6 @@
this.options = appView.options();
this.codeRewriter = new CodeRewriter(appView);
this.rewriterPassCollection = CodeRewriterPassCollection.create(appView);
- this.assertionErrorTwoArgsConstructorRewriter =
- appView.options().desugarState.isOn()
- ? new AssertionErrorTwoArgsConstructorRewriter(appView)
- : null;
this.classInitializerDefaultsOptimization =
new ClassInitializerDefaultsOptimization(appView, this);
this.deadCodeRemover = new DeadCodeRemover(appView);
@@ -210,7 +204,6 @@
this.devirtualizer = null;
this.typeChecker = null;
this.stringSwitchRemover = null;
- this.serviceLoaderRewriter = null;
this.methodOptimizationInfoCollector = null;
this.enumUnboxer = EnumUnboxer.empty();
this.numberUnboxer = NumberUnboxer.empty();
@@ -262,10 +255,6 @@
this.devirtualizer =
options.enableDevirtualization ? new Devirtualizer(appViewWithLiveness) : null;
this.typeChecker = new TypeChecker(appViewWithLiveness, VerifyTypesHelper.create(appView));
- this.serviceLoaderRewriter =
- options.enableServiceLoaderRewriting
- ? new ServiceLoaderRewriter(appViewWithLiveness, appView.apiLevelCompute())
- : null;
} else {
AppView<AppInfo> appViewWithoutClassHierarchy = appView.withoutClassHierarchy();
this.assumeInserter = null;
@@ -283,7 +272,6 @@
this.identifierNameStringMarker = null;
this.devirtualizer = null;
this.typeChecker = null;
- this.serviceLoaderRewriter = null;
this.methodOptimizationInfoCollector = null;
this.enumUnboxer = EnumUnboxer.empty();
this.numberUnboxer = NumberUnboxer.empty();
@@ -298,14 +286,6 @@
this(AppView.createForD8(appInfo));
}
- public void clearEnumUnboxer() {
- enumUnboxer = EnumUnboxer.empty();
- }
-
- public void clearServiceLoaderRewriter() {
- serviceLoaderRewriter = null;
- }
-
public Inliner getInliner() {
return inliner;
}
@@ -631,10 +611,12 @@
CheckNotNullConverter.runIfNecessary(appView, code);
previous = printMethod(code, "IR after disable assertions (SSA)", previous);
- if (serviceLoaderRewriter != null) {
- assert appView.appInfo().hasLiveness();
+ if (appView.hasLiveness()
+ && methodProcessor.isPrimaryMethodProcessor()
+ && options.enableServiceLoaderRewriting) {
timing.begin("Rewrite service loaders");
- serviceLoaderRewriter.rewrite(code, methodProcessor, methodProcessingContext);
+ new ServiceLoaderRewriter(appView.withLiveness())
+ .rewrite(code, methodProcessor, methodProcessingContext);
timing.end();
previous = printMethod(code, "IR after service rewriting (SSA)", previous);
}
@@ -732,10 +714,11 @@
assert code.verifyTypes(appView);
- if (assertionErrorTwoArgsConstructorRewriter != null) {
+ if (appView.options().desugarState.isOn()
+ && (methodProcessor.isPrimaryMethodProcessor() || methodProcessor.isD8MethodProcessor())) {
timing.begin("Rewrite AssertionError");
- assertionErrorTwoArgsConstructorRewriter.rewrite(
- code, methodProcessor, methodProcessingContext);
+ new AssertionErrorTwoArgsConstructorRewriter(appView)
+ .rewrite(code, methodProcessor, methodProcessingContext);
timing.end();
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
index 941930c..6da063b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LirConverter.java
@@ -37,7 +37,7 @@
public class LirConverter {
public static void enterLirSupportedPhase(
- AppView<AppInfoWithClassHierarchy> appView, ExecutorService executorService)
+ AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService)
throws ExecutionException {
assert appView.testing().canUseLir(appView);
assert appView.testing().isPreLirPhase();
@@ -161,7 +161,8 @@
// Clear the reference type cache after conversion to reduce memory pressure.
appView.dexItemFactory().clearTypeElementsCache();
// At this point all code has been mapped according to the graph lens.
- appView.clearCodeRewritings(executorService, timing);
+ assert appView.graphLens().isMemberRebindingIdentityLens()
+ && appView.graphLens().asMemberRebindingIdentityLens().getPrevious() == appView.codeLens();
}
private static void finalizeLirMethodToOutputFormat(
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
index 625a337..eb16aef 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryD8L8IRConverter.java
@@ -71,11 +71,6 @@
reportNestDesugarDependencies();
clearNestAttributes();
- if (assertionErrorTwoArgsConstructorRewriter != null) {
- processSimpleSynthesizeMethods(
- assertionErrorTwoArgsConstructorRewriter.getSynthesizedMethods(), executorService);
- }
-
application = commitPendingSyntheticItems(appView, application);
postProcessingDesugaringForD8(methodProcessor, interfaceProcessor, executorService);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
index 663f27f..71f3df9 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/PrimaryR8IRConverter.java
@@ -273,17 +273,9 @@
PostMethodProcessor.Builder postMethodProcessorBuilder, ExecutorService executorService)
throws ExecutionException {
pruneItems(executorService);
- if (assertionErrorTwoArgsConstructorRewriter != null) {
- assertionErrorTwoArgsConstructorRewriter.onLastWaveDone(postMethodProcessorBuilder);
- assertionErrorTwoArgsConstructorRewriter = null;
- }
if (inliner != null) {
inliner.onLastWaveDone(postMethodProcessorBuilder, executorService, timing);
}
- if (serviceLoaderRewriter != null) {
- serviceLoaderRewriter.onLastWaveDone(postMethodProcessorBuilder);
- serviceLoaderRewriter = null;
- }
// Ensure determinism of method-to-reprocess set.
appView.testing().checkDeterminism(postMethodProcessorBuilder::dump);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
index d1201b5..be2e313 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/AssertionErrorTwoArgsConstructorRewriter.java
@@ -22,7 +22,6 @@
import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.MethodProcessor;
-import com.android.tools.r8.ir.conversion.PostMethodProcessor;
import com.android.tools.r8.ir.desugar.backports.BackportedMethods;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
import com.android.tools.r8.utils.InternalOptions;
@@ -42,7 +41,6 @@
this.dexItemFactory = appView.dexItemFactory();
}
- @SuppressWarnings("ReferenceEquality")
public void rewrite(
IRCode code,
MethodProcessor methodProcessor,
@@ -61,7 +59,8 @@
InvokeDirect invoke = insnIterator.next().asInvokeDirect();
if (invoke != null) {
DexMethod invokedMethod = invoke.getInvokedMethod();
- if (invokedMethod == dexItemFactory.assertionErrorMethods.initMessageAndCause) {
+ if (invokedMethod.isIdenticalTo(
+ dexItemFactory.assertionErrorMethods.initMessageAndCause)) {
assert invoke.arguments().size() == 3; // receiver, message, cause
Value newInstanceValue = invoke.getReceiver();
Instruction definition = newInstanceValue.getDefinition();
@@ -90,12 +89,6 @@
assert code.isConsistentSSA(appView);
}
- private final List<ProgramMethod> synthesizedMethods = new ArrayList<>();
-
- public List<ProgramMethod> getSynthesizedMethods() {
- return synthesizedMethods;
- }
-
private ProgramMethod createSynthetic(
MethodProcessor methodProcessor, MethodProcessingContext methodProcessingContext) {
DexItemFactory factory = appView.dexItemFactory();
@@ -117,25 +110,19 @@
methodSig ->
BackportedMethods.AssertionErrorMethods_createAssertionError(
factory, methodSig)));
- synchronized (synthesizedMethods) {
- synthesizedMethods.add(method);
- OptimizationFeedback.getSimpleFeedback()
- .setDynamicReturnType(
- method,
- appView,
- DynamicType.createExact(
- dexItemFactory
- .assertionErrorType
- .toTypeElement(appView, Nullability.definitelyNotNull())
- .asClassType()));
- }
+ OptimizationFeedback.getSimpleFeedback()
+ .setDynamicReturnType(
+ method,
+ appView,
+ DynamicType.createExact(
+ dexItemFactory
+ .assertionErrorType
+ .toTypeElement(appView, Nullability.definitelyNotNull())
+ .asClassType()));
+ methodProcessor.scheduleDesugaredMethodForProcessing(method);
methodProcessor
.getEventConsumer()
.acceptAssertionErrorCreateMethod(method, methodProcessingContext.getMethodContext());
return method;
}
-
- public void onLastWaveDone(PostMethodProcessor.Builder postMethodProcessorBuilder) {
- postMethodProcessorBuilder.addAll(synthesizedMethods, appView.graphLens());
- }
}
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 9e7e988..455ef32 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.InvokeVirtual;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.MethodProcessor;
-import com.android.tools.r8.ir.conversion.PostMethodProcessor;
import com.android.tools.r8.ir.desugar.ServiceLoaderSourceCode;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.BooleanBox;
@@ -70,12 +69,9 @@
private final Reporter reporter;
private final ServiceLoaderMethods serviceLoaderMethods;
- private final List<ProgramMethod> synthesizedServiceLoadMethods = new ArrayList<>();
-
- public ServiceLoaderRewriter(
- AppView<AppInfoWithLiveness> appView, AndroidApiLevelCompute apiLevelCompute) {
+ public ServiceLoaderRewriter(AppView<AppInfoWithLiveness> appView) {
this.appView = appView;
- this.apiLevelCompute = apiLevelCompute;
+ this.apiLevelCompute = appView.apiLevelCompute();
serviceLoaderMethods = appView.dexItemFactory().serviceLoaderMethods;
reporter = shouldReportWhyAreYouNotInliningServiceLoaderLoad() ? appView.reporter() : null;
}
@@ -91,7 +87,6 @@
IRCode code,
MethodProcessor methodProcessor,
MethodProcessingContext methodProcessingContext) {
- assert !methodProcessor.isPostMethodProcessor();
InstructionListIterator instructionIterator = code.instructionListIterator();
// Create a map from service type to loader methods local to this context since two
// service loader calls to the same type in different methods and in the same wave can race.
@@ -243,10 +238,6 @@
assert code.isConsistentSSA(appView);
}
- public void onLastWaveDone(PostMethodProcessor.Builder postMethodProcessorBuilder) {
- postMethodProcessorBuilder.addAll(synthesizedServiceLoadMethods, appView.graphLens());
- }
-
private void report(ProgramMethod method, DexType serviceLoaderType, String message) {
if (reporter != null) {
reporter.info(
@@ -286,9 +277,7 @@
m ->
ServiceLoaderSourceCode.generate(
serviceType, classes, appView.dexItemFactory())));
- synchronized (synthesizedServiceLoadMethods) {
- synthesizedServiceLoadMethods.add(method);
- }
+ methodProcessor.scheduleDesugaredMethodForProcessing(method);
methodProcessor
.getEventConsumer()
.acceptServiceLoaderLoadUtilityMethod(method, methodProcessingContext.getMethodContext());
diff --git a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
index f15bba1..8bfa3ec 100644
--- a/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/FieldNameMinifier.java
@@ -3,18 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.naming;
-import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
-
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
-import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.FieldAccessInfo;
-import com.android.tools.r8.graph.FieldAccessInfoCollection;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.TopDownClassHierarchyTraversal;
@@ -70,10 +65,6 @@
renameFieldsInClasses();
renameFieldsInUnrelatedClasspathClasses();
timing.end();
- // Rename the references that are not rebound to definitions for some reasons.
- timing.begin("rename-references");
- renameNonReboundReferences();
- timing.end();
return new FieldRenaming(renaming);
}
@@ -281,35 +272,6 @@
return newName;
}
- private void renameNonReboundReferences() {
- FieldAccessInfoCollection<?> fieldAccessInfoCollection =
- appView.appInfo().getFieldAccessInfoCollection();
- fieldAccessInfoCollection.forEach(this::renameNonReboundAccessesToField);
- }
-
- private void renameNonReboundAccessesToField(FieldAccessInfo fieldAccessInfo) {
- fieldAccessInfo.forEachIndirectAccess(this::renameNonReboundAccessToField);
- }
-
- @SuppressWarnings("ReferenceEquality")
- private void renameNonReboundAccessToField(DexField field) {
- // If the given field reference is a non-rebound reference to a program field, then assign the
- // same name as the resolved field.
- if (renaming.containsKey(field)) {
- return;
- }
- DexProgramClass holder = asProgramClassOrNull(appView.definitionForHolder(field));
- if (holder == null) {
- return;
- }
- DexEncodedField definition = appView.appInfo().resolveFieldOn(holder, field).getResolvedField();
- if (definition != null
- && definition.getReference() != field
- && renaming.containsKey(definition.getReference())) {
- renaming.put(field, renaming.get(definition.getReference()));
- }
- }
-
static class InterfacePartitioning {
private final FieldNameMinifier minifier;
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index fa5089d..ceb8d73b 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -10,26 +10,20 @@
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMember;
import com.android.tools.r8.graph.DexClassAndMethod;
-import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.graph.MethodAccessInfoCollection;
-import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.graph.TopDownClassHierarchyTraversal;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
-import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.WorkList;
import com.android.tools.r8.utils.collections.DexClassAndMethodSet;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableMap;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -38,9 +32,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
import java.util.function.Function;
/**
@@ -191,11 +182,7 @@
}
MethodRenaming computeRenaming(
- Iterable<DexClass> interfaces,
- SubtypingInfo subtypingInfo,
- ExecutorService executorService,
- Timing timing)
- throws ExecutionException {
+ Iterable<DexClass> interfaces, SubtypingInfo subtypingInfo, Timing timing) {
// Phase 1: Reserve all the names that need to be kept and allocate linked state in the
// library part.
timing.begin("Phase 1");
@@ -216,9 +203,6 @@
assignNamesToClassesMethods();
renameMethodsInUnrelatedClasspathClasses();
timing.end();
- timing.begin("Phase 5: non-rebound references");
- renameNonReboundReferences(executorService);
- timing.end();
return new MethodRenaming(renaming);
}
@@ -436,65 +420,6 @@
return reservationState;
}
- private void renameNonReboundReferences(ExecutorService executorService)
- throws ExecutionException {
- Map<DexMethod, DexString> nonReboundRenamings = new ConcurrentHashMap<>();
- MethodAccessInfoCollection methodAccessInfoCollection =
- appView.appInfo().getMethodAccessInfoCollection();
- ThreadUtils.processItems(
- methodAccessInfoCollection::forEachMethodReference,
- method -> renameNonReboundMethodReference(method, nonReboundRenamings),
- appView.options().getThreadingModule(),
- executorService);
- renaming.putAll(nonReboundRenamings);
- }
-
- @SuppressWarnings("ReferenceEquality")
- private void renameNonReboundMethodReference(
- DexMethod method, Map<DexMethod, DexString> nonReboundRenamings) {
- if (method.getHolderType().isArrayType()) {
- return;
- }
-
- DexClass holder = appView.contextIndependentDefinitionFor(method.getHolderType());
- if (holder == null) {
- return;
- }
-
- MethodResolutionResult resolutionResult =
- appView.appInfo().resolveMethodOnLegacy(holder, method);
- if (resolutionResult.isSingleResolution()) {
- DexEncodedMethod resolvedMethod = resolutionResult.getSingleTarget();
- if (resolvedMethod.getReference() == method) {
- return;
- }
-
- DexString newName = renaming.get(resolvedMethod.getReference());
- if (newName != null) {
- assert newName != resolvedMethod.getName();
- nonReboundRenamings.put(method, newName);
- }
- return;
- }
-
- // If resolution fails, the method must be renamed consistently with the targets that give rise
- // to the failure.
- assert resolutionResult.isFailedResolution();
-
- List<DexEncodedMethod> targets = new ArrayList<>();
- resolutionResult
- .asFailedResolution()
- .forEachFailureDependency(ConsumerUtils.emptyConsumer(), targets::add);
- if (!targets.isEmpty()) {
- DexString newName = renaming.get(targets.get(0).getReference());
- assert targets.stream().allMatch(target -> renaming.get(target.getReference()) == newName);
- if (newName != null) {
- assert newName != targets.get(0).getName();
- nonReboundRenamings.put(method, newName);
- }
- }
- }
-
// Shuffles the given methods if assertions are enabled and deterministic debugging is disabled.
// Used to ensure that the generated output is deterministic.
private static Iterable<DexClassAndMethod> shuffleMethods(
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 376c969..335caa5 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -8,29 +8,40 @@
import static com.android.tools.r8.utils.SymbolGenerationUtils.RESERVED_NAMES;
import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndField;
import com.android.tools.r8.graph.DexClassAndMethod;
+import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.MethodResolutionResult;
import com.android.tools.r8.graph.ProgramField;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ReferencedMembersCollector;
+import com.android.tools.r8.graph.ReferencedMembersCollector.ReferencedMembersConsumer;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.naming.ClassNameMinifier.ClassNamingStrategy;
import com.android.tools.r8.naming.ClassNameMinifier.ClassRenaming;
import com.android.tools.r8.naming.FieldNameMinifier.FieldRenaming;
import com.android.tools.r8.naming.MethodNameMinifier.MethodRenaming;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.SymbolGenerationUtils;
import com.android.tools.r8.utils.SymbolGenerationUtils.MixedCasing;
import com.android.tools.r8.utils.Timing;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.function.BiPredicate;
@@ -70,7 +81,7 @@
timing.begin("MinifyMethods");
MethodRenaming methodRenaming =
new MethodNameMinifier(appView, minifyMembers)
- .computeRenaming(interfaces, subtypingInfo, executorService, timing);
+ .computeRenaming(interfaces, subtypingInfo, timing);
timing.end();
assert new MinifiedRenaming(appView, classRenaming, methodRenaming, FieldRenaming.empty())
@@ -82,6 +93,11 @@
.computeRenaming(interfaces, timing);
timing.end();
+ // Rename the references that are not rebound to definitions.
+ timing.begin("non-rebound-references");
+ renameNonReboundReferences(appView, fieldRenaming, methodRenaming, executorService);
+ timing.end();
+
NamingLens lens = new MinifiedRenaming(appView, classRenaming, methodRenaming, fieldRenaming);
assert lens.verifyNoCollisions(appView.appInfo().classes(), appView.dexItemFactory());
@@ -90,6 +106,75 @@
appView.setNamingLens(lens);
}
+ public static void renameNonReboundReferences(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ FieldRenaming fieldRenaming,
+ MethodRenaming methodRenaming,
+ ExecutorService executorService)
+ throws ExecutionException {
+ Map<DexField, DexString> fieldNames = new ConcurrentHashMap<>(fieldRenaming.renaming);
+ fieldRenaming.renaming.clear();
+ Map<DexMethod, DexString> methodNames = new ConcurrentHashMap<>(methodRenaming.renaming);
+ methodRenaming.renaming.clear();
+ ReferencedMembersConsumer consumer =
+ new ReferencedMembersConsumer() {
+
+ @Override
+ public void onFieldReference(DexField field, ProgramMethod context) {
+ // If the given field reference is a non-rebound reference to a program field, then
+ // assign the same name as the resolved field.
+ if (fieldNames.containsKey(field)) {
+ return;
+ }
+ DexEncodedField resolvedField =
+ appView.appInfo().resolveField(field).getResolvedField();
+ if (resolvedField != null
+ && resolvedField.getReference().isNotIdenticalTo(field)
+ && fieldNames.containsKey(resolvedField.getReference())) {
+ fieldNames.put(field, fieldNames.get(resolvedField.getReference()));
+ }
+ }
+
+ @Override
+ public void onMethodReference(DexMethod method, ProgramMethod context) {
+ // If the given method reference is a non-rebound reference to a program method, then
+ // assign the same name as the resolved method.
+ if (method.getHolderType().isArrayType() || methodNames.containsKey(method)) {
+ return;
+ }
+ MethodResolutionResult resolutionResult =
+ appView.appInfo().unsafeResolveMethodDueToDexFormat(method);
+ DexEncodedMethod resolvedMethod = resolutionResult.getResolvedMethod();
+ if (resolvedMethod != null
+ && resolvedMethod.getReference().isNotIdenticalTo(method)
+ && methodNames.containsKey(resolvedMethod.getReference())) {
+ methodNames.put(method, methodNames.get(resolvedMethod.getReference()));
+ }
+ // If resolution fails, the method must be renamed consistently with the targets that
+ // give rise to the failure.
+ if (resolutionResult.isFailedResolution()) {
+ List<DexEncodedMethod> targets = new ArrayList<>();
+ resolutionResult
+ .asFailedResolution()
+ .forEachFailureDependency(ConsumerUtils.emptyConsumer(), targets::add);
+ if (!targets.isEmpty()) {
+ DexString newName = methodNames.get(targets.get(0).getReference());
+ assert targets.stream()
+ .allMatch(
+ target -> newName.isIdenticalTo(methodNames.get(target.getReference())));
+ if (newName != null) {
+ assert newName.isNotIdenticalTo(targets.get(0).getName());
+ methodNames.put(method, newName);
+ }
+ }
+ }
+ }
+ };
+ new ReferencedMembersCollector(appView, consumer).run(executorService);
+ fieldRenaming.renaming.putAll(fieldNames);
+ methodRenaming.renaming.putAll(methodNames);
+ }
+
abstract static class BaseMinificationNamingStrategy {
// We have to ensure that the names proposed by the minifier is not used in the obfuscation
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
index d5f4683..d2f2e8a 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -10,6 +10,7 @@
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.getInterfaceClassType;
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.isCompanionClassType;
import static com.android.tools.r8.ir.desugar.itf.InterfaceDesugaringSyntheticHelper.staticAsMethodOfCompanionClass;
+import static com.android.tools.r8.naming.Minifier.renameNonReboundReferences;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
@@ -138,7 +139,7 @@
timing.begin("MinifyMethods");
MethodRenaming methodRenaming =
new MethodNameMinifier(appView, nameStrategy)
- .computeRenaming(interfaces, subtypingInfo, executorService, timing);
+ .computeRenaming(interfaces, subtypingInfo, timing);
// Amend the method renamings with the default interface methods.
methodRenaming.renaming.putAll(companionClassInterfaceMethodImplementationNames);
methodRenaming.renaming.putAll(additionalMethodNamings);
@@ -151,6 +152,11 @@
fieldRenaming.renaming.putAll(additionalFieldNamings);
timing.end();
+ // Rename the references that are not rebound to definitions.
+ timing.begin("non-rebound-references");
+ renameNonReboundReferences(appView, fieldRenaming, methodRenaming, executorService);
+ timing.end();
+
appView.options().reporter.failIfPendingErrors();
NamingLens lens =
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
index 0ea0a9a..76e600d 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLens.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
@@ -21,6 +22,7 @@
import java.util.Deque;
import java.util.IdentityHashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* This lens is used to populate the rebound field and method reference during lookup, such that
@@ -48,7 +50,16 @@
public static Builder builder(
AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens previousLens) {
- return new Builder(appView, previousLens);
+ return new Builder(appView, previousLens, new IdentityHashMap<>(), new IdentityHashMap<>());
+ }
+
+ public static Builder concurrentBuilder(AppView<? extends AppInfoWithClassHierarchy> appView) {
+ return concurrentBuilder(appView, appView.graphLens());
+ }
+
+ public static Builder concurrentBuilder(
+ AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens previousLens) {
+ return new Builder(appView, previousLens, new ConcurrentHashMap<>(), new ConcurrentHashMap<>());
}
public void addNonReboundMethodReference(
@@ -174,14 +185,18 @@
private final AppView<? extends AppInfoWithClassHierarchy> appView;
private final GraphLens previousLens;
- private final Map<DexField, DexField> nonReboundFieldReferenceToDefinitionMap =
- new IdentityHashMap<>();
- private final Map<DexMethod, DexMethod> nonReboundMethodReferenceToDefinitionMap =
- new IdentityHashMap<>();
+ private final Map<DexField, DexField> nonReboundFieldReferenceToDefinitionMap;
+ private final Map<DexMethod, DexMethod> nonReboundMethodReferenceToDefinitionMap;
- private Builder(AppView<? extends AppInfoWithClassHierarchy> appView, GraphLens previousLens) {
+ private Builder(
+ AppView<? extends AppInfoWithClassHierarchy> appView,
+ GraphLens previousLens,
+ Map<DexField, DexField> nonReboundFieldReferenceToDefinitionMap,
+ Map<DexMethod, DexMethod> nonReboundMethodReferenceToDefinitionMap) {
this.appView = appView;
this.previousLens = previousLens;
+ this.nonReboundFieldReferenceToDefinitionMap = nonReboundFieldReferenceToDefinitionMap;
+ this.nonReboundMethodReferenceToDefinitionMap = nonReboundMethodReferenceToDefinitionMap;
}
void recordNonReboundFieldAccesses(FieldAccessInfo fieldAccessInfo) {
@@ -203,11 +218,21 @@
nonReboundMethodReference, reboundMethodReference);
}
+ void recordFieldAccess(DexField reference) {
+ DexEncodedField resolvedField = appView.appInfo().resolveField(reference).getResolvedField();
+ if (resolvedField != null && resolvedField.getReference().isNotIdenticalTo(reference)) {
+ recordNonReboundFieldAccess(reference, resolvedField.getReference());
+ }
+ }
+
void recordMethodAccess(DexMethod reference) {
if (reference.getHolderType().isArrayType()) {
return;
}
- DexClass holder = appView.contextIndependentDefinitionFor(reference.getHolderType());
+ // TODO(b/324526473): Use normal definitionFor() when LIR constant pool does not have any
+ // outdated, unused constants.
+ DexClass holder =
+ appView.appInfo().definitionForWithoutExistenceAssert(reference.getHolderType());
if (holder != null) {
SingleResolutionResult<?> resolutionResult =
appView.appInfo().resolveMethodOnLegacy(holder, reference).asSingleResolution();
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java
index 19e25d2..f2a6f2b 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingIdentityLensFactory.java
@@ -4,24 +4,17 @@
package com.android.tools.r8.optimize;
-import com.android.tools.r8.graph.AbstractAccessContexts.ConcreteAccessContexts;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
-import com.android.tools.r8.graph.DefaultUseRegistry;
-import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.FieldAccessInfoCollection;
-import com.android.tools.r8.graph.FieldAccessInfoCollectionImpl;
-import com.android.tools.r8.graph.FieldAccessInfoImpl;
import com.android.tools.r8.graph.MethodAccessInfoCollection;
-import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.graph.ReferencedMembersCollector;
+import com.android.tools.r8.graph.ReferencedMembersCollector.ReferencedMembersConsumer;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
-import com.android.tools.r8.utils.SetUtils;
-import com.android.tools.r8.utils.ThreadUtils;
-import com.android.tools.r8.utils.collections.ProgramMethodSet;
-import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
@@ -29,62 +22,39 @@
public class MemberRebindingIdentityLensFactory {
- /**
- * In order to construct an instance of {@link MemberRebindingIdentityLens} we need a mapping from
- * non-rebound field and method references to their definitions.
- *
- * <p>If shrinking or minification is enabled, we retrieve these from {@link AppInfoWithLiveness}.
- * Otherwise we apply the {@link NonReboundMemberReferencesRegistry} below to all code objects to
- * compute the mapping.
- */
- public static MemberRebindingIdentityLens rebuild(
- AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService)
- throws ExecutionException {
- FieldAccessInfoCollectionImpl mutableFieldAccessInfoCollection =
- new FieldAccessInfoCollectionImpl(new ConcurrentHashMap<>());
- MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder =
- MethodAccessInfoCollection.concurrentBuilder();
- initializeMemberAccessInfoCollectionsForMemberRebinding(
- appView,
- mutableFieldAccessInfoCollection,
- methodAccessInfoCollectionBuilder,
- executorService);
- return create(
- appView, mutableFieldAccessInfoCollection, methodAccessInfoCollectionBuilder.build());
+ public static MemberRebindingIdentityLens createFromAppInfo(
+ AppView<AppInfoWithLiveness> appView) {
+ FieldAccessInfoCollection<?> fieldAccessInfoCollection =
+ appView.appInfo().getFieldAccessInfoCollection();
+ MethodAccessInfoCollection methodAccessInfoCollection =
+ appView.appInfo().getMethodAccessInfoCollection();
+ return create(appView, fieldAccessInfoCollection, methodAccessInfoCollection);
}
- /**
- * In order to construct an instance of {@link MemberRebindingIdentityLens} we need a mapping from
- * non-rebound field and method references to their definitions.
- *
- * <p>If shrinking or minification is enabled, we retrieve these from {@link AppInfoWithLiveness}.
- * Otherwise we apply the {@link NonReboundMemberReferencesRegistry} below to all code objects to
- * compute the mapping.
- */
- public static MemberRebindingIdentityLens create(
+ public static MemberRebindingIdentityLens createFromLir(
AppView<? extends AppInfoWithClassHierarchy> appView, ExecutorService executorService)
throws ExecutionException {
- FieldAccessInfoCollection<?> fieldAccessInfoCollection;
- MethodAccessInfoCollection methodAccessInfoCollection;
- if (appView.appInfo().hasLiveness()
- && appView.options().testing.alwaysUseExistingAccessInfoCollectionsInMemberRebinding) {
- AppInfoWithLiveness appInfo = appView.appInfo().withLiveness();
- fieldAccessInfoCollection = appInfo.getFieldAccessInfoCollection();
- methodAccessInfoCollection = appInfo.getMethodAccessInfoCollection();
- } else {
- FieldAccessInfoCollectionImpl mutableFieldAccessInfoCollection =
- new FieldAccessInfoCollectionImpl(new ConcurrentHashMap<>());
- MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder =
- MethodAccessInfoCollection.concurrentBuilder();
- initializeMemberAccessInfoCollectionsForMemberRebinding(
- appView,
- mutableFieldAccessInfoCollection,
- methodAccessInfoCollectionBuilder,
- executorService);
- fieldAccessInfoCollection = mutableFieldAccessInfoCollection;
- methodAccessInfoCollection = methodAccessInfoCollectionBuilder.build();
- }
- return create(appView, fieldAccessInfoCollection, methodAccessInfoCollection);
+ MemberRebindingIdentityLens.Builder builder =
+ MemberRebindingIdentityLens.concurrentBuilder(appView);
+ Set<DexMember<?, ?>> seen = ConcurrentHashMap.newKeySet();
+ ReferencedMembersConsumer consumer =
+ new ReferencedMembersConsumer() {
+ @Override
+ public void onFieldReference(DexField field, ProgramMethod context) {
+ if (seen.add(field)) {
+ builder.recordFieldAccess(field);
+ }
+ }
+
+ @Override
+ public void onMethodReference(DexMethod method, ProgramMethod context) {
+ if (seen.add(method)) {
+ builder.recordMethodAccess(method);
+ }
+ }
+ };
+ new ReferencedMembersCollector(appView, consumer).run(executorService);
+ return builder.build();
}
public static MemberRebindingIdentityLens create(
@@ -96,165 +66,4 @@
methodAccessInfoCollection.forEachMethodReference(builder::recordMethodAccess);
return builder.build();
}
-
- /**
- * Applies {@link NonReboundMemberReferencesRegistry} to all code objects to construct a mapping
- * from non-rebound field references to their definition.
- */
- private static void initializeMemberAccessInfoCollectionsForMemberRebinding(
- AppView<? extends AppInfoWithClassHierarchy> appView,
- FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
- MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder,
- ExecutorService executorService)
- throws ExecutionException {
- Set<DexField> seenFieldReferences = SetUtils.newConcurrentHashSet();
- Set<DexMethod> seenMethodReferences = SetUtils.newConcurrentHashSet();
- ThreadUtils.processItems(
- appView.appInfo()::forEachMethod,
- method ->
- new NonReboundMemberReferencesRegistry(
- appView,
- method,
- fieldAccessInfoCollection,
- methodAccessInfoCollectionBuilder,
- seenFieldReferences,
- seenMethodReferences)
- .accept(method),
- appView.options().getThreadingModule(),
- executorService);
- }
-
- private static class NonReboundMemberReferencesRegistry
- extends DefaultUseRegistry<ProgramMethod> {
-
- private final AppInfoWithClassHierarchy appInfo;
- private final FieldAccessInfoCollectionImpl fieldAccessInfoCollection;
- private final MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder;
- private final Set<DexField> seenFieldReferences;
- private final Set<DexMethod> seenMethodReferences;
-
- public NonReboundMemberReferencesRegistry(
- AppView<? extends AppInfoWithClassHierarchy> appView,
- ProgramMethod context,
- FieldAccessInfoCollectionImpl fieldAccessInfoCollection,
- MethodAccessInfoCollection.ConcurrentBuilder methodAccessInfoCollectionBuilder,
- Set<DexField> seenFieldReferences,
- Set<DexMethod> seenMethodReferences) {
- super(appView, context);
- this.appInfo = appView.appInfo();
- this.fieldAccessInfoCollection = fieldAccessInfoCollection;
- this.methodAccessInfoCollectionBuilder = methodAccessInfoCollectionBuilder;
- this.seenFieldReferences = seenFieldReferences;
- this.seenMethodReferences = seenMethodReferences;
- }
-
- @Override
- public void registerInstanceFieldRead(DexField field) {
- registerFieldAccess(field);
- }
-
- @Override
- public void registerInstanceFieldWrite(DexField field) {
- registerFieldAccess(field);
- }
-
- @Override
- public void registerStaticFieldRead(DexField field) {
- registerFieldAccess(field);
- }
-
- @Override
- public void registerStaticFieldWrite(DexField field) {
- registerFieldAccess(field);
- }
-
- @SuppressWarnings("ReferenceEquality")
- private void registerFieldAccess(DexField field) {
- if (!seenFieldReferences.add(field)) {
- return;
- }
- appInfo
- .resolveField(field)
- .forEachSuccessfulFieldResolutionResult(
- resolutionResult -> {
- DexField reboundReference = resolutionResult.getResolvedField().getReference();
- if (field == reboundReference) {
- // For the purpose of member rebinding, we don't care about already rebound
- // references.
- return;
- }
- FieldAccessInfoImpl fieldAccessInfo =
- fieldAccessInfoCollection.computeIfAbsent(
- reboundReference, FieldAccessInfoImpl::new);
- synchronized (fieldAccessInfo) {
- // Record the fact that there is a non-rebound access to the given field. We don't
- // distinguish between non-rebound reads and writes, so we just record it as a
- // read.
- if (fieldAccessInfo.getReadsWithContexts().isBottom()) {
- fieldAccessInfo.setReadsWithContexts(new ConcreteAccessContexts());
- } else {
- assert fieldAccessInfo.getReadsWithContexts().isConcrete();
- }
- // For the purpose of member rebinding, we don't care about the access contexts,
- // so we
- // simply use the empty set.
- ConcreteAccessContexts accessContexts =
- fieldAccessInfo.getReadsWithContexts().asConcrete();
- accessContexts.getAccessesWithContexts().put(field, ProgramMethodSet.empty());
- }
- });
- }
-
- @Override
- public void registerInvokeDirect(DexMethod method) {
- registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getDirectInvokes());
- }
-
- @Override
- public void registerInvokeInterface(DexMethod method) {
- registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getInterfaceInvokes());
- }
-
- @Override
- public void registerInvokeStatic(DexMethod method) {
- registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getStaticInvokes());
- }
-
- @Override
- public void registerInvokeSuper(DexMethod method) {
- registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getSuperInvokes());
- }
-
- @Override
- public void registerInvokeVirtual(DexMethod method) {
- registerInvokeMethod(method, methodAccessInfoCollectionBuilder.getVirtualInvokes());
- }
-
- @SuppressWarnings("ReferenceEquality")
- private void registerInvokeMethod(DexMethod method, Map<DexMethod, ProgramMethodSet> invokes) {
- if (!seenMethodReferences.add(method)) {
- return;
- }
- if (method.getHolderType().isArrayType()) {
- return;
- }
- DexClass holder = appInfo.definitionFor(method.getHolderType(), getContext());
- if (holder == null) {
- return;
- }
- SingleResolutionResult<?> resolutionResult =
- appInfo.resolveMethodOnLegacy(holder, method).asSingleResolution();
- if (resolutionResult == null) {
- return;
- }
- DexMethod reboundReference = resolutionResult.getResolvedMethod().getReference();
- if (method == reboundReference) {
- // For the purpose of member rebinding, we don't care about already rebound references.
- return;
- }
- // For the purpose of member rebinding, we don't care about the access contexts, so we
- // simply use the empty set.
- invokes.put(method, ProgramMethodSet.empty());
- }
- }
}
diff --git a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
index b1e1922..9c045cf 100644
--- a/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
+++ b/src/main/java/com/android/tools/r8/optimize/redundantbridgeremoval/RedundantBridgeRemover.java
@@ -3,7 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.optimize.redundantbridgeremoval;
+import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
+
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DefaultUseRegistry;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexEncodedMethod;
@@ -27,6 +30,7 @@
import com.android.tools.r8.shaking.KeepMethodInfo;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.WorkList;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.Collection;
import java.util.List;
@@ -36,8 +40,14 @@
public class RedundantBridgeRemover {
+ public enum RedundantBridgeRemoverMode {
+ INITIAL,
+ FINAL
+ }
+
private final AppView<AppInfoWithLiveness> appView;
private final ImmediateProgramSubtypingInfo immediateSubtypingInfo;
+ private final RedundantBridgeRemoverMode mode;
private final RedundantBridgeRemovalOptions redundantBridgeRemovalOptions;
private final RedundantBridgeRemovalLens.Builder lensBuilder =
@@ -45,9 +55,11 @@
private boolean mustRetargetInvokesToTargetMethod = false;
- public RedundantBridgeRemover(AppView<AppInfoWithLiveness> appView) {
+ public RedundantBridgeRemover(
+ AppView<AppInfoWithLiveness> appView, RedundantBridgeRemoverMode mode) {
this.appView = appView;
this.immediateSubtypingInfo = ImmediateProgramSubtypingInfo.create(appView);
+ this.mode = mode;
this.redundantBridgeRemovalOptions = appView.options().getRedundantBridgeRemovalOptions();
}
@@ -264,6 +276,7 @@
extends DepthFirstTopDownClassHierarchyTraversal {
private final ProgramMethodSet removedBridges = ProgramMethodSet.create();
+ private ProgramMethodSet superTargets = null;
RedundantBridgeRemoverClassHierarchyTraversal() {
super(
@@ -316,11 +329,7 @@
return false;
}
// Check if the current method is an interface method targeted by invoke-super.
- if (method.getHolder().isInterface()
- && appView
- .appInfo()
- .getMethodAccessInfoCollection()
- .hasSuperInvoke(method.getReference())) {
+ if (method.getHolder().isInterface() && hasSuperInvoke(method)) {
return false;
}
// Check if all possible contexts that have access to the holder of the redundant bridge
@@ -353,5 +362,48 @@
public void prune(DexProgramClass clazz) {
// Empty.
}
+
+ private boolean hasSuperInvoke(ProgramMethod method) {
+ if (mode == RedundantBridgeRemoverMode.INITIAL) {
+ return appView
+ .appInfo()
+ .getMethodAccessInfoCollection()
+ .hasSuperInvoke(method.getReference());
+ }
+ return getOrCreateSuperTargets(method.getHolder()).contains(method);
+ }
+
+ private ProgramMethodSet getOrCreateSuperTargets(DexProgramClass root) {
+ if (superTargets != null) {
+ return superTargets;
+ }
+ AppView<AppInfoWithLiveness> appViewWithLiveness = appView;
+ superTargets = ProgramMethodSet.create();
+ WorkList<DexProgramClass> worklist =
+ WorkList.newIdentityWorkList(immediateSubtypingInfo.getSubclasses(root));
+ while (worklist.hasNext()) {
+ DexProgramClass clazz = worklist.next();
+ clazz.forEachProgramMethodMatching(
+ DexEncodedMethod::hasCode,
+ method ->
+ method.registerCodeReferences(
+ new DefaultUseRegistry<>(appView, method) {
+
+ @Override
+ public void registerInvokeSuper(DexMethod method) {
+ ProgramMethod superTarget =
+ asProgramMethodOrNull(
+ appViewWithLiveness
+ .appInfo()
+ .lookupSuperTarget(method, getContext(), appViewWithLiveness));
+ if (superTarget != null) {
+ superTargets.add(superTarget);
+ }
+ }
+ }));
+ worklist.addIfNotSeen(immediateSubtypingInfo.getSubclasses(clazz));
+ }
+ return superTargets;
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java b/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
index 3a0e9a1..126960b 100644
--- a/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
+++ b/src/main/java/com/android/tools/r8/optimize/singlecaller/SingleCallerInliner.java
@@ -176,7 +176,6 @@
});
PrunedItems prunedItems = prunedItemsBuilder.build();
appView.pruneItems(prunedItems, executorService, Timing.empty());
- appView.appInfo().getMethodAccessInfoCollection().withoutPrunedItems(prunedItems);
}
private static class SingleCallerInlinerImpl extends Inliner {
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
index a41b281..6680806 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -467,7 +467,6 @@
@Override
public void notifyMinifierFinished() {
liveMethods = ThrowingSet.get();
- getMethodAccessInfoCollection().destroy();
}
public void notifyTreePrunerFinished(Enqueuer.Mode mode) {
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 eee85a1..3640796 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -4481,7 +4481,7 @@
toDescriptorSet(liveMethods.getItems()),
// Filter out library fields and pinned fields, because these are read by default.
fieldAccessInfoCollection,
- methodAccessInfoCollection.build(),
+ methodAccessInfoCollection.build(mode),
objectAllocationInfoCollection.build(appInfo),
callSites,
keepInfo,
diff --git a/src/test/examples/naming001/keep-rules-001.txt b/src/test/examples/naming001/keep-rules-001.txt
index 72be5a2..885f5cf 100644
--- a/src/test/examples/naming001/keep-rules-001.txt
+++ b/src/test/examples/naming001/keep-rules-001.txt
@@ -3,5 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep class naming001.A
diff --git a/src/test/examples/naming001/keep-rules-002.txt b/src/test/examples/naming001/keep-rules-002.txt
index 1554e31..62e3976 100644
--- a/src/test/examples/naming001/keep-rules-002.txt
+++ b/src/test/examples/naming001/keep-rules-002.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep !final class naming001.A {
private <methods>;
diff --git a/src/test/examples/naming001/keep-rules-003.txt b/src/test/examples/naming001/keep-rules-003.txt
index cdcab79..4846f64 100644
--- a/src/test/examples/naming001/keep-rules-003.txt
+++ b/src/test/examples/naming001/keep-rules-003.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep !final class naming001.A {
!private <methods>;
diff --git a/src/test/examples/naming001/keep-rules-005.txt b/src/test/examples/naming001/keep-rules-005.txt
index ef4b5c8..b15cc5c 100644
--- a/src/test/examples/naming001/keep-rules-005.txt
+++ b/src/test/examples/naming001/keep-rules-005.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep class naming001.D {
public static void main(...);
diff --git a/src/test/examples/naming001/keep-rules-006.txt b/src/test/examples/naming001/keep-rules-006.txt
index 7a8e99e..2b69f6c 100644
--- a/src/test/examples/naming001/keep-rules-006.txt
+++ b/src/test/examples/naming001/keep-rules-006.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep class naming001.G {
public static void main(...);
diff --git a/src/test/examples/naming001/keep-rules-014.txt b/src/test/examples/naming001/keep-rules-014.txt
index 6423782..6c10eb8 100644
--- a/src/test/examples/naming001/keep-rules-014.txt
+++ b/src/test/examples/naming001/keep-rules-014.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep class naming001.Reflect {
*** keep6();
diff --git a/src/test/examples/naming001/keep-rules-017.txt b/src/test/examples/naming001/keep-rules-017.txt
index b146df8..20f585f 100644
--- a/src/test/examples/naming001/keep-rules-017.txt
+++ b/src/test/examples/naming001/keep-rules-017.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep class naming001.K {
void keep();
diff --git a/src/test/examples/naming001/keep-rules-105.txt b/src/test/examples/naming001/keep-rules-105.txt
index 011596b..02a54e6 100644
--- a/src/test/examples/naming001/keep-rules-105.txt
+++ b/src/test/examples/naming001/keep-rules-105.txt
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
-allowaccessmodification
+-dontshrink
-keep class naming001.D {
public static void main(...);
diff --git a/src/test/examples/naming001/keep-rules-106.txt b/src/test/examples/naming001/keep-rules-106.txt
index ca320eb..744c783 100644
--- a/src/test/examples/naming001/keep-rules-106.txt
+++ b/src/test/examples/naming001/keep-rules-106.txt
@@ -2,4 +2,5 @@
# 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.
--applymapping mapping-106.txt
\ No newline at end of file
+-applymapping mapping-106.txt
+-dontshrink
\ No newline at end of file
diff --git a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
index c71f930..daff675 100644
--- a/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
+++ b/src/test/java/com/android/tools/r8/naming/NamingTestBase.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.ir.conversion.LirConverter;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.Timing;
@@ -53,6 +54,7 @@
dexItemFactory = appView.dexItemFactory();
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
+ LirConverter.enterLirSupportedPhase(appView, executor);
new Minifier(appView).run(executor, Timing.empty());
} finally {
executor.shutdown();