[K/N] Remove hack from suspend function inheritance to allow export
Before that commit, function in coroutine implementation class was override for both SuspendFunctionN's and FunctionN+1's invoke, which somehow works, but breaks exporting classes with such functions. Now it's two separate functions, as it should be normally. ^KT-49395
This commit is contained in:
+4
-9
@@ -251,12 +251,10 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
|
||||
} else {
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
val functionClass: IrClass
|
||||
val functionClass: IrClass?
|
||||
val suspendFunctionClass: IrClass?
|
||||
if (isKSuspendFunction) {
|
||||
functionClass = symbols.functionN(numberOfParameters + 1).owner
|
||||
val continuationType = continuationClassSymbol.typeWith(referencedFunction.returnType)
|
||||
superTypes += functionClass.typeWith(functionParameterTypes + continuationType + irBuiltIns.anyNType)
|
||||
functionClass = null
|
||||
suspendFunctionClass = symbols.kSuspendFunctionN(numberOfParameters).owner
|
||||
superTypes += suspendFunctionClass.typeWith(functionParameterTypes + referencedFunction.returnType)
|
||||
} else {
|
||||
@@ -275,13 +273,10 @@ internal class FunctionReferenceLowering(val context: Context): FileLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
if (!isKSuspendFunction)
|
||||
if (functionClass != null)
|
||||
buildInvokeMethod(functionClass.getInvokeFunction())
|
||||
if (suspendFunctionClass != null) {
|
||||
buildInvokeMethod(suspendFunctionClass.getInvokeFunction()).also {
|
||||
if (isKSuspendFunction)
|
||||
it.overriddenSymbols += functionClass.getInvokeFunction().symbol
|
||||
}
|
||||
buildInvokeMethod(suspendFunctionClass.getInvokeFunction())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrSetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSuspendableExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSuspensionPointImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
@@ -59,6 +60,20 @@ internal class NativeSuspendFunctionsLowering(ctx: Context): AbstractSuspendFunc
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override fun IrBuilderWithScope.launchSuspendFunctionWithGivenContinuation(
|
||||
symbol: IrSimpleFunctionSymbol, dispatchReceiver: IrExpression,
|
||||
arguments: List<IrExpression>, continuation: IrExpression
|
||||
) = irCall(this@NativeSuspendFunctionsLowering.context.ir.symbols.coroutineLaunchpad).apply {
|
||||
putValueArgument(0, irCall(symbol).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>) {
|
||||
|
||||
+8
-3
@@ -613,7 +613,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
private fun mapReturnType(actualType: IrType, returnType: IrType) = mapWrappedType(actualType, returnType)
|
||||
|
||||
|
||||
private fun getNode(expression: IrExpression): Scoped<DataFlowIR.Node> {
|
||||
private fun getNode(expression: IrExpression, continuationOverride: DataFlowIR.Node? = null): Scoped<DataFlowIR.Node> {
|
||||
if (expression is IrGetValue) {
|
||||
val valueDeclaration = expression.symbol.owner
|
||||
if (valueDeclaration is IrValueParameter)
|
||||
@@ -715,7 +715,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
}
|
||||
|
||||
is IrCall -> when (value.symbol) {
|
||||
getContinuationSymbol -> getContinuation().value
|
||||
getContinuationSymbol -> continuationOverride ?: getContinuation().value
|
||||
|
||||
symbols.coroutineLaunchpad -> getNode(
|
||||
value.getValueArgument(0)!!,
|
||||
continuationOverride = expressionToEdge(value.getValueArgument(1)!!).node
|
||||
).value
|
||||
|
||||
in arrayGetSymbols -> {
|
||||
val actualCallee = value.actualCallee
|
||||
@@ -765,7 +770,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
.map { expressionToEdge(it.second) }
|
||||
.let {
|
||||
if (callee.isSuspend)
|
||||
it + DataFlowIR.Edge(getContinuation().value, null)
|
||||
it + DataFlowIR.Edge(continuationOverride ?: getContinuation().value, null)
|
||||
else
|
||||
it
|
||||
}
|
||||
|
||||
+4
-13
@@ -1372,21 +1372,12 @@ internal object DevirtualizationAnalysis {
|
||||
callSite.origin,
|
||||
actualCallee.parentAsClass.symbol
|
||||
)
|
||||
if (actualCallee.explicitParametersCount == arguments.size) {
|
||||
arguments.forEachIndexed { index, argument -> call.putArgument(index, argument) }
|
||||
return call
|
||||
}
|
||||
assert(actualCallee.isSuspend && actualCallee.explicitParametersCount == arguments.size - 1) {
|
||||
"Incorrect number of arguments: expected [${actualCallee.explicitParametersCount}] but was [${arguments.size - 1}]\n" +
|
||||
assert(actualCallee.explicitParametersCount == arguments.size) {
|
||||
"Incorrect number of arguments: expected [${actualCallee.explicitParametersCount}] but was [${arguments.size}]\n" +
|
||||
actualCallee.dump()
|
||||
}
|
||||
val continuation = arguments.last()
|
||||
for (index in 0..arguments.size - 2)
|
||||
call.putArgument(index, arguments[index])
|
||||
return irCall(context.ir.symbols.coroutineLaunchpad, actualType).apply {
|
||||
putValueArgument(0, call)
|
||||
putValueArgument(1, continuation)
|
||||
}
|
||||
arguments.forEachIndexed { index, argument -> call.putArgument(index, argument) }
|
||||
return call
|
||||
}
|
||||
|
||||
fun IrBuilderWithScope.irDevirtualizedCall(callee: IrCall, actualType: IrType,
|
||||
|
||||
+10
@@ -235,6 +235,7 @@ 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>()
|
||||
@@ -489,6 +490,13 @@ internal object FileInitializersOptimization {
|
||||
return curData
|
||||
}
|
||||
|
||||
private fun processCoroutineLaunchpad(expression: IrCall, data: BitSet): BitSet {
|
||||
val call = expression.getValueArgument(0)!!
|
||||
val continuation = expression.getValueArgument(1)!!
|
||||
val curData = continuation.accept(this, data)
|
||||
return call.accept(this, curData)
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: BitSet) =
|
||||
processCall(expression, expression.actualCallee, data)
|
||||
|
||||
@@ -499,6 +507,8 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user