diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt index 0b19812337d..a74bac12dc6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineTransformationClassBuilder.kt @@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.coroutines import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.optimization.MandatoryMethodTransformer -import org.jetbrains.kotlin.codegen.optimization.SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.insnListOf @@ -70,8 +69,6 @@ class CoroutineTransformerMethodVisitor( processUninitializedStores(methodNode) - methodNode.visibleAnnotations.add(AnnotationNode(SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC)) - val suspensionPoints = collectSuspensionPoints(methodNode) if (suspensionPoints.isEmpty()) return diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/MandatoryMethodTransforker.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/MandatoryMethodTransforker.kt index 00466a41ff2..6695595b03e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/MandatoryMethodTransforker.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/MandatoryMethodTransforker.kt @@ -20,16 +20,11 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransfor import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.org.objectweb.asm.tree.MethodNode -val SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC = "Lkotlin/SkipMandatoryTransformations;" - class MandatoryMethodTransformer : MethodTransformer() { private val labelNormalization = LabelNormalizationMethodTransformer() private val fixStack = FixStackMethodTransformer() override fun transform(internalClassName: String, methodNode: MethodNode) { - // Mandatory transformations have already been applied - if (methodNode.visibleAnnotations?.removeAll { it.desc == SKIP_MANDATORY_TRANSFORMATIONS_ANNOTATION_DESC } == true) return - labelNormalization.transform(internalClassName, methodNode) fixStack.transform(internalClassName, methodNode) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/MethodAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/MethodAnalyzer.kt index adafd31f8f9..8fa5d5fc116 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/MethodAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/MethodAnalyzer.kt @@ -136,7 +136,12 @@ open class MethodAnalyzer( private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame, insn: Int) { var jump = instructions.indexOf(insnNode.dflt) processControlFlowEdge(current, insn, jump) - for (label in insnNode.labels) { + // In most cases order of visiting switch labels should not matter + // The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead + // in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved) + // So we just fix the order of labels being traversed: the first one should be one at the method beginning + // Using 'reversed' is because nodes are processed in LIFO order + for (label in insnNode.labels.reversed()) { jump = instructions.indexOf(label) processControlFlowEdge(current, insn, jump) } diff --git a/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt new file mode 100644 index 00000000000..54c1ac51acf --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt @@ -0,0 +1,29 @@ + +class Controller { + suspend fun suspendHere(v: String, x: Continuation) { + x.resume(v) + } +} + +fun builder(coroutine c: Controller.() -> Continuation) { + c(Controller()).resume(Unit) +} + +inline fun run(block: () -> Unit) { + block() +} + +fun box(): String { + var result = "" + run { + builder { + try { + result += suspendHere("O") + } finally { + result += suspendHere("K") + } + } + } + + return result +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 33c632d7240..0c8d4c6a79a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -4200,6 +4200,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/suspendInTheMiddleOfObjectConstruction.kt"); doTest(fileName); } + + @TestMetadata("tryFinallyInsideInlineLambda.kt") + public void testTryFinallyInsideInlineLambda() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/tryFinallyInsideInlineLambda.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/dataClasses")