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()) {