[ApiModel] Do not stub references when merging

Also, do not process when the type is prefixed with java. Adding this check will remove some of the contention on the seen set.

Bug: b/273232160
Change-Id: I73cb44c2bbe411841554a2e55d45e1086c996163
diff --git a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
index 261497d..8bbfcfd 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -24,10 +24,12 @@
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.synthesis.CommittedItems;
 import com.android.tools.r8.synthesis.SyntheticItems;
+import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.WorkList;
 import com.google.common.collect.Sets;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -58,7 +60,16 @@
   public void run(ExecutorService executorService) throws ExecutionException {
     if (appView.options().isGeneratingDex()
         && appView.options().apiModelingOptions().enableStubbingOfClasses) {
-      ThreadUtils.processItems(appView.appInfo().classes(), this::processClass, executorService);
+      Collection<DexProgramClass> classes =
+          ListUtils.filter(
+              appView.appInfo().classes(), DexProgramClass::originatesFromClassResource);
+      // Finding super types is really fast so no need to pay the overhead of threading if the
+      // number of classes is low.
+      if (classes.size() > 2) {
+        ThreadUtils.processItems(classes, this::processClass, executorService);
+      } else {
+        classes.forEach(this::processClass);
+      }
     }
     if (!libraryClassesToMock.isEmpty()) {
       libraryClassesToMock.forEach(
@@ -98,6 +109,7 @@
   }
 
   public void processClass(DexProgramClass clazz) {
+    assert clazz.originatesFromClassResource();
     if (isAlreadyOutlined(clazz)) {
       return;
     }
@@ -124,7 +136,7 @@
   }
 
   private void findReferencedLibraryClasses(DexType type, DexProgramClass context) {
-    if (!type.isClassType()) {
+    if (!type.isClassType() || isJavaType(type)) {
       return;
     }
     WorkList<DexType> workList = WorkList.newIdentityWorkList(type, seenTypes);
@@ -147,17 +159,18 @@
     }
   }
 
+  private boolean isJavaType(DexType type) {
+    return type == appView.dexItemFactory().objectType
+        || type.getDescriptor().startsWith(appView.dexItemFactory().javaDescriptorPrefix);
+  }
+
   private void mockMissingLibraryClass(
       DexLibraryClass libraryClass,
       ThrowExceptionCode throwExceptionCode,
       ApiReferenceStubberEventConsumer eventConsumer) {
     DexItemFactory factory = appView.dexItemFactory();
     // Do not stub the anything starting with java (including the object type).
-    if (libraryClass.getType() == appView.dexItemFactory().objectType
-        || libraryClass
-            .getType()
-            .getDescriptor()
-            .startsWith(appView.dexItemFactory().javaDescriptorPrefix)) {
+    if (isJavaType(libraryClass.getType())) {
       return;
     }
     // Check if desugared library will bridge the type.