[LIR] Introduce a type for constant pool items
This refactoring is in preparation for implementing structural
comparisons on LirCode. For that having a more restrictive type
of items in the pool will help ensure completeness.
Bug: b/225838009
Change-Id: Ibbff8cbde8282685b7060e40e35de7f775a3eaa2
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index f5d8cea..2f84316 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -10,6 +10,7 @@
import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
import com.android.tools.r8.graph.DexValue.DexValueMethodType;
import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.lightir.LirConstant;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
@@ -25,7 +26,8 @@
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
-public final class DexCallSite extends IndexedDexItem implements StructuralItem<DexCallSite> {
+public final class DexCallSite extends IndexedDexItem
+ implements StructuralItem<DexCallSite>, LirConstant {
public final DexString methodName;
public final DexProto methodProto;
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
index 0e72940..a61182e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.lightir.LirConstant;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
@@ -15,7 +16,7 @@
import org.objectweb.asm.Opcodes;
public class DexMethodHandle extends IndexedDexItem
- implements NamingLensComparable<DexMethodHandle> {
+ implements NamingLensComparable<DexMethodHandle>, LirConstant {
public enum MethodHandleType {
STATIC_PUT((short) 0x00),
diff --git a/src/main/java/com/android/tools/r8/graph/DexProto.java b/src/main/java/com/android/tools/r8/graph/DexProto.java
index b85f0da..3e9d428 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProto.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProto.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.lightir.LirConstant;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
@@ -11,7 +12,8 @@
import java.util.Collections;
import java.util.function.Consumer;
-public class DexProto extends IndexedDexItem implements NamingLensComparable<DexProto> {
+public class DexProto extends IndexedDexItem
+ implements NamingLensComparable<DexProto>, LirConstant {
public static final DexProto SENTINEL = new DexProto(null, null, null);
diff --git a/src/main/java/com/android/tools/r8/graph/DexReference.java b/src/main/java/com/android/tools/r8/graph/DexReference.java
index 1e84335..c8e374d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexReference.java
+++ b/src/main/java/com/android/tools/r8/graph/DexReference.java
@@ -5,13 +5,14 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.lightir.LirConstant;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
/** A common interface for {@link DexType}, {@link DexField}, and {@link DexMethod}. */
-public abstract class DexReference extends IndexedDexItem {
+public abstract class DexReference extends IndexedDexItem implements LirConstant {
public abstract <T> T apply(
Function<DexType, T> classConsumer,
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index 0399618..f8f9132 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -5,6 +5,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.lightir.LirConstant;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.IdentifierUtils;
@@ -17,7 +18,8 @@
import java.util.Arrays;
import java.util.NoSuchElementException;
-public class DexString extends IndexedDexItem implements NamingLensComparable<DexString> {
+public class DexString extends IndexedDexItem
+ implements NamingLensComparable<DexString>, LirConstant {
public static final DexString[] EMPTY_ARRAY = {};
private static final int ARRAY_CHARACTER = '[';
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
index 73a842f..cc457a3 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -7,12 +7,10 @@
import com.android.tools.r8.cf.code.CfArithmeticBinop.Opcode;
import com.android.tools.r8.cf.code.CfLogicalBinop;
import com.android.tools.r8.cf.code.CfNumberConversion;
-import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
@@ -68,7 +66,7 @@
private final DexItemFactory factory;
private final ByteArrayWriter byteWriter = new ByteArrayWriter();
private final LirWriter writer = new LirWriter(byteWriter);
- private final Reference2IntMap<DexItem> constants;
+ private final Reference2IntMap<LirConstant> constants;
private final List<PositionEntry> positionTable;
private int argumentCount = 0;
private int instructionCount = 0;
@@ -91,17 +89,12 @@
private final Int2ReferenceMap<int[]> debugLocalEnds = new Int2ReferenceOpenHashMap<>();
/**
- * Internal "DexItem" for the instruction payloads such that they can be put in the pool.
+ * Internal "LirConstant" for the instruction payloads such that they can be put in the pool.
*
- * <p>The instruction encoding assumes the instruction operand payload size is u1, so this allows
- * the data payload to be stored in the constant pool instead.
+ * <p>The instruction encoding is optimized for an instruction operand payload size of u1, so this
+ * allows potentially large data payloads to be stored in the constant pool instead.
*/
- public abstract static class InstructionPayload extends DexItem {
- @Override
- protected final void collectMixedSectionItems(MixedSectionCollection collection) {
- throw new Unreachable();
- }
- }
+ public abstract static class InstructionPayload implements LirConstant {}
/**
* Internal "DexItem" for the fill-array payloads such that they can be put in the pool.
@@ -246,17 +239,17 @@
return true;
}
- private int getConstantIndex(DexItem item) {
+ private int getConstantIndex(LirConstant item) {
int nextIndex = constants.size();
Integer oldIndex = constants.putIfAbsent(item, nextIndex);
return oldIndex != null ? oldIndex : nextIndex;
}
- private int constantIndexSize(DexItem item) {
+ private int constantIndexSize(LirConstant item) {
return 4;
}
- private void writeConstantIndex(DexItem item) {
+ private void writeConstantIndex(LirConstant item) {
int index = getConstantIndex(item);
assert constantIndexSize(item) == ByteUtils.intEncodingSize(index);
ByteUtils.writeEncodedInt(index, writer::writeOperand);
@@ -341,7 +334,7 @@
return this;
}
- private LirBuilder<V, EV> addOneItemInstruction(int opcode, DexItem item) {
+ private LirBuilder<V, EV> addOneItemInstruction(int opcode, LirConstant item) {
return addInstructionTemplate(opcode, Collections.singletonList(item), Collections.emptyList());
}
@@ -356,10 +349,10 @@
}
private LirBuilder<V, EV> addInstructionTemplate(
- int opcode, List<DexItem> items, List<V> values) {
+ int opcode, List<LirConstant> items, List<V> values) {
int instructionIndex = advanceInstructionState();
int operandSize = 0;
- for (DexItem item : items) {
+ for (LirConstant item : items) {
operandSize += constantIndexSize(item);
}
for (int i = 0; i < values.size(); i++) {
@@ -368,7 +361,7 @@
operandSize += encodedValueIndexSize(encodedValueIndex);
}
writer.writeInstruction(opcode, operandSize);
- for (DexItem item : items) {
+ for (LirConstant item : items) {
writeConstantIndex(item);
}
for (int i = 0; i < values.size(); i++) {
@@ -587,10 +580,15 @@
LirOpcodes.PUTFIELD, Collections.singletonList(field), ImmutableList.of(object, value));
}
- public LirBuilder<V, EV> addInvokeInstruction(int opcode, DexItem method, List<V> arguments) {
+ public LirBuilder<V, EV> addInvokeInstruction(int opcode, DexMethod method, List<V> arguments) {
return addInstructionTemplate(opcode, Collections.singletonList(method), arguments);
}
+ public LirBuilder<V, EV> addInvokeInstruction(
+ int opcode, DexCallSite callSite, List<V> arguments) {
+ return addInstructionTemplate(opcode, Collections.singletonList(callSite), arguments);
+ }
+
public LirBuilder<V, EV> addInvokeDirect(
DexMethod method, List<V> arguments, boolean isInterface) {
int opcode = isInterface ? LirOpcodes.INVOKEDIRECT_ITF : LirOpcodes.INVOKEDIRECT;
@@ -788,7 +786,7 @@
public LirCode<EV> build() {
assert metadata != null;
int constantsCount = constants.size();
- DexItem[] constantTable = new DexItem[constantsCount];
+ LirConstant[] constantTable = new LirConstant[constantsCount];
constants.forEach((item, index) -> constantTable[index] = item);
DebugLocalInfoTable<EV> debugTable =
debugLocals.isEmpty() ? null : new DebugLocalInfoTable<>(debugLocals, debugLocalEnds);
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java
index a55ab1d..00930a8 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexType;
@@ -145,7 +144,7 @@
private final IRMetadata irMetadata;
/** Constant pool of items. */
- private final DexItem[] constants;
+ private final LirConstant[] constants;
private final PositionEntry[] positionTable;
@@ -175,7 +174,7 @@
/** Should be constructed using {@link LirBuilder}. */
LirCode(
IRMetadata irMetadata,
- DexItem[] constants,
+ LirConstant[] constants,
PositionEntry[] positions,
int argumentCount,
byte[] instructions,
@@ -241,11 +240,11 @@
return irMetadata;
}
- public DexItem getConstantItem(int index) {
+ public LirConstant getConstantItem(int index) {
return constants[index];
}
- public DexItem[] getConstantPool() {
+ public LirConstant[] getConstantPool() {
return constants;
}
@@ -463,8 +462,8 @@
}
}
- public LirCode<EV> newCodeWithRewrittenConstantPool(Function<DexItem, DexItem> rewriter) {
- DexItem[] rewrittenConstants = ArrayUtils.map(constants, rewriter, new DexItem[0]);
+ public LirCode<EV> newCodeWithRewrittenConstantPool(Function<LirConstant, LirConstant> rewriter) {
+ LirConstant[] rewrittenConstants = ArrayUtils.map(constants, rewriter, new LirConstant[0]);
if (constants == rewrittenConstants) {
return this;
}
@@ -497,7 +496,7 @@
}
public LirCode<EV> copyWithNewConstantsAndInstructions(
- IRMetadata irMetadata, DexItem[] constants, byte[] instructions) {
+ IRMetadata irMetadata, LirConstant[] constants, byte[] instructions) {
return new LirCode<>(
irMetadata,
constants,
diff --git a/src/main/java/com/android/tools/r8/lightir/LirConstant.java b/src/main/java/com/android/tools/r8/lightir/LirConstant.java
new file mode 100644
index 0000000..6c3dc4d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/lightir/LirConstant.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.lightir;
+
+/** Interface for items that can be put in the LIR constant pool. */
+public interface LirConstant {}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
index 18125bd..cdd50cc 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -8,7 +8,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexProto;
@@ -523,7 +522,7 @@
onInstruction();
}
- private DexItem getConstantItem(int index) {
+ private LirConstant getConstantItem(int index) {
return code.getConstantItem(index);
}
@@ -538,7 +537,7 @@
}
case LirOpcodes.LDC:
{
- DexItem item = getConstantItem(view.getNextConstantOperand());
+ LirConstant item = getConstantItem(view.getNextConstantOperand());
if (item instanceof DexString) {
onConstString((DexString) item);
return;
@@ -559,7 +558,7 @@
}
case LirOpcodes.CONSTCLASS_IGNORE_COMPAT:
{
- DexItem item = getConstantItem(view.getNextConstantOperand());
+ LirConstant item = getConstantItem(view.getNextConstantOperand());
onConstClass((DexType) item, true);
return;
}
@@ -1070,7 +1069,7 @@
}
case LirOpcodes.NEW:
{
- DexItem item = getConstantItem(view.getNextConstantOperand());
+ LirConstant item = getConstantItem(view.getNextConstantOperand());
if (item instanceof DexType) {
onNewInstance((DexType) item);
return;
diff --git a/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java b/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java
index 9bf133a..d093823 100644
--- a/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java
+++ b/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java
@@ -7,7 +7,6 @@
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
@@ -35,7 +34,7 @@
private final LensCodeRewriterUtils helper;
private int numberOfInvokeTypeChanges = 0;
- private Map<DexItem, DexItem> constantPoolMapping = null;
+ private Map<LirConstant, LirConstant> constantPoolMapping = null;
public SimpleLensLirRewriter(
LirCode<EV> code,
@@ -85,7 +84,7 @@
}
}
- private void addRewrittenMapping(DexItem item, DexItem rewrittenItem) {
+ private void addRewrittenMapping(LirConstant item, LirConstant rewrittenItem) {
if (item == rewrittenItem) {
return;
}
@@ -95,7 +94,7 @@
// Avoid using initial capacity larger than the number of actual constants.
Math.min(getCode().getConstantPool().length, 32));
}
- DexItem old = constantPoolMapping.put(item, rewrittenItem);
+ LirConstant old = constantPoolMapping.put(item, rewrittenItem);
if (old != null && old != rewrittenItem) {
throw new Unreachable(
"Unexpected rewriting of item: "
@@ -152,7 +151,7 @@
// First pass scans just the constant pool to see if any types change or if there are any
// fields/methods that need to be examined.
boolean hasPotentialRewrittenMethod = false;
- for (DexItem constant : code.getConstantPool()) {
+ for (LirConstant constant : code.getConstantPool()) {
if (constant instanceof DexType) {
onTypeReference((DexType) constant);
} else if (constant instanceof DexField) {
@@ -191,9 +190,9 @@
// Build a small map from method refs to index in case the type-dependent methods are already
// in the constant pool.
Reference2IntMap<DexMethod> methodIndices = new Reference2IntOpenHashMap<>();
- DexItem[] rewrittenConstants = code.getConstantPool();
- for (int i = 0, dexItemsLength = rewrittenConstants.length; i < dexItemsLength; i++) {
- DexItem constant = rewrittenConstants[i];
+ LirConstant[] rewrittenConstants = code.getConstantPool();
+ for (int i = 0, length = rewrittenConstants.length; i < length; i++) {
+ LirConstant constant = rewrittenConstants[i];
if (constant instanceof DexMethod) {
methodIndices.put((DexMethod) constant, i);
}
@@ -202,7 +201,7 @@
IRMetadata irMetadata = code.getMetadataForIR();
ByteArrayWriter byteWriter = new ByteArrayWriter();
LirWriter lirWriter = new LirWriter(byteWriter);
- List<DexItem> methodsToAppend = new ArrayList<>(numberOfInvokeTypeChanges);
+ List<LirConstant> methodsToAppend = new ArrayList<>(numberOfInvokeTypeChanges);
for (LirInstructionView view : code) {
int opcode = view.getOpcode();
// Instructions that do not have an invoke-type change are just mapped via identity.