Disentangle instantiating context from keep reason.
Bug: 142378367
Change-Id: Ic84572cf07259cafd728dca388b39b7e73aded56
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
index 7ad4c5b..2b55be8 100644
--- a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerAnalysis.java
@@ -9,12 +9,11 @@
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.EnqueuerWorklist;
-import com.android.tools.r8.shaking.KeepReason;
public abstract class EnqueuerAnalysis {
/** Called when a class is found to be instantiated. */
- public void processNewlyInstantiatedClass(DexProgramClass clazz, KeepReason reason) {}
+ public void processNewlyInstantiatedClass(DexProgramClass clazz, DexEncodedMethod context) {}
/** Called when a field is found to be live. */
public void processNewlyLiveField(DexEncodedField field) {}
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 54b03a6..e7c6418 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
@@ -7,9 +7,9 @@
import com.android.tools.r8.graph.AppInfoWithSubtyping;
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.shaking.KeepReason;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -61,10 +61,10 @@
}
@Override
- public void processNewlyInstantiatedClass(DexProgramClass clazz, KeepReason reason) {
+ public void processNewlyInstantiatedClass(DexProgramClass clazz, DexEncodedMethod context) {
DexType key = clazz.type;
DexType objectType = appView.dexItemFactory().objectType;
- if (!reason.isInstantiatedIn()) {
+ if (context == null) {
// Record that we don't know anything about the set of classes that are guaranteed to be
// initialized in the instance methods of `clazz`.
mapping.put(key, objectType);
@@ -73,7 +73,7 @@
// Record that the enclosing class is guaranteed to be initialized at the allocation site.
AppInfoWithSubtyping appInfo = appView.appInfo();
- DexType guaranteedToBeInitialized = reason.asInstantiatedIn().getMethod().holder;
+ DexType guaranteedToBeInitialized = context.method.holder;
DexType existingGuaranteedToBeInitialized =
mapping.getOrDefault(key, guaranteedToBeInitialized);
mapping.put(
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 4db35df..1863757 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -424,7 +424,7 @@
if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
markInterfaceAsInstantiated(clazz, witness);
} else {
- workList.enqueueMarkInstantiatedAction(clazz, witness);
+ workList.enqueueMarkInstantiatedAction(clazz, null, witness);
if (clazz.hasDefaultInitializer()) {
DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
if (forceProguardCompatibility) {
@@ -767,16 +767,17 @@
@Override
public boolean registerNewInstance(DexType type) {
- return registerNewInstance(type, KeepReason.instantiatedIn(currentMethod));
+ return registerNewInstance(type, currentMethod, KeepReason.instantiatedIn(currentMethod));
}
- public boolean registerNewInstance(DexType type, KeepReason keepReason) {
+ public boolean registerNewInstance(
+ DexType type, DexEncodedMethod context, KeepReason keepReason) {
DexProgramClass clazz = getProgramClassOrNull(type);
if (clazz != null) {
if (clazz.isInterface()) {
markTypeAsLive(clazz, graphReporter.registerClass(clazz, keepReason));
} else {
- markInstantiated(clazz, keepReason);
+ markInstantiated(clazz, context, keepReason);
}
}
return true;
@@ -913,7 +914,7 @@
if (clazz.isInterface() && !clazz.accessFlags.isAnnotation()) {
markInterfaceAsInstantiated(clazz, graphReporter.registerClass(clazz, reason));
} else {
- markInstantiated(clazz, reason);
+ markInstantiated(clazz, null, reason);
}
}
}
@@ -981,7 +982,8 @@
registerInvokeDirect(method, KeepReason.invokedFromLambdaCreatedIn(currentMethod));
break;
case INVOKE_CONSTRUCTOR:
- registerNewInstance(method.holder, KeepReason.invokedFromLambdaCreatedIn(currentMethod));
+ registerNewInstance(
+ method.holder, null, KeepReason.invokedFromLambdaCreatedIn(currentMethod));
break;
default:
throw new Unreachable();
@@ -1416,13 +1418,14 @@
* depending on the currently seen invokes and field reads.
*/
// Package protected due to entry point from worklist.
- void processNewlyInstantiatedClass(DexProgramClass clazz, KeepReason reason) {
+ void processNewlyInstantiatedClass(
+ DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
// Notify analyses. This is done even if `clazz` has already been marked as instantiated,
// because each analysis may depend on seeing all the (clazz, reason) pairs. Thus, not doing so
// could lead to nondeterminism.
analyses.forEach(
- analysis -> analysis.processNewlyInstantiatedClass(clazz.asProgramClass(), reason));
+ analysis -> analysis.processNewlyInstantiatedClass(clazz.asProgramClass(), context));
if (!instantiatedTypes.add(clazz, reason)) {
return;
@@ -1691,11 +1694,12 @@
analyses.forEach(analysis -> analysis.processNewlyLiveField(field));
}
- private void markInstantiated(DexProgramClass clazz, KeepReason reason) {
+ private void markInstantiated(
+ DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
if (Log.ENABLED) {
Log.verbose(getClass(), "Register new instantiation of `%s`.", clazz);
}
- workList.enqueueMarkInstantiatedAction(clazz, reason);
+ workList.enqueueMarkInstantiatedAction(clazz, context, reason);
}
private void markLambdaInstantiated(DexType itf, DexEncodedMethod method) {
@@ -2459,7 +2463,7 @@
}
private void markClassAsInstantiatedWithReason(DexProgramClass clazz, KeepReason reason) {
- workList.enqueueMarkInstantiatedAction(clazz, reason);
+ workList.enqueueMarkInstantiatedAction(clazz, null, reason);
if (clazz.hasDefaultInitializer()) {
workList.enqueueMarkReachableDirectAction(clazz.getDefaultInitializer().method, reason);
}
@@ -2471,7 +2475,7 @@
markInterfaceAsInstantiated(clazz, witness);
return;
}
- workList.enqueueMarkInstantiatedAction(clazz, witness);
+ workList.enqueueMarkInstantiatedAction(clazz, null, witness);
if (clazz.hasDefaultInitializer()) {
DexEncodedMethod defaultInitializer = clazz.getDefaultInitializer();
workList.enqueueMarkReachableDirectAction(
@@ -2535,7 +2539,7 @@
return;
}
if (!clazz.isInterface()) {
- markInstantiated(clazz, KeepReason.reflectiveUseIn(method));
+ markInstantiated(clazz, null, KeepReason.reflectiveUseIn(method));
if (clazz.hasDefaultInitializer()) {
DexEncodedMethod initializer = clazz.getDefaultInitializer();
KeepReason reason = KeepReason.reflectiveUseIn(method);
@@ -2562,7 +2566,7 @@
!encodedField.accessFlags.isStatic()
&& dexItemFactory.atomicFieldUpdaterMethods.isFieldUpdater(invokedMethod);
if (keepClass) {
- markInstantiated(clazz, KeepReason.reflectiveUseIn(method));
+ markInstantiated(clazz, null, KeepReason.reflectiveUseIn(method));
}
markFieldAsKept(encodedField, KeepReason.reflectiveUseIn(method));
// Fields accessed by reflection is marked as both read and written.
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index 5b06e48..275e5a7 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -95,16 +95,19 @@
static class MarkInstantiatedAction extends Action {
final DexProgramClass target;
+ final DexEncodedMethod context;
final KeepReason reason;
- public MarkInstantiatedAction(DexProgramClass target, KeepReason reason) {
+ public MarkInstantiatedAction(
+ DexProgramClass target, DexEncodedMethod context, KeepReason reason) {
this.target = target;
+ this.context = context;
this.reason = reason;
}
@Override
public void run(Enqueuer enqueuer) {
- enqueuer.processNewlyInstantiatedClass(target, reason);
+ enqueuer.processNewlyInstantiatedClass(target, context, reason);
}
}
@@ -194,9 +197,12 @@
queue.add(new MarkReachableFieldAction(field, reason));
}
- void enqueueMarkInstantiatedAction(DexProgramClass clazz, KeepReason reason) {
+ // TODO(b/142378367): Context is the containing method that is cause of the instantiation.
+ // Consider updating call sites with the context information to increase precision where possible.
+ void enqueueMarkInstantiatedAction(
+ DexProgramClass clazz, DexEncodedMethod context, KeepReason reason) {
assert !clazz.isInterface() || clazz.accessFlags.isAnnotation();
- queue.add(new MarkInstantiatedAction(clazz, reason));
+ queue.add(new MarkInstantiatedAction(clazz, context, reason));
}
void enqueueMarkMethodLiveAction(
diff --git a/src/main/java/com/android/tools/r8/shaking/KeepReason.java b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
index 9dbb65e..680c0b5 100644
--- a/src/main/java/com/android/tools/r8/shaking/KeepReason.java
+++ b/src/main/java/com/android/tools/r8/shaking/KeepReason.java
@@ -64,14 +64,6 @@
return false;
}
- public boolean isInstantiatedIn() {
- return false;
- }
-
- public InstatiatedIn asInstantiatedIn() {
- return null;
- }
-
public static KeepReason targetedBySuperFrom(DexEncodedMethod from) {
return new TargetedBySuper(from);
}
@@ -111,16 +103,6 @@
}
@Override
- public boolean isInstantiatedIn() {
- return true;
- }
-
- @Override
- public InstatiatedIn asInstantiatedIn() {
- return this;
- }
-
- @Override
public EdgeKind edgeKind() {
return EdgeKind.InstantiatedIn;
}