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;
     }