Add caching of ranges when constructing and parsing a map
Bug: b/240037206
Change-Id: Ia809b92aa769844afe16878fb730f0e3e59c315a
diff --git a/src/main/java/com/android/tools/r8/naming/PositionRangeAllocator.java b/src/main/java/com/android/tools/r8/naming/PositionRangeAllocator.java
new file mode 100644
index 0000000..957e660
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/naming/PositionRangeAllocator.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2022, 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.naming;
+
+public abstract class PositionRangeAllocator {
+
+ private static final int MAX_POSITION = 256;
+ private static final int MAX_DELTA = 1;
+
+ final Range[] cache = new Range[MAX_POSITION];
+
+ public Range get(int index) {
+ return (index >= 0 && index < MAX_POSITION) ? cache[index] : new Range(index);
+ }
+
+ public static CardinalPositionRangeAllocator createCardinalPositionRangeAllocator() {
+ return new CardinalPositionRangeAllocator();
+ }
+
+ public static NonCardinalPositionRangeAllocator createNonCardinalPositionRangeAllocator() {
+ return new NonCardinalPositionRangeAllocator();
+ }
+
+ public static class CardinalPositionRangeAllocator extends PositionRangeAllocator {
+
+ private CardinalPositionRangeAllocator() {
+ super();
+ for (int i = 0; i < MAX_POSITION; i++) {
+ cache[i] = new Range(i);
+ }
+ }
+ }
+
+ public static class NonCardinalPositionRangeFixedDeltaCache extends PositionRangeAllocator {
+
+ public NonCardinalPositionRangeFixedDeltaCache(int delta) {
+ super();
+ for (int i = 0; i < MAX_POSITION; i++) {
+ cache[i] = new Range(i, i + delta);
+ }
+ }
+ }
+
+ public static class NonCardinalPositionRangeAllocator extends PositionRangeAllocator {
+
+ private final NonCardinalPositionRangeFixedDeltaCache[] cache =
+ new NonCardinalPositionRangeFixedDeltaCache[MAX_DELTA + 1];
+
+ private NonCardinalPositionRangeAllocator() {
+ for (int i = 0; i <= MAX_DELTA; i++) {
+ cache[i] = new NonCardinalPositionRangeFixedDeltaCache(i);
+ }
+ }
+
+ public Range get(int from, int to) {
+ if (from >= MAX_POSITION) {
+ return new Range(from, to);
+ }
+ int thisDelta = to - from;
+ if (thisDelta < 0) {
+ return new Range(from, to);
+ }
+ if (thisDelta > MAX_DELTA) {
+ return new Range(from, to);
+ }
+ return cache[thisDelta].get(from);
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
index 6bde14bf..a3a3aa0 100644
--- a/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
+++ b/src/main/java/com/android/tools/r8/naming/ProguardMapReader.java
@@ -8,6 +8,8 @@
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.MemberNaming.Signature;
+import com.android.tools.r8.naming.PositionRangeAllocator.CardinalPositionRangeAllocator;
+import com.android.tools.r8.naming.PositionRangeAllocator.NonCardinalPositionRangeAllocator;
import com.android.tools.r8.naming.mappinginformation.MapVersionMappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.mappinginformation.MappingInformationDiagnostics;
@@ -68,6 +70,11 @@
private final boolean allowEmptyMappedRanges;
private final boolean allowExperimentalMapping;
+ private final CardinalPositionRangeAllocator cardinalRangeCache =
+ PositionRangeAllocator.createCardinalPositionRangeAllocator();
+ private final NonCardinalPositionRangeAllocator nonCardinalRangeCache =
+ PositionRangeAllocator.createNonCardinalPositionRangeAllocator();
+
@Override
public void close() throws IOException {
reader.close();
@@ -623,12 +630,12 @@
int from = parseNumber();
skipWhitespace();
if (peekChar(0) != ':') {
- return new Range(from);
+ return cardinalRangeCache.get(from);
}
expect(':');
skipWhitespace();
int to = parseNumber();
- return new Range(from, to);
+ return nonCardinalRangeCache.get(from, to);
}
private int parseNumber() {
diff --git a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
index 74b7b06..a0a2a74 100644
--- a/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
+++ b/src/main/java/com/android/tools/r8/utils/LineNumberOptimizer.java
@@ -57,6 +57,9 @@
import com.android.tools.r8.naming.MemberNaming;
import com.android.tools.r8.naming.MemberNaming.FieldSignature;
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.naming.PositionRangeAllocator;
+import com.android.tools.r8.naming.PositionRangeAllocator.CardinalPositionRangeAllocator;
+import com.android.tools.r8.naming.PositionRangeAllocator.NonCardinalPositionRangeAllocator;
import com.android.tools.r8.naming.ProguardMapSupplier;
import com.android.tools.r8.naming.ProguardMapSupplier.ProguardMapId;
import com.android.tools.r8.naming.Range;
@@ -509,6 +512,11 @@
? new NativePcSupport()
: new Pc2PcMappingSupport(appView.options().allowDiscardingResidualDebugInfo());
+ CardinalPositionRangeAllocator cardinalRangeCache =
+ PositionRangeAllocator.createCardinalPositionRangeAllocator();
+ NonCardinalPositionRangeAllocator nonCardinalRangeCache =
+ PositionRangeAllocator.createNonCardinalPositionRangeAllocator();
+
// Collect which files contain which classes that need to have their line numbers optimized.
for (DexProgramClass clazz : appView.appInfo().classes()) {
boolean isSyntheticClass = appView.getSyntheticItems().isSyntheticClass(clazz);
@@ -718,10 +726,11 @@
&& definition.getCode().asDexCode().getDebugInfo()
== DexDebugInfoForSingleLineMethod.getInstance()) {
assert firstPosition.originalLine == lastPosition.originalLine;
- obfuscatedRange = new Range(0, MAX_LINE_NUMBER);
+ obfuscatedRange = nonCardinalRangeCache.get(0, MAX_LINE_NUMBER);
} else {
obfuscatedRange =
- new Range(firstPosition.obfuscatedLine, lastPosition.obfuscatedLine);
+ nonCardinalRangeCache.get(
+ firstPosition.obfuscatedLine, lastPosition.obfuscatedLine);
}
ClassNaming.Builder classNamingBuilder = onDemandClassNamingBuilder.computeIfAbsent();
MappedRange lastMappedRange =
@@ -732,9 +741,11 @@
firstPosition.method,
obfuscatedName,
obfuscatedRange,
- new Range(firstPosition.originalLine, lastPosition.originalLine),
+ nonCardinalRangeCache.get(
+ firstPosition.originalLine, lastPosition.originalLine),
firstPosition.caller,
- prunedInlinedClasses);
+ prunedInlinedClasses,
+ cardinalRangeCache);
for (MappingInformation info : methodMappingInfo) {
lastMappedRange.addMappingInformation(info, Unreachable::raise);
}
@@ -758,10 +769,12 @@
classNamingBuilder,
position.getMethod(),
obfuscatedName,
- new Range(placeHolderLineToBeFixed, placeHolderLineToBeFixed),
- new Range(position.getLine(), position.getLine()),
+ nonCardinalRangeCache.get(
+ placeHolderLineToBeFixed, placeHolderLineToBeFixed),
+ nonCardinalRangeCache.get(position.getLine(), position.getLine()),
position.getCallerPosition(),
- prunedInlinedClasses);
+ prunedInlinedClasses,
+ cardinalRangeCache);
});
outlinesToFix
.computeIfAbsent(
@@ -838,7 +851,8 @@
Range obfuscatedRange,
Range originalLine,
Position caller,
- Map<DexType, String> prunedInlineHolder) {
+ Map<DexType, String> prunedInlineHolder,
+ CardinalPositionRangeAllocator cardinalRangeCache) {
MappedRange lastMappedRange =
classNamingBuilder.addMappedRange(
obfuscatedRange,
@@ -859,7 +873,8 @@
classNamingBuilder.addMappedRange(
obfuscatedRange,
getOriginalMethodSignature.apply(caller.getMethod()),
- new Range(Math.max(caller.getLine(), 0)), // Prevent against "no-position".
+ cardinalRangeCache.get(
+ Math.max(caller.getLine(), 0)), // Prevent against "no-position".
obfuscatedName);
if (caller.isRemoveInnerFramesIfThrowingNpe()) {
lastMappedRange.addMappingInformation(