diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt index 7b72275ddec..ea76cbff2c6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -57,6 +57,7 @@ class AnonymousObjectTransformer( lateinit var superClassName: String var sourceInfo: String? = null var debugInfo: String? = null + var debugMetadataAnnotation: AnnotationNode? = null createClassReader().accept(object : ClassVisitor(Opcodes.API_VERSION, classBuilder.visitor) { override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String, interfaces: Array) { @@ -77,7 +78,8 @@ class AnonymousObjectTransformer( val innerClassesInfo = FileBasedKotlinClass.InnerClassesInfo() return FileBasedKotlinClass.convertAnnotationVisitor(metadataReader, desc, innerClassesInfo) } else if (desc == DEBUG_METADATA_ANNOTATION_ASM_TYPE.descriptor) { - return null + debugMetadataAnnotation = AnnotationNode(desc) + return debugMetadataAnnotation } return super.visitAnnotation(desc, visible) } @@ -137,12 +139,20 @@ class AnonymousObjectTransformer( methodsToTransform, superClassName ) + var putDebugMetadata = false loop@ for (next in methodsToTransform) { val deferringVisitor = when { coroutineTransformer.shouldSkip(next) -> continue@loop coroutineTransformer.shouldGenerateStateMachine(next) -> coroutineTransformer.newMethod(next) - else -> newMethod(classBuilder, next) + else -> { + // Debug metadata is not put, but we should keep, since we do not generate state-machine, + // if the lambda does not capture crossinline lambdas. + if (coroutineTransformer.suspendLambdaWithGeneratedStateMachine(next)) { + putDebugMetadata = true + } + newMethod(classBuilder, next) + } } if (next.name == "") { @@ -190,6 +200,13 @@ class AnonymousObjectTransformer( writeTransformedMetadata(header, classBuilder) } + // debugMetadataAnnotation can be null in LV < 1.3 + if (putDebugMetadata && debugMetadataAnnotation != null) { + visitor.visitAnnotation(debugMetadataAnnotation!!.desc, true).also { + debugMetadataAnnotation!!.accept(it) + } + } + writeOuterInfo(visitor) if (inliningContext.generateAssertField && fieldNames.none { it.key == ASSERTIONS_DISABLED_FIELD_NAME }) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/coroutines/CoroutineTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/coroutines/CoroutineTransformer.kt index 708a865de45..c2c3e5b12cd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/coroutines/CoroutineTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/coroutines/CoroutineTransformer.kt @@ -43,11 +43,14 @@ class CoroutineTransformer( fun shouldGenerateStateMachine(node: MethodNode): Boolean { // Continuations are similar to lambdas from bird's view, but we should never generate state machine for them if (isContinuationNotLambda()) return false - // there can be suspend lambdas inside inline functions, which do not - // capture crossinline lambdas, thus, there is no need to transform them return isSuspendFunctionWithFakeConstructorCall(node) || (isSuspendLambda(node) && !isStateMachine(node)) } + // there can be suspend lambdas inside inline functions, which do not + // capture crossinline lambdas, thus, there is no need to transform them + fun suspendLambdaWithGeneratedStateMachine(node: MethodNode): Boolean = + !isContinuationNotLambda() && isSuspendLambda(node) && isStateMachine(node) + private fun isContinuationNotLambda(): Boolean = inliningContext.isContinuation && if (state.languageVersionSettings.isReleaseCoroutines()) superClassName.endsWith("ContinuationImpl") else methods.any { it.name == "getLabel" } diff --git a/compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt b/compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt new file mode 100644 index 00000000000..1abfca2af49 --- /dev/null +++ b/compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt @@ -0,0 +1,36 @@ +// WITH_RUNTIME +// TARGET_BACKEND: JVM + +// FILE: inline.kt + +package test + +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun runBlocking(c: suspend () -> Unit) { + c.startCoroutine(Continuation(EmptyCoroutineContext){}) +} + +inline fun foo(noinline block: (String) -> Unit) = runBlocking { + runCatching { + runBlocking { + var c: Continuation? = null + suspendCoroutineUninterceptedOrReturn { c = it; Unit } + block(c!!.toString()) + } + } + Unit +} + +// FILE: test.kt + +import test.* + +fun box(): String { + var res = "FAIL" + foo { + res = it + } + return if (res.contains(".invokeSuspend(inline.kt:")) "OK" else res +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index ff91b91b751..d4995cf85a8 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -3818,6 +3818,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt", "kotlin.coroutines"); } + @TestMetadata("debugMetadataCrossinline.kt") + public void testDebugMetadataCrossinline() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt"); + } + @TestMetadata("delegatedProperties.kt") public void testDelegatedProperties_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/delegatedProperties.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index fcab45b07eb..c9efac6fcbd 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -3818,6 +3818,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt", "kotlin.coroutines"); } + @TestMetadata("debugMetadataCrossinline.kt") + public void testDebugMetadataCrossinline() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt"); + } + @TestMetadata("delegatedProperties.kt") public void testDelegatedProperties_1_2() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/delegatedProperties.kt", "kotlin.coroutines.experimental"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java index 45a0a700a51..9477afd7221 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxInlineCodegenTestGenerated.java @@ -3808,6 +3808,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt", "kotlin.coroutines"); } + @TestMetadata("debugMetadataCrossinline.kt") + public void testDebugMetadataCrossinline() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt"); + } + @TestMetadata("delegatedProperties.kt") public void testDelegatedProperties_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/delegatedProperties.kt", "kotlin.coroutines"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 6d387a98518..dd8fb1ece1c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -3808,6 +3808,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt", "kotlin.coroutines"); } + @TestMetadata("debugMetadataCrossinline.kt") + public void testDebugMetadataCrossinline() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt"); + } + @TestMetadata("delegatedProperties.kt") public void testDelegatedProperties_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/delegatedProperties.kt", "kotlin.coroutines"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java index 8fdeb4c283f..84ed9fee1ec 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -3808,6 +3808,11 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt", "kotlin.coroutines"); } + @TestMetadata("debugMetadataCrossinline.kt") + public void testDebugMetadataCrossinline() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt"); + } + @TestMetadata("delegatedProperties.kt") public void testDelegatedProperties_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/delegatedProperties.kt", "kotlin.coroutines"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java index 6d5f10cff4c..1130c931085 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -3808,6 +3808,11 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/crossinlineSuspendLambdaInsideCrossinlineSuspendLambda.kt", "kotlin.coroutines"); } + @TestMetadata("debugMetadataCrossinline.kt") + public void testDebugMetadataCrossinline() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/debugMetadataCrossinline.kt"); + } + @TestMetadata("delegatedProperties.kt") public void testDelegatedProperties_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/boxInline/suspend/delegatedProperties.kt", "kotlin.coroutines");