JVM_IR: carry less state while transforming suspend funs into views

This commit is contained in:
pyos
2020-02-26 13:46:06 +01:00
committed by Ilmir Usmanov
parent 5896d8003e
commit 6184171a11
@@ -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) {