Account for isMutable call after inlining of edition 2023 builder
Change-Id: I5cb96dfec5632d86f2d125d485854a6857fc919b
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
index 4c9ab2c..04c491e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
@@ -493,6 +493,7 @@
// MessageLite and GeneratedMessageLite heuristics.
alwaysInlineCreateBuilderFromGeneratedMessageLite();
+ alwaysInlineNewMutableInstanceFromGeneratedMessageLite();
neverMergeMessageLite();
// * extends GeneratedMessageLite heuristics.
@@ -534,6 +535,10 @@
alwaysInline.add(references.generatedMessageLiteMethods.createBuilderMethod);
}
+ private void alwaysInlineNewMutableInstanceFromGeneratedMessageLite() {
+ alwaysInline.add(references.generatedMessageLiteMethods.newMutableInstanceMethod);
+ }
+
private void neverMergeGeneratedMessageLiteBuilder() {
// For consistency, never merge the GeneratedMessageLite builders. These will only have a
// unique subtype if the application has a single proto message, which mostly happens during
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 812c0ee..8bacc2d 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
@@ -283,6 +283,7 @@
public final DexMethod createBuilderMethod;
public final DexMethod dynamicMethodBridgeMethod;
public final DexMethod dynamicMethodBridgeMethodWithObject;
+ public final DexMethod newMutableInstanceMethod;
public final DexMethod newRepeatedGeneratedExtension;
public final DexMethod newSingularGeneratedExtension;
@@ -303,6 +304,11 @@
dexItemFactory.createProto(
dexItemFactory.objectType, methodToInvokeType, dexItemFactory.objectType),
"dynamicMethod");
+ newMutableInstanceMethod =
+ dexItemFactory.createMethod(
+ generatedMessageLiteType,
+ dexItemFactory.createProto(generatedMessageLiteType),
+ "newMutableInstance");
newRepeatedGeneratedExtension =
dexItemFactory.createMethod(
generatedMessageLiteType,
diff --git a/src/test/java/com/android/tools/r8/internal/proto/ProtoBuilderShrinkingTest.java b/src/test/java/com/android/tools/r8/internal/proto/ProtoBuilderShrinkingTest.java
index 40560ff..dfd201a 100644
--- a/src/test/java/com/android/tools/r8/internal/proto/ProtoBuilderShrinkingTest.java
+++ b/src/test/java/com/android/tools/r8/internal/proto/ProtoBuilderShrinkingTest.java
@@ -260,9 +260,25 @@
outputInspector.clazz("com.google.protobuf.GeneratedMessageLite");
assertThat(generatedMessageLiteClassSubject, isPresent());
+ MethodSubject computeSerializedSizeMethodSubject =
+ generatedMessageLiteClassSubject.uniqueMethodWithOriginalName("computeSerializedSize");
+
+ MethodSubject equalsMethodSubject =
+ generatedMessageLiteClassSubject.uniqueMethodWithOriginalName("equals");
+
MethodSubject isInitializedMethodSubject =
generatedMessageLiteClassSubject.uniqueMethodWithOriginalName("isInitialized");
+ MethodSubject isMutableMethodSubject =
+ generatedMessageLiteClassSubject.uniqueMethodWithOriginalName("isMutable");
+
+ List<MethodSubject> allowList =
+ ImmutableList.of(
+ computeSerializedSizeMethodSubject,
+ equalsMethodSubject,
+ isInitializedMethodSubject,
+ isMutableMethodSubject);
+
DexType methodToInvokeType =
outputInspector.clazz(METHOD_TO_INVOKE_ENUM).getDexProgramClass().getType();
for (String main : config.getMainClasses()) {
@@ -270,23 +286,21 @@
assertThat(mainMethodSubject, isPresent());
// Verify that the calls to GeneratedMessageLite.createBuilder() have been inlined.
- // TODO(b/339100248): Investigate inadequate inlining with edition2023.
- if (protoRuntime.isLegacy()) {
- assertTrue(
- mainMethodSubject
- .streamInstructions()
- .filter(InstructionSubject::isInvoke)
- .map(InstructionSubject::getMethod)
- .allMatch(
- method ->
- method.getHolderType()
- != generatedMessageLiteClassSubject.getDexProgramClass().getType()
- || (isInitializedMethodSubject.isPresent()
- && method
- == isInitializedMethodSubject
- .getProgramMethod()
- .getReference())));
- }
+ assertTrue(
+ mainMethodSubject
+ .streamInstructions()
+ .filter(InstructionSubject::isInvoke)
+ .map(InstructionSubject::getMethod)
+ .allMatch(
+ method ->
+ method.getHolderType()
+ != generatedMessageLiteClassSubject.getDexProgramClass().getType()
+ || allowList.stream()
+ .anyMatch(
+ m ->
+ m.isPresent()
+ && method.isIdenticalTo(
+ m.getProgramMethod().getReference()))));
// Verify that there are no accesses to MethodToInvoke after inlining createBuilder() -- and
// specifically no accesses to MethodToInvoke.NEW_BUILDER.