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.copyValueParametersInsertingContinuationFrom
|
||||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
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.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilder
|
import org.jetbrains.kotlin.codegen.ClassBuilder
|
||||||
@@ -71,8 +72,8 @@ internal fun generateStateMachineForNamedFunction(
|
|||||||
internalNameForDispatchReceiver = classCodegen.visitor.thisName,
|
internalNameForDispatchReceiver = classCodegen.visitor.thisName,
|
||||||
putContinuationParameterToLvt = false,
|
putContinuationParameterToLvt = false,
|
||||||
disableTailCallOptimizationForFunctionReturningUnit = irFunction.returnType.isUnit() &&
|
disableTailCallOptimizationForFunctionReturningUnit = irFunction.returnType.isUnit() &&
|
||||||
(irFunction as? IrSimpleFunction)?.overriddenSymbols?.let { symbols ->
|
(irFunction as? IrSimpleFunction)?.allOverridden()?.toList()?.let { functions ->
|
||||||
symbols.isNotEmpty() && symbols.any { !it.owner.returnType.isUnit() }
|
functions.isNotEmpty() && functions.any { !it.returnType.isUnit() }
|
||||||
} == true
|
} == true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -135,10 +136,10 @@ internal fun IrFunction.getOrCreateSuspendFunctionViewIfNeeded(context: JvmBacke
|
|||||||
if (!isSuspend || origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW ||
|
if (!isSuspend || origin == JvmLoweredDeclarationOrigin.SUSPEND_FUNCTION_VIEW ||
|
||||||
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW
|
origin == JvmLoweredDeclarationOrigin.FOR_INLINE_STATE_MACHINE_TEMPLATE_CAPTURES_CROSSINLINE_VIEW
|
||||||
) return this
|
) 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)
|
require(this.isSuspend && this is IrSimpleFunction)
|
||||||
// For SuspendFunction{N}.invoke we need to generate INVOKEINTERFACE Function{N+1}.invoke(...Ljava/lang/Object;)...
|
// 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;)...
|
// 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)
|
continuationValueParam = it.addValueParameter(SUSPEND_FUNCTION_COMPLETION_PARAMETER_NAME, continuationType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the suspend function view to the map before transforming the body to make sure
|
if (generateBody) {
|
||||||
// that recursive suspend functions do not lead to unbounded recursion at compile time.
|
// Add the suspend function view to the map before transforming the body to make sure
|
||||||
context.recordSuspendFunctionView(this, it)
|
// 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()
|
val valueParametersMapping = explicitParameters.zip(it.explicitParameters.filter { it != continuationValueParam }).toMap()
|
||||||
it.body = body?.deepCopyWithSymbols(this)
|
it.body = body?.deepCopyWithSymbols(this)
|
||||||
it.body?.transformChildrenVoid(object : VariableRemapper(valueParametersMapping) {
|
it.body?.transformChildrenVoid(object : VariableRemapper(valueParametersMapping) {
|
||||||
// Do not cross class boundaries inside functions. Otherwise, callable references will try to access wrong $completion.
|
// 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 visitClass(declaration: IrClass): IrStatement = declaration
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression =
|
override fun visitCall(expression: IrCall): IrExpression =
|
||||||
super.visitCall(expression.createSuspendFunctionCallViewIfNeeded(context, it, callerIsInlineLambda = false))
|
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)
|
val sw = if (skipGenericSignature) JvmSignatureWriter() else BothSignatureWriter(BothSignatureWriter.Mode.METHOD)
|
||||||
|
|
||||||
typeMapper.writeFormalTypeParameters(function.typeParameters, sw)
|
typeMapper.writeFormalTypeParameters(function.typeParameters, sw)
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// 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
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
-1
@@ -1,6 +1,5 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// IGNORE_BACKEND: JVM_IR
|
|
||||||
// FULL_JDK
|
// FULL_JDK
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
|
|||||||
Reference in New Issue
Block a user