JVM_IR: detect lambdas capturing crossinline through fields
This commit is contained in:
+12
-32
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user