filled-new-array: Add support for InvokeNewArray to Enqueuer
Fixes the proguard compatibility mode tests
Bug: 246971330
Change-Id: I35e2af1993e703ebf36d9fc331dbfe1b37b264ef
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
index 27227a0..2a543a8 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/StaticFieldValueAnalysis.java
@@ -256,18 +256,9 @@
return null;
}
- int valuesSize;
- if (newArrayEmpty != null) {
- if (!newArrayEmpty.size().isConstNumber()) {
- return null;
- }
- valuesSize = newArrayEmpty.size().getConstInstruction().asConstNumber().getIntValue();
- } else {
- valuesSize = invokeNewArray.inValues().size();
- }
-
- if (valuesSize == 0) {
- // No need to compute the state of an empty array.
+ int valuesSize = newArrayEmpty != null ? newArrayEmpty.sizeIfConst() : invokeNewArray.size();
+ if (valuesSize < 1) {
+ // Array is empty or non-const size.
return null;
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
index a2e815f..f0715b5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
@@ -221,4 +221,9 @@
void internalRegisterUse(UseRegistry<?> registry, DexClassAndMethod context) {
registry.registerTypeReference(type);
}
+
+ // Returns the number of elements in the array.
+ public int size() {
+ return inValues.size();
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index a5f71e5..a829247 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -167,4 +167,10 @@
void internalRegisterUse(UseRegistry<?> registry, DexClassAndMethod context) {
registry.registerTypeReference(type);
}
+
+ // Returns the size of the array if it is known, -1 otherwise.
+ public int sizeIfConst() {
+ Value size = size();
+ return size.isConstNumber() ? size.getConstInstruction().asConstNumber().getIntValue() : -1;
+ }
}
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 213819d..93d387e 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -104,7 +104,9 @@
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.InvokeNewArray;
import com.android.tools.r8.ir.code.InvokeVirtual;
+import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringCollection;
import com.android.tools.r8.ir.desugar.CfInstructionDesugaringEventConsumer;
@@ -5079,25 +5081,43 @@
return;
}
Value parametersValue = constructorDefinition.inValues().get(1);
- if (parametersValue.isPhi() || !parametersValue.definition.isNewArrayEmpty()) {
+ if (parametersValue.isPhi()) {
// Give up, we can't tell which constructor is being invoked.
return;
}
-
- Value parametersSizeValue = parametersValue.definition.asNewArrayEmpty().size();
- if (parametersSizeValue.isPhi() || !parametersSizeValue.definition.isConstNumber()) {
- // Give up, we can't tell which constructor is being invoked.
+ NewArrayEmpty newArrayEmpty = parametersValue.definition.asNewArrayEmpty();
+ InvokeNewArray invokeNewArray = parametersValue.definition.asInvokeNewArray();
+ int parametersSize =
+ newArrayEmpty != null
+ ? newArrayEmpty.sizeIfConst()
+ : invokeNewArray != null ? invokeNewArray.size() : -1;
+ if (parametersSize < 0) {
return;
}
ProgramMethod initializer = null;
- int parametersSize = parametersSizeValue.definition.asConstNumber().getIntValue();
if (parametersSize == 0) {
initializer = clazz.getProgramDefaultInitializer();
} else {
DexType[] parameterTypes = new DexType[parametersSize];
int missingIndices = parametersSize;
+
+ if (newArrayEmpty != null) {
+ missingIndices = parametersSize;
+ } else {
+ missingIndices = 0;
+ List<Value> values = invokeNewArray.inValues();
+ for (int i = 0; i < parametersSize; ++i) {
+ DexType type =
+ ConstantValueUtils.getDexTypeRepresentedByValueForTracing(values.get(i), appView);
+ if (type == null) {
+ return;
+ }
+ parameterTypes[i] = type;
+ }
+ }
+
for (Instruction user : parametersValue.uniqueUsers()) {
if (user.isArrayPut()) {
ArrayPut arrayPutInstruction = user.asArrayPut();
@@ -5159,20 +5179,31 @@
}
Value interfacesValue = invoke.arguments().get(1);
- if (interfacesValue.isPhi() || !interfacesValue.definition.isNewArrayEmpty()) {
+ if (interfacesValue.isPhi()) {
// Give up, we can't tell which interfaces the proxy implements.
return;
}
- WorkList<DexProgramClass> worklist = WorkList.newIdentityWorkList();
- for (Instruction user : interfacesValue.uniqueUsers()) {
- if (!user.isArrayPut()) {
- continue;
+ InvokeNewArray invokeNewArray = interfacesValue.definition.asInvokeNewArray();
+ NewArrayEmpty newArrayEmpty = interfacesValue.definition.asNewArrayEmpty();
+ List<Value> values;
+ if (invokeNewArray != null) {
+ values = invokeNewArray.inValues();
+ } else if (newArrayEmpty != null) {
+ values = new ArrayList<>(interfacesValue.uniqueUsers().size());
+ for (Instruction user : interfacesValue.uniqueUsers()) {
+ ArrayPut arrayPut = user.asArrayPut();
+ if (arrayPut != null) {
+ values.add(arrayPut.value());
+ }
}
+ } else {
+ return;
+ }
- ArrayPut arrayPut = user.asArrayPut();
- DexType type =
- ConstantValueUtils.getDexTypeRepresentedByValueForTracing(arrayPut.value(), appView);
+ WorkList<DexProgramClass> worklist = WorkList.newIdentityWorkList();
+ for (Value value : values) {
+ DexType type = ConstantValueUtils.getDexTypeRepresentedByValueForTracing(value, appView);
if (type == null || !type.isClassType()) {
continue;
}