JVM_IR: carry less state while transforming suspend funs into views
This commit is contained in:
+27
-46
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.types.*
|
|||||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
@@ -596,33 +597,28 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun addContinuationObjectAndContinuationParameterToSuspendFunctions(irFile: IrFile) {
|
private fun addContinuationObjectAndContinuationParameterToSuspendFunctions(irFile: IrFile) {
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
|
class MutableFlag(var capturesCrossinline: Boolean)
|
||||||
private val functionsStack = arrayListOf<IrFunction>()
|
irFile.accept(object : IrElementTransformer<MutableFlag?> {
|
||||||
private val suspendFunctionsCapturingCrossinline = mutableSetOf<IrFunction>()
|
override fun visitClass(declaration: IrClass, data: MutableFlag?): IrStatement {
|
||||||
private val functionsToAdd = arrayListOf<MutableSet<IrFunction>>()
|
declaration.transformDeclarationsFlat {
|
||||||
|
if (it is IrSimpleFunction && it.isSuspend && it.origin != IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA)
|
||||||
override fun visitClass(declaration: IrClass): IrStatement {
|
return@transformDeclarationsFlat transformToView(it)
|
||||||
functionsToAdd.push(mutableSetOf())
|
it.accept(this, null)
|
||||||
return (super.visitClass(declaration) as IrClass).also { irClass ->
|
null
|
||||||
for (function in functionsToAdd.pop()) {
|
|
||||||
function.parent = irClass
|
|
||||||
irClass.declarations.add(function)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
private fun transformToView(function: IrSimpleFunction): List<IrFunction>? {
|
||||||
functionsStack.push(declaration)
|
val flag = MutableFlag(false)
|
||||||
val function = super.visitFunction(declaration) as IrFunction
|
function.accept(this, flag)
|
||||||
functionsStack.pop()
|
|
||||||
if (!function.isSuspend || function.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) return function
|
|
||||||
|
|
||||||
val view = function.getOrCreateSuspendFunctionViewIfNeeded(context) as IrSimpleFunction
|
val view = function.getOrCreateSuspendFunctionViewIfNeeded(context) as IrSimpleFunction
|
||||||
|
val result = mutableListOf(view)
|
||||||
|
if (function.body == null || !function.hasContinuation()) return result
|
||||||
|
|
||||||
if (function.body == null || !function.hasContinuation()) return view
|
if (flag.capturesCrossinline || function.isInline) {
|
||||||
|
result += buildFunWithDescriptorForInlining(view.descriptor) {
|
||||||
if (function in suspendFunctionsCapturingCrossinline || function.isInline) {
|
|
||||||
val newFunction = buildFunWithDescriptorForInlining(view.descriptor) {
|
|
||||||
name = Name.identifier(view.name.asString() + FOR_INLINE_SUFFIX)
|
name = Name.identifier(view.name.asString() + FOR_INLINE_SUFFIX)
|
||||||
returnType = view.returnType
|
returnType = view.returnType
|
||||||
modality = view.modality
|
modality = view.modality
|
||||||
@@ -637,44 +633,29 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
|||||||
copyAttributes(view)
|
copyAttributes(view)
|
||||||
body = view.copyBodyTo(this)
|
body = view.copyBodyTo(this)
|
||||||
}
|
}
|
||||||
registerNewFunction(newFunction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val newFunction = if ((function as IrSimpleFunction).isOverridable) {
|
val newFunction = if (function.isOverridable) {
|
||||||
// Create static method for the suspend state machine method so that reentering the method
|
// Create static method for the suspend state machine method so that reentering the method
|
||||||
// does not lead to virtual dispatch to the wrong method.
|
// does not lead to virtual dispatch to the wrong method.
|
||||||
registerNewFunction(view)
|
createStaticSuspendImpl(view).also { result += it }
|
||||||
createStaticSuspendImpl(view)
|
|
||||||
} else view
|
} else view
|
||||||
|
|
||||||
newFunction.body = context.createIrBuilder(newFunction.symbol).irBlockBody {
|
newFunction.body = context.createIrBuilder(newFunction.symbol).irBlockBody {
|
||||||
+generateContinuationClassForNamedFunction(
|
+generateContinuationClassForNamedFunction(newFunction, view.dispatchReceiverParameter, function)
|
||||||
newFunction,
|
|
||||||
view.dispatchReceiverParameter,
|
|
||||||
declaration as IrAttributeContainer
|
|
||||||
)
|
|
||||||
for (statement in newFunction.body!!.statements) {
|
for (statement in newFunction.body!!.statements) {
|
||||||
+statement
|
+statement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newFunction
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun registerNewFunction(function: IrFunction) {
|
|
||||||
functionsToAdd.peek()!!.add(function)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitFieldAccess(expression: IrFieldAccessExpression): IrExpression {
|
|
||||||
val result = super.visitFieldAccess(expression)
|
|
||||||
val function = functionsStack.peek() ?: return result
|
|
||||||
if (function.isSuspend &&
|
|
||||||
expression.symbol.owner.origin == LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
|
|
||||||
) {
|
|
||||||
suspendFunctionsCapturingCrossinline += function
|
|
||||||
}
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
override fun visitFieldAccess(expression: IrFieldAccessExpression, data: MutableFlag?): IrExpression {
|
||||||
|
if (expression.symbol.owner.origin == LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE)
|
||||||
|
data?.capturesCrossinline = true
|
||||||
|
return super.visitFieldAccess(expression, data)
|
||||||
|
}
|
||||||
|
}, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SuspendLambdaInfo(val reference: IrFunctionReference) {
|
private class SuspendLambdaInfo(val reference: IrFunctionReference) {
|
||||||
|
|||||||
Reference in New Issue
Block a user