From 63f6d515bc06ba1e6540eea88dafa8af2ff481eb Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Wed, 18 Sep 2019 21:59:36 +0300 Subject: [PATCH] JVM_IR: Generate correct invoke of numbered suspend lambda Instead of continuation type as last parameter's type, generate Object type. --- .../kotlin/codegen/inline/MethodInliner.kt | 4 ++-- .../backend/jvm/codegen/CoroutineCodegen.kt | 17 +++++++++++------ .../kotlin/backend/jvm/codegen/PromisedValue.kt | 3 ++- .../coroutines/debug/firstSuspensionPoint.kt | 2 +- .../intrinsicSemantics/intercepted.kt | 1 - .../startCoroutineUninterceptedOrReturn.kt | 1 - ...oroutineUninterceptedOrReturnInterception.kt | 1 - .../suspendCoroutineUninterceptedOrReturn.kt | 1 - .../testData/codegen/box/coroutines/kt28844.kt | 2 +- .../localFunctions/named/insideLambda.kt | 1 - .../inlineTwoReceivers.kt | 1 - .../suspendFunctionTypeCall/localVal.kt | 1 - .../suspendFunctionTypeCall/suspendModifier.kt | 1 - .../codegen/boxInline/suspend/multipleLocals.kt | 2 -- .../suspend/multipleSuspensionPoints.kt | 2 -- .../innerLambdaWithoutCrossinline.kt | 2 -- 16 files changed, 17 insertions(+), 25 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt index 6a171a84c02..582da911cff 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.kt @@ -243,8 +243,8 @@ class MethodInliner( // if this does not happen, insert fake continuation, since we could not have one yet. val argumentTypes = Type.getArgumentTypes(desc) if (argumentTypes.size != parametersSize && - // TODO: Workaround IR-related problem. In IR we already have lowered lambda, while in Old BE we don't. - !(inliningContext.root.state.isIrBackend && desc.endsWith("Lkotlin/coroutines/Continuation;)Ljava/lang/Object;")) + // But do not add it in IR. In IR we already have lowered lambdas with additional parameter, while in Old BE we don't. + !inliningContext.root.state.isIrBackend ) { addFakeContinuationMarker(this) coroutineDesc = Type.getMethodDescriptor(Type.getReturnType(desc), *argumentTypes, AsmTypes.OBJECT_TYPE) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt index 7ccf28fe7d4..51806011706 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/CoroutineCodegen.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_COMPLETION_PARAM import org.jetbrains.kotlin.config.isReleaseCoroutines import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction @@ -32,10 +33,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl import org.jetbrains.kotlin.ir.types.createType import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection -import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols -import org.jetbrains.kotlin.ir.util.explicitParameters -import org.jetbrains.kotlin.ir.util.isSuspend -import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.psi.KtElement @@ -100,6 +98,9 @@ internal fun generateStateMachineForLambda( internal fun IrFunction.isInvokeSuspendOfLambda(context: JvmBackendContext): Boolean = name.asString() == INVOKE_SUSPEND_METHOD_NAME && parent in context.suspendLambdaToOriginalFunctionMap +internal fun IrFunction.isInvokeOfSuspendLambda(context: JvmBackendContext): Boolean = + name.asString() == "invoke" && parent in context.suspendLambdaToOriginalFunctionMap + internal fun IrFunction.isInvokeSuspendOfContinuation(context: JvmBackendContext): Boolean = name.asString() == INVOKE_SUSPEND_METHOD_NAME && parentAsClass in context.suspendFunctionContinuations.values @@ -115,6 +116,9 @@ private object SUSPEND_FUNCTION_VIEW : IrDeclarationOriginImpl("SUSPEND_FUNCTION private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFunction { require(this.isSuspend && this is IrSimpleFunction) val originalDescriptor = this.descriptor + // For SuspendFunction{N}.invoke we need to generate INVOKEINTERFACE Function{N+1}.invoke(...Ljava/lang/Object;)... + // instead of INVOKEINTERFACE Function{N+1}.invoke(...Lkotlin/coroutines/Continuation;)... + val isInvokeOfNumberedSuspendFunction = (symbol.owner.parent as? IrClass)?.defaultType?.isSuspendFunction() == true val descriptor = if (originalDescriptor is DescriptorWithContainerSource && originalDescriptor.containerSource != null) WrappedFunctionDescriptorWithContainerSource(originalDescriptor.containerSource!!) @@ -134,8 +138,9 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti valueParameters.mapTo(it.valueParameters) { p -> p.copyTo(it) } it.addValueParameter( - SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, context.ir.symbols.continuationClass - .createType(false, listOf(makeTypeProjection(returnType, Variance.INVARIANT))) + SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, + if (isInvokeOfNumberedSuspendFunction) context.irBuiltIns.anyNType + else context.ir.symbols.continuationClass.createType(false, listOf(makeTypeProjection(returnType, Variance.INVARIANT))) ) val valueParametersMapping = explicitParameters.zip(it.explicitParameters).toMap() it.body = body?.deepCopyWithSymbols(this) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt index 04e84e95a58..277839842e1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt @@ -90,7 +90,8 @@ fun PromisedValue.coerce(target: Type, irTarget: IrType): PromisedValue { // Boxing and unboxing kotlin.Result leads to CCE in generated code val doNotCoerceKotlinResultInContinuation = - codegen.irFunction.isInvokeSuspendOfContinuation(codegen.context) && (irType.isKotlinResult() || irTarget.isKotlinResult()) + (codegen.irFunction.isInvokeSuspendOfContinuation(codegen.context) || codegen.irFunction.isInvokeOfSuspendLambda(codegen.context)) + && (irType.isKotlinResult() || irTarget.isKotlinResult()) // Coerce inline classes if ((isFromTypeInlineClass || isToTypeInlineClass) && !doNotCoerceKotlinResultInContinuation) { diff --git a/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt b/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt index 15e6c7c17f7..9e7bb3be67e 100644 --- a/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt +++ b/compiler/testData/codegen/box/coroutines/debug/firstSuspensionPoint.kt @@ -1,4 +1,4 @@ -// IGNORE_BACKEND: JVM_IR +// This test depends on line numbers // TARGET_BACKEND: JVM // WITH_RUNTIME // FULL_JDK diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/intercepted.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/intercepted.kt index 469857ca656..75bbf60adee 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/intercepted.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/intercepted.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt index 1ef5224af52..51bee8a6ded 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturn.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt index 0de6b44a0c6..73361284dc5 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/startCoroutineUninterceptedOrReturnInterception.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/suspendCoroutineUninterceptedOrReturn.kt b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/suspendCoroutineUninterceptedOrReturn.kt index ae726a55d72..77a3e04b449 100644 --- a/compiler/testData/codegen/box/coroutines/intrinsicSemantics/suspendCoroutineUninterceptedOrReturn.kt +++ b/compiler/testData/codegen/box/coroutines/intrinsicSemantics/suspendCoroutineUninterceptedOrReturn.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/kt28844.kt b/compiler/testData/codegen/box/coroutines/kt28844.kt index 331db670ef5..7fbb3846bd5 100644 --- a/compiler/testData/codegen/box/coroutines/kt28844.kt +++ b/compiler/testData/codegen/box/coroutines/kt28844.kt @@ -1,7 +1,7 @@ // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST -// IGNORE_BACKEND: JVM_IR, NATIVE +// IGNORE_BACKEND: NATIVE import helpers.* import COROUTINES_PACKAGE.* diff --git a/compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt b/compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt index bf8b5b94897..d03f2546a69 100644 --- a/compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt +++ b/compiler/testData/codegen/box/coroutines/localFunctions/named/insideLambda.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/inlineTwoReceivers.kt b/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/inlineTwoReceivers.kt index 57b6b7ad53d..678765c6e7b 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/inlineTwoReceivers.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFunctionAsCoroutine/inlineTwoReceivers.kt @@ -1,5 +1,4 @@ // KJS_WITH_FULL_RUNTIME -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt b/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt index 645c130ade2..02113d0964d 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/localVal.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // WITH_COROUTINES // COMMON_COROUTINES_TEST diff --git a/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/suspendModifier.kt b/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/suspendModifier.kt index 941476e8be7..e80bb76623c 100644 --- a/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/suspendModifier.kt +++ b/compiler/testData/codegen/box/coroutines/suspendFunctionTypeCall/suspendModifier.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // WITH_RUNTIME // COMMON_COROUTINES_TEST // WITH_COROUTINES diff --git a/compiler/testData/codegen/boxInline/suspend/multipleLocals.kt b/compiler/testData/codegen/boxInline/suspend/multipleLocals.kt index cdc2dc5c298..a8960ae97fe 100644 --- a/compiler/testData/codegen/boxInline/suspend/multipleLocals.kt +++ b/compiler/testData/codegen/boxInline/suspend/multipleLocals.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: inlined.kt // COMMON_COROUTINES_TEST // WITH_RUNTIME diff --git a/compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt b/compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt index ce8d495d327..4309e753c7c 100644 --- a/compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt +++ b/compiler/testData/codegen/boxInline/suspend/multipleSuspensionPoints.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: inlined.kt // COMMON_COROUTINES_TEST // WITH_RUNTIME diff --git a/compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt b/compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt index cdf811aa86a..6edf3d7c16c 100644 --- a/compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt +++ b/compiler/testData/codegen/boxInline/suspend/stateMachine/innerLambdaWithoutCrossinline.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// IGNORE_BACKEND_MULTI_MODULE: JVM_IR // FILE: inlined.kt // COMMON_COROUTINES_TEST // WITH_RUNTIME