Introduce list of nested Positions to preserve callers for inlining.
Bug:
Change-Id: I2b97da816ee900ea3652646557f4ed77af53b445
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index a05299c..083c865 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.conversion.DexSourceCode;
import com.android.tools.r8.ir.conversion.IRBuilder;
@@ -161,16 +162,18 @@
@Override
public IRCode buildIR(DexEncodedMethod encodedMethod, InternalOptions options)
throws ApiLevelException {
- DexSourceCode source = new DexSourceCode(this, encodedMethod);
+ DexSourceCode source = new DexSourceCode(this, encodedMethod, null);
IRBuilder builder = new IRBuilder(encodedMethod, source, options);
return builder.build();
}
public IRCode buildIR(
DexEncodedMethod encodedMethod,
- InternalOptions options, ValueNumberGenerator valueNumberGenerator)
+ InternalOptions options,
+ ValueNumberGenerator valueNumberGenerator,
+ Position callerPosition)
throws ApiLevelException {
- DexSourceCode source = new DexSourceCode(this, encodedMethod);
+ DexSourceCode source = new DexSourceCode(this, encodedMethod, callerPosition);
IRBuilder builder = new IRBuilder(encodedMethod, source, options, valueNumberGenerator);
return builder.build();
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
index f083794..908372a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntry.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.ImmutableMap;
import java.util.SortedSet;
@@ -16,19 +17,27 @@
public final boolean prologueEnd;
public final boolean epilogueBegin;
public final ImmutableMap<Integer, DebugLocalInfo> locals;
+ public final DexMethod method;
+ public final Position callerPosition;
- public DexDebugEntry(int address,
+ public DexDebugEntry(
+ int address,
int line,
DexString sourceFile,
boolean prologueEnd,
boolean epilogueBegin,
- ImmutableMap<Integer, DebugLocalInfo> locals) {
+ ImmutableMap<Integer, DebugLocalInfo> locals,
+ DexMethod method,
+ Position callerPosition) {
this.address = address;
this.line = line;
this.sourceFile = sourceFile;
this.prologueEnd = prologueEnd;
this.epilogueBegin = epilogueBegin;
this.locals = locals;
+ this.method = method;
+ assert method != null;
+ this.callerPosition = callerPosition;
}
@Override
@@ -46,6 +55,10 @@
if (sourceFile != null) {
builder.append(", file ").append(sourceFile);
}
+ if (callerPosition != null) {
+ builder.append(", method ").append(method);
+ builder.append(" <-(").append(callerPosition).append(")");
+ }
if (prologueEnd) {
builder.append(", prologue_end = true");
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
index c51e6e3..6ca2268 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueType;
import com.google.common.collect.ImmutableMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceArrayMap;
@@ -43,10 +44,13 @@
private int currentPc = 0;
private int currentLine;
private DexString currentFile = null;
+ private DexMethod currentMethod = null;
+ private Position currentCallerPosition = null;
private boolean prologueEnd = false;
private boolean epilogueBegin = false;
private final Map<Integer, LocalEntry> locals = new HashMap<>();
private final Int2ReferenceMap<DebugLocalInfo> arguments = new Int2ReferenceArrayMap<>();
+ private final DexMethod method;
// Delayed construction of an entry. Is finalized once locals information has been collected.
private DexDebugEntry pending = null;
@@ -57,11 +61,16 @@
// Resulting debug entries.
private List<DexDebugEntry> entries = new ArrayList<>();
- public DexDebugEntryBuilder(int startLine) {
+ public DexDebugEntryBuilder(int startLine, DexMethod method) {
currentLine = startLine;
+ this.method = method;
+ assert this.method != null;
+ currentMethod = method;
}
public DexDebugEntryBuilder(DexEncodedMethod method, DexItemFactory factory) {
+ this.method = method.method;
+ assert this.method != null;
DexCode code = method.getCode().asDexCode();
DexDebugInfo info = code.getDebugInfo();
int argumentRegister = code.registerSize - code.incomingRegisterSize;
@@ -81,6 +90,7 @@
argumentRegister += ValueType.fromDexType(types[i]).requiredRegisters();
}
currentLine = info.startLine;
+ currentMethod = this.method;
for (DexDebugEvent event : info.events) {
event.addToBuilder(this);
}
@@ -94,6 +104,13 @@
currentFile = file;
}
+ public void setInlineFrame(DexMethod callee, Position caller) {
+ assert (caller == null && callee == method)
+ || (caller != null && caller.getOutermostCaller().method == method);
+ currentMethod = callee;
+ currentCallerPosition = caller;
+ }
+
public void advancePC(int pcDelta) {
assert pcDelta >= 0;
currentPc += pcDelta;
@@ -133,15 +150,29 @@
assert pcDelta >= 0;
if (pending != null) {
// Local changes contribute to the pending position entry.
- entries.add(new DexDebugEntry(
- pending.address, pending.line, pending.sourceFile,
- pending.prologueEnd, pending.epilogueBegin,
- getLocals()));
+ entries.add(
+ new DexDebugEntry(
+ pending.address,
+ pending.line,
+ pending.sourceFile,
+ pending.prologueEnd,
+ pending.epilogueBegin,
+ getLocals(),
+ pending.method,
+ pending.callerPosition));
}
currentPc += pcDelta;
currentLine += lineDelta;
- pending = new DexDebugEntry(
- currentPc, currentLine, currentFile, prologueEnd, epilogueBegin, null);
+ pending =
+ new DexDebugEntry(
+ currentPc,
+ currentLine,
+ currentFile,
+ prologueEnd,
+ epilogueBegin,
+ null,
+ currentMethod,
+ currentCallerPosition);
prologueEnd = false;
epilogueBegin = false;
}
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 8d64cf4..724c10b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -7,6 +7,8 @@
import com.android.tools.r8.dex.DebugBytecodeWriter;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
+import com.android.tools.r8.ir.code.Position;
+import java.util.Objects;
abstract public class DexDebugEvent extends DexItem {
@@ -379,6 +381,47 @@
}
}
+ public static class SetInlineFrame extends DexDebugEvent {
+
+ final DexMethod callee;
+ final Position caller;
+
+ SetInlineFrame(DexMethod callee, Position caller) {
+ assert callee != null;
+ this.callee = callee;
+ this.caller = caller;
+ }
+
+ @Override
+ public void writeOn(DebugBytecodeWriter writer, ObjectToOffsetMapping mapping) {
+ // CallerPosition will not be written.
+ }
+
+ @Override
+ public void addToBuilder(DexDebugEntryBuilder builder) {
+ builder.setInlineFrame(callee, caller);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("SET_INLINE_FRAME %s %s", callee, caller);
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * callee.hashCode() + Objects.hashCode(caller);
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof SetInlineFrame)) {
+ return false;
+ }
+ SetInlineFrame o = (SetInlineFrame) other;
+ return callee == o.callee && Objects.equals(caller, o.caller);
+ }
+ }
+
public static class Default extends DexDebugEvent {
final int 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 c52d12c..1c71b9b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -210,7 +210,7 @@
}
assert emittedPosition.isNone();
startLine = position.line;
- emittedPosition = position;
+ emittedPosition = new Position(position.line, null, method.method, null);
}
debugPositionListBuilder.add(position.line, position.line);
emitAdvancementEvents(emittedPc, emittedPosition, pc, position, events, factory);
@@ -250,6 +250,10 @@
if (nextPosition.file != previousPosition.file) {
events.add(factory.createSetFile(nextPosition.file));
}
+ if (nextPosition.method != previousPosition.method
+ || nextPosition.callerPosition != previousPosition.callerPosition) {
+ events.add(factory.createSetInlineFrame(nextPosition.method, nextPosition.callerPosition));
+ }
if (lineDelta < Constants.DBG_LINE_BASE
|| lineDelta - Constants.DBG_LINE_BASE >= Constants.DBG_LINE_RANGE) {
events.add(factory.createAdvanceLine(lineDelta));
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
index ae669a2..99d1227 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -24,8 +24,8 @@
hashCode();
}
- public List<DexDebugEntry> computeEntries() {
- DexDebugEntryBuilder builder = new DexDebugEntryBuilder(startLine);
+ public List<DexDebugEntry> computeEntries(DexMethod method) {
+ DexDebugEntryBuilder builder = new DexDebugEntryBuilder(startLine, method);
for (DexDebugEvent event : events) {
event.addToBuilder(builder);
}
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 c8932be..8fbcbce 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -24,6 +24,7 @@
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Invoke;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -273,7 +274,15 @@
throws ApiLevelException {
return code == null
? null
- : code.asDexCode().buildIR(this, options, valueNumberGenerator);
+ : code.asDexCode().buildIR(this, options, valueNumberGenerator, null);
+ }
+
+ public IRCode buildIR(
+ InternalOptions options, ValueNumberGenerator valueNumberGenerator, Position callerPosition)
+ throws ApiLevelException {
+ return code == null
+ ? null
+ : code.asDexCode().buildIR(this, options, valueNumberGenerator, callerPosition);
}
public void setCode(Code code) {
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 a7d44ba..4ca9e94 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -12,8 +12,10 @@
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.SetInlineFrame;
import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.naming.NamingLens;
import com.google.common.collect.ImmutableSet;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@@ -47,6 +49,7 @@
private final SetEpilogueBegin setEpilogueBegin = new SetEpilogueBegin();
private final SetPrologueEnd setPrologueEnd = new SetPrologueEnd();
private final Map<DexString, SetFile> setFiles = new HashMap<>();
+ private final Map<SetInlineFrame, SetInlineFrame> setInlineFrames = new HashMap<>();
boolean sorted = false;
@@ -452,6 +455,13 @@
}
}
+ // TODO(tamaskenez) b/69024229 Measure if canonicalization is worth it.
+ public SetInlineFrame createSetInlineFrame(DexMethod callee, Position caller) {
+ synchronized (setInlineFrames) {
+ return setInlineFrames.computeIfAbsent(new SetInlineFrame(callee, caller), p -> p);
+ }
+ }
+
public boolean isConstructor(DexMethod method) {
return method.name == constructorMethodName;
}
diff --git a/src/main/java/com/android/tools/r8/graph/JarCode.java b/src/main/java/com/android/tools/r8/graph/JarCode.java
index 44bc529..ce2de41 100644
--- a/src/main/java/com/android/tools/r8/graph/JarCode.java
+++ b/src/main/java/com/android/tools/r8/graph/JarCode.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.Resource.Origin;
import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.JarSourceCode;
@@ -94,39 +95,49 @@
throws ApiLevelException {
triggerDelayedParsingIfNeccessary();
return options.debug
- ? internalBuildWithLocals(encodedMethod, options, null)
- : internalBuild(encodedMethod, options, null);
+ ? internalBuildWithLocals(encodedMethod, options, null, null)
+ : internalBuild(encodedMethod, options, null, null);
}
public IRCode buildIR(
- DexEncodedMethod encodedMethod, InternalOptions options, ValueNumberGenerator generator)
+ DexEncodedMethod encodedMethod,
+ InternalOptions options,
+ ValueNumberGenerator generator,
+ Position callerPosition)
throws ApiLevelException {
assert generator != null;
triggerDelayedParsingIfNeccessary();
return options.debug
- ? internalBuildWithLocals(encodedMethod, options, generator)
- : internalBuild(encodedMethod, options, generator);
+ ? internalBuildWithLocals(encodedMethod, options, generator, callerPosition)
+ : internalBuild(encodedMethod, options, generator, callerPosition);
}
private IRCode internalBuildWithLocals(
- DexEncodedMethod encodedMethod, InternalOptions options, ValueNumberGenerator generator)
+ DexEncodedMethod encodedMethod,
+ InternalOptions options,
+ ValueNumberGenerator generator,
+ Position callerPosition)
throws ApiLevelException {
try {
- return internalBuild(encodedMethod, options, generator);
+ return internalBuild(encodedMethod, options, generator, callerPosition);
} catch (InvalidDebugInfoException e) {
options.warningInvalidDebugInfo(encodedMethod, origin, e);
node.localVariables.clear();
- return internalBuild(encodedMethod, options, generator);
+ return internalBuild(encodedMethod, options, generator, callerPosition);
}
}
private IRCode internalBuild(
- DexEncodedMethod encodedMethod, InternalOptions options, ValueNumberGenerator generator)
+ DexEncodedMethod encodedMethod,
+ InternalOptions options,
+ ValueNumberGenerator generator,
+ Position callerPosition)
throws ApiLevelException {
if (!options.debug) {
node.localVariables.clear();
}
- JarSourceCode source = new JarSourceCode(clazz, node, application);
+ JarSourceCode source =
+ new JarSourceCode(clazz, node, application, encodedMethod.method, callerPosition);
IRBuilder builder =
(generator == null)
? new IRBuilder(encodedMethod, source, options)
diff --git a/src/main/java/com/android/tools/r8/ir/code/Position.java b/src/main/java/com/android/tools/r8/ir/code/Position.java
index 08298bb..9b6ac1b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Position.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Position.java
@@ -3,42 +3,75 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.code;
+import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexString;
import java.util.Objects;
public class Position {
- private static final Position NO_POSITION = new Position(-1, null, false);
+ private static final Position NO_POSITION = new Position(-1, null, false, null, null);
public final int line;
public final DexString file;
public final boolean synthetic;
- public Position(int line, DexString file) {
- this(line, file, false);
+ // If there's no inlining, callerPosition is null.
+ //
+ // For an inlined instruction its Position contains the inlinee's line and method and
+ // callerPosition is the position of the invoke instruction in the caller.
+
+ public final DexMethod method;
+ public final Position callerPosition;
+
+ public Position(int line, DexString file, DexMethod method, Position callerPosition) {
+ this(line, file, false, method, callerPosition);
assert line >= 0;
}
- private Position(int line, DexString file, boolean synthetic) {
+ private Position(
+ int line, DexString file, boolean synthetic, DexMethod method, Position callerPosition) {
this.line = line;
this.file = file;
this.synthetic = synthetic;
+ this.method = method;
+ this.callerPosition = callerPosition;
+ assert callerPosition == null || callerPosition.method != null;
+ assert line == -1 || method != null; // It's NO_POSITION or must have valid method.
}
- public static Position synthetic(int line) {
- return new Position(line, null, true);
+ public static Position synthetic(int line, DexMethod method, Position callerPosition) {
+ assert line >= 0;
+ return new Position(line, null, true, method, callerPosition);
}
public static Position none() {
return NO_POSITION;
}
+ // This factory method is used by the Inliner to create Positions when the caller has no valid
+ // positions. Since the callee still may have valid positions we need a non-null Position to set
+ // it as the caller of the inlined Positions.
+ public static Position noneWithMethod(DexMethod method, Position callerPosition) {
+ assert method != null;
+ return new Position(-1, null, false, method, callerPosition);
+ }
+
public boolean isNone() {
- return this == NO_POSITION;
+ return line == -1;
}
public boolean isSome() {
- return this != NO_POSITION;
+ return !isNone();
+ }
+
+ // Follow the linked list of callerPositions and return the last.
+ // Return this if no inliner.
+ public Position getOutermostCaller() {
+ Position lastPosition = this;
+ while (lastPosition.callerPosition != null) {
+ lastPosition = lastPosition.callerPosition;
+ }
+ return lastPosition;
}
@Override
@@ -48,7 +81,11 @@
}
if (other instanceof Position) {
Position o = (Position) other;
- return !isNone() && line == o.line && file == o.file;
+ return !isNone()
+ && line == o.line
+ && file == o.file
+ && method == o.method
+ && Objects.equals(callerPosition, o.callerPosition);
}
return false;
}
@@ -58,11 +95,12 @@
int result = line;
result = 31 * result + Objects.hashCode(file);
result = 31 * result + (synthetic ? 1 : 0);
+ result = 31 * result + Objects.hashCode(method);
+ result = 31 * result + Objects.hashCode(callerPosition);
return result;
}
- @Override
- public String toString() {
+ private String toString(boolean forceMethod) {
if (isNone()) {
return "--";
}
@@ -70,7 +108,18 @@
if (file != null) {
builder.append(file).append(":");
}
- builder.append(line);
+ if (method != null && (forceMethod || callerPosition != null)) {
+ builder.append("[").append(method).append("]");
+ }
+ builder.append("#").append(line);
+ if (callerPosition != null) {
+ builder.append(" <- ").append(callerPosition.toString(true));
+ }
return builder.toString();
}
+
+ @Override
+ public String toString() {
+ return toString(false);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
index e353a70..eb055f2 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/DexSourceCode.java
@@ -37,6 +37,7 @@
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.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.MethodAccessFlags;
@@ -73,17 +74,28 @@
private final List<ValueType> argumentTypes;
private List<DexDebugEntry> debugEntries = null;
+ private Position callerPosition; // In case of inlining the position of the invoke in the caller.
+ private final DexMethod method;
- public DexSourceCode(DexCode code, DexEncodedMethod method) {
+ public DexSourceCode(DexCode code, DexEncodedMethod method, Position callerPosition) {
this.code = code;
this.proto = method.method.proto;
this.accessFlags = method.accessFlags;
argumentTypes = computeArgumentTypes();
DexDebugInfo info = code.getDebugInfo();
if (info != null) {
- debugEntries = info.computeEntries();
+ debugEntries = info.computeEntries(method.method);
canonicalPositions = new HashMap<>(debugEntries.size());
}
+ if (info != null && callerPosition != null) {
+ // Canonicalize callerPosition
+ this.callerPosition = callerPosition;
+ canonicalPositions.put(callerPosition, callerPosition);
+ } else {
+ this.callerPosition = null;
+ }
+
+ this.method = method.method;
}
@Override
@@ -217,15 +229,44 @@
if (current == null) {
currentPosition = Position.none();
} else {
- currentPosition = getCanonicalPosition(current);
+ currentPosition = getCanonicalPositionAppendCaller(current);
if (current.address == offset) {
builder.addDebugPosition(currentPosition);
}
}
}
- private Position getCanonicalPosition(DexDebugEntry entry) {
- return canonicalPositions.computeIfAbsent(new Position(entry.line, entry.sourceFile), p -> p);
+ private Position getCanonicalPosition(Position position) {
+ Position canonical = canonicalPositions.putIfAbsent(position, position);
+ return canonical != null ? canonical : position;
+ }
+
+ private Position canonicalizeCallerPosition(Position caller) {
+ if (caller == null) {
+ return callerPosition;
+ }
+ if (caller.callerPosition == null && callerPosition == null) {
+ return getCanonicalPosition(caller);
+ }
+ Position callerOfCaller = canonicalizeCallerPosition(caller.callerPosition);
+ return getCanonicalPosition(
+ caller.isNone()
+ ? Position.noneWithMethod(caller.method, callerOfCaller)
+ : new Position(caller.line, caller.file, caller.method, callerOfCaller));
+ }
+
+ private Position getCanonicalPositionAppendCaller(DexDebugEntry entry) {
+ // If this instruction has already been inlined then this.method must be the outermost caller.
+ assert (entry.callerPosition == null && entry.method == method)
+ || (entry.callerPosition != null
+ && entry.callerPosition.getOutermostCaller().method == method);
+
+ return getCanonicalPosition(
+ new Position(
+ entry.line,
+ entry.sourceFile,
+ entry.method,
+ canonicalizeCallerPosition(entry.callerPosition)));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 04a2685..700d9da 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -181,12 +181,22 @@
// Cooked position to indicate positions in synthesized code (ie, for synchronization).
private Position syntheticPosition = null;
- public JarSourceCode(DexType clazz, MethodNode node, JarApplicationReader application) {
+ private final DexMethod method;
+ private final Position callerPosition;
+
+ public JarSourceCode(
+ DexType clazz,
+ MethodNode node,
+ JarApplicationReader application,
+ DexMethod method,
+ Position callerPosition) {
assert node != null;
assert node.desc != null;
this.node = node;
this.application = application;
+ this.method = method;
this.clazz = clazz;
+ this.callerPosition = callerPosition;
parameterTypes = Arrays.asList(Type.getArgumentTypes(node.desc));
state = new JarState(node.maxLocals, node.localVariables, this, application);
AbstractInsnNode first = node.instructions.getFirst();
@@ -2840,7 +2850,8 @@
}
private Position getCanonicalPosition(int line) {
- return canonicalPositions.computeIfAbsent(line, l -> new Position(l, null));
+ return canonicalPositions.computeIfAbsent(
+ line, l -> new Position(l, null, method, callerPosition));
}
// If we need to emit a synthetic position for exceptional monitor exits, we try to cook up a
@@ -2862,8 +2873,8 @@
}
syntheticPosition =
(min == Integer.MAX_VALUE)
- ? Position.none()
- : Position.synthetic(min < max ? min - 1 : min);
+ ? Position.noneWithMethod(method, callerPosition)
+ : Position.synthetic(min < max ? min - 1 : min, method, callerPosition);
}
return syntheticPosition;
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 3c7fe40..5386163 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1986,7 +1986,7 @@
InstructionListIterator iterator = block.listIterator();
// Attach some synthetic position to all inserted code.
- Position position = Position.synthetic(1);
+ Position position = Position.synthetic(1, method.method, null);
iterator.setInsertionPosition(position);
// Split arguments into their own block.
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index b15d254..cd51b25 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -21,6 +21,7 @@
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.Invoke;
import com.android.tools.r8.ir.code.InvokeMethod;
+import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.conversion.CallSiteInformation;
@@ -231,18 +232,23 @@
return reason != Reason.SIMPLE;
}
- public IRCode buildIR(ValueNumberGenerator generator, AppInfoWithSubtyping appInfo,
- GraphLense graphLense, InternalOptions options) throws ApiLevelException {
+ public IRCode buildIR(
+ ValueNumberGenerator generator,
+ AppInfoWithSubtyping appInfo,
+ GraphLense graphLense,
+ InternalOptions options,
+ Position callerPosition)
+ throws ApiLevelException {
if (target.isProcessed()) {
assert target.getCode().isDexCode();
- return target.buildIR(options, generator);
+ return target.buildIR(options, generator, callerPosition);
} else {
// Build the IR for a yet not processed method, and perform minimal IR processing.
IRCode code;
if (target.getCode().isJarCode()) {
- code = target.getCode().asJarCode().buildIR(target, options, generator);
+ code = target.getCode().asJarCode().buildIR(target, options, generator, callerPosition);
} else {
- code = target.getCode().asDexCode().buildIR(target, options, generator);
+ code = target.getCode().asDexCode().buildIR(target, options, generator, callerPosition);
}
new LensCodeRewriter(graphLense, appInfo).rewrite(code, target);
return code;
@@ -359,8 +365,16 @@
InlineAction result = invoke.computeInlining(oracle);
if (result != null) {
DexEncodedMethod target = result.target;
- IRCode inlinee = result
- .buildIR(code.valueNumberGenerator, appInfo, graphLense, options);
+ Position invokePosition = invoke.getPosition();
+ if (invokePosition.method == null) {
+ assert invokePosition.isNone();
+ invokePosition = Position.noneWithMethod(method.method, null);
+ }
+ assert invokePosition.getOutermostCaller().method == method.method;
+
+ IRCode inlinee =
+ result.buildIR(
+ code.valueNumberGenerator, appInfo, graphLense, options, invokePosition);
if (inlinee != null) {
// TODO(64432527): Get rid of this additional check by improved inlining.
if (block.hasCatchHandlers() && inlinee.computeNormalExitBlocks().isEmpty()) {