JVM: use precise line bounds when regenerating objects with no SMAPs

This commit is contained in:
pyos
2020-04-24 13:02:21 +02:00
committed by max-kammerer
parent 7222a732c1
commit c51c537504
5 changed files with 43 additions and 16 deletions
@@ -117,7 +117,8 @@ class AnonymousObjectTransformer(
// When regenerating objects in inline lambdas, keep the old SMAP and don't remap the line numbers to
// save time. The result is effectively the same anyway.
val debugInfoToParse = if (inliningContext.isInliningLambda) null else debugInfo
sourceMap = SMAPParser.parseOrCreateDefault(debugInfoToParse, sourceInfo, oldObjectType.internalName, 1, 65535)
val (firstLine, lastLine) = (methodsToTransform + listOfNotNull(constructor)).lineNumberRange()
sourceMap = SMAPParser.parseOrCreateDefault(debugInfoToParse, sourceInfo, oldObjectType.internalName, firstLine, lastLine)
sourceMapper = SourceMapper(sourceMap.fileMappings.firstOrNull { it.name == sourceInfo }?.toSourceInfo())
val allCapturedParamBuilder = ParametersBuilder.newBuilder()
@@ -92,12 +92,8 @@ internal fun getMethodNode(
val cr = ClassReader(classData)
var node: MethodNode? = null
val debugInfo = arrayOfNulls<String>(2)
val lines = IntArray(2)
lines[0] = Integer.MAX_VALUE
lines[1] = Integer.MIN_VALUE
cr.accept(object : ClassVisitor(Opcodes.API_VERSION) {
override fun visitSource(source: String?, debug: String?) {
super.visitSource(source, debug)
debugInfo[0] = source
@@ -123,16 +119,8 @@ internal fun getMethodNode(
node?.let { existing ->
throw AssertionError("Can't find proper '$name' method for inline: ambiguity between '${existing.name + existing.desc}' and '${name + desc}'")
}
return object : MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions) {
override fun visitLineNumber(line: Int, start: Label) {
super.visitLineNumber(line, start)
lines[0] = min(lines[0], line)
lines[1] = max(lines[1], line)
}
}.also {
node = it
}
node = MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions)
return node!!
}
}, ClassReader.SKIP_FRAMES or if (GENERATE_SMAP) 0 else ClassReader.SKIP_DEBUG)
@@ -140,10 +128,25 @@ internal fun getMethodNode(
return null
}
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, lines[0], lines[1])
val (first, last) = listOfNotNull(node).lineNumberRange()
val smap = SMAPParser.parseOrCreateDefault(debugInfo[1], debugInfo[0], classType.internalName, first, last)
return SMAPAndMethodNode(node!!, smap)
}
internal fun Collection<MethodNode>.lineNumberRange(): Pair<Int, Int> {
var minLine = Int.MAX_VALUE
var maxLine = Int.MIN_VALUE
for (node in this) {
for (insn in node.instructions.asSequence()) {
if (insn is LineNumberNode) {
minLine = min(minLine, insn.line)
maxLine = max(maxLine, insn.line)
}
}
}
return minLine to maxLine
}
internal fun findVirtualFile(state: GenerationState, classId: ClassId): VirtualFile? {
return VirtualFileFinder.getInstance(state.project, state.module).findVirtualFileWithHeader(classId)
}
@@ -0,0 +1,13 @@
fun box(): String {
var result = ""
run {
object {
init {
result = "OK"
}
}
}
return result
}
// 1 LINENUMBER 6
@@ -3452,6 +3452,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt");
}
@TestMetadata("inlineLambdaObjectInit.kt")
public void testInlineLambdaObjectInit() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineLambdaObjectInit.kt");
}
@TestMetadata("singleThen.kt")
public void testSingleThen() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/singleThen.kt");
@@ -3537,6 +3537,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineCondition2.kt");
}
@TestMetadata("inlineLambdaObjectInit.kt")
public void testInlineLambdaObjectInit() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/inlineLambdaObjectInit.kt");
}
@TestMetadata("singleThen.kt")
public void testSingleThen() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/lineNumbers/singleThen.kt");