[K/N] Use suspend function desugaring lowerings.

This commit is contained in:
Pavel Kunyavskiy
2022-09-05 16:14:29 +02:00
committed by Space Team
parent 8886e1b8b4
commit 817dba8564
19 changed files with 227 additions and 169 deletions
@@ -20,6 +20,7 @@ interface Mapping {
val capturedConstructors: Delegate<IrConstructor, IrConstructor>
val reflectedNameAccessor: Delegate<IrClass, IrSimpleFunction>
val suspendFunctionsToFunctionWithContinuations: Delegate<IrSimpleFunction, IrSimpleFunction>
val functionWithContinuationsToSuspendFunctions: Delegate<IrSimpleFunction, IrSimpleFunction>
abstract class Delegate<K : IrDeclaration, V> {
abstract operator fun get(key: K): V?
@@ -77,6 +78,7 @@ open class DefaultMapping(delegateFactory: DelegateFactory = DefaultDelegateFact
override val capturedConstructors: Mapping.Delegate<IrConstructor, IrConstructor> = delegateFactory.newDeclarationToDeclarationMapping()
override val reflectedNameAccessor: Mapping.Delegate<IrClass, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
override val suspendFunctionsToFunctionWithContinuations: Mapping.Delegate<IrSimpleFunction, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
override val functionWithContinuationsToSuspendFunctions: Mapping.Delegate<IrSimpleFunction, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
}
fun <V : Any> KMutableProperty0<V?>.getOrPut(fn: () -> V) = this.get() ?: fn().also {
@@ -6,8 +6,6 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement
@@ -19,7 +17,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
@@ -33,9 +30,6 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
protected abstract val stateMachineMethodName: Name
protected abstract fun getCoroutineBaseClass(function: IrFunction): IrClassSymbol
protected abstract fun nameForCoroutineClass(function: IrFunction): Name
protected abstract fun IrBuilderWithScope.launchSuspendFunctionWithGivenContinuation(
symbol: IrSimpleFunctionSymbol, superQualifierSymbol: IrClassSymbol?, dispatchReceiver: IrExpression,
arguments: List<IrExpression>, continuation: IrExpression) : IrExpression
protected abstract fun buildStateMachine(
stateMachineFunction: IrFunction,
@@ -57,106 +51,6 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
markSuspendLambdas(irFile)
buildCoroutines(irFile)
transformCallableReferencesToSuspendLambdas(irFile)
addMissingSupertypesToSuspendFunctionImplementingClasses(irFile)
}
private fun addMissingSupertypesToSuspendFunctionImplementingClasses(irFile: IrFile) {
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
// Don't need to iterate through children. All local classes are already moved to the top level by this moment.
}
override fun visitClass(declaration: IrClass) {
addMissingSupertypes(declaration)
declaration.acceptChildrenVoid(this)
}
private fun addMissingSupertypes(clazz: IrClass) {
val suspendFunctionTypes = getAllSubstitutedSupertypes(clazz).filter {
// SuspendFunction class is some hack in old Kotlin/Native compiler versions.
// It's not used now, but is considered as SuspendFunction-like class in isSuspendFunction util,
// if found in old klib. We need just to ignore it.
it.isSuspendFunction() && it.classOrNull?.owner?.name?.toString() != "SuspendFunction"
}.toSet()
for (suspendFunctionType in suspendFunctionTypes) {
val suspendFunctionClassSymbol = suspendFunctionType.classOrNull ?: continue
val suspendFunction = suspendFunctionClassSymbol.owner.simpleFunctions().single {
it.name == OperatorNameConventions.INVOKE
}
val invokeFunction = clazz.simpleFunctions().single {
it.name == OperatorNameConventions.INVOKE && it.overrides(suspendFunction)
}
if (invokeFunction.modality == Modality.ABSTRACT) {
continue
}
val suspendFunctionArity = suspendFunction.valueParameters.size
val functionClassSymbol = symbols.functionN(suspendFunctionArity + 1)
val functionSymbol = functionClassSymbol.owner.simpleFunctions().single {
it.name == OperatorNameConventions.INVOKE
}.symbol
val functionClassTypeArguments = suspendFunctionType.arguments.mapIndexed { index, argument ->
val type = (argument as IrTypeProjection).type
if (index == suspendFunctionArity) continuationClassSymbol.typeWith(type) else type
} + context.irBuiltIns.anyNType
val functionType = functionClassSymbol.typeWith(functionClassTypeArguments)
clazz.superTypes += functionType
context.irFactory.buildFun {
startOffset = SYNTHETIC_OFFSET
endOffset = SYNTHETIC_OFFSET
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
name = OperatorNameConventions.INVOKE
visibility = DescriptorVisibilities.PROTECTED
returnType = context.irBuiltIns.anyNType
}.apply {
parent = clazz
clazz.declarations += this
typeParameters = invokeFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
valueParameters = invokeFunction.valueParameters
.mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
valueParameters += buildValueParameter(this) {
index = valueParameters.size
type = context.irBuiltIns.anyNType
name = "completion".synthesizedName
}
this.createDispatchReceiverParameter()
overriddenSymbols += functionSymbol
val thisReceiver = dispatchReceiverParameter!!
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
+irReturn(
launchSuspendFunctionWithGivenContinuation(
invokeFunction.symbol,
superQualifierSymbol = invokeFunction.parentAsClass.symbol, // Call non-virtually.
irGet(thisReceiver),
valueParameters.dropLast(1).map { irGet(it) },
irGet(valueParameters.last())
)
)
}
}
}
}
})
}
private fun buildCoroutines(irFile: IrFile) {
@@ -433,7 +327,9 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
)
val suspendInvokeFunction =
suspendFunctionClass!!.simpleFunctions().single { it.name == OperatorNameConventions.INVOKE }
suspendFunctionClass!!.simpleFunctions().single { it.name == OperatorNameConventions.INVOKE }.let {
context.mapping.functionWithContinuationsToSuspendFunctions[it] ?: it
}
buildInvokeMethod(
functionInvokeFunction = suspendInvokeFunction,
@@ -722,3 +618,5 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
private val CREATE_IDENTIFIER = Name.identifier("create")
}
}
@@ -226,7 +226,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
body = context.createIrBuilder(symbol).irBlockBody {
+irReturn(
irCall(
wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }.symbol,
getSuspendFunctionWithoutContinuation(wrappedFunctionClass.functions.single { it.name == OperatorNameConventions.INVOKE }).symbol,
originalSuperMethod.returnType
).apply {
dispatchReceiver = irGetField(irGet(dispatchReceiverParameter!!), field)
@@ -88,12 +88,14 @@ private fun transformSuspendFunction(context: CommonBackendContext, function: Ir
fun IrSimpleFunction.getOrCreateFunctionWithContinuationStub(context: CommonBackendContext): IrSimpleFunction {
return context.mapping.suspendFunctionsToFunctionWithContinuations.getOrPut(this) {
createSuspendFunctionStub(context)
createSuspendFunctionStub(context).also {
context.mapping.functionWithContinuationsToSuspendFunctions[it] = this
}
}
}
private fun IrSimpleFunction.createSuspendFunctionStub(context: CommonBackendContext): IrSimpleFunction {
require(this.isSuspend)
require(this.isSuspend) { "$fqNameWhenAvailable should be a suspend function to create version with contunation" }
return factory.buildFun {
updateFrom(this@createSuspendFunctionStub)
isSuspend = false
@@ -103,9 +105,9 @@ private fun IrSimpleFunction.createSuspendFunctionStub(context: CommonBackendCon
}.also { function ->
function.parent = parent
function.annotations += annotations
function.metadata = metadata
function.copyAnnotationsFrom(this)
function.copyAttributes(this)
function.copyTypeParametersFrom(this)
val substitutionMap = makeTypeParameterSubstitutionMap(this, function)
@@ -2,6 +2,7 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.coroutines.AddContinuationToNonLocalSuspendFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesExtractionFromInlineFunctionsLowering
import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunctionsLowering
@@ -383,8 +384,13 @@ internal val varargPhase = makeKonanFileLoweringPhase(
prerequisite = setOf(functionReferencePhase, defaultParameterExtentPhase, interopPhase, functionsWithoutBoundCheck)
)
internal val coroutinesPhase = makeKonanFileLoweringPhase(
::NativeSuspendFunctionsLowering,
internal val coroutinesPhase = makeKonanFileOpPhase(
{ context, irFile ->
NativeSuspendFunctionsLowering(context).lower(irFile)
AddContinuationToNonLocalSuspendFunctionsLowering(context).lower(irFile)
NativeAddContinuationToFunctionCallsLowering(context).lower(irFile)
AddFunctionSupertypeToSuspendFunctionLowering(context).lower(irFile)
},
name = "Coroutines",
description = "Coroutines lowering",
prerequisite = setOf(localFunctionsPhase, finallyBlocksPhase, kotlinNothingValueExceptionPhase)
@@ -356,6 +356,7 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
val interfaceVTableEntries: List<IrSimpleFunction> by lazy {
require(irClass.isInterface)
irClass.simpleFunctions()
.map { it.getLoweredVersion() }
.filter { f ->
f.isOverridable && f.bridgeTarget == null
&& (f.isReal || f.overriddenSymbols.any { f.needBridgeTo(it.owner) })
@@ -503,8 +504,15 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) {
}
}
/**
* Normally, function should be already replaced. But if the function come from LazyIr, it can be not replaced.
*/
fun IrSimpleFunction.getLoweredVersion() = context.mapping.suspendFunctionsToFunctionWithContinuations[this] ?: this
private val overridableOrOverridingMethods: List<IrSimpleFunction>
get() = irClass.simpleFunctions().filter { it.isOverridableOrOverrides && it.bridgeTarget == null }
get() = irClass.simpleFunctions()
.map {it.getLoweredVersion() }
.filter { it.isOverridableOrOverrides && it.bridgeTarget == null }
private val IrFunction.uniqueName get() = computeFunctionName()
}
@@ -324,8 +324,6 @@ internal class KonanSymbols(
override val returnIfSuspended = internalFunction("returnIfSuspended")
val coroutineLaunchpad = internalFunction("coroutineLaunchpad")
override val suspendCoroutineUninterceptedOrReturn = internalFunction("suspendCoroutineUninterceptedOrReturn")
private val coroutinesIntrinsicsPackage =
@@ -72,7 +72,6 @@ internal enum class IntrinsicType {
// Coroutines
GET_CONTINUATION,
RETURN_IF_SUSPENDED,
COROUTINE_LAUNCHPAD,
// Interop
INTEROP_READ_BITS,
INTEROP_WRITE_BITS,
@@ -160,6 +159,7 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
* processes it. Otherwise it returns null.
*/
fun tryEvaluateSpecialCall(callSite: IrFunctionAccessExpression, resultSlot: LLVMValueRef?): LLVMValueRef? {
resultSlot.let{}
val function = callSite.symbol.owner
if (!function.isTypedIntrinsic) {
return null
@@ -184,18 +184,6 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
)
codegen.theUnitInstanceRef.llvm
}
IntrinsicType.COROUTINE_LAUNCHPAD -> {
val suspendFunctionCall = callSite.getValueArgument(0) as IrCall
val continuation = environment.evaluateExpression(callSite.getValueArgument(1)!!, null)
val suspendFunction = suspendFunctionCall.symbol.owner
assert(suspendFunction.isSuspend) { "Call to a suspend function expected but was ${suspendFunction.dump()}" }
environment.evaluateCall(suspendFunction,
environment.evaluateExplicitArgs(suspendFunctionCall) + listOf(continuation),
environment.calculateLifetime(suspendFunctionCall),
suspendFunctionCall.superQualifierSymbol?.owner,
resultSlot,
)
}
else -> null
}
}
@@ -270,7 +258,6 @@ internal class IntrinsicGenerator(private val environment: IntrinsicGeneratorEnv
reportNonLoweredIntrinsic(intrinsicType)
IntrinsicType.INIT_INSTANCE,
IntrinsicType.OBJC_INIT_BY,
IntrinsicType.COROUTINE_LAUNCHPAD,
IntrinsicType.OBJC_GET_SELECTOR,
IntrinsicType.IMMUTABLE_BLOB ->
reportSpecialIntrinsic(intrinsicType)
@@ -0,0 +1,119 @@
/*
* Copyright 2010-2022 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.
*/
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.coroutines.getOrCreateFunctionWithContinuationStub
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.util.OperatorNameConventions
/**
* This lowering is a hack, to provide compatibility with leaked jvm implementation detail.
*
* On jvm SuspendFunctionN<Args, Ret> is implicitly implementing FunctionN+1<Args, Continuation, Any(?)>,
* and visa versa, and it can be used for reusing continuation objects for performance improvements.
*
* Also, it is used in startCoroutineUninterceptedOrReturn intrinsic.
*
* So we are adding corresponding FunctionN+1 into supper types.
* At the current point, lowered suspend function signature is overriding its invoke method.
*
*/
internal class AddFunctionSupertypeToSuspendFunctionLowering(val context: Context) : FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
// Don't need to iterate through children. All local classes are already moved to the top level by this moment.
}
override fun visitClass(declaration: IrClass) {
addMissingSupertypes(declaration)
declaration.acceptChildrenVoid(this)
}
private fun IrSimpleFunction.getLowered() = if (isSuspend)
getOrCreateFunctionWithContinuationStub(context)
else
this
private fun IrClass.getInvokeFunction() = simpleFunctions().single {
it.name == OperatorNameConventions.INVOKE
}.getLowered()
private fun addOverride(clazz: IrClass, alreadyOverridden: IrType, toOverride: IrType) {
val alreadyOverriddenFunction = alreadyOverridden.classOrNull!!.owner.getInvokeFunction()
val functionToOverride = toOverride.classOrNull!!.owner.getInvokeFunction()
val invokeFunction = clazz.simpleFunctions().single { it.overrides(alreadyOverriddenFunction) }
if (invokeFunction.modality == Modality.ABSTRACT) return
clazz.superTypes += toOverride
invokeFunction.overriddenSymbols += functionToOverride.symbol
}
private fun addMissingSupertypes(clazz: IrClass) {
val suspendFunctionSuperTypes = getAllSubstitutedSupertypes(clazz).filter {
// SuspendFunction class is some hack in old Kotlin/Native compiler versions.
// It's not used now, but is considered as SuspendFunction-like class in isSuspendFunction util,
// if found in old klib. We need just to ignore it.
it.isSuspendFunction() && it.classOrNull?.owner?.name?.toString() != "SuspendFunction"
}.toSet()
val continuationClassSymbol = context.ir.symbols.continuationClass
fun IrSimpleType.getClassAt(index: Int) = (this.arguments.getOrNull(index) as? IrTypeProjection)?.type?.classOrNull
val functionWithContinuationSuperTypes = getAllSubstitutedSupertypes(clazz).filter {
it.isFunction() &&
it.getClassAt(it.arguments.size - 2) == continuationClassSymbol
}.toSet()
for (suspendFunctionType in suspendFunctionSuperTypes) {
val functionClassTypeArguments = suspendFunctionType.arguments.mapIndexed { index, argument ->
val type = (argument as IrTypeProjection).type
if (index == suspendFunctionType.arguments.indices.last) {
continuationClassSymbol.typeWith(type)
} else {
type
}
} + context.irBuiltIns.anyNType
val functionType = context.ir.symbols.functionN(functionClassTypeArguments.size - 1).typeWith(functionClassTypeArguments)
addOverride(clazz, suspendFunctionType, functionType)
}
for (functionType in functionWithContinuationSuperTypes) {
val suspendFunctionClassTypeArguments = functionType.arguments.dropLast(1).mapIndexed { index, argument ->
val type = (argument as IrTypeProjection).type
if (index == functionType.arguments.indices.last - 1) {
require(type.classOrNull == continuationClassSymbol)
when (val typeArgument = (type as IrSimpleType).arguments.single()) {
is IrTypeProjection -> typeArgument.type
else -> context.irBuiltIns.anyNType
}
} else {
type
}
}
val suspendFunctionType = context.ir.symbols.suspendFunctionN(suspendFunctionClassTypeArguments.size - 1).typeWith(suspendFunctionClassTypeArguments)
addOverride(clazz, functionType, suspendFunctionType)
}
}
})
}
}
@@ -171,8 +171,6 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
private val irBuiltIns = context.irBuiltIns
private val symbols = context.ir.symbols
private val getContinuationSymbol = symbols.getContinuation
private val continuationClassSymbol = getContinuationSymbol.owner.returnType.classifierOrFail as IrClassSymbol
private val startOffset = functionReference.startOffset
private val endOffset = functionReference.endOffset
private val referencedFunction = functionReference.symbol.owner
@@ -268,18 +266,8 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
superTypes += suspendFunctionClass.typeWith(functionParameterAndReturnTypes)
} else {
functionClass = (if (isKFunction) symbols.kFunctionN(numberOfParameters) else symbols.functionN(numberOfParameters)).owner
suspendFunctionClass = null
superTypes += functionClass.typeWith(functionParameterAndReturnTypes)
val lastParameterType = unboundFunctionParameters.lastOrNull()?.type
if (lastParameterType?.classifierOrNull != continuationClassSymbol)
suspendFunctionClass = null
else {
lastParameterType as IrSimpleType
// If the last parameter is Continuation<> inherit from SuspendFunction.
suspendFunctionClass = symbols.suspendFunctionN(numberOfParameters - 1).owner
val suspendFunctionClassTypeParameters = functionParameterTypes.dropLast(1) +
(lastParameterType.arguments.single().typeOrNull ?: irBuiltIns.anyNType)
superTypes += suspendFunctionClass.symbol.typeWith(suspendFunctionClassTypeParameters)
}
}
if (functionClass != null)
@@ -440,7 +428,10 @@ internal class FunctionReferenceLowering(val context: Context) : FileLoweringPas
return false
}
private fun buildInvokeMethod(superFunction: IrSimpleFunction): IrSimpleFunction {
private fun buildInvokeMethod(superFunction: IrSimpleFunction) =
buildInvokeMethodImpl(context.mapping.functionWithContinuationsToSuspendFunctions[superFunction] ?: superFunction)
private fun buildInvokeMethodImpl(superFunction: IrSimpleFunction): IrSimpleFunction {
return IrFunctionImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2022 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.
*/
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.lower.coroutines.AbstractAddContinuationToFunctionCallsLowering
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.overrides
internal class NativeAddContinuationToFunctionCallsLowering(override val context: Context) : AbstractAddContinuationToFunctionCallsLowering() {
/*
* In complex cases suspend functions are converted to state-machine class with invokeSuspend method.
* In that case continuation is an object itself
* In simple cases, function is left as is, and receives continuation as its last parameter
* We should handle both cases here
*/
override fun IrSimpleFunction.getContinuationParameter() = when {
overrides(context.ir.symbols.invokeSuspendFunction.owner) -> dispatchReceiverParameter!!
else -> {
valueParameters.lastOrNull().also {
require(origin == IrDeclarationOrigin.LOWERED_SUSPEND_FUNCTION) { "Continuation parameter only exists in lowered suspend functions, but function origin is $origin" }
require(it != null && it.origin == IrDeclarationOrigin.CONTINUATION) { "Continuation parameter is expected to be last one" }
}!!
}
}
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.lower.SingleAbstractMethodLowering
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
@@ -24,4 +25,8 @@ internal class NativeSingleAbstractMethodLowering(context: Context) : SingleAbst
}
override val IrType.needEqualsHashCodeMethods get() = true
override fun getSuspendFunctionWithoutContinuation(function: IrSimpleFunction) = function.let {
context.mapping.functionWithContinuationsToSuspendFunctions[it] ?: it
}
}
@@ -59,19 +59,6 @@ internal class NativeSuspendFunctionsLowering(ctx: Context): AbstractSuspendFunc
}
override fun IrBuilderWithScope.launchSuspendFunctionWithGivenContinuation(
symbol: IrSimpleFunctionSymbol, superQualifierSymbol: IrClassSymbol?, dispatchReceiver: IrExpression,
arguments: List<IrExpression>, continuation: IrExpression
) = irCall(this@NativeSuspendFunctionsLowering.context.ir.symbols.coroutineLaunchpad).apply {
putValueArgument(0, irCall(symbol.owner, superQualifierSymbol = superQualifierSymbol).apply {
this.dispatchReceiver = dispatchReceiver
arguments.forEachIndexed { index, irExpression ->
putValueArgument(index, irExpression)
}
})
putValueArgument(1, continuation)
}
override fun buildStateMachine(stateMachineFunction: IrFunction,
transformingFunction: IrFunction,
argumentToPropertiesMap: Map<IrValueParameter, IrField>) {
@@ -714,11 +714,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
is IrCall -> when (value.symbol) {
getContinuationSymbol -> continuationOverride ?: getContinuation().value
symbols.coroutineLaunchpad -> getNode(
value.getValueArgument(0)!!,
continuationOverride = expressionToEdge(value.getValueArgument(1)!!).node
).value
in arrayGetSymbols -> {
val actualCallee = value.actualCallee
@@ -234,7 +234,6 @@ internal object FileInitializersOptimization {
}
private val executeImplSymbol = context.ir.symbols.executeImpl
private val coroutineLaunchpadSymbol = context.ir.symbols.coroutineLaunchpad
private val getContinuationSymbol = context.ir.symbols.getContinuation
private var dummySet = mutableSetOf<IrFunctionAccessExpression>()
@@ -506,8 +505,6 @@ internal object FileInitializersOptimization {
return processExecuteImpl(expression, data)
if (expression.symbol == getContinuationSymbol)
return data
if (expression.symbol == coroutineLaunchpadSymbol)
return processCoroutineLaunchpad(expression, data)
if (!expression.isVirtualCall)
return processCall(expression, expression.actualCallee, data)
val devirtualizedCallSite = virtualCallSites[expression] ?: return data
@@ -4,6 +4,7 @@
*/
package codegen.function.unreachable_statement_after_return
import kotlin.coroutines.*
fun test1(): Any? {
return 1
@@ -25,10 +26,42 @@ fun test4(): Int {
42
}
suspend fun test5(): Any? {
return 5
42
}
suspend fun test6(): Int? {
return 6
42
}
suspend fun test7(): Any {
return 7
42
}
suspend fun test8(): Int {
return 8
42
}
@Suppress("UNCHECKED_CAST")
private fun <T> (suspend () -> T).runCoroutine() : T {
var result : Any? = null
startCoroutine(Continuation(EmptyCoroutineContext) { result = it.getOrThrow() })
return result as T
}
fun main() {
println(test1())
println(test2())
println(test3())
println(test4())
println(::test5.runCoroutine())
println(::test6.runCoroutine())
println(::test7.runCoroutine())
println(::test8.runCoroutine())
}
@@ -25,6 +25,3 @@ internal inline suspend fun getCoroutineContext(): CoroutineContext =
@TypedIntrinsic(IntrinsicType.RETURN_IF_SUSPENDED)
@PublishedApi
internal external suspend fun <T> returnIfSuspended(@Suppress("UNUSED_PARAMETER") argument: Any?): T
@TypedIntrinsic(IntrinsicType.COROUTINE_LAUNCHPAD)
internal external fun coroutineLaunchpad(suspendFunctionCall: Any?, continuation: Continuation<*>): Any?
@@ -61,7 +61,6 @@ class IntrinsicType {
// Coroutines
const val GET_CONTINUATION = "GET_CONTINUATION"
const val RETURN_IF_SUSPENDED = "RETURN_IF_SUSPENDED"
const val COROUTINE_LAUNCHPAD = "COROUTINE_LAUNCHPAD"
// Interop
const val INTEROP_READ_PRIMITIVE = "INTEROP_READ_PRIMITIVE"