Restrict proto enqueuer extension to proto instance fields

Bug: 174530756
Bug: 172880350
Change-Id: I4b669f261dc1597de92ab144e618613e3db11a38
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java
index 2ef11c9..2d89bdf 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java
@@ -4,8 +4,11 @@
 
 package com.android.tools.r8.ir.analysis.proto;
 
+import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
+
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
+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.ir.analysis.proto.schema.ProtoEnqueuerExtension;
@@ -47,17 +50,29 @@
 
   /**
    * Unlike {@link DefaultEnqueuerUseRegistry#registerStaticFieldRead(DexField)}, this method does
-   * not trace any static-get instructions in every implementation of dynamicMethod().
+   * not trace any static-get instructions in every implementation of dynamicMethod() that accesses
+   * an 'INSTANCE' or a 'DEFAULT_INSTANCE' field.
    *
    * <p>The static-get instructions that remain after the proto schema has been optimized will be
    * traced manually by {@link ProtoEnqueuerExtension#tracePendingInstructionsInDynamicMethods}.
    */
   @Override
   public void registerStaticFieldRead(DexField field) {
-    if (references.isDynamicMethod(getContextMethod())) {
+    if (references.isDynamicMethod(getContextMethod())
+        && isStaticFieldReadForProtoSchemaDefinition(field)) {
       enqueuer.addDeadProtoTypeCandidate(field.holder);
       return;
     }
     super.registerStaticFieldRead(field);
   }
+
+  private boolean isStaticFieldReadForProtoSchemaDefinition(DexField field) {
+    if (field == references.getDefaultInstanceField(getContextHolder())) {
+      return true;
+    }
+    DexProgramClass holder = asProgramClassOrNull(enqueuer.definitionFor(field.getHolderType()));
+    return holder != null
+        && holder.interfaces.contains(references.enumVerifierType)
+        && field == references.getEnumVerifierInstanceField(holder);
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
index 84aabe8..b25f946 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoReferences.java
@@ -21,6 +21,7 @@
 
   public final DexType enumLiteType;
   public final DexType enumLiteMapType;
+  public final DexType enumVerifierType;
   public final DexType extendableMessageType;
   public final DexType extensionDescriptorType;
   public final DexType extensionRegistryLiteType;
@@ -42,6 +43,7 @@
   public final MethodToInvokeMembers methodToInvokeMembers;
 
   public final DexString defaultInstanceFieldName;
+  public final DexString instanceFieldName;
   public final DexString internalValueMapFieldName;
   public final DexString dynamicMethodName;
   public final DexString findLiteExtensionByNumberName;
@@ -63,6 +65,7 @@
     // Types.
     enumLiteType = factory.createType("Lcom/google/protobuf/Internal$EnumLite;");
     enumLiteMapType = factory.createType("Lcom/google/protobuf/Internal$EnumLiteMap;");
+    enumVerifierType = factory.createType("Lcom/google/protobuf/Internal$EnumVerifier;");
     extendableMessageType =
         factory.createType("Lcom/google/protobuf/GeneratedMessageLite$ExtendableMessage;");
     extensionDescriptorType =
@@ -85,6 +88,7 @@
 
     // Names.
     defaultInstanceFieldName = factory.createString("DEFAULT_INSTANCE");
+    instanceFieldName = factory.createString("INSTANCE");
     internalValueMapFieldName = factory.createString("internalValueMap");
     dynamicMethodName = factory.createString("dynamicMethod");
     findLiteExtensionByNumberName = factory.createString("findLiteExtensionByNumber");
@@ -129,6 +133,10 @@
     return dexItemFactory.createField(holder.type, holder.type, defaultInstanceFieldName);
   }
 
+  public DexField getEnumVerifierInstanceField(DexProgramClass holder) {
+    return dexItemFactory.createField(holder.type, enumVerifierType, instanceFieldName);
+  }
+
   public boolean isAbstractGeneratedMessageLiteBuilder(DexProgramClass clazz) {
     return clazz.type == generatedMessageLiteBuilderType
         || clazz.type == generatedMessageLiteExtendableBuilderType;
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 fd7c46d..c36bc6f 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -517,7 +517,7 @@
     return clazz.lookupMethod(method);
   }
 
-  private DexClass definitionFor(DexType type) {
+  public DexClass definitionFor(DexType type) {
     DexClass clazz = appView.definitionFor(type);
     if (clazz == null) {
       reportMissingClass(type);