JVM_IR: Fix bridges generation for suspend functions
Use view's signature as jvm signature.
This commit is contained in:
+18
-15
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyValueParametersInsertingContinuationFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||
import org.jetbrains.kotlin.backend.common.lower.allOverridden
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||
@@ -71,8 +72,8 @@ internal fun generateStateMachineForNamedFunction(
|
||||
internalNameForDispatchReceiver = classCodegen.visitor.thisName,
|
||||
putContinuationParameterToLvt = false,
|
||||
disableTailCallOptimizationForFunctionReturningUnit = irFunction.returnType.isUnit() &&
|
||||
(irFunction as? IrSimpleFunction)?.overriddenSymbols?.let { symbols ->
|
||||
symbols.isNotEmpty() && symbols.any { !it.owner.returnType.isUnit() }
|
||||
(irFunction as? IrSimpleFunction)?.allOverridden()?.toList()?.let { functions ->
|
||||
functions.isNotEmpty() && functions.any { !it.returnType.isUnit() }
|
||||
} == true
|
||||
)
|
||||
}
|
||||
@@ -135,10 +136,10 @@ internal fun IrFunction.getOrCreateSuspendFunctionViewIfNeeded(context: JvmBacke
|
||||
if (!isSuspend || origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW ||
|
||||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW
|
||||
) return this
|
||||
return context.suspendFunctionOriginalToView[this] ?: suspendFunctionView(context)
|
||||
return context.suspendFunctionOriginalToView[this] ?: suspendFunctionView(context, true)
|
||||
}
|
||||
|
||||
private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFunction {
|
||||
fun IrFunction.suspendFunctionView(context: JvmBackendContext, generateBody: Boolean): IrFunction {
|
||||
require(this.isSuspend && this is IrSimpleFunction)
|
||||
// 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;)...
|
||||
@@ -175,19 +176,21 @@ private fun IrFunction.suspendFunctionView(context: JvmBackendContext): IrFuncti
|
||||
continuationValueParam = it.addValueParameter(SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, continuationType)
|
||||
}
|
||||
|
||||
// Add the suspend function view to the map before transforming the body to make sure
|
||||
// that recursive suspend functions do not lead to unbounded recursion at compile time.
|
||||
context.recordSuspendFunctionView(this, it)
|
||||
if (generateBody) {
|
||||
// Add the suspend function view to the map before transforming the body to make sure
|
||||
// that recursive suspend functions do not lead to unbounded recursion at compile time.
|
||||
context.recordSuspendFunctionView(this, it)
|
||||
|
||||
val valueParametersMapping = explicitParameters.zip(it.explicitParameters.filter { it != continuationValueParam }).toMap()
|
||||
it.body = body?.deepCopyWithSymbols(this)
|
||||
it.body?.transformChildrenVoid(object : VariableRemapper(valueParametersMapping) {
|
||||
// Do not cross class boundaries inside functions. Otherwise, callable references will try to access wrong $completion.
|
||||
override fun visitClass(declaration: IrClass): IrStatement = declaration
|
||||
val valueParametersMapping = explicitParameters.zip(it.explicitParameters.filter { it != continuationValueParam }).toMap()
|
||||
it.body = body?.deepCopyWithSymbols(this)
|
||||
it.body?.transformChildrenVoid(object : VariableRemapper(valueParametersMapping) {
|
||||
// Do not cross class boundaries inside functions. Otherwise, callable references will try to access wrong $completion.
|
||||
override fun visitClass(declaration: IrClass): IrStatement = declaration
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression =
|
||||
super.visitCall(expression.createSuspendFunctionCallViewIfNeeded(context, it, callerIsInlineLambda = false))
|
||||
})
|
||||
override fun visitCall(expression: IrCall): IrExpression =
|
||||
super.visitCall(expression.createSuspendFunctionCallViewIfNeeded(context, it, callerIsInlineLambda = false))
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
@@ -208,6 +208,13 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
}
|
||||
}
|
||||
|
||||
if (function.isSuspend && function.origin != JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW &&
|
||||
function.origin != JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW &&
|
||||
(function.parent as? IrClass)?.origin != JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
|
||||
) {
|
||||
return mapSignature(function.suspendFunctionView(context, false), skipGenericSignature)
|
||||
}
|
||||
|
||||
val sw = if (skipGenericSignature) JvmSignatureWriter() else BothSignatureWriter(BothSignatureWriter.Mode.METHOD)
|
||||
|
||||
typeMapper.writeFormalTypeParameters(function.typeParameters, sw)
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
@kotlin.Metadata
|
||||
public interface Base {
|
||||
public abstract @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
final class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$1 {
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
synthetic final field this$0: Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
||||
public method <init>(p0: Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1, 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 Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2 {
|
||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2
|
||||
public method <init>(): void
|
||||
public synthetic @org.jetbrains.annotations.Nullable method invoke(): java.lang.Object
|
||||
public final method invoke(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1 {
|
||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1
|
||||
inner class Override5Kt$box$1$invokeSuspend$$inlined$inlineMe$1$2
|
||||
public method <init>(): void
|
||||
public @org.jetbrains.annotations.Nullable method generic$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class Override5Kt$box$1 {
|
||||
private field label: int
|
||||
inner class Override5Kt$box$1
|
||||
public method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object): java.lang.Object
|
||||
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
|
||||
final class Override5Kt$inlineMe$1$generic$1 {
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
@org.jetbrains.annotations.NotNull field result: java.lang.Object
|
||||
private field this$0: Override5Kt$inlineMe$1
|
||||
public method <init>(p0: Override5Kt$inlineMe$1, 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 Override5Kt$inlineMe$1$generic$2 {
|
||||
inner class Override5Kt$inlineMe$1
|
||||
inner class Override5Kt$inlineMe$1$generic$2
|
||||
public method <init>(): void
|
||||
public synthetic @org.jetbrains.annotations.Nullable method invoke(): java.lang.Object
|
||||
public final method invoke(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Override5Kt$inlineMe$1 {
|
||||
private synthetic final field $c: kotlin.jvm.functions.Function1
|
||||
inner class Override5Kt$inlineMe$1
|
||||
inner class Override5Kt$inlineMe$1$generic$2
|
||||
public method <init>(p0: kotlin.jvm.functions.Function1): void
|
||||
public @org.jetbrains.annotations.Nullable method generic$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public @org.jetbrains.annotations.Nullable method generic(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Override5Kt {
|
||||
private static field c: kotlin.coroutines.Continuation
|
||||
inner class Override5Kt$box$1
|
||||
inner class Override5Kt$inlineMe$1
|
||||
public final static method <clinit>(): void
|
||||
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 getC(): kotlin.coroutines.Continuation
|
||||
public final static @org.jetbrains.annotations.NotNull method inlineMe(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1): Base
|
||||
public final static method setC(@org.jetbrains.annotations.Nullable p0: kotlin.coroutines.Continuation): void
|
||||
}
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// FULL_JDK
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
|
||||
Reference in New Issue
Block a user