From 266976ac1e006e47e510e293c554a6018c987a09 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Wed, 8 May 2019 02:19:35 +0300 Subject: [PATCH] Fix Java interop of inline suspend functions with suspend parameters In 1.3.31 I fixed Java interop for inline function with coroutines (TL;DR: when we need a state machine, generate two methods: one with normal name, and the other one with $$forInline suffix, for the inliner to use, just like inline suspend functions), however, I forgot a case with inline suspend function with inline suspend function parameter. In this case, the compiler a generated two functions, as needed, but, neither of them had a state-machine. This change adds the state-machine for the method with normal name. Note, that suspend inline functions with crossinline parameter, which are also supported by the change, did not cause incorrect behaviour, since until now they were generated as synthetic. #KT-31354 Fixed --- .../SuspendFunctionGenerationStrategy.kt | 31 +++++--- ...SuspendInlineFunctionGenerationStrategy.kt | 53 ++++++++++++- .../kotlin/resolve/inline/inlineOnly.kt | 5 +- .../suspendInlineWithCrossinline.kt | 78 +++++++++++++++++++ .../tailCallOptimizations/crossinline.txt | 51 +++++++++++- .../tailCallOptimizations/crossinline_1_2.txt | 53 ++++++++++++- .../innerObjectRetransformation.txt | 3 +- .../innerObjectRetransformation_1_2.txt | 3 +- .../bytecodeListing/inline/simpleNamed.txt | 6 +- .../bytecodeListing/tcoContinuation.txt | 3 +- .../bytecodeListing/tcoContinuation_1_3.txt | 3 +- .../codegen/BlackBoxCodegenTestGenerated.java | 10 +++ .../LightAnalysisModeTestGenerated.java | 10 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 10 +++ 14 files changed, 293 insertions(+), 26 deletions(-) create mode 100644 compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt 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 5194de23804..e557003142f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendFunctionGenerationStrategy.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendFunctionGenerationStrategy.kt @@ -30,7 +30,7 @@ open class SuspendFunctionGenerationStrategy( state: GenerationState, protected val originalSuspendDescriptor: FunctionDescriptor, protected val declaration: KtFunction, - private val containingClassInternalName: String, + protected val containingClassInternalName: String, private val constructorCallNormalizationMode: JVMConstructorCallNormalizationMode, protected val functionCodegen: FunctionCodegen ) : FunctionGenerationStrategy.CodegenBased(state) { @@ -53,16 +53,7 @@ open class SuspendFunctionGenerationStrategy( override fun wrapMethodVisitor(mv: MethodVisitor, access: Int, name: String, desc: String): MethodVisitor { if (access and Opcodes.ACC_ABSTRACT != 0) return mv - val stateMachineBuilder = CoroutineTransformerMethodVisitor( - mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState, - isForNamedFunction = true, - element = declaration, - diagnostics = state.diagnostics, - shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization, - needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null, - internalNameForDispatchReceiver = containingClassInternalNameOrNull(), - languageVersionSettings = languageVersionSettings - ) + val stateMachineBuilder = createStateMachineBuilder(mv, access, name, desc) val forInline = state.bindingContext[CodegenBinding.CAPTURES_CROSSINLINE_LAMBDA, originalSuspendDescriptor] == true // Both capturing and inline functions share the same suffix, however, inline functions can also be capturing @@ -95,6 +86,24 @@ open class SuspendFunctionGenerationStrategy( ) else stateMachineBuilder } + protected fun createStateMachineBuilder( + mv: MethodVisitor, + access: Int, + name: String, + desc: String + ): CoroutineTransformerMethodVisitor { + return CoroutineTransformerMethodVisitor( + mv, access, name, desc, null, null, containingClassInternalName, this::classBuilderForCoroutineState, + isForNamedFunction = true, + element = declaration, + diagnostics = state.diagnostics, + shouldPreserveClassInitialization = constructorCallNormalizationMode.shouldPreserveClassInitialization, + needDispatchReceiver = originalSuspendDescriptor.dispatchReceiverParameter != null, + internalNameForDispatchReceiver = containingClassInternalNameOrNull(), + languageVersionSettings = languageVersionSettings + ) + } + private fun containingClassInternalNameOrNull() = originalSuspendDescriptor.containingDeclaration.safeAs()?.let(state.typeMapper::mapClass)?.internalName diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendInlineFunctionGenerationStrategy.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendInlineFunctionGenerationStrategy.kt index 749e55c1119..601f98fff31 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendInlineFunctionGenerationStrategy.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/coroutines/SuspendInlineFunctionGenerationStrategy.kt @@ -5,20 +5,30 @@ package org.jetbrains.kotlin.codegen.coroutines +import org.jetbrains.kotlin.builtins.isSuspendFunctionType import org.jetbrains.kotlin.codegen.ExpressionCodegen import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.FunctionGenerationStrategy import org.jetbrains.kotlin.codegen.TransformationMethodVisitor import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX +import org.jetbrains.kotlin.codegen.inline.coroutines.findReceiverOfInvoke +import org.jetbrains.kotlin.codegen.inline.coroutines.surroundInvokesWithSuspendMarkers +import org.jetbrains.kotlin.codegen.inline.isInvokeOnLambda +import org.jetbrains.kotlin.codegen.optimization.common.asSequence +import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer +import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.JVMConstructorCallNormalizationMode import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.psi.KtFunction +import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.org.objectweb.asm.MethodVisitor import org.jetbrains.org.objectweb.asm.Opcodes -import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.tree.* +import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter // For named suspend function we generate two methods: // 1) to use as noinline function, which have state machine @@ -44,7 +54,10 @@ class SuspendInlineFunctionGenerationStrategy( if (access and Opcodes.ACC_ABSTRACT != 0) return mv return MethodNodeCopyingMethodVisitor( - super.wrapMethodVisitor(mv, access, name, desc), access, name, desc, + SurroundSuspendParameterCallsWithSuspendMarkersMethodVisitor( + createStateMachineBuilder(mv, access, name, desc), + access, name, desc, containingClassInternalName, originalSuspendDescriptor.valueParameters + ), access, name, desc, newMethod = { origin, newAccess, newName, newDesc -> functionCodegen.newMethod(origin, newAccess, newName, newDesc, null, null) }, keepAccess = false @@ -78,3 +91,39 @@ class MethodNodeCopyingMethodVisitor( else access or Opcodes.ACC_PRIVATE and Opcodes.ACC_PUBLIC.inv() and Opcodes.ACC_PROTECTED.inv() } } + +private class SurroundSuspendParameterCallsWithSuspendMarkersMethodVisitor( + delegate: MethodVisitor, + access: Int, + name: String, + desc: String, + private val thisName: String, + private val valueParameters: List +): TransformationMethodVisitor(delegate, access, name, desc, null, null) { + override fun performTransformations(methodNode: MethodNode) { + fun AbstractInsnNode.index() = methodNode.instructions.indexOf(this) + fun AbstractInsnNode.isInlineSuspendParameter(): Boolean { + if (this !is VarInsnNode) return false + val index = `var` - (if (methodNode.access and Opcodes.ACC_STATIC != 0) 0 else 1) + return opcode == Opcodes.ALOAD && index < valueParameters.size && InlineUtil.isInlineParameter(valueParameters[index]) && + valueParameters[index].type.isSuspendFunctionType + } + + FixStackMethodTransformer().transform(thisName, methodNode) + + val sourceFrames = MethodTransformer.analyze(thisName, methodNode, SourceInterpreter()) + + val noinlineInvokes = arrayListOf>() + + for (insn in methodNode.instructions.asSequence()) { + if (insn.opcode != Opcodes.INVOKEINTERFACE) continue + insn as MethodInsnNode + if (!isInvokeOnLambda(insn.owner, insn.name)) continue + val frame = sourceFrames[insn.index()] ?: continue + val aload = findReceiverOfInvoke(frame, insn).takeIf { it?.isInlineSuspendParameter() == true } as? VarInsnNode ?: continue + noinlineInvokes.add(insn to aload) + } + + surroundInvokesWithSuspendMarkers(methodNode, noinlineInvokes) + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt index f3a48f1518d..e8b941b96c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/inline/inlineOnly.kt @@ -1,5 +1,5 @@ /* - * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ @@ -18,8 +18,7 @@ fun MemberDescriptor.isInlineOnlyOrReifiable(): Boolean = this is CallableMemberDescriptor && (isReifiable() || DescriptorUtils.getDirectMember(this).isReifiable() || isInlineOnly()) fun MemberDescriptor.isEffectivelyInlineOnly(): Boolean = - isInlineOnlyOrReifiable() || (this is FunctionDescriptor && isSuspend && isInline && - (valueParameters.any { it.isCrossinline } || visibility == Visibilities.PRIVATE)) + isInlineOnlyOrReifiable() || (this is FunctionDescriptor && isSuspend && isInline && visibility == Visibilities.PRIVATE) fun MemberDescriptor.isInlineOnly(): Boolean = this is FunctionDescriptor && isInline && diff --git a/compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt b/compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt new file mode 100644 index 00000000000..4ead14b567d --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt @@ -0,0 +1,78 @@ +// IGNORE_BACKEND: JVM_IR +// TARGET_BACKEND: JVM +// COMMON_COROUTINES_TEST +// WITH_RUNTIME +// WITH_COROUTINES +// NO_CHECK_LAMBDA_INLINING +// CHECK_STATE_MACHINE + +// FILE: inlineMe.kt + +package test + +inline suspend fun inlineMe(crossinline c: suspend () -> Unit) { c(); c() } + +inline suspend fun inlineMe2(c: suspend () -> Unit) { c(); c() } + +// FILE: A.java + +import test.InlineMeKt; +import helpers.CoroutineUtilKt; +import helpers.EmptyContinuation; +import kotlin.jvm.functions.Function1; +import COROUTINES_PACKAGE.Continuation; +import kotlin.Unit; + +public class A { + static Function1, Object> callback = new Function1, Object>() { + @Override + public Object invoke(Continuation continuation) { + return CoroutineUtilKt.getStateMachineChecker().suspendHere(continuation); + } + }; + public static void call(Continuation cont) { + InlineMeKt.inlineMe(callback, cont); + } + public static void call2(Continuation cont) { + InlineMeKt.inlineMe2(callback, cont); + } +} + +// FILE: box.kt + +import test.* +import helpers.* +import COROUTINES_PACKAGE.* +import COROUTINES_PACKAGE.intrinsics.* + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(CheckStateMachineContinuation) +} + +fun box(): String { + A.call(CheckStateMachineContinuation) + StateMachineChecker.check(2) + StateMachineChecker.reset() + + builder { + inlineMe { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + } + } + StateMachineChecker.check(4) + StateMachineChecker.reset() + + A.call2(CheckStateMachineContinuation) + StateMachineChecker.check(2) + + StateMachineChecker.reset() + builder { + inlineMe2 { + StateMachineChecker.suspendHere() + StateMachineChecker.suspendHere() + } + } + StateMachineChecker.check(4) + 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 5f29a1e1af7..e8cb1d1f635 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline.txt @@ -272,6 +272,50 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 { public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object } +@kotlin.Metadata +@kotlin.coroutines.jvm.internal.DebugMetadata +public final class CrossinlineKt$fold$$inlined$consumeEach$2$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$2 + inner class CrossinlineKt$fold$$inlined$consumeEach$2 + inner class CrossinlineKt$fold$$inlined$consumeEach$2$1 + public method (p0: CrossinlineKt$fold$$inlined$consumeEach$2, p1: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + +@kotlin.Metadata +public final class CrossinlineKt$fold$$inlined$consumeEach$2 { + synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef + synthetic final field $operation$inlined: kotlin.jvm.functions.Function3 + inner class CrossinlineKt$fold$$inlined$consumeEach$2 + inner class CrossinlineKt$fold$$inlined$consumeEach$2$1 + public method (p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void + public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void + public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object + public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object +} + +@kotlin.Metadata +@kotlin.coroutines.jvm.internal.DebugMetadata +public final class CrossinlineKt$fold$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 + inner class CrossinlineKt$fold$1 + public method (p0: kotlin.coroutines.Continuation): void + public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object +} + @kotlin.Metadata @kotlin.coroutines.jvm.internal.DebugMetadata public final class CrossinlineKt$range$$inlined$source$1$1 { @@ -330,12 +374,15 @@ public final class CrossinlineKt$source$1 { public final class CrossinlineKt { inner class CrossinlineKt$box$1 inner class CrossinlineKt$consumeEach$2 + inner class CrossinlineKt$fold$1 inner class CrossinlineKt$source$1 public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void - private final static method consumeEach(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method consumeEach$$forInline(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method consumeEach(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method filter(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1): SourceCrossinline - private final static method fold(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, p2: kotlin.jvm.functions.Function3, p3: kotlin.coroutines.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method fold$$forInline(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function3, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method fold(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function3, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): java.lang.Object public final static method isGood(p0: int): boolean public final static @org.jetbrains.annotations.NotNull method range(@org.jetbrains.annotations.NotNull p0: SourceCrossinline$Factory, p1: int, p2: int): SourceCrossinline public final static @org.jetbrains.annotations.NotNull method source(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): SourceCrossinline 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 a6578175370..9a3c8b6af5d 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline_1_2.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/crossinline_1_2.txt @@ -280,6 +280,52 @@ public final class CrossinlineKt$fold$$inlined$consumeEach$1 { public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object } +@kotlin.Metadata +public final class CrossinlineKt$fold$$inlined$consumeEach$2$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$2 + inner class CrossinlineKt$fold$$inlined$consumeEach$2 + inner class CrossinlineKt$fold$$inlined$consumeEach$2$1 + public method (p0: CrossinlineKt$fold$$inlined$consumeEach$2, p1: kotlin.coroutines.experimental.Continuation): void + public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object + synthetic final method getLabel(): int + synthetic final method setLabel(p0: int): void +} + +@kotlin.Metadata +public final class CrossinlineKt$fold$$inlined$consumeEach$2 { + synthetic final field $acc$inlined: kotlin.jvm.internal.Ref$ObjectRef + synthetic final field $operation$inlined: kotlin.jvm.functions.Function3 + inner class CrossinlineKt$fold$$inlined$consumeEach$2 + inner class CrossinlineKt$fold$$inlined$consumeEach$2$1 + public method (p0: kotlin.jvm.internal.Ref$ObjectRef, p1: kotlin.jvm.functions.Function3): void + public method close(@org.jetbrains.annotations.Nullable p0: java.lang.Throwable): void + public @org.jetbrains.annotations.Nullable method send$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object + public @org.jetbrains.annotations.Nullable method send(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.experimental.Continuation): java.lang.Object +} + +@kotlin.Metadata +public final class CrossinlineKt$fold$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 + inner class CrossinlineKt$fold$1 + public method (p0: kotlin.coroutines.experimental.Continuation): void + public final @org.jetbrains.annotations.Nullable method doResume(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.Nullable p1: java.lang.Throwable): java.lang.Object + synthetic final method getLabel(): int + synthetic final method setLabel(p0: int): void +} + @kotlin.Metadata public final class CrossinlineKt$range$$inlined$source$1$1 { field I$0: int @@ -340,12 +386,15 @@ public final class CrossinlineKt$source$1 { public final class CrossinlineKt { inner class CrossinlineKt$box$1 inner class CrossinlineKt$consumeEach$2 + inner class CrossinlineKt$fold$1 inner class CrossinlineKt$source$1 public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void - private final static method consumeEach(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.experimental.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method consumeEach$$forInline(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method consumeEach(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.experimental.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method filter(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function1): SourceCrossinline - private final static method fold(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, p2: kotlin.jvm.functions.Function3, p3: kotlin.coroutines.experimental.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method fold$$forInline(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function3, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method fold(@org.jetbrains.annotations.NotNull p0: SourceCrossinline, p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function3, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.experimental.Continuation): java.lang.Object public final static method isGood(p0: int): boolean public final static @org.jetbrains.annotations.NotNull method range(@org.jetbrains.annotations.NotNull p0: SourceCrossinline$Factory, p1: int, p2: int): SourceCrossinline public final static @org.jetbrains.annotations.NotNull method source(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): SourceCrossinline diff --git a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt index 0fc94600efa..9c7f2197e52 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation.txt @@ -174,7 +174,8 @@ public final class flow/InnerObjectRetransformationKt { public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void public final static @org.jetbrains.annotations.Nullable method check(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object - private final static method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): flow.Flow public final static @org.jetbrains.annotations.NotNull method flowWith(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): flow.Flow } 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 fdaa97d17a4..d5da1039d9e 100644 --- a/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation_1_2.txt +++ b/compiler/testData/codegen/box/coroutines/tailCallOptimizations/innerObjectRetransformation_1_2.txt @@ -180,7 +180,8 @@ public final class flow/InnerObjectRetransformationKt { public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String public final static method builder(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): void public final static @org.jetbrains.annotations.Nullable method check(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object - private final static method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.experimental.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.experimental.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): flow.Flow public final static @org.jetbrains.annotations.NotNull method flowWith(@org.jetbrains.annotations.NotNull p0: flow.Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): flow.Flow } diff --git a/compiler/testData/codegen/bytecodeListing/inline/simpleNamed.txt b/compiler/testData/codegen/bytecodeListing/inline/simpleNamed.txt index 8be4b63ffe6..4e5a791ff5a 100644 --- a/compiler/testData/codegen/bytecodeListing/inline/simpleNamed.txt +++ b/compiler/testData/codegen/bytecodeListing/inline/simpleNamed.txt @@ -1,7 +1,8 @@ @kotlin.Metadata public final class Foo { public method (): void - private final method acceptsCrossinline(p0: kotlin.jvm.functions.Function0, p1: kotlin.coroutines.Continuation): java.lang.Object + private final @org.jetbrains.annotations.Nullable method acceptsCrossinline$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object + public final @org.jetbrains.annotations.Nullable method acceptsCrossinline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object private final @org.jetbrains.annotations.Nullable method generic$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object private final @org.jetbrains.annotations.Nullable method generic$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object public final @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object @@ -18,7 +19,8 @@ public final class Foo { @kotlin.Metadata public final class SimpleNamedKt { - private final static method acceptsCrossinline(p0: kotlin.jvm.functions.Function0, p1: kotlin.coroutines.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method acceptsCrossinline$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method acceptsCrossinline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function0, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object private final static @org.jetbrains.annotations.Nullable method generic$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object private final static @org.jetbrains.annotations.Nullable method generic$$forInline(p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object public final static @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object diff --git a/compiler/testData/codegen/bytecodeListing/tcoContinuation.txt b/compiler/testData/codegen/bytecodeListing/tcoContinuation.txt index 9eff51e4b3a..ee8f5375bca 100644 --- a/compiler/testData/codegen/bytecodeListing/tcoContinuation.txt +++ b/compiler/testData/codegen/bytecodeListing/tcoContinuation.txt @@ -347,7 +347,8 @@ public final class TcoContinuationKt$transform$$inlined$flow$3 { public final class TcoContinuationKt { inner class TcoContinuationKt$collect$2 inner class TcoContinuationKt$flow$1 - private final static method collect(@org.jetbrains.annotations.NotNull p0: Flow, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.experimental.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.experimental.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.experimental.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): Flow public final static @org.jetbrains.annotations.Nullable method foo(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.experimental.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method map(@org.jetbrains.annotations.NotNull p0: Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): Flow diff --git a/compiler/testData/codegen/bytecodeListing/tcoContinuation_1_3.txt b/compiler/testData/codegen/bytecodeListing/tcoContinuation_1_3.txt index 2f37543ae51..90de9a89fa2 100644 --- a/compiler/testData/codegen/bytecodeListing/tcoContinuation_1_3.txt +++ b/compiler/testData/codegen/bytecodeListing/tcoContinuation_1_3.txt @@ -322,7 +322,8 @@ public final class TcoContinuationKt$transform$$inlined$flow$3 { public final class TcoContinuationKt { inner class TcoContinuationKt$collect$2 inner class TcoContinuationKt$flow$1 - private final static method collect(@org.jetbrains.annotations.NotNull p0: Flow, p1: kotlin.jvm.functions.Function2, p2: kotlin.coroutines.Continuation): java.lang.Object + private final static @org.jetbrains.annotations.Nullable method collect$$forInline(@org.jetbrains.annotations.NotNull p0: Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object + public final static @org.jetbrains.annotations.Nullable method collect(@org.jetbrains.annotations.NotNull p0: Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method flow(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): Flow public final static @org.jetbrains.annotations.Nullable method foo(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object public final static @org.jetbrains.annotations.NotNull method map(@org.jetbrains.annotations.NotNull p0: Flow, @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): Flow diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f6da264818e..749c9ecb9c4 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -7441,6 +7441,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { public void testSeveralCaptures_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines"); } + + @TestMetadata("suspendInlineWithCrossinline.kt") + public void testSuspendInlineWithCrossinline_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("suspendInlineWithCrossinline.kt") + public void testSuspendInlineWithCrossinline_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.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 92092b90dab..12825b2c909 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7441,6 +7441,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes public void testSeveralCaptures_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines"); } + + @TestMetadata("suspendInlineWithCrossinline.kt") + public void testSuspendInlineWithCrossinline_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("suspendInlineWithCrossinline.kt") + public void testSuspendInlineWithCrossinline_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.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 f15c9ad7864..65abff12dff 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -7441,6 +7441,16 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes public void testSeveralCaptures_1_3() throws Exception { runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/severalCaptures.kt", "kotlin.coroutines"); } + + @TestMetadata("suspendInlineWithCrossinline.kt") + public void testSuspendInlineWithCrossinline_1_2() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt", "kotlin.coroutines.experimental"); + } + + @TestMetadata("suspendInlineWithCrossinline.kt") + public void testSuspendInlineWithCrossinline_1_3() throws Exception { + runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/javaInterop/suspendInlineWithCrossinline.kt", "kotlin.coroutines"); + } } @TestMetadata("compiler/testData/codegen/box/coroutines/localFunctions")