From effd21d074fb07e64797aef4db624cae0decbf42 Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 29 Apr 2022 13:29:42 +0200 Subject: [PATCH] JVM_IR: do not optimize suspend$$forInline functions `$$forInline` functions do not pass through the state machine generator, and optimizing `Ref`s before that changes how assignments inside lambdas passed to `suspendCoroutine`, etc. behave: without a `Ref`, the assignment is not reflected in the continuation object, so the variable has old value on resumption. These functions will be optimized later, after they are inlined somewhere and the state machine is generated. ^KT-52198 Fixed --- .../optimization/OptimizationClassBuilder.kt | 2 + .../optimization/OptimizationMethodVisitor.kt | 3 +- ...FirBlackBoxInlineCodegenTestGenerated.java | 6 +++ ...reeBlackBoxInlineCodegenTestGenerated.java | 6 +++ .../jvm/diagnostics/JvmDeclarationOrigin.kt | 3 +- .../backend/jvm/codegen/ClassCodegen.kt | 14 ++++--- .../codegen/boxInline/suspend/kt52198.kt | 40 +++++++++++++++++++ .../BlackBoxInlineCodegenTestGenerated.java | 6 +++ ...otlinAgainstInlineKotlinTestGenerated.java | 6 +++ .../IrBlackBoxInlineCodegenTestGenerated.java | 6 +++ ...otlinAgainstInlineKotlinTestGenerated.java | 6 +++ ...otlinAgainstInlineKotlinTestGenerated.java | 6 +++ ...JvmIrAgainstOldBoxInlineTestGenerated.java | 6 +++ ...JvmOldAgainstIrBoxInlineTestGenerated.java | 6 +++ 14 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/codegen/boxInline/suspend/kt52198.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationClassBuilder.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationClassBuilder.kt index d023a57e191..6b02f8129ad 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationClassBuilder.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationClassBuilder.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.DelegatingClassBuilder import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin +import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind import org.jetbrains.org.objectweb.asm.MethodVisitor class OptimizationClassBuilder(private val delegate: ClassBuilder, private val generationState: GenerationState) : @@ -36,6 +37,7 @@ class OptimizationClassBuilder(private val delegate: ClassBuilder, private val g ): MethodVisitor { return OptimizationMethodVisitor( super.newMethod(origin, access, name, desc, signature, exceptions), + origin.originKind == JvmDeclarationOriginKind.INLINE_VERSION_OF_SUSPEND_FUN, generationState, access, name, desc, signature, exceptions ) } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt index 5ad4e6de7b8..23c4e371912 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt @@ -34,6 +34,7 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode class OptimizationMethodVisitor( delegate: MethodVisitor, + private val mandatoryTransformationsOnly: Boolean, private val generationState: GenerationState, access: Int, name: String, @@ -67,7 +68,7 @@ class OptimizationMethodVisitor( normalizationMethodTransformer.transform("fake", methodNode) UninitializedStoresProcessor(methodNode).run() - if (canBeOptimized(methodNode) && !generationState.disableOptimization) { + if (!mandatoryTransformationsOnly && canBeOptimized(methodNode) && !generationState.disableOptimization) { optimizationTransformer.transform("fake", methodNode) } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java index 95335adb981..a8e5d2d02fa 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxInlineCodegenTestGenerated.java @@ -5054,6 +5054,12 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxInlineCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxInlineCodegenTestGenerated.java index b7906b1a4db..7ca5784e5a6 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxInlineCodegenTestGenerated.java @@ -5054,6 +5054,12 @@ public class FirLightTreeBlackBoxInlineCodegenTestGenerated extends AbstractFirL runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt index 01da0071b09..e8a2509b915 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/JvmDeclarationOrigin.kt @@ -33,7 +33,8 @@ enum class JvmDeclarationOriginKind { AUGMENTED_BUILTIN_API, ERASED_INLINE_CLASS, UNBOX_METHOD_OF_INLINE_CLASS, - JVM_OVERLOADS + JVM_OVERLOADS, + INLINE_VERSION_OF_SUSPEND_FUN, } class JvmDeclarationOrigin( diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 36339960f2c..ea127191051 100644 --- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -57,7 +57,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.org.objectweb.asm.* import org.jetbrains.org.objectweb.asm.commons.Method import java.io.File -import java.lang.RuntimeException class ClassCodegen private constructor( val irClass: IrClass, @@ -509,10 +508,15 @@ class ClassCodegen private constructor( private val IrDeclaration.descriptorOrigin: JvmDeclarationOrigin get() { val psiElement = PsiSourceManager.findPsiElement(this) - return if (origin == IrDeclarationOrigin.FILE_CLASS) - JvmDeclarationOrigin(JvmDeclarationOriginKind.PACKAGE_PART, psiElement, toIrBasedDescriptor()) - else - OtherOrigin(psiElement, toIrBasedDescriptor()) + return when { + origin == IrDeclarationOrigin.FILE_CLASS -> + JvmDeclarationOrigin(JvmDeclarationOriginKind.PACKAGE_PART, psiElement, toIrBasedDescriptor()) + (this is IrSimpleFunction && isSuspend && isEffectivelyInlineOnly()) || + origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE || + origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE -> + JvmDeclarationOrigin(JvmDeclarationOriginKind.INLINE_VERSION_OF_SUSPEND_FUN, psiElement, toIrBasedDescriptor()) + else -> OtherOrigin(psiElement, toIrBasedDescriptor()) + } } private fun storeSerializedIr(serializedIr: ByteArray) { diff --git a/compiler/testData/codegen/boxInline/suspend/kt52198.kt b/compiler/testData/codegen/boxInline/suspend/kt52198.kt new file mode 100644 index 00000000000..81b07b6a40a --- /dev/null +++ b/compiler/testData/codegen/boxInline/suspend/kt52198.kt @@ -0,0 +1,40 @@ +// WITH_COROUTINES +// WITH_STDLIB +// TARGET_BACKEND: JVM +// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_IR_AGAINST_OLD +// FILE: lib.kt +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +suspend fun foo(value: String): String { + var x = "fail" + suspendCoroutineUninterceptedOrReturn { + x = value + it.resume(Unit) + COROUTINE_SUSPENDED + } + return x +} + +suspend inline fun fooInline(value: String): String { + var x = "fail" + suspendCoroutineUninterceptedOrReturn { + x = value + it.resume(Unit) + COROUTINE_SUSPENDED + } + return x +} + +// FILE: main.kt +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* + +fun box(): String { + var result = "" + suspend { + result = foo("O") + fooInline("K") + }.startCoroutine(EmptyContinuation) + return result +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java index c9ec532b54e..51e95af9db3 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -5018,6 +5018,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 557eef9f661..bedbd3bb0ce 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -5018,6 +5018,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java index c2a0a03812e..4cb180be451 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxInlineCodegenTestGenerated.java @@ -5054,6 +5054,12 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java index 6e3f1a1bb15..b078820b24e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -5054,6 +5054,12 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java index 9312700d337..9c900512df7 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated.java @@ -5054,6 +5054,12 @@ public class IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated extends Ab runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java index 1489a1acde4..e91e70f0bbf 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmIrAgainstOldBoxInlineTestGenerated.java @@ -5054,6 +5054,12 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java index decf086e675..7cefa0f89cd 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/JvmOldAgainstIrBoxInlineTestGenerated.java @@ -5018,6 +5018,12 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst runTest("compiler/testData/codegen/boxInline/suspend/kt26658.kt"); } + @Test + @TestMetadata("kt52198.kt") + public void testKt52198() throws Exception { + runTest("compiler/testData/codegen/boxInline/suspend/kt52198.kt"); + } + @Test @TestMetadata("maxStackWithCrossinline.kt") public void testMaxStackWithCrossinline() throws Exception {