Use computeSingleUseArrayValues() in RawMessageDecoder
Removes some one-off array value collecting logic with a common helper
method.
Change-Id: I6d3647d2d6f41658a5920427734858d3c93cf750
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
index fad733e..1b3837a 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteShrinker.java
@@ -7,7 +7,7 @@
import static com.android.tools.r8.graph.DexClassAndMethod.asProgramMethodOrNull;
import static com.android.tools.r8.graph.DexProgramClass.asProgramClassOrNull;
import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getInfoValueFromMessageInfoConstructionInvoke;
-import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getObjectsValueFromMessageInfoConstructionInvoke;
+import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getObjectsArrayValuesFromMessageInfoConstructionInvoke;
import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.setObjectsValueForMessageInfoConstructionInvoke;
import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;
@@ -49,6 +49,7 @@
import com.android.tools.r8.shaking.DependentMinimumKeepInfoCollection;
import com.android.tools.r8.shaking.KeepMethodInfo;
import com.android.tools.r8.utils.Timing;
+import com.android.tools.r8.utils.ValueUtils.ArrayValues;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import java.util.ArrayList;
import java.util.List;
@@ -297,17 +298,19 @@
if (newMessageInfoInvoke != null) {
Value infoValue =
getInfoValueFromMessageInfoConstructionInvoke(newMessageInfoInvoke, references);
- Value objectsValue =
- getObjectsValueFromMessageInfoConstructionInvoke(newMessageInfoInvoke, references);
+ ArrayValues objectsValues =
+ getObjectsArrayValuesFromMessageInfoConstructionInvoke(newMessageInfoInvoke, references);
// Decode the arguments passed to newMessageInfo().
- ProtoMessageInfo protoMessageInfo = decoder.run(method, infoValue, objectsValue);
+ ProtoMessageInfo protoMessageInfo = decoder.run(method, infoValue, objectsValues);
if (protoMessageInfo != null) {
// Rewrite the arguments to newMessageInfo().
rewriteArgumentsToNewMessageInfo(code, newMessageInfoInvoke, infoValue, protoMessageInfo);
// Ensure that the definition of the original `objects` value is removed.
- IRCodeUtils.removeArrayAndTransitiveInputsIfNotUsed(code, objectsValue.definition);
+ if (objectsValues != null) {
+ IRCodeUtils.removeArrayAndTransitiveInputsIfNotUsed(code, objectsValues.getDefinition());
+ }
} else {
// We should generally be able to decode the arguments passed to newMessageInfo().
assert false;
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoUtils.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoUtils.java
index ac5c7aa..36de73e 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoUtils.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoUtils.java
@@ -9,6 +9,8 @@
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.utils.ValueUtils;
+import com.android.tools.r8.utils.ValueUtils.ArrayValues;
public class ProtoUtils {
@@ -43,7 +45,7 @@
}
@SuppressWarnings("ReferenceEquality")
- static Value getObjectsValueFromMessageInfoConstructionInvoke(
+ private static Value getObjectsValueFromMessageInfoConstructionInvoke(
InvokeMethod invoke, ProtoReferences references) {
assert references.isMessageInfoConstruction(invoke);
if (invoke.getInvokedMethod().match(references.newMessageInfoMethod)) {
@@ -64,6 +66,12 @@
throw new Unreachable();
}
+ static ArrayValues getObjectsArrayValuesFromMessageInfoConstructionInvoke(
+ InvokeMethod invoke, ProtoReferences references) {
+ Value arrayValue = getObjectsValueFromMessageInfoConstructionInvoke(invoke, references);
+ return ValueUtils.computeSingleUseArrayValues(arrayValue, invoke);
+ }
+
@SuppressWarnings("ReferenceEquality")
static void setObjectsValueForMessageInfoConstructionInvoke(
InvokeMethod invoke, Value newObjectsValue, ProtoReferences references) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
index 049920e..ef36cea 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/RawMessageInfoDecoder.java
@@ -5,7 +5,7 @@
package com.android.tools.r8.ir.analysis.proto;
import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getInfoValueFromMessageInfoConstructionInvoke;
-import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getObjectsValueFromMessageInfoConstructionInvoke;
+import static com.android.tools.r8.ir.analysis.proto.ProtoUtils.getObjectsArrayValuesFromMessageInfoConstructionInvoke;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.graph.DexEncodedField;
@@ -24,23 +24,19 @@
import com.android.tools.r8.ir.analysis.proto.schema.ProtoObjectFromInvokeStatic;
import com.android.tools.r8.ir.analysis.proto.schema.ProtoObjectFromStaticGet;
import com.android.tools.r8.ir.analysis.proto.schema.ProtoTypeObject;
-import com.android.tools.r8.ir.code.ArrayPut;
-import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.Instruction;
-import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeStatic;
-import com.android.tools.r8.ir.code.NewArrayEmpty;
-import com.android.tools.r8.ir.code.NewArrayFilled;
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ThrowingCharIterator;
import com.android.tools.r8.utils.ThrowingIntIterator;
import com.android.tools.r8.utils.ThrowingIterator;
+import com.android.tools.r8.utils.ValueUtils.ArrayValues;
import java.io.UTFDataFormatException;
import java.util.ArrayList;
import java.util.List;
@@ -82,11 +78,13 @@
public ProtoMessageInfo run(ProgramMethod dynamicMethod, InvokeMethod invoke) {
assert references.isMessageInfoConstruction(invoke);
Value infoValue = getInfoValueFromMessageInfoConstructionInvoke(invoke, references);
- Value objectsValue = getObjectsValueFromMessageInfoConstructionInvoke(invoke, references);
- return run(dynamicMethod, infoValue, objectsValue);
+ ArrayValues objectsValues =
+ getObjectsArrayValuesFromMessageInfoConstructionInvoke(invoke, references);
+ return run(dynamicMethod, infoValue, objectsValues);
}
- public ProtoMessageInfo run(ProgramMethod dynamicMethod, Value infoValue, Value objectsValue) {
+ public ProtoMessageInfo run(
+ ProgramMethod dynamicMethod, Value infoValue, ArrayValues objectsValues) {
try {
ProtoMessageInfo.Builder builder = ProtoMessageInfo.builder(dynamicMethod);
ThrowingIntIterator<InvalidRawMessageInfoException> infoIterator =
@@ -120,8 +118,11 @@
infoIterator.nextIntComputeIfAbsent(this::invalidInfoFailure);
}
+ if (objectsValues == null) {
+ throw new InvalidRawMessageInfoException();
+ }
ThrowingIterator<Value, InvalidRawMessageInfoException> objectIterator =
- createObjectIterator(objectsValue);
+ ThrowingIterator.fromIterator(objectsValues.getElementValues().iterator());
for (int i = 0; i < numberOfOneOfObjects; i++) {
ProtoObject oneOfObject =
@@ -297,102 +298,5 @@
};
}
- /**
- * Returns an iterator that yields the values that are stored in the `objects` array that is
- * passed to GeneratedMessageLite.newMessageInfo(). The array values are returned in-order, i.e.,
- * the value objects[i] will be returned prior to the value objects[i+1].
- */
- private static ThrowingIterator<Value, InvalidRawMessageInfoException> createObjectIterator(
- Value objectsValue) throws InvalidRawMessageInfoException {
- if (objectsValue.isPhi()) {
- throw new InvalidRawMessageInfoException();
- }
-
- NewArrayEmpty newArrayEmpty = objectsValue.definition.asNewArrayEmpty();
- NewArrayFilled newArrayFilled = objectsValue.definition.asNewArrayFilled();
-
- if (newArrayEmpty == null && newArrayFilled == null) {
- throw new InvalidRawMessageInfoException();
- }
- // Verify that the array is used in only one spot.
- if (newArrayFilled != null) {
- if (!objectsValue.hasSingleUniqueUser()) {
- throw new InvalidRawMessageInfoException();
- }
- return ThrowingIterator.fromIterator(newArrayFilled.inValues().iterator());
- }
-
- Value sizeValue = newArrayEmpty.size().getAliasedValue();
- if (sizeValue.isPhi() || !sizeValue.definition.isConstNumber()) {
- throw new InvalidRawMessageInfoException();
- }
- int arraySize = sizeValue.definition.asConstNumber().getIntValue();
- if (arraySize != objectsValue.uniqueUsers().size() - 1) {
- throw new InvalidRawMessageInfoException();
- }
-
- // Create an iterator for the block of interest.
- InstructionIterator instructionIterator = newArrayEmpty.getBlock().iterator();
- instructionIterator.nextUntil(instruction -> instruction == newArrayEmpty);
- return new ArrayPutIterator(instructionIterator, objectsValue);
- }
-
- private static class ArrayPutIterator
- extends ThrowingIterator<Value, InvalidRawMessageInfoException> {
-
- private InstructionIterator instructionIterator;
- private final Value objectsValue;
- private int expectedNextIndex;
-
- public ArrayPutIterator(InstructionIterator instructionIterator, Value objectsValue) {
- this.instructionIterator = instructionIterator;
- this.objectsValue = objectsValue;
- expectedNextIndex = 0;
- }
-
- @Override
- public boolean hasNext() {
- while (instructionIterator.hasNext()) {
- Instruction next = instructionIterator.peekNext();
- if (isArrayPutOfInterest(next)) {
- return true;
- }
- if (next.isGoto()) {
- // We may have split the block so allow continuing in linear jumps.
- BasicBlock target = next.asGoto().getTarget();
- assert target.hasUniquePredecessor();
- instructionIterator = target.iterator();
- continue;
- }
- if (next.isJumpInstruction()) {
- return false;
- }
- instructionIterator.next();
- }
- return false;
- }
-
- @Override
- public Value next() throws InvalidRawMessageInfoException {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- ArrayPut arrayPut = instructionIterator.next().asArrayPut();
-
- // Verify that the index correct.
- if (arrayPut.indexOrDefault(-1) != expectedNextIndex) {
- throw new InvalidRawMessageInfoException();
- }
-
- expectedNextIndex++;
- return arrayPut.value().getAliasedValue();
- }
-
- private boolean isArrayPutOfInterest(Instruction instruction) {
- return instruction.isArrayPut()
- && instruction.asArrayPut().array().getAliasedValue() == objectsValue;
- }
- }
-
private static class InvalidRawMessageInfoException extends Exception {}
}