From a793055ec22c771233c555bd42f10f45270fac88 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Wed, 17 Apr 2019 19:33:33 +0300 Subject: [PATCH] Check variables, captured by outer object when searching for suspend crossinline parameters --- .../kotlin/codegen/FunctionCodegen.java | 5 +- .../codegen/coroutines/CoroutineCodegen.kt | 18 +- .../SuspendFunctionGenerationStrategy.kt | 5 +- .../inline/AnonymousObjectTransformer.kt | 4 +- .../kotlin/codegen/inline/LambdaInfo.kt | 5 +- .../inline/coroutines/CoroutineTransformer.kt | 44 ++- .../coroutines/javaInterop/severalCaptures.kt | 283 ++++++++++++++++++ .../tailCallOptimizations/crossinline.txt | 6 + .../tailCallOptimizations/crossinline_1_2.txt | 5 + .../innerObjectRetransformation.txt | 5 + .../innerObjectRetransformation_1_2.txt | 4 + .../codegen/BlackBoxCodegenTestGenerated.java | 10 + .../LightAnalysisModeTestGenerated.java | 10 + .../ir/IrBlackBoxCodegenTestGenerated.java | 10 + 14 files changed, 387 insertions(+), 27 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 3e64f36f1bd..80503323b9e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -14,6 +14,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.backend.common.bridges.Bridge; +import org.jetbrains.kotlin.codegen.binding.CalculatedClosure; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.context.*; import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt; @@ -1645,7 +1646,7 @@ public class FunctionCodegen { } @Nullable - public Map getCaptureVariables() { - return owner.closure == null ? null : owner.closure.getCaptureVariables(); + public CalculatedClosure getClosure() { + return owner.closure; } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt index 039aa8579e8..66859f64d2d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/CoroutineCodegen.kt @@ -8,10 +8,11 @@ package org.jetbrains.kotlin.codegen.coroutines import com.intellij.util.ArrayUtil import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.binding.CalculatedClosure import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA +import org.jetbrains.kotlin.codegen.binding.CodegenBinding.CLOSURE import org.jetbrains.kotlin.codegen.context.ClosureContext -import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor import org.jetbrains.kotlin.codegen.context.MethodContext import org.jetbrains.kotlin.codegen.inline.coroutines.SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION @@ -26,6 +27,7 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.module @@ -479,7 +481,7 @@ class CoroutineCodegenForLambda private constructor( MethodNodeCopyingMethodVisitor( SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor( stateMachineBuilder, access, name, desc, v.thisName, - isCapturedSuspendLambda = { isCapturedSuspendLambda(closure.captureVariables, it.name) } + isCapturedSuspendLambda = { isCapturedSuspendLambda(closure, it.name, state.bindingContext) } ), access, name, desc, newMethod = { origin, newAccess, newName, newDesc -> functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null) @@ -528,13 +530,19 @@ class CoroutineCodegenForLambda private constructor( } } -fun isCapturedSuspendLambda(captureVariables: Map, name: String): Boolean { - for ((param, value) in captureVariables) { +fun isCapturedSuspendLambda(closure: CalculatedClosure, name: String, bindingContext: BindingContext): Boolean { + for ((param, value) in closure.captureVariables) { if (param !is ValueParameterDescriptor) continue if (value.fieldName != name) continue return param.type.isSuspendFunctionTypeOrSubtype } - return false + val classDescriptor = closure.capturedOuterClassDescriptor ?: return false + return isCapturedSuspendLambda(classDescriptor, name, bindingContext) +} + +fun isCapturedSuspendLambda(classDescriptor: ClassDescriptor, name: String, bindingContext: BindingContext): Boolean { + val closure = bindingContext[CLOSURE, classDescriptor] ?: return false + return isCapturedSuspendLambda(closure, name, bindingContext) } private class AddEndLabelMethodVisitor( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendFunctionGenerationStrategy.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendFunctionGenerationStrategy.kt index 2acdd95ad2e..6dbc068f773 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendFunctionGenerationStrategy.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendFunctionGenerationStrategy.kt @@ -76,10 +76,11 @@ open class SuspendFunctionGenerationStrategy( access, name, desc, containingClassInternalName, isCapturedSuspendLambda = { isCapturedSuspendLambda( - functionCodegen.captureVariables.sure { + functionCodegen.closure.sure { "Anonymous object should have closure" }, - it.name + it.name, + state.bindingContext ) } ), access, name, desc, 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 ced9eb9be7b..1bf2e9d3743 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.kt @@ -484,9 +484,9 @@ class AnonymousObjectTransformer( alreadyAddedParam?.newFieldName ?: getNewFieldName(desc.fieldName, false), alreadyAddedParam != null ) - if (info is PsiExpressionLambda && info.captureVariables.any { it.value.fieldName == desc.fieldName }) { + if (info is PsiExpressionLambda && info.closure.captureVariables.any { it.value.fieldName == desc.fieldName }) { recapturedParamInfo.functionalArgument = NonInlineableArgumentForInlineableParameterCalledInSuspend( - isCapturedSuspendLambda(info.captureVariables, desc.fieldName) + isCapturedSuspendLambda(info.closure, desc.fieldName, inliningContext.state.bindingContext) ) } val composed = StackValue.field( diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt index 44d451b2002..c78069aaba2 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/LambdaInfo.kt @@ -230,7 +230,8 @@ class PsiExpressionLambda( private val labels: Set - private var closure: CalculatedClosure + var closure: CalculatedClosure + private set init { val bindingContext = typeMapper.bindingContext @@ -307,6 +308,4 @@ class PsiExpressionLambda( val isPropertyReference: Boolean get() = propertyReferenceInfo != null - - val captureVariables = closure.captureVariables } \ No newline at end of file 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 cb174ce7b5a..3daf8ca1d1a 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 @@ -10,13 +10,13 @@ import org.jetbrains.kotlin.codegen.AsmUtil.CAPTURED_THIS_FIELD import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.TransformationMethodVisitor import org.jetbrains.kotlin.codegen.coroutines.* -import org.jetbrains.kotlin.codegen.coroutines.getLastParameterIndex -import org.jetbrains.kotlin.codegen.coroutines.replaceFakeContinuationsWithRealOnes import org.jetbrains.kotlin.codegen.inline.* import org.jetbrains.kotlin.codegen.optimization.common.asSequence import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.config.isReleaseCoroutines +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.utils.addToStdlib.cast @@ -98,7 +98,7 @@ class CoroutineTransformer( ArrayUtil.toStringArray(node.exceptions) ) ) { - val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded( + val stateMachineBuilder = surroundNoinlineCallsWithMarkers( node, CoroutineTransformerMethodVisitor( createNewMethodFrom(node, name), node.access, name, node.desc, null, null, @@ -137,7 +137,7 @@ class CoroutineTransformer( ArrayUtil.toStringArray(node.exceptions) ) ) { - val stateMachineBuilder = surroundNoinlineCallsWithMarkersIfNeeded( + val stateMachineBuilder = surroundNoinlineCallsWithMarkers( node, CoroutineTransformerMethodVisitor( createNewMethodFrom(node, name), node.access, name, node.desc, null, null, @@ -165,16 +165,34 @@ class CoroutineTransformer( } } - private fun surroundNoinlineCallsWithMarkersIfNeeded(node: MethodNode, delegate: MethodVisitor): MethodVisitor = - if (capturedParams.any { it.functionalArgument?.isSuspendLambda() == true }) - SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor( - delegate, node.access, node.name, node.desc, classBuilder.thisName, this::isCapturedSuspendLambda - ) - else - delegate + private fun surroundNoinlineCallsWithMarkers(node: MethodNode, delegate: MethodVisitor): MethodVisitor = + SurroundSuspendLambdaCallsWithSuspendMarkersMethodVisitor( + delegate, node.access, node.name, node.desc, classBuilder.thisName, this::fieldIsCapturedSuspendLambda + ) - private fun isCapturedSuspendLambda(field: FieldInsnNode): Boolean = - capturedParams.find { it.newFieldName == field.name }?.functionalArgument?.isSuspendLambda() == true + private fun fieldIsCapturedSuspendLambda(field: FieldInsnNode): Boolean = + capturedParams.find { it.newFieldName == field.name }?.let { it.functionalArgument?.isSuspendLambda() == true } + ?: isSuspendLambdaCapturedByOuterObjectOrLambda(field) + + // We cannot find the lambda in captured parameters: it came from object outside of the our reach: + // this can happen when the lambda capture by non-transformed closure: + // inline fun inlineMe(crossinline c: suspend() -> Unit) = suspend { c() } + // inline fun inlineMe2(crossinline c: suspend() -> Unit) = suspend { inlineMe { c() }() } + // Suppose, we inline inlineMe into inlineMe2: the only knowledge we have about inlineMe$1 is captured receiver (this$0) + // Thus, transformed lambda from inlineMe, inlineMe3$$inlined$inlineMe2$1 contains the following bytecode + // ALOAD 0 + // GETFIELD inlineMe2$1$invokeSuspend$$inlined$inlineMe$1.this$0 : LScratchKt$inlineMe2$1; + // GETFIELD inlineMe2$1.$c : Lkotlin/jvm/functions/Function1; + // Since inlineMe2's lambda is outside of reach of the inliner, find crossinline parameter from compilation context: + private fun isSuspendLambdaCapturedByOuterObjectOrLambda(field: FieldInsnNode): Boolean { + val functionDescriptor = inliningContext.root.sourceCompilerForInline.compilationContextFunctionDescriptor + val classDescriptor = functionDescriptor.findContainingClassOrLambda() ?: return false + return isCapturedSuspendLambda(classDescriptor, field.name, inliningContext.state.bindingContext) + } + + private tailrec fun DeclarationDescriptor.findContainingClassOrLambda(): ClassDescriptor? = + if (containingDeclaration is ClassDescriptor) containingDeclaration as ClassDescriptor + else containingDeclaration?.findContainingClassOrLambda() private fun createNewMethodFrom(node: MethodNode, name: String): MethodVisitor { return classBuilder.newMethod( diff --git a/compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt b/compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt new file mode 100644 index 00000000000..a888fe5d71d --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt @@ -0,0 +1,283 @@ +// IGNORE_BACKEND: JVM_IR +// TARGET_BACKEND: JVM +// COMMON_COROUTINES_TEST +// WITH_RUNTIME +// WITH_COROUTINES +// CHECK_STATE_MACHINE + +// FILE: inlineMe.kt + +package test + +import helpers.* + +interface SuspendRunnable { + suspend fun run1() + suspend fun run2() +} + +inline fun inlineMe(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable { + override suspend fun run1() { + c1(); c1() + } + override suspend fun run2() { + c2(); c2() + } +} + +inline fun inlineMe2(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = inlineMe({ c1(); c1() }) { c2(); c2() } + +inline fun inlineMe3(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable { + override suspend fun run1() { + val sr = inlineMe({ c1(); c1() }) { c2(); c2() } + sr.run1() + sr.run2() + } + override suspend fun run2() { + val sr = inlineMe2({ c1(); c1() }) { c2(); c2() } + sr.run1() + sr.run2() + } +} + +inline fun inlineMe4(crossinline c1: suspend () -> Unit, crossinline c2: suspend () -> Unit) = object : SuspendRunnable { + override suspend fun run1() { + val sr = suspend { + c1(); + c2() + } + sr() + sr() + } + override suspend fun run2() { + val sr = object : SuspendRunnable { + override suspend fun run1() { + c1(); c1() + } + override suspend fun run2() { + c2(); c2() + } + } + sr.run1() + sr.run2() + } +} + +inline fun inlineMe5(crossinline c1: suspend () -> Unit) = inlineMe({ c1(); c1() }) { + StateMachineChecker.suspendHere() +} + +// FILE: A.java + +import test.InlineMeKt; +import helpers.CoroutineUtilKt; +import helpers.EmptyContinuation; +import kotlin.Unit; + +public class A { + public static Object call() { + return InlineMeKt.inlineMe((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation), + (continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation)); + } + public static Object call2() { + return InlineMeKt.inlineMe2((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation), + (continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation)); + } + public static Object call3() { + return InlineMeKt.inlineMe3((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation), + (continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation)); + } + public static Object call4() { + return InlineMeKt.inlineMe4((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation), + (continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation)); + } + public static Object call5() { + return InlineMeKt.inlineMe5((continuation) -> CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation)); + } +} + +// FILE: box.kt + +import test.* +import helpers.* +import COROUTINES_PACKAGE.* + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(CheckStateMachineContinuation) +} + +fun box(): String { + builder { + (A.call() as SuspendRunnable).run1() + } + StateMachineChecker.check(2) + StateMachineChecker.reset() + + builder { + (A.call() as SuspendRunnable).run2() + } + StateMachineChecker.check(2) + StateMachineChecker.reset() + + builder { + (A.call2() as SuspendRunnable).run1() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + builder { + (A.call2() as SuspendRunnable).run2() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + builder { + (A.call3() as SuspendRunnable).run1() + } + StateMachineChecker.check(8) + StateMachineChecker.reset() + + builder { + (A.call3() as SuspendRunnable).run2() + } + StateMachineChecker.check(16) + StateMachineChecker.reset() + + builder { + (A.call4() as SuspendRunnable).run1() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + builder { + (A.call4() as SuspendRunnable).run2() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + builder { + (A.call5() as SuspendRunnable).run1() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + builder { + (A.call5() as SuspendRunnable).run2() + } + StateMachineChecker.check(2) + StateMachineChecker.reset() + + builder { + inlineMe({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run1() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + builder { + inlineMe({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run2() + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + builder { + inlineMe2 ({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run1() + } + StateMachineChecker.check(8) + StateMachineChecker.reset() + builder { + inlineMe2 ({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run2() + } + StateMachineChecker.check(8) + StateMachineChecker.reset() + + builder { + inlineMe3 ({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run1() + } + StateMachineChecker.check(16) + StateMachineChecker.reset() + + builder { + inlineMe3 ({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run2() + } + StateMachineChecker.check(32) + StateMachineChecker.reset() + + builder { + inlineMe4 ({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run1() + } + StateMachineChecker.check(8) + StateMachineChecker.reset() + + builder { + inlineMe4 ({ + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }) { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run2() + } + StateMachineChecker.check(8) + StateMachineChecker.reset() + + builder { + inlineMe5 { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run1() + } + StateMachineChecker.check(8) + StateMachineChecker.reset() + + builder { + inlineMe5 { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + }.run2() + } + StateMachineChecker.check(2) + StateMachineChecker.reset() + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.txt index 4141346df72..da675c88f90 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.txt @@ -261,7 +261,13 @@ public final class CrossinlineKt$filter$$inlined$source$1 { } @kotlin.Metadata +@kotlin.coroutines.jvm.internal.DebugMetadata public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 { + field L$0: java.lang.Object + field L$1: java.lang.Object + field L$2: java.lang.Object + field L$3: java.lang.Object + field L$4: java.lang.Object field label: int synthetic field result: java.lang.Object synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1 diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline_1_2.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline_1_2.txt index 972ee4b2f66..a646c9b197a 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline_1_2.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline_1_2.txt @@ -271,6 +271,11 @@ public final class CrossinlineKt$filter$$inlined$source$1 { @kotlin.Metadata public final class CrossinlineKt$fold$$inlined$consumeEach$1$1 { + field L$0: java.lang.Object + field L$1: java.lang.Object + field L$2: java.lang.Object + field L$3: java.lang.Object + field L$4: java.lang.Object synthetic field data: java.lang.Object synthetic field exception: java.lang.Throwable synthetic final field this$0: CrossinlineKt$fold$$inlined$consumeEach$1 diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt index c3268eca4e3..c7598ec4b36 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt @@ -140,7 +140,12 @@ public final class flow/InnerObjectRetransformationKt$flow$1 { } @kotlin.Metadata +@kotlin.coroutines.jvm.internal.DebugMetadata public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 { + field L$0: java.lang.Object + field L$1: java.lang.Object + field L$2: java.lang.Object + field L$3: java.lang.Object field label: int synthetic field result: java.lang.Object synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1 diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation_1_2.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation_1_2.txt index 2bdb79ad62a..658a534934f 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation_1_2.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation_1_2.txt @@ -149,6 +149,10 @@ public final class flow/InnerObjectRetransformationKt$flow$1 { @kotlin.Metadata public final class flow/InnerObjectRetransformationKt$flowWith$$inlined$flow$1$1 { + field L$0: java.lang.Object + field L$1: java.lang.Object + field L$2: java.lang.Object + field L$3: java.lang.Object synthetic field data: java.lang.Object synthetic field exception: java.lang.Throwable synthetic final field this$0: flow.InnerObjectRetransformationKt$flowWith$$inlined$flow$1 diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 6455ce90148..74a85505d15 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -7426,6 +7426,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testReturnObject_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines"); } + + @TestMetadata("severalCaptures.kt") + public void testSeveralCaptures_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("severalCaptures.kt") + public void testSeveralCaptures_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 11f0b727be0..d032d7a13ff 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7426,6 +7426,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testReturnObject_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines"); } + + @TestMetadata("severalCaptures.kt") + public void testSeveralCaptures_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("severalCaptures.kt") + public void testSeveralCaptures_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 78d8f932f28..96acd1e0e82 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -7426,6 +7426,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testReturnObject_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/returnObject.kt", "kotlin.coroutines"); } + + @TestMetadata("severalCaptures.kt") + public void testSeveralCaptures_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("severalCaptures.kt") + public void testSeveralCaptures_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")