JVM_IR: Generate correct invoke of numbered suspend lambda

Instead of continuation type as last parameter's type, generate Object
type.
This commit is contained in:
Ilmir Usmanov
2019-09-18 21:59:36 +03:00
parent 587fcafc85
commit 63f6d515bc
16 changed files with 17 additions and 25 deletions
@@ -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)
@@ -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)
@@ -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) {
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JVM_IR
// This test depends on line numbers
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FULL_JDK
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
+1 -1
View File
@@ -1,7 +1,7 @@
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
// IGNORE_BACKEND: JVM_IR, NATIVE
// IGNORE_BACKEND: NATIVE
import helpers.*
import COROUTINES_PACKAGE.*
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,5 +1,4 @@
// KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// WITH_COROUTINES
// COMMON_COROUTINES_TEST
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
// COMMON_COROUTINES_TEST
// WITH_COROUTINES
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: inlined.kt
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: inlined.kt
// COMMON_COROUTINES_TEST
// WITH_RUNTIME
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: inlined.kt
// COMMON_COROUTINES_TEST
// WITH_RUNTIME