From 5dea245a37f6258bdc9ab14225a61ffbf76324f4 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Tue, 18 Sep 2018 16:26:59 +0300 Subject: [PATCH] Fix linenumbers written to debug metadata #KT-26848 Fixed --- .../CoroutineTransformerMethodVisitor.kt | 23 ++++--- .../coroutines/debug/firstSuspensionPoint.kt | 62 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 5 ++ .../LightAnalysisModeTestGenerated.java | 5 ++ .../ir/IrBlackBoxCodegenTestGenerated.java | 5 ++ 5 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt index 62fa96f4da2..4ea1a7fb1b4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformerMethodVisitor.kt @@ -129,12 +129,17 @@ class CoroutineTransformerMethodVisitor( val suspendMarkerVarIndex = methodNode.maxLocals++ - val suspensionPointLabels = suspensionPoints.withIndex().map { + val suspensionPointLineNumbers = + suspensionPoints.map { suspensionPoint -> + suspensionPoint.suspensionCallBegin.findPreviousOrNull { it is LineNumberNode } as LineNumberNode? + } + + val continuationLabels = suspensionPoints.withIndex().map { transformCallAndReturnContinuationLabel(it.index + 1, it.value, methodNode, suspendMarkerVarIndex) } - val tableSwitchLabel = LabelNode() methodNode.instructions.apply { + val tableSwitchLabel = LabelNode() val firstStateLabel = LabelNode() val defaultLabel = LabelNode() @@ -153,7 +158,7 @@ class CoroutineTransformerMethodVisitor( 0, suspensionPoints.size, defaultLabel, - firstStateLabel, *suspensionPointLabels.toTypedArray() + firstStateLabel, *continuationLabels.toTypedArray() ), firstStateLabel ) @@ -182,11 +187,7 @@ class CoroutineTransformerMethodVisitor( fixLvtForParameters(methodNode, startLabel, endLabel) if (languageVersionSettings.isReleaseCoroutines() && !isCrossinlineLambda) { - val suspensionPointLabelNodes = listOf(tableSwitchLabel) + suspensionPointLabels.map { - it.label.info.safeAs() - .sure { "suspensionPointLabel shall have valid info. Check state-machine generation." } - } - writeDebugMetadata(methodNode, suspensionPointLabelNodes, spilledToVariableMapping) + writeDebugMetadata(methodNode, suspensionPointLineNumbers, spilledToVariableMapping) } } @@ -217,12 +218,10 @@ class CoroutineTransformerMethodVisitor( private fun writeDebugMetadata( methodNode: MethodNode, - suspensionPointLabels: List, + suspensionPointLineNumbers: List, spilledToLocalMapping: List> ) { - val lines = suspensionPointLabels.map { label -> - label.safeAs()?.findNextOrNull { it is LineNumberNode }.safeAs()?.line ?: -1 - } + val lines = suspensionPointLineNumbers.map { it?.line ?: -1 } val metadata = classBuilderForCoroutineState.newAnnotation(DEBUG_METADATA_ANNOTATION_ASM_TYPE.descriptor, true) metadata.visit(COROUTINES_METADATA_SOURCE_FILE_JVM_NAME, sourceFile) metadata.visit(COROUTINES_METADATA_LINE_NUMBERS_JVM_NAME, lines.toIntArray()) diff --git a/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt b/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt new file mode 100644 index 00000000000..46971d6a98b --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt @@ -0,0 +1,62 @@ +// !LANGUAGE: +ReleaseCoroutines + +// IGNORE_BACKEND: JVM_IR +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// FULL_JDK +// WITH_COROUTINES + +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +suspend fun foo() { + /* + A + LOT + OF + EMPTY + LINES + */ + suspendHere() + suspendHere() +} + +val lambda: suspend () -> Unit = { + /* + A + LOT + OF + EMPTY + LINES + */ + suspendHere() + suspendHere() +} + +var continuation: Continuation? = null + +suspend fun suspendHere() = suspendCoroutineUninterceptedOrReturn { + continuation = it + COROUTINE_SUSPENDED +} + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +fun box(): String { + builder { + foo() + } + if (!"$continuation".contains("21")) return "$continuation" + continuation!!.resumeWith(Result.success(Unit)) + if (!"$continuation".contains("22")) return "$continuation" + builder { + lambda() + } + if (!"$continuation".contains("33")) return "$continuation" + continuation!!.resumeWith(Result.success(Unit)) + if (!"$continuation".contains("34")) return "$continuation" + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index d71b0277d9b..8cd3bd7923f 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -6461,6 +6461,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/coroutines/debug/debuggerMetadata.kt"); } + @TestMetadata("firstSuspensionPoint.kt") + public void testFirstSuspensionPoint() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt"); + } + @TestMetadata("runtimeDebugMetadata.kt") public void testRuntimeDebugMetadata() throws Exception { runTest("compiler/testData/codegen/box/coroutines/debug/runtimeDebugMetadata.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index bd3eab708fb..46de80ad1c4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -6461,6 +6461,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/coroutines/debug/debuggerMetadata.kt"); } + @TestMetadata("firstSuspensionPoint.kt") + public void testFirstSuspensionPoint() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt"); + } + @TestMetadata("runtimeDebugMetadata.kt") public void testRuntimeDebugMetadata() throws Exception { runTest("compiler/testData/codegen/box/coroutines/debug/runtimeDebugMetadata.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index ad3a5a329a8..3ed29c8d197 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -6461,6 +6461,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/coroutines/debug/debuggerMetadata.kt"); } + @TestMetadata("firstSuspensionPoint.kt") + public void testFirstSuspensionPoint() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt"); + } + @TestMetadata("runtimeDebugMetadata.kt") public void testRuntimeDebugMetadata() throws Exception { runTest("compiler/testData/codegen/box/coroutines/debug/runtimeDebugMetadata.kt");