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