Reland "Use definition values where possible when accessing keep info."
Bug: b/265251427
Change-Id: I9cd365f4e53e0b21677d4dbf4a34bdebbe1ff37f
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 82e4b48..38bf4ee 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -392,8 +392,7 @@
return false;
}
// If tree shaking, only keep annotations on kept methods.
- if (appView.appInfo().hasLiveness()
- && !appView.appInfo().withLiveness().isPinned(method.getReference())) {
+ if (appView.appInfo().hasLiveness() && !appView.appInfo().withLiveness().isPinned(method)) {
return false;
}
return true;
@@ -774,7 +773,7 @@
// The enqueuer might build IR to trace reflective behaviour. At that point liveness is not
// known, so be conservative with collection parameter name information.
if (appView.appInfo().hasLiveness()
- && !appView.appInfo().withLiveness().isPinned(encodedMethod.getReference())) {
+ && !appView.appInfo().withLiveness().isPinned(encodedMethod)) {
return DexEncodedMethod.NO_PARAMETER_INFO;
}
diff --git a/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java b/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
index 4062f96..7d6b3a2 100644
--- a/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
+++ b/src/main/java/com/android/tools/r8/graph/EnclosingMethodAttribute.java
@@ -101,10 +101,10 @@
public boolean isEnclosingPinned(AppView<AppInfoWithLiveness> appView) {
if (enclosingMethod != null) {
- return appView.appInfo().isPinned(enclosingMethod);
+ return appView.appInfo().isPinnedWithDefinitionLookup(enclosingMethod);
}
if (enclosingClass != null) {
- return appView.appInfo().isPinned(enclosingClass);
+ return appView.appInfo().isPinnedWithDefinitionLookup(enclosingClass);
}
return false;
}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
index 0d19daa..d849002 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/InitializedClassesInInstanceMethodsAnalysis.java
@@ -35,7 +35,7 @@
// If `subject` is kept, then it is instantiated by reflection, which means that the analysis
// has not seen all allocation sites. In that case, we conservatively return false.
AppInfoWithClassHierarchy appInfo = appView.appInfo();
- if (appInfo.hasLiveness() && appInfo.withLiveness().isPinned(subject.type)) {
+ if (appInfo.hasLiveness() && appInfo.withLiveness().isPinned(subject)) {
return false;
}
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
index 9af0407..33ab115 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/ValueMayDependOnEnvironmentAnalysis.java
@@ -275,7 +275,8 @@
return root.isDefinedByInstructionSatisfying(Instruction::isConstClass)
&& !appView
.getKeepInfo()
- .isPinned(root.getDefinition().asConstClass().getType(), appView, options);
+ .isPinnedWithDefinitionLookup(
+ root.getDefinition().asConstClass().getType(), options, appView);
}
private boolean addLogicalBinopValueToValueGraph(
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
index ef1b959..66ef64e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ClassInitializerDefaultsOptimization.java
@@ -332,7 +332,7 @@
}
if (appView.enableWholeProgramOptimizations()
- && appView.withLiveness().appInfo().isMinificationAllowed(holder)) {
+ && appView.withLiveness().appInfo().isMinificationAllowed(clazz)) {
if (invokedMethod == dexItemFactory.classMethods.getName) {
return new DexItemBasedValueString(holder, ClassNameComputationInfo.getInstance(NAME));
}
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 753b6ce..12030bf 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
@@ -113,7 +113,7 @@
ConstClass constClass = argument.getConstInstruction().asConstClass();
// Check that the service is not kept.
- if (appView.appInfo().isPinned(constClass.getValue())) {
+ if (appView.appInfo().isPinnedWithDefinitionLookup(constClass.getValue())) {
continue;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
index c02b953..ed89e93 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MethodOptimizationInfoCollector.java
@@ -235,7 +235,7 @@
IRCode code,
OptimizationFeedback feedback,
InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos) {
- assert !appView.appInfo().isPinned(method.getReference());
+ assert !appView.appInfo().isPinned(method);
if (!method.isInstanceInitializer()) {
return;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index 1d0e301..09c8163 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -350,7 +350,7 @@
}
boolean mayBeRenamed =
appView.enableWholeProgramOptimizations()
- && appView.withLiveness().appInfo().isMinificationAllowed(holder.type);
+ && appView.withLiveness().appInfo().isMinificationAllowed(holder);
// b/120138731: Filter out escaping uses. In such case, the result of this optimization will
// be stored somewhere, which can lead to a regression if the corresponding class is in a deep
// package hierarchy. For local cases, it is likely a one-time computation, but make sure the
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java b/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java
index d2ec4d6..4d3075c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/typechecks/CheckCastAndInstanceOfMethodSpecialization.java
@@ -119,8 +119,8 @@
// Verify that the methods are not pinned. They shouldn't be, since we've computed an abstract
// return value for both.
- assert !appView.appInfo().isPinned(method.getReference());
- assert !appView.appInfo().isPinned(parentMethod.getReference());
+ assert !appView.appInfo().isPinned(method);
+ assert !appView.appInfo().isPinned(parentMethod);
if (appView
.appInfo()
diff --git a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
index 415995e..c06aea8 100644
--- a/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
+++ b/src/main/java/com/android/tools/r8/kotlin/KotlinMetadataRewriter.java
@@ -110,7 +110,7 @@
if (oldMeta == null
|| kotlinInfo == getNoKotlinInfo()
|| (appView.appInfo().hasLiveness()
- && !appView.withLiveness().appInfo().isPinned(clazz.type))) {
+ && !appView.withLiveness().appInfo().isPinned(clazz))) {
// Remove @Metadata in DexAnnotation when there is no kotlin info and the type is not
// missing.
if (oldMeta != null) {
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 00c0d9f..52fee79 100644
--- a/src/main/java/com/android/tools/r8/naming/Minifier.java
+++ b/src/main/java/com/android/tools/r8/naming/Minifier.java
@@ -312,7 +312,7 @@
if (!allowMemberRenaming(holder)
|| holder.accessFlags.isAnnotation()
|| method.accessFlags.isConstructor()
- || !appView.appInfo().isMinificationAllowed(method.getReference())) {
+ || !appView.appInfo().isMinificationAllowed(method)) {
return method.getReference().name;
}
if (desugaredLibraryRenaming
@@ -327,8 +327,7 @@
@Override
public DexString getReservedName(DexEncodedField field, DexClass holder) {
- if (holder.isLibraryClass()
- || !appView.appInfo().isMinificationAllowed(field.getReference())) {
+ if (holder.isLibraryClass() || !appView.appInfo().isMinificationAllowed(field)) {
return field.getReference().name;
}
return null;
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 6637177..3c128fb 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapMinifier.java
@@ -408,7 +408,7 @@
return mappings.get(type);
}
if (clazz.isProgramClass()) {
- if (appView.appInfo().isMinificationAllowed(type)) {
+ if (appView.appInfo().isMinificationAllowed(clazz.asProgramClass())) {
return mappings.get(type);
}
// TODO(b/136694827): Report a warning here if in the mapping since the user may find this
@@ -454,7 +454,7 @@
nextName = reservedName;
} else {
assert !mappedNames.containsKey(reference);
- assert appView.appInfo().isMinificationAllowed(reference);
+ assert appView.appInfo().isMinificationAllowed(method);
nextName = super.next(method, internalState, isAvailable);
}
assert nextName == reference.name || !method.isInitializer();
@@ -477,7 +477,7 @@
return reservedName;
}
assert !mappedNames.containsKey(reference);
- assert appView.appInfo().isMinificationAllowed(reference);
+ assert appView.appInfo().isMinificationAllowed(field);
return super.next(field, internalState, isAvailable);
}
diff --git a/src/main/java/com/android/tools/r8/optimize/AccessModifier.java b/src/main/java/com/android/tools/r8/optimize/AccessModifier.java
index c1ee380..b2d577c 100644
--- a/src/main/java/com/android/tools/r8/optimize/AccessModifier.java
+++ b/src/main/java/com/android/tools/r8/optimize/AccessModifier.java
@@ -223,7 +223,7 @@
boolean wasSeen = methodPoolCollection.markIfNotSeen(method.getHolder(), method.getReference());
if (wasSeen) {
// We can't do anything further because even renaming is not allowed due to the keep rule.
- if (!appView.appInfo().isMinificationAllowed(method.getReference())) {
+ if (!appView.appInfo().isMinificationAllowed(method)) {
return false;
}
// TODO(b/111118390): Renaming will enable more private instance methods to be publicized.
diff --git a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
index e6df4a0..b6236d8 100644
--- a/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
+++ b/src/main/java/com/android/tools/r8/optimize/bridgehoisting/BridgeHoisting.java
@@ -154,7 +154,7 @@
// If the method is defined on the parent class, we cannot hoist the bridge.
// TODO(b/153147967): If the declared method is abstract, we could replace it by the bridge.
// Add a test.
- if (clazz.lookupMethod(method) != null) {
+ if (clazz.lookupProgramMethod(method) != null) {
return;
}
@@ -278,8 +278,8 @@
representative.getReference());
// Remove all of the bridges in the eligible subclasses.
+ assert !appView.appInfo().isPinnedWithDefinitionLookup(method);
for (DexProgramClass subclass : eligibleSubclasses) {
- assert !appView.appInfo().isPinned(method);
DexEncodedMethod removed = subclass.removeMethod(method);
assert removed != null;
}
diff --git a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
index e0c7f83..edfa788 100644
--- a/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
+++ b/src/main/java/com/android/tools/r8/shaking/AbstractMethodRemover.java
@@ -6,13 +6,14 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.SubtypingInfo;
import com.android.tools.r8.logging.Log;
import com.android.tools.r8.shaking.ScopedDexMethodSet.AddMethodIfMoreVisibleResult;
-import com.android.tools.r8.utils.IterableUtils;
-import com.android.tools.r8.utils.ListUtils;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
/**
* Removes abstract methods if they only shadow methods of the same signature in a superclass.
@@ -43,39 +44,38 @@
DexClass holder = appView.definitionFor(type);
scope = scope.newNestedScope();
if (holder != null && holder.isProgramClass()) {
- DexEncodedMethod[] newVirtualMethods =
- processMethods(IterableUtils.ensureUnmodifiableList(holder.virtualMethods()));
- if (newVirtualMethods != null) {
- holder.setVirtualMethods(newVirtualMethods);
- }
+ processMethods(holder.asProgramClass());
}
// TODO(b/154881041): Does this need the full subtype hierarchy of referenced types!?
subtypingInfo.forAllImmediateExtendsSubtypes(type, this::processClass);
scope = scope.getParent();
}
- private DexEncodedMethod[] processMethods(List<DexEncodedMethod> virtualMethods) {
- if (virtualMethods == null) {
- return null;
+ private void processMethods(DexProgramClass clazz) {
+ Set<DexEncodedMethod> toRemove = null;
+ for (ProgramMethod method : clazz.virtualProgramMethods()) {
+ if (!isNonAbstractPinnedOrWideningVisibility(method)) {
+ if (toRemove == null) {
+ toRemove = new HashSet<>();
+ }
+ toRemove.add(method.getDefinition());
+ }
}
- // Removal of abstract methods is rare, ListUtils.filterOrElse does no copying if nothing is
- // filtered out.
- List<DexEncodedMethod> filteredMethods =
- ListUtils.filterOrElse(virtualMethods, this::isNonAbstractPinnedOrWideningVisibility);
- return filteredMethods == virtualMethods
- ? null
- : filteredMethods.toArray(DexEncodedMethod.EMPTY_ARRAY);
+ if (toRemove != null) {
+ clazz.getMethodCollection().removeMethods(toRemove);
+ }
}
- private boolean isNonAbstractPinnedOrWideningVisibility(DexEncodedMethod method) {
- if (!method.accessFlags.isAbstract()) {
+ private boolean isNonAbstractPinnedOrWideningVisibility(ProgramMethod method) {
+ if (!method.getAccessFlags().isAbstract()) {
return true;
}
// Check if the method widens visibility. Adding to the scope mutates it.
- if (scope.addMethodIfMoreVisible(method) != AddMethodIfMoreVisibleResult.NOT_ADDED) {
+ if (scope.addMethodIfMoreVisible(method.getDefinition())
+ != AddMethodIfMoreVisibleResult.NOT_ADDED) {
return true;
}
- if (appView.appInfo().isPinned(method.getReference())) {
+ if (appView.appInfo().isPinned(method)) {
return true;
}
// We will filter the method out since it is not pinned.
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 387186f..cb80e54 100644
--- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
+++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -918,7 +918,7 @@
assert info.isRead() || info.isWritten();
return true;
}
- assert getKeepInfo().getFieldInfo(reference, this).isShrinkingAllowed(options());
+ assert getKeepInfo().getFieldInfo(field, this).isShrinkingAllowed(options());
return false;
}
@@ -929,7 +929,7 @@
if (info != null && info.isRead()) {
return true;
}
- if (isPinned(field)) {
+ if (isPinned(encodedField)) {
return true;
}
// For library classes we don't know whether a field is read.
@@ -938,8 +938,7 @@
public boolean isFieldWritten(DexEncodedField encodedField) {
assert checkIfObsolete();
- return isFieldWrittenByFieldPutInstruction(encodedField)
- || isPinned(encodedField.getReference());
+ return isFieldWrittenByFieldPutInstruction(encodedField) || isPinned(encodedField);
}
public boolean isFieldWrittenByFieldPutInstruction(DexEncodedField encodedField) {
@@ -957,7 +956,7 @@
public boolean isFieldOnlyWrittenInMethod(DexEncodedField field, DexEncodedMethod method) {
assert checkIfObsolete();
assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
- if (isPinned(field.getReference())) {
+ if (isPinned(field)) {
return false;
}
return isFieldOnlyWrittenInMethodIgnoringPinning(field, method);
@@ -980,7 +979,7 @@
public boolean isInstanceFieldWrittenOnlyInInstanceInitializers(DexEncodedField field) {
assert checkIfObsolete();
assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written";
- if (isPinned(field.getReference())) {
+ if (isPinned(field)) {
return false;
}
FieldAccessInfo fieldAccessInfo = getFieldAccessInfoCollection().get(field.getReference());
@@ -1027,7 +1026,7 @@
if (neverPropagateValue.contains(field)) {
return false;
}
- if (isPinned(field) && !field.getType().isAlwaysNull(appView)) {
+ if (isPinnedWithDefinitionLookup(field) && !field.getType().isAlwaysNull(appView)) {
return false;
}
return true;
@@ -1039,7 +1038,9 @@
return false;
}
if (!method.getReturnType().isAlwaysNull(appView)
- && !getKeepInfo().getMethodInfo(method, this).isOptimizationAllowed(options())) {
+ && !getKeepInfo()
+ .getMethodInfoWithDefinitionLookup(method, this)
+ .isOptimizationAllowed(options())) {
return false;
}
return true;
@@ -1071,18 +1072,29 @@
return !isPinned(clazz) && !neverClassInline.contains(clazz.getType());
}
- public boolean isMinificationAllowed(DexReference reference) {
+ public boolean isMinificationAllowed(DexProgramClass clazz) {
return options().isMinificationEnabled()
- && keepInfo.getInfo(reference, this).isMinificationAllowed(options());
+ && keepInfo.getInfo(clazz).isMinificationAllowed(options());
+ }
+
+ public boolean isMinificationAllowed(ProgramDefinition definition) {
+ return options().isMinificationEnabled()
+ && keepInfo.getInfo(definition).isMinificationAllowed(options());
+ }
+
+ public boolean isMinificationAllowed(DexDefinition definition) {
+ return options().isMinificationEnabled()
+ && keepInfo.getInfo(definition, this).isMinificationAllowed(options());
+ }
+
+ public boolean isMinificationAllowed(DexType reference) {
+ return options().isMinificationEnabled()
+ && keepInfo.getClassInfo(reference, this).isMinificationAllowed(options());
}
public boolean isAccessModificationAllowed(ProgramDefinition definition) {
- return isAccessModificationAllowed(definition.getReference());
- }
-
- public boolean isAccessModificationAllowed(DexReference reference) {
assert options().getProguardConfiguration().isAccessModificationAllowed();
- return keepInfo.getInfo(reference, this).isAccessModificationAllowed(options());
+ return keepInfo.getInfo(definition).isAccessModificationAllowed(options());
}
public boolean isRepackagingAllowed(DexProgramClass clazz, AppView<?> appView) {
@@ -1099,27 +1111,30 @@
return applyMappingSeedMapper == null || !applyMappingSeedMapper.hasMapping(clazz.type);
}
- public boolean isPinned(DexReference reference) {
+ public boolean isPinnedWithDefinitionLookup(DexReference reference) {
assert checkIfObsolete();
- return keepInfo.isPinned(reference, this, options());
+ return keepInfo.isPinnedWithDefinitionLookup(reference, options(), this);
}
public boolean isPinned(DexDefinition definition) {
- assert definition != null;
- return isPinned(definition.getReference());
+ return keepInfo.isPinned(definition, options(), this);
}
- public boolean isPinned(DexClassAndMember<?, ?> member) {
- assert member != null;
- return isPinned(member.getReference());
+ public boolean isPinned(DexProgramClass clazz) {
+ return keepInfo.isPinned(clazz, options());
+ }
+
+ public boolean isPinned(ProgramDefinition definition) {
+ assert definition != null;
+ return keepInfo.isPinned(definition, options());
}
public boolean hasPinnedInstanceInitializer(DexType type) {
assert type.isClassType();
DexProgramClass clazz = asProgramClassOrNull(definitionFor(type));
if (clazz != null) {
- for (DexEncodedMethod method : clazz.directMethods()) {
- if (method.isInstanceInitializer() && isPinned(method.getReference())) {
+ for (ProgramMethod method : clazz.directProgramMethods()) {
+ if (method.getDefinition().isInstanceInitializer() && isPinned(method)) {
return true;
}
}
@@ -1495,11 +1510,11 @@
}
private boolean isInstantiatedOrPinned(DexProgramClass clazz) {
- return isInstantiatedDirectly(clazz) || isPinned(clazz.type) || isInstantiatedInterface(clazz);
+ return isInstantiatedDirectly(clazz) || isPinned(clazz) || isInstantiatedInterface(clazz);
}
public boolean isPinnedNotProgramOrLibraryOverride(DexDefinition definition) {
- if (isPinned(definition.getReference())) {
+ if (isPinned(definition)) {
return true;
}
if (definition.isDexEncodedMethod()) {
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 59b7ae3..610cfa9 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -2918,8 +2918,7 @@
instantiation.apply(subTypeConsumer, lambdaConsumer);
},
definition ->
- keepInfo.isPinned(
- definition.getReference(), appInfo, options));
+ keepInfo.isPinned(definition, options, appInfo));
lookupResult.forEach(
target ->
markVirtualDispatchTargetAsLive(
@@ -3422,7 +3421,7 @@
(type, subTypeConsumer, lambdaConsumer) ->
objectAllocationInfoCollection.forEachInstantiatedSubType(
type, subTypeConsumer, lambdaConsumer, appInfo),
- definition -> keepInfo.isPinned(definition.getReference(), appInfo, options))
+ definition -> keepInfo.isPinned(definition, options, appInfo))
.forEach(
target ->
markVirtualDispatchTargetAsLive(
@@ -4328,7 +4327,7 @@
(methodReference, companionReference) -> {
ProgramMethod companion = appView.definitionFor(companionReference).asProgramMethod();
KeepMethodInfo.Joiner minimumKeepInfoForCompanion =
- keepInfo.getMethodInfo(methodReference, appInfo).joiner();
+ keepInfo.getMethodInfoWithDefinitionLookup(methodReference, appInfo).joiner();
KeepMethodInfo.Joiner extraMinimumKeepInfoForCompanion =
dependentMinimumKeepInfo
.getUnconditionalMinimumKeepInfoOrDefault(MinimumKeepInfoCollection.empty())
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
index c78e39a..f13a407 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepInfoCollection.java
@@ -9,6 +9,8 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexDefinition;
import com.android.tools.r8.graph.DexDefinitionSupplier;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMember;
@@ -92,9 +94,14 @@
return getMethodInfo(member.asDexEncodedMethod(), holder);
}
+ public final KeepClassInfo getClassInfo(DexClass clazz) {
+ return clazz != null && clazz.isProgramClass()
+ ? getClassInfo(clazz.asProgramClass())
+ : keepInfoForNonProgramClass();
+ }
+
public final KeepClassInfo getClassInfo(DexType type, DexDefinitionSupplier definitions) {
- DexProgramClass clazz = asProgramClassOrNull(definitions.definitionFor(type));
- return clazz == null ? keepInfoForNonProgramClass() : getClassInfo(clazz);
+ return getClassInfo(definitions.contextIndependentDefinitionFor(type));
}
public final KeepMemberInfo<?, ?> getMemberInfo(ProgramMember<?, ?> member) {
@@ -105,8 +112,21 @@
return getMethodInfo(method.getDefinition(), method.getHolder());
}
- public final KeepMethodInfo getMethodInfo(DexMethod method, DexDefinitionSupplier definitions) {
- DexProgramClass holder = asProgramClassOrNull(definitions.definitionFor(method.holder));
+ public final KeepMethodInfo getMethodInfo(
+ DexEncodedMethod method, DexDefinitionSupplier definitions) {
+ DexProgramClass holder =
+ asProgramClassOrNull(definitions.contextIndependentDefinitionFor(method.getHolderType()));
+ if (holder == null) {
+ return keepInfoForNonProgramMethod();
+ }
+ assert method == holder.lookupMethod(method.getReference());
+ return getMethodInfo(method, holder);
+ }
+
+ public final KeepMethodInfo getMethodInfoWithDefinitionLookup(
+ DexMethod method, DexDefinitionSupplier definitions) {
+ DexProgramClass holder =
+ asProgramClassOrNull(definitions.contextIndependentDefinitionFor(method.holder));
if (holder == null) {
return keepInfoForNonProgramMethod();
}
@@ -118,7 +138,19 @@
return getFieldInfo(field.getDefinition(), field.getHolder());
}
- public final KeepFieldInfo getFieldInfo(DexField field, DexDefinitionSupplier definitions) {
+ public final KeepFieldInfo getFieldInfo(
+ DexEncodedField field, DexDefinitionSupplier definitions) {
+ DexProgramClass holder =
+ asProgramClassOrNull(definitions.contextIndependentDefinitionFor(field.getHolderType()));
+ if (holder == null) {
+ return keepInfoForNonProgramField();
+ }
+ assert holder.lookupField(field.getReference()) == field;
+ return getFieldInfo(field, holder);
+ }
+
+ private KeepFieldInfo getFieldInfoWithDefinitionLookup(
+ DexField field, DexDefinitionSupplier definitions) {
DexProgramClass holder = asProgramClassOrNull(definitions.definitionFor(field.holder));
if (holder == null) {
return keepInfoForNonProgramField();
@@ -127,15 +159,29 @@
return definition == null ? KeepFieldInfo.bottom() : getFieldInfo(definition, holder);
}
- public final KeepInfo<?, ?> getInfo(DexReference reference, DexDefinitionSupplier definitions) {
+ private KeepInfo<?, ?> getInfoWithDefinitionLookup(
+ DexReference reference, DexDefinitionSupplier definitions) {
if (reference.isDexType()) {
return getClassInfo(reference.asDexType(), definitions);
}
if (reference.isDexMethod()) {
- return getMethodInfo(reference.asDexMethod(), definitions);
+ return getMethodInfoWithDefinitionLookup(reference.asDexMethod(), definitions);
}
if (reference.isDexField()) {
- return getFieldInfo(reference.asDexField(), definitions);
+ return getFieldInfoWithDefinitionLookup(reference.asDexField(), definitions);
+ }
+ throw new Unreachable();
+ }
+
+ public final KeepInfo<?, ?> getInfo(DexDefinition definition, DexDefinitionSupplier definitions) {
+ if (definition.isDexClass()) {
+ return getClassInfo(definition.asDexClass());
+ }
+ if (definition.isDexEncodedMethod()) {
+ return getMethodInfo(definition.asDexEncodedMethod(), definitions);
+ }
+ if (definition.isDexEncodedField()) {
+ return getFieldInfo(definition.asDexEncodedField(), definitions);
}
throw new Unreachable();
}
@@ -158,37 +204,28 @@
}
public final boolean isPinned(
+ ProgramDefinition definition, GlobalKeepInfoConfiguration configuration) {
+ return getInfo(definition).isPinned(configuration);
+ }
+
+ public final boolean isPinned(
+ DexDefinition definition,
+ GlobalKeepInfoConfiguration configuration,
+ DexDefinitionSupplier definitions) {
+ return getInfo(definition, definitions).isPinned(configuration);
+ }
+
+ public final boolean isPinnedWithDefinitionLookup(
DexReference reference,
- DexDefinitionSupplier definitions,
- GlobalKeepInfoConfiguration configuration) {
- return getInfo(reference, definitions).isPinned(configuration);
- }
-
- public final boolean isPinned(
- DexType type, DexDefinitionSupplier definitions, GlobalKeepInfoConfiguration configuration) {
- return getClassInfo(type, definitions).isPinned(configuration);
- }
-
- public final boolean isPinned(
- DexMethod method,
- DexDefinitionSupplier definitions,
- GlobalKeepInfoConfiguration configuration) {
- return getMethodInfo(method, definitions).isPinned(configuration);
- }
-
- public final boolean isPinned(
- DexField field,
- DexDefinitionSupplier definitions,
- GlobalKeepInfoConfiguration configuration) {
- return getFieldInfo(field, definitions).isPinned(configuration);
+ GlobalKeepInfoConfiguration configuration,
+ DexDefinitionSupplier definitions) {
+ return getInfoWithDefinitionLookup(reference, definitions).isPinned(configuration);
}
public final boolean isMinificationAllowed(
- DexReference reference,
- DexDefinitionSupplier definitions,
- GlobalKeepInfoConfiguration configuration) {
+ ProgramDefinition definition, GlobalKeepInfoConfiguration configuration) {
return configuration.isMinificationEnabled()
- && getInfo(reference, definitions).isMinificationAllowed(configuration);
+ && getInfo(definition).isMinificationAllowed(configuration);
}
public abstract boolean verifyPinnedTypesAreLive(Set<DexType> liveTypes, InternalOptions options);
diff --git a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
index a728063..7d8610b 100644
--- a/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
+++ b/src/main/java/com/android/tools/r8/shaking/RootSetUtils.java
@@ -2083,12 +2083,14 @@
(reference, minimumKeepInfo) -> {
if (reference.isDexType()) {
DexType type = reference.asDexType();
- assert !appInfo.hasLiveness() || appInfo.withLiveness().isPinned(type)
+ assert !appInfo.hasLiveness()
+ || appInfo.withLiveness().isPinnedWithDefinitionLookup(type)
: "Expected reference `" + type.toSourceString() + "` to be pinned";
requiredMembersPerType.computeIfAbsent(type, key -> Sets.newIdentityHashSet());
} else {
DexMember<?, ?> member = reference.asDexMember();
- assert !appInfo.hasLiveness() || appInfo.withLiveness().isPinned(member)
+ assert !appInfo.hasLiveness()
+ || appInfo.withLiveness().isPinnedWithDefinitionLookup(member)
: "Expected reference `" + member.toSourceString() + "` to be pinned";
requiredMembersPerType
.computeIfAbsent(member.holder, key -> Sets.newIdentityHashSet())
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 32878da..4819d4d 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -359,7 +359,7 @@
private void markTypeAsPinned(DexType type, AbortReason reason) {
DexType baseType = type.toBaseType(appView.dexItemFactory());
- if (!baseType.isClassType() || appInfo.isPinned(baseType)) {
+ if (!baseType.isClassType() || appInfo.isPinnedWithDefinitionLookup(baseType)) {
// We check for the case where the type is pinned according to appInfo.isPinned,
// so we only need to add it here if it is not the case.
return;
@@ -380,14 +380,13 @@
if (allocationInfo.isInstantiatedDirectly(sourceClass)
|| allocationInfo.isInterfaceWithUnknownSubtypeHierarchy(sourceClass)
|| allocationInfo.isImmediateInterfaceOfInstantiatedLambda(sourceClass)
- || appInfo.isPinned(sourceClass.type)
+ || appInfo.isPinned(sourceClass)
|| pinnedTypes.contains(sourceClass.type)
|| appInfo.isNoVerticalClassMergingOfType(sourceClass.type)) {
return false;
}
assert Streams.stream(Iterables.concat(sourceClass.fields(), sourceClass.methods()))
- .map(DexEncodedMember::getReference)
.noneMatch(appInfo::isPinned);
if (!FeatureSplitBoundaryOptimizationUtils.isSafeForVerticalClassMerging(
@@ -395,7 +394,7 @@
return false;
}
if (appView.appServices().allServiceTypes().contains(sourceClass.type)
- && appInfo.isPinned(targetClass.type)) {
+ && appInfo.isPinned(targetClass)) {
if (Log.ENABLED) {
AbortReason.SERVICE_LOADER.printLogMessageForClass(sourceClass);
}
diff --git a/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java
index c1e6850..11f01d2 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/LineNumberOptimizer.java
@@ -170,7 +170,7 @@
}
allSeenAreInstanceInitializers = false;
// If the method is pinned, we cannot minify it.
- if (!keepInfo.isMinificationAllowed(method.getReference(), appView, appView.options())) {
+ if (!keepInfo.isMinificationAllowed(method, appView.options())) {
continue;
}
// With desugared library, call-backs names are reserved here.