JVM: map synthetic line numbers through the SMAP

This is necessary so that IDEA does not ignore the line number.
This commit is contained in:
pyos
2020-04-24 11:47:13 +02:00
committed by max-kammerer
parent d17a18f96d
commit 25e1fb8502
10 changed files with 36 additions and 56 deletions
@@ -278,7 +278,7 @@ class MethodInliner(
visitInsn(Opcodes.NOP)
}
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info)
inlineOnlySmapSkipper?.onInlineLambdaStart(remappingMethodAdapter, info, sourceMapper.parent)
addInlineMarker(this, true)
val lambdaParameters = info.addAllParameters(nodeRemapper)
@@ -62,19 +62,22 @@ class SourceMapCopier(val parent: SourceMapper, private val smap: SMAP, val call
private var lastVisitedRange: RangeMapping? = null
fun mapLineNumber(lineNumber: Int): Int {
if (lineNumber in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) {
return lineNumber
}
val mappedLineNumber = visitedLines.get(lineNumber)
if (mappedLineNumber > 0) {
return mappedLineNumber
}
val range = lastVisitedRange?.takeIf { lineNumber in it } ?: smap.findRange(lineNumber) ?: return -1
val newLineNumber = parent.mapLineNumber(range.mapDestToSource(lineNumber), callSite ?: range.callSite)
val newLineNumber = if (lineNumber in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) {
// This is a compatibility hack for reading bytecode generated by 1.4-M1. Once the bootstrap
// compiler is updated to a newer version, it can be removed (as newer bytecode explicitly lists
// this range in the SMAP).
parent.mapSyntheticLineNumber(lineNumber)
} else {
val range = lastVisitedRange?.takeIf { lineNumber in it } ?: smap.findRange(lineNumber) ?: return -1
lastVisitedRange = range
parent.mapLineNumber(range.mapDestToSource(lineNumber), callSite ?: range.callSite)
}
visitedLines.put(lineNumber, newLineNumber)
lastVisitedRange = range
return newLineNumber
}
}
@@ -107,6 +110,11 @@ class SourceMapper(val sourceInfo: SourceInfo?) {
maxUsedValue = max(maxUsedValue, mappedLineIndex)
return mappedLineIndex
}
fun mapSyntheticLineNumber(id: Int): Int {
assert(id in JvmAbi.SYNTHETIC_MARKER_LINE_NUMBERS) { "$id is not a synthetic line number" }
return mapLineNumber(SourcePosition(id, "fake.kt", "kotlin/jvm/internal/FakeKt"), null)
}
}
class SMAP(val fileMappings: List<FileMapping>) {
@@ -541,7 +541,7 @@ internal fun isThis0(name: String): Boolean = AsmUtil.CAPTURED_THIS_FIELD == nam
class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
private val callLineNumber = codegen.lastLineNumber
fun onInlineLambdaStart(mv: MethodVisitor, info: LambdaInfo) {
fun onInlineLambdaStart(mv: MethodVisitor, info: LambdaInfo, smap: SourceMapper) {
val firstLine = info.node.node.instructions.asSequence().mapNotNull { it as? LineNumberNode }.firstOrNull()?.line ?: -1
if (callLineNumber >= 0 && firstLine == callLineNumber) {
// We want the debugger to be able to break both on the inline call itself, plus on each
@@ -552,7 +552,7 @@ class InlineOnlySmapSkipper(codegen: BaseExpressionCodegen) {
// number that is remapped by the SMAP to a line that does not exist.
val label = Label()
mv.visitLabel(label)
mv.visitLineNumber(JvmAbi.LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER, label)
mv.visitLineNumber(smap.mapSyntheticLineNumber(JvmAbi.LOCAL_VARIABLE_INLINE_ARGUMENT_SYNTHETIC_LINE_NUMBER), label)
}
}