Reland "Add instanceof and check cast enqueuer callbacks"

Change-Id: I87044610d68dba9ea64c5c9ae33a0f2d71b93f92
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
new file mode 100644
index 0000000..503e74e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerCheckCastAnalysis.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.graph.analysis;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
+
+public interface EnqueuerCheckCastAnalysis {
+  void traceCheckCast(DexType type, ProgramMethod context);
+}
diff --git a/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
new file mode 100644
index 0000000..abda4d1
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/graph/analysis/EnqueuerInstanceOfAnalysis.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.graph.analysis;
+
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.ProgramMethod;
+
+public interface EnqueuerInstanceOfAnalysis {
+  void traceInstanceOf(DexType type, ProgramMethod context);
+}
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 df7690c..449be4a 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -72,6 +72,8 @@
 import com.android.tools.r8.graph.UseRegistry.MethodHandleUse;
 import com.android.tools.r8.graph.analysis.DesugaredLibraryConversionWrapperAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerCheckCastAnalysis;
+import com.android.tools.r8.graph.analysis.EnqueuerInstanceOfAnalysis;
 import com.android.tools.r8.graph.analysis.EnqueuerInvokeAnalysis;
 import com.android.tools.r8.ir.analysis.proto.ProtoEnqueuerUseRegistry;
 import com.android.tools.r8.ir.analysis.proto.schema.ProtoEnqueuerExtension;
@@ -184,6 +186,8 @@
 
   private Set<EnqueuerAnalysis> analyses = Sets.newIdentityHashSet();
   private Set<EnqueuerInvokeAnalysis> invokeAnalyses = Sets.newIdentityHashSet();
+  private Set<EnqueuerInstanceOfAnalysis> instanceOfAnalyses = Sets.newIdentityHashSet();
+  private Set<EnqueuerCheckCastAnalysis> checkCastAnalyses = Sets.newIdentityHashSet();
 
   // Don't hold a direct pointer to app info (use appView).
   private AppInfoWithClassHierarchy appInfo;
@@ -436,6 +440,16 @@
     return this;
   }
 
+  public Enqueuer registerInstanceOfAnalysis(EnqueuerInstanceOfAnalysis analysis) {
+    instanceOfAnalyses.add(analysis);
+    return this;
+  }
+
+  public Enqueuer registerCheckCastAnalysis(EnqueuerCheckCastAnalysis analysis) {
+    checkCastAnalyses.add(analysis);
+    return this;
+  }
+
   public void setAnnotationRemoverBuilder(AnnotationRemover.Builder annotationRemoverBuilder) {
     this.annotationRemoverBuilder = annotationRemoverBuilder;
   }
@@ -905,9 +919,13 @@
   }
 
   boolean traceCheckCast(DexType type, ProgramMethod currentMethod) {
+    checkCastAnalyses.forEach(analysis -> analysis.traceCheckCast(type, currentMethod));
     return traceConstClassOrCheckCast(type, currentMethod);
   }
 
+  // TODO(b/163311975): traceInstanceOf (impl. by b/163471800) should call
+  // analysis.traceInstanceOf(...)
+
   boolean traceConstClass(DexType type, ProgramMethod currentMethod) {
     // We conservatively group T.class and T[].class to ensure that we do not merge T with S if
     // potential locks on T[].class and S[].class exists.