JVM_IR: detect lambdas capturing crossinline through fields

This commit is contained in:
pyos
2020-02-17 12:22:11 +01:00
committed by Ilmir Usmanov
parent 285aa123b7
commit 5d603a8be4
2 changed files with 12 additions and 33 deletions
@@ -666,53 +666,33 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
private fun findSuspendAndInlineLambdas(irElement: IrElement): List<SuspendLambdaInfo> { private fun findSuspendAndInlineLambdas(irElement: IrElement): List<SuspendLambdaInfo> {
val suspendLambdas = arrayListOf<SuspendLambdaInfo>() val suspendLambdas = arrayListOf<SuspendLambdaInfo>()
val capturesCrossinline = mutableSetOf<IrCallableReference>()
val inlineReferences = mutableSetOf<IrCallableReference>() val inlineReferences = mutableSetOf<IrCallableReference>()
irElement.acceptChildrenVoid(object : IrInlineReferenceLocator(context) { irElement.acceptChildrenVoid(object : IrInlineReferenceLocator(context) {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitInlineReference(argument: IrCallableReference) { override fun visitInlineReference(argument: IrCallableReference) {
inlineReferences.add(argument) inlineReferences.add(argument)
val getValue = (argument as? IrGetValue) ?: return
val parameter = getValue.symbol.owner as? IrValueParameter ?: return
if (parameter.isCrossinline) {
capturesCrossinline += argument
}
} }
override fun visitFunctionReference(expression: IrFunctionReference) { override fun visitFunctionReference(expression: IrFunctionReference) {
expression.acceptChildrenVoid(this) expression.acceptChildrenVoid(this)
if (expression.isSuspend && expression !in inlineReferences && expression.origin == IrStatementOrigin.LAMBDA) { if (expression.isSuspend && expression.origin == IrStatementOrigin.LAMBDA && expression !in inlineReferences) {
var expressionCapturesCrossinline = false suspendLambdas += SuspendLambdaInfo(expression)
for (i in 0 until expression.valueArgumentsCount) {
val getValue = expression.getValueArgument(i) as? IrGetValue ?: continue
val owner = getValue.symbol.owner as? IrValueParameter ?: continue
if (owner.isCrossinline) {
expressionCapturesCrossinline = true
break
}
}
suspendLambdas += SuspendLambdaInfo(
expression.symbol.owner,
(expression.type as IrSimpleType).arguments.size - 1,
expression,
expressionCapturesCrossinline || expression in capturesCrossinline
)
} }
} }
}) })
return suspendLambdas return suspendLambdas
} }
private class SuspendLambdaInfo( private class SuspendLambdaInfo(val reference: IrFunctionReference) {
val function: IrFunction, val function = reference.symbol.owner
val arity: Int, val arity = (reference.type as IrSimpleType).arguments.size - 1
val reference: IrFunctionReference, val capturesCrossinline = function.valueParameters.any {
val capturesCrossinline: Boolean when (val argument = reference.getValueArgument(it.index)) {
) { is IrGetValue -> (argument.symbol.owner as? IrValueParameter)?.isCrossinline == true
is IrGetField -> argument.symbol.owner.origin == LocalDeclarationsLowering.DECLARATION_ORIGIN_FIELD_FOR_CROSSINLINE_CAPTURED_VALUE
else -> false
}
}
lateinit var constructor: IrConstructor lateinit var constructor: IrConstructor
} }
} }
@@ -1,5 +1,4 @@
// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM // TARGET_BACKEND: JVM
// COMMON_COROUTINES_TEST // COMMON_COROUTINES_TEST
// WITH_RUNTIME // WITH_RUNTIME