[LIR] Reallocate collections when building LirCode
This saves about half of the memory associated with the code objects.
Bug: b/225838009
Change-Id: I9ebb4130dd7637c12c62c7117a47adc47b17cae3
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index 45e136d..ea4f7b1 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -93,6 +93,7 @@
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
+import com.android.tools.r8.lightir.LirCode.TryCatchTable;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
@@ -172,12 +173,14 @@
// instruction denotes a new block.
if (currentBlock == null) {
currentBlock = getBasicBlock(nextInstructionIndex);
- CatchHandlers<Integer> handlers =
- code.getTryCatchTable().getHandlersForBlock(nextInstructionIndex);
- if (handlers != null) {
- List<BasicBlock> targets = ListUtils.map(handlers.getAllTargets(), this::getBasicBlock);
- targets.forEach(currentBlock::link);
- currentBlock.linkCatchSuccessors(handlers.getGuards(), targets);
+ TryCatchTable tryCatchTable = code.getTryCatchTable();
+ if (tryCatchTable != null) {
+ CatchHandlers<Integer> handlers = tryCatchTable.getHandlersForBlock(nextInstructionIndex);
+ if (handlers != null) {
+ List<BasicBlock> targets = ListUtils.map(handlers.getAllTargets(), this::getBasicBlock);
+ targets.forEach(currentBlock::link);
+ currentBlock.linkCatchSuccessors(handlers.getGuards(), targets);
+ }
}
} else {
assert !blocks.containsKey(nextInstructionIndex);
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 3a44a61..b88f1f7 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -181,6 +181,7 @@
private void setPositionIndex(int instructionIndex, Position position) {
assert positionTable.isEmpty()
|| ListUtils.last(positionTable).fromInstructionIndex < instructionIndex;
+ assert positionTable.isEmpty() || !ListUtils.last(positionTable).position.equals(position);
positionTable.add(new PositionEntry(instructionIndex, position));
}
@@ -707,6 +708,8 @@
constants.forEach((item, index) -> constantTable[index] = item);
DebugLocalInfoTable<EV> debugTable =
debugLocals.isEmpty() ? null : new DebugLocalInfoTable<>(debugLocals, debugLocalEnds);
+ TryCatchTable tryCatchTable =
+ tryCatchRanges.isEmpty() ? null : new TryCatchTable(tryCatchRanges);
return new LirCode<>(
metadata,
constantTable,
@@ -714,7 +717,7 @@
argumentCount,
byteWriter.toByteArray(),
instructionCount,
- new TryCatchTable(tryCatchRanges),
+ tryCatchTable,
debugTable,
strategy.getStrategyInfo());
}
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 1a07558..f1c04ec 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -10,7 +10,9 @@
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.IRMetadata;
import com.android.tools.r8.ir.code.Position;
+import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
+import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import java.util.Map;
import java.util.function.BiConsumer;
@@ -30,7 +32,9 @@
final Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers;
public TryCatchTable(Int2ReferenceMap<CatchHandlers<Integer>> tryCatchHandlers) {
- this.tryCatchHandlers = tryCatchHandlers;
+ assert !tryCatchHandlers.isEmpty();
+ // Copy the map to ensure it has not over-allocated the backing store.
+ this.tryCatchHandlers = new Int2ReferenceOpenHashMap<>(tryCatchHandlers);
}
public CatchHandlers<Integer> getHandlersForBlock(int blockIndex) {
@@ -46,8 +50,19 @@
Map<EV, DebugLocalInfo> valueToLocalMap, Int2ReferenceMap<int[]> instructionToEndUseMap) {
assert !valueToLocalMap.isEmpty();
// TODO(b/283049198): Debug ends may not be maintained so we can't assume they are non-empty.
- this.valueToLocalMap = valueToLocalMap;
- this.instructionToEndUseMap = instructionToEndUseMap;
+ // Copy the maps to ensure they have not over-allocated the backing store.
+ this.valueToLocalMap = ImmutableMap.copyOf(valueToLocalMap);
+ this.instructionToEndUseMap =
+ instructionToEndUseMap.isEmpty()
+ ? null
+ : new Int2ReferenceOpenHashMap<>(instructionToEndUseMap);
+ }
+
+ public int[] getEnds(int index) {
+ if (instructionToEndUseMap == null) {
+ return null;
+ }
+ return instructionToEndUseMap.get(index);
}
public void forEachLocalDefinition(BiConsumer<EV, DebugLocalInfo> fn) {
@@ -73,7 +88,7 @@
/** Cached value for the number of logical instructions (excludes arguments, includes phis). */
private final int instructionCount;
- /** Table of try-catch handlers for each basic block. */
+ /** Table of try-catch handlers for each basic block (if present). */
private final TryCatchTable tryCatchTable;
/** Table of debug local information for each SSA value (if present). */
@@ -153,9 +168,7 @@
}
public int[] getDebugLocalEnds(int instructionValueIndex) {
- return debugLocalInfoTable == null
- ? null
- : debugLocalInfoTable.instructionToEndUseMap.get(instructionValueIndex);
+ return debugLocalInfoTable == null ? null : debugLocalInfoTable.getEnds(instructionValueIndex);
}
@Override