Merge "Use a pool for DexDebugEvents."
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index cd92f2d..d273090 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -109,7 +109,8 @@
if (!options.skipDebugInfoOpt && (application.getProguardMap() != null)) {
try {
timing.begin("DebugStripper");
- DebugStripper stripper = new DebugStripper(application.getProguardMap(), options);
+ DebugStripper stripper =
+ new DebugStripper(application.getProguardMap(), options, appInfo.dexItemFactory);
application.classes().forEach(stripper::processClass);
} finally {
timing.end();
diff --git a/src/main/java/com/android/tools/r8/dex/DexFileReader.java b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
index 627d106..02b0ce8 100644
--- a/src/main/java/com/android/tools/r8/dex/DexFileReader.java
+++ b/src/main/java/com/android/tools/r8/dex/DexFileReader.java
@@ -24,7 +24,6 @@
import com.android.tools.r8.graph.DexCode.TryHandler;
import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
import com.android.tools.r8.graph.DexDebugEvent;
-import com.android.tools.r8.graph.DexDebugEvent.SetEpilogueBegin;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexEncodedArray;
@@ -446,10 +445,10 @@
for (int head = file.getUbyte(); head != Constants.DBG_END_SEQUENCE; head = file.getUbyte()) {
switch (head) {
case Constants.DBG_ADVANCE_PC:
- events.add(new DexDebugEvent.AdvancePC(file.getUleb128()));
+ events.add(dexItemFactory.createAdvancePC(file.getUleb128()));
break;
case Constants.DBG_ADVANCE_LINE:
- events.add(new DexDebugEvent.AdvanceLine(file.getSleb128()));
+ events.add(dexItemFactory.createAdvanceLine(file.getSleb128()));
break;
case Constants.DBG_START_LOCAL: {
int registerNum = file.getUleb128();
@@ -475,30 +474,30 @@
break;
}
case Constants.DBG_END_LOCAL: {
- events.add(new DexDebugEvent.EndLocal(file.getUleb128()));
+ events.add(dexItemFactory.createEndLocal(file.getUleb128()));
break;
}
case Constants.DBG_RESTART_LOCAL: {
- events.add(new DexDebugEvent.RestartLocal(file.getUleb128()));
+ events.add(dexItemFactory.createRestartLocal(file.getUleb128()));
break;
}
case Constants.DBG_SET_PROLOGUE_END: {
- events.add(new DexDebugEvent.SetPrologueEnd());
+ events.add(dexItemFactory.createSetPrologueEnd());
break;
}
case Constants.DBG_SET_EPILOGUE_BEGIN: {
- events.add(new SetEpilogueBegin());
+ events.add(dexItemFactory.createSetEpilogueBegin());
break;
}
case Constants.DBG_SET_FILE: {
int nameIdx = file.getUleb128p1();
DexString sourceFile = nameIdx == NO_INDEX ? null : indexedItems.getString(nameIdx);
- events.add(new DexDebugEvent.SetFile(sourceFile));
+ events.add(dexItemFactory.createSetFile(sourceFile));
break;
}
default: {
assert head >= 0x0a && head <= 0xff;
- events.add(new DexDebugEvent.Default(head));
+ events.add(dexItemFactory.createDefault(head));
}
}
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index b8bab7e..572e655 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -41,7 +41,7 @@
writer.putUleb128(delta);
}
- public AdvancePC(int delta) {
+ AdvancePC(int delta) {
this.delta = delta;
}
@@ -68,7 +68,7 @@
public static class SetPrologueEnd extends DexDebugEvent {
- public SetPrologueEnd() {
+ SetPrologueEnd() {
}
public void writeOn(DebugBytecodeWriter writer, ObjectToOffsetMapping mapping) {
@@ -96,7 +96,7 @@
public static class SetEpilogueBegin extends DexDebugEvent {
- public SetEpilogueBegin() {
+ SetEpilogueBegin() {
}
public void writeOn(DebugBytecodeWriter writer, ObjectToOffsetMapping mapping) {
@@ -124,7 +124,7 @@
final int delta;
- public AdvanceLine(int delta) {
+ AdvanceLine(int delta) {
this.delta = delta;
}
@@ -233,7 +233,7 @@
final int registerNum;
- public EndLocal(int registerNum) {
+ EndLocal(int registerNum) {
this.registerNum = registerNum;
}
@@ -265,7 +265,7 @@
final int registerNum;
- public RestartLocal(int registerNum) {
+ RestartLocal(int registerNum) {
this.registerNum = registerNum;
}
@@ -297,7 +297,7 @@
final DexString fileName;
- public SetFile(DexString fileName) {
+ SetFile(DexString fileName) {
this.fileName = fileName;
}
@@ -334,7 +334,7 @@
final int value;
- public Default(int value) {
+ Default(int value) {
assert (value >= Constants.DBG_FIRST_SPECIAL) && (value <= Constants.DBG_LAST_SPECIAL);
this.value = value;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index 5295c55..26349c2 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -40,6 +40,8 @@
private final DexMethod method;
+ private final DexItemFactory dexItemFactory;
+
// Previous and current position info to delay emitting position changes.
private final PositionState previous;
private final PositionState current;
@@ -59,8 +61,9 @@
private int startLine = NO_LINE_INFO;
- public DexDebugEventBuilder(DexMethod method) {
+ public DexDebugEventBuilder(DexMethod method, DexItemFactory dexItemFactory) {
this.method = method;
+ this.dexItemFactory = dexItemFactory;
arguments = new ArrayList<>(method.proto.parameters.values.length);
current = new PositionState();
previous = new PositionState();
@@ -147,16 +150,16 @@
assert pcDelta >= 0;
if (current.file != previous.file) {
assert current.file == null || !current.file.equals(previous.file);
- events.add(new SetFile(current.file));
+ events.add(dexItemFactory.createSetFile(current.file));
}
if (lineDelta < Constants.DBG_LINE_BASE
|| lineDelta - Constants.DBG_LINE_BASE >= Constants.DBG_LINE_RANGE) {
- events.add(new AdvanceLine(lineDelta));
+ events.add(dexItemFactory.createAdvanceLine(lineDelta));
// TODO(herhut): To be super clever, encode only the part that is above limit.
lineDelta = 0;
}
if (pcDelta >= Constants.DBG_ADDRESS_RANGE) {
- events.add(new AdvancePC(pcDelta));
+ events.add(dexItemFactory.createAdvancePC(pcDelta));
pcDelta = 0;
}
// TODO(herhut): Maybe only write this one if needed (would differ from DEX).
@@ -164,7 +167,7 @@
0x0a + (lineDelta - Constants.DBG_LINE_BASE) + Constants.DBG_LINE_RANGE * pcDelta;
assert specialOpcode >= 0x0a;
assert specialOpcode <= 0xff;
- events.add(new Default(specialOpcode));
+ events.add(dexItemFactory.createDefault(specialOpcode));
previous.pc = current.pc;
previous.line = current.line;
previous.file = current.file;
@@ -178,7 +181,7 @@
SortedSet<Integer> positionRegisters = new TreeSet<>(current.locals.keySet());
for (Integer register : currentRegisters) {
if (!positionRegisters.contains(register)) {
- events.add(new EndLocal(register));
+ events.add(dexItemFactory.createEndLocal(register));
openLocals.put(register, null);
}
}
@@ -188,7 +191,7 @@
if (currentLocal != positionLocal) {
openLocals.put(register, positionLocal);
if (currentLocal == null && lastKnownLocals.get(register) == positionLocal) {
- events.add(new RestartLocal(register));
+ events.add(dexItemFactory.createRestartLocal(register));
} else {
events.add(new StartLocal(register, positionLocal));
lastKnownLocals.put(register, positionLocal);
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 5ea8edd..8b86ca8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -121,15 +121,17 @@
: code.asDexCode().buildIR(this, valueNumberGenerator, options);
}
- public void setCode(IRCode ir, RegisterAllocator registerAllocator) {
- final DexBuilder builder = new DexBuilder(ir, registerAllocator);
+ public void setCode(
+ IRCode ir, RegisterAllocator registerAllocator, DexItemFactory dexItemFactory) {
+ final DexBuilder builder = new DexBuilder(ir, registerAllocator, dexItemFactory);
code = builder.build(method.proto.parameters.values.length);
}
// Replaces the dex code in the method by setting code to result of compiling the IR.
public void setCode(IRCode ir, RegisterAllocator registerAllocator,
- DexString firstJumboString) {
- final DexBuilder builder = new DexBuilder(ir, registerAllocator, firstJumboString);
+ DexItemFactory dexItemFactory, DexString firstJumboString) {
+ final DexBuilder builder =
+ new DexBuilder(ir, registerAllocator, dexItemFactory, firstJumboString);
code = builder.build(method.proto.parameters.values.length);
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index ce974ce..5bff70d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -4,9 +4,19 @@
package com.android.tools.r8.graph;
import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.DexDebugEvent.AdvanceLine;
+import com.android.tools.r8.graph.DexDebugEvent.AdvancePC;
+import com.android.tools.r8.graph.DexDebugEvent.Default;
+import com.android.tools.r8.graph.DexDebugEvent.EndLocal;
+import com.android.tools.r8.graph.DexDebugEvent.RestartLocal;
+import com.android.tools.r8.graph.DexDebugEvent.SetEpilogueBegin;
+import com.android.tools.r8.graph.DexDebugEvent.SetFile;
+import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
import com.android.tools.r8.naming.NamingLens;
import com.google.common.collect.ImmutableSet;
+import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -25,6 +35,16 @@
private final Map<DexCallSite, DexCallSite> callSites = new HashMap<>();
private final Map<DexMethodHandle, DexMethodHandle> methodHandles = new HashMap<>();
+ // DexDebugEvent Canonicalization.
+ private final Int2ObjectMap<AdvanceLine> advanceLines = new Int2ObjectOpenHashMap<>();
+ private final Int2ObjectMap<AdvancePC> advancePCs = new Int2ObjectOpenHashMap<>();
+ private final Int2ObjectMap<Default> defaults = new Int2ObjectOpenHashMap<>();
+ private final Int2ObjectMap<EndLocal> endLocals = new Int2ObjectOpenHashMap<>();
+ private final Int2ObjectMap<RestartLocal> restartLocals = new Int2ObjectOpenHashMap<>();
+ private final SetEpilogueBegin setEpilogueBegin = new SetEpilogueBegin();
+ private final SetPrologueEnd setPrologueEnd = new SetPrologueEnd();
+ private final Map<DexString, SetFile> setFiles = new HashMap<>();
+
boolean sorted = false;
public static final DexType catchAllType = new DexType(new DexString("CATCH_ALL"));
@@ -306,6 +326,80 @@
return createMethod(clazz, proto, name);
}
+ public AdvanceLine createAdvanceLine(int delta) {
+ synchronized (advanceLines) {
+ AdvanceLine result = advanceLines.get(delta);
+ if (result == null) {
+ result = new AdvanceLine(delta);
+ advanceLines.put(delta, result);
+ }
+ return result;
+ }
+ }
+
+ public AdvancePC createAdvancePC(int delta) {
+ synchronized (advancePCs) {
+ AdvancePC result = advancePCs.get(delta);
+ if (result == null) {
+ result = new AdvancePC(delta);
+ advancePCs.put(delta, result);
+ }
+ return result;
+ }
+ }
+
+ public Default createDefault(int value) {
+ synchronized (defaults) {
+ Default result = defaults.get(value);
+ if (result == null) {
+ result = new Default(value);
+ defaults.put(value, result);
+ }
+ return result;
+ }
+ }
+
+ public EndLocal createEndLocal(int registerNum) {
+ synchronized (endLocals) {
+ EndLocal result = endLocals.get(registerNum);
+ if (result == null) {
+ result = new EndLocal(registerNum);
+ endLocals.put(registerNum, result);
+ }
+ return result;
+ }
+ }
+
+ public RestartLocal createRestartLocal(int registerNum) {
+ synchronized (restartLocals) {
+ RestartLocal result = restartLocals.get(registerNum);
+ if (result == null) {
+ result = new RestartLocal(registerNum);
+ restartLocals.put(registerNum, result);
+ }
+ return result;
+ }
+ }
+
+ public SetEpilogueBegin createSetEpilogueBegin() {
+ return setEpilogueBegin;
+ }
+
+ public SetPrologueEnd createSetPrologueEnd() {
+ return setPrologueEnd;
+ }
+
+ public SetFile createSetFile(DexString fileName) {
+ synchronized (setFiles) {
+ SetFile result = setFiles.get(fileName);
+ if (result == null) {
+ result = new SetFile(fileName);
+ setFiles.put(fileName, result);
+ }
+ return result;
+ }
+ }
+
public boolean isConstructor(DexMethod method) {
return method.name == constructorMethodName;
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
index 511f36b..4484aec 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexBuilder.java
@@ -74,6 +74,8 @@
// The register allocator providing register assignments for the code to build.
private final RegisterAllocator registerAllocator;
+ private final DexItemFactory dexItemFactory;
+
// List of information about switch payloads that have to be created at the end of the
// dex code.
private final List<SwitchPayloadInfo> switchPayloadInfos = new ArrayList<>();
@@ -105,19 +107,24 @@
BasicBlock nextBlock;
- public DexBuilder(IRCode ir, RegisterAllocator registerAllocator) {
+ public DexBuilder(IRCode ir, RegisterAllocator registerAllocator, DexItemFactory dexItemFactory) {
assert ir != null;
assert registerAllocator != null;
+ assert dexItemFactory != null;
this.ir = ir;
this.registerAllocator = registerAllocator;
+ this.dexItemFactory = dexItemFactory;
this.firstJumboString = null;
}
- public DexBuilder(IRCode ir, RegisterAllocator registerAllocator, DexString firstJumboString) {
+ public DexBuilder(IRCode ir, RegisterAllocator registerAllocator,
+ DexItemFactory dexItemFactory, DexString firstJumboString) {
assert ir != null;
assert registerAllocator != null;
+ assert dexItemFactory != null;
this.ir = ir;
this.registerAllocator = registerAllocator;
+ this.dexItemFactory = dexItemFactory;
this.firstJumboString = firstJumboString;
}
@@ -184,7 +191,8 @@
} while (!ifsNeedingRewrite.isEmpty());
// Build instructions.
- DexDebugEventBuilder debugEventBuilder = new DexDebugEventBuilder(ir.method.method);
+ DexDebugEventBuilder debugEventBuilder =
+ new DexDebugEventBuilder(ir.method.method, dexItemFactory);
List<Instruction> dexInstructions = new ArrayList<>(numberOfInstructions);
int instructionOffset = 0;
InstructionIterator instructionIterator = ir.instructionIterator();
@@ -1124,4 +1132,4 @@
this.dex = dex;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index d4b03e3..fa7ee4d 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -316,7 +316,7 @@
}
assert code.isConsistentSSA();
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
- method.setCode(code, registerAllocator);
+ method.setCode(code, registerAllocator, appInfo.dexItemFactory);
if (Log.ENABLED) {
Log.debug(getClass(), "Resulting dex code for %s:\n%s",
method.toSourceString(), logCode(options, method));
@@ -448,7 +448,7 @@
printMethod(code, "Optimized IR (SSA)");
// Perform register allocation.
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
- method.setCode(code, registerAllocator);
+ method.setCode(code, registerAllocator, appInfo.dexItemFactory);
updateHighestSortingStrings(method);
if (Log.ENABLED) {
Log.debug(getClass(), "Resulting dex code for %s:\n%s",
@@ -502,7 +502,7 @@
// Perform register allocation.
RegisterAllocator registerAllocator = performRegisterAllocation(code, method);
- method.setCode(code, registerAllocator, firstJumboString);
+ method.setCode(code, registerAllocator, appInfo.dexItemFactory, firstJumboString);
if (Log.ENABLED) {
Log.debug(getClass(), "Resulting dex code for %s:\n%s",
diff --git a/src/main/java/com/android/tools/r8/optimize/DebugStripper.java b/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
index 998bc8d..9d39d29 100644
--- a/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
+++ b/src/main/java/com/android/tools/r8/optimize/DebugStripper.java
@@ -9,6 +9,7 @@
import com.android.tools.r8.graph.DexDebugEventBuilder;
import com.android.tools.r8.graph.DexDebugInfo;
import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexString;
@@ -30,10 +31,13 @@
private final ClassNameMapper classNameMapper;
private final InternalOptions options;
+ private final DexItemFactory dexItemFactory;
- public DebugStripper(ClassNameMapper classNameMapper, InternalOptions options) {
+ public DebugStripper(
+ ClassNameMapper classNameMapper, InternalOptions options, DexItemFactory dexItemFactory) {
this.classNameMapper = classNameMapper;
this.options = options;
+ this.dexItemFactory = dexItemFactory;
}
private String descriptorToName(String descriptor) {
@@ -70,7 +74,7 @@
// Maintain line and address but only when entering or leaving a range of line numbers
// that pertains to a different method body.
Range currentRange = naming.topLevelRange;
- DexDebugEventBuilder builder = new DexDebugEventBuilder(method);
+ DexDebugEventBuilder builder = new DexDebugEventBuilder(method, dexItemFactory);
// Always start with a no-op bytecode to make sure that the start-line is manifested by
// the Dalvik VM and the event based processing in R8. This also avoids empty bytecode
// sequences.
diff --git a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
index 7840b6e..7c75610 100644
--- a/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
+++ b/src/test/java/com/android/tools/r8/maindexlist/MainDexListTests.java
@@ -283,7 +283,7 @@
code);
IRCode ir = code.buildIR(method, options);
RegisterAllocator allocator = new LinearScanRegisterAllocator(ir);
- method.setCode(ir, allocator);
+ method.setCode(ir, allocator, factory);
virtualMethods[i] = method;
}
builder.addClassPromise(