diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt index 8b44e0388b4..f8f40db9211 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/AbstractClosureAnnotator.kt @@ -5,7 +5,6 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression -import org.jetbrains.kotlin.ir.expressions.impl.IrSetterCallImpl import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid @@ -15,7 +14,13 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny // TODO: synchronize with JVM BE class Closure(val capturedValues: List) -abstract class AbstractClosureAnnotator : IrElementVisitorVoid { +private fun MutableList.push(element: E) = this.add(element) + +private fun MutableList.pop() = this.removeAt(size - 1) + +private fun MutableList.peek(): E? = if (size == 0) null else this[size - 1] + +abstract class AbstractClosureAnnotator { protected abstract fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) protected abstract fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) @@ -48,83 +53,117 @@ abstract class AbstractClosureAnnotator : IrElementVisitorVoid { } } - private val classClosures = mutableMapOf() - private val closuresStack = mutableListOf() + val functionClosures = mutableMapOf() - private fun MutableList.push(element: E) = this.add(element) - - private fun MutableList.pop() = this.removeAt(size - 1) - - private fun MutableList.peek(): E? = if (size == 0) null else this[size - 1] - - override fun visitElement(element: IrElement) { - element.acceptChildrenVoid(this) + fun annotate(declaration: IrDeclaration) { + // First pass - collect all closures for classes and functions. + declaration.acceptChildrenVoid(ClosureCollectorVisitor()) + // Second pass - add callees' closures for callers' ones. + declaration.acceptChildrenVoid(CallsCollectorVisitor()) } - override fun visitClass(declaration: IrClass) { - val classDescriptor = declaration.descriptor - val closureBuilder = ClosureBuilder() + private abstract class ClosureCollectorVisitorBase : IrElementVisitorVoid { + open protected fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) {} + open protected fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) {} - closureBuilder.declareVariable(classDescriptor.thisAsReceiverParameter) - if (classDescriptor.isInner) - closureBuilder.declareVariable((classDescriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter) + protected val closuresStack = mutableListOf() + protected val classClosures = mutableMapOf() - closuresStack.push(closureBuilder) - declaration.acceptChildrenVoid(this) - closuresStack.pop() - - val superClassClosure = classClosures[classDescriptor.getSuperClassOrAny()] - if (superClassClosure != null) { - // Capture all values from the super class since we need to call constructor of super class - // with its captured values. - closureBuilder.addNested(superClassClosure) + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) } - val closure = closureBuilder.buildClosure() + override fun visitClass(declaration: IrClass) { + val classDescriptor = declaration.descriptor + val closureBuilder = ClosureBuilder() - if (DescriptorUtils.isLocal(classDescriptor)) { - recordClassClosure(classDescriptor, closure) - classClosures[classDescriptor] = closure + closureBuilder.declareVariable(classDescriptor.thisAsReceiverParameter) + if (classDescriptor.isInner) + closureBuilder.declareVariable((classDescriptor.containingDeclaration as ClassDescriptor).thisAsReceiverParameter) + + closuresStack.push(closureBuilder) + declaration.acceptChildrenVoid(this) + closuresStack.pop() + + val superClassClosure = classClosures[classDescriptor.getSuperClassOrAny()] + if (superClassClosure != null) { + // Capture all values from the super class since we need to call constructor of super class + // with its captured values. + closureBuilder.addNested(superClassClosure) + } + + val closure = closureBuilder.buildClosure() + + if (DescriptorUtils.isLocal(classDescriptor)) { + recordClassClosure(classDescriptor, closure) + classClosures[classDescriptor] = closure + } + + closuresStack.peek()?.addNested(closure) } - closuresStack.peek()?.addNested(closure) - } + override fun visitFunction(declaration: IrFunction) { + val functionDescriptor = declaration.descriptor + val closureBuilder = ClosureBuilder() - override fun visitFunction(declaration: IrFunction) { - val functionDescriptor = declaration.descriptor - val closureBuilder = ClosureBuilder() + functionDescriptor.valueParameters.forEach { closureBuilder.declareVariable(it) } + closureBuilder.declareVariable(functionDescriptor.dispatchReceiverParameter) + closureBuilder.declareVariable(functionDescriptor.extensionReceiverParameter) + if (functionDescriptor is ConstructorDescriptor) + closureBuilder.declareVariable(functionDescriptor.constructedClass.thisAsReceiverParameter) - functionDescriptor.valueParameters.forEach { closureBuilder.declareVariable(it) } - closureBuilder.declareVariable(functionDescriptor.dispatchReceiverParameter) - closureBuilder.declareVariable(functionDescriptor.extensionReceiverParameter) - if (functionDescriptor is ConstructorDescriptor) - closureBuilder.declareVariable(functionDescriptor.constructedClass.thisAsReceiverParameter) + closuresStack.push(closureBuilder) + declaration.acceptChildrenVoid(this) + closuresStack.pop() - closuresStack.push(closureBuilder) - declaration.acceptChildrenVoid(this) - closuresStack.pop() + val closure = closureBuilder.buildClosure() - val closure = closureBuilder.buildClosure() + if (DescriptorUtils.isLocal(functionDescriptor)) { + recordFunctionClosure(functionDescriptor, closure) + } - if (DescriptorUtils.isLocal(functionDescriptor)) { - recordFunctionClosure(functionDescriptor, closure) + closuresStack.peek()?.addNested(closure) } - closuresStack.peek()?.addNested(closure) + override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) { + // Getter and setter of local delegated properties are special generated functions and don't have closure. + declaration.delegate.initializer?.acceptVoid(this) + } + + override fun visitVariableAccess(expression: IrValueAccessExpression) { + closuresStack.peek()?.seeVariable(expression.descriptor) + super.visitVariableAccess(expression) + } + + override fun visitVariable(declaration: IrVariable) { + closuresStack.peek()?.declareVariable(declaration.descriptor) + super.visitVariable(declaration) + } } - override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) { - // Getter and setter of local delegated properties are special generated functions and don't have closure. - declaration.delegate.initializer?.acceptVoid(this) + private inner class ClosureCollectorVisitor : ClosureCollectorVisitorBase() { + override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) { + functionClosures[functionDescriptor] = closure + } + + override fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) = + this@AbstractClosureAnnotator.recordClassClosure(classDescriptor, closure) } - override fun visitVariableAccess(expression: IrValueAccessExpression) { - closuresStack.peek()?.seeVariable(expression.descriptor) - super.visitVariableAccess(expression) - } + private inner class CallsCollectorVisitor : ClosureCollectorVisitorBase() { + override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) = + this@AbstractClosureAnnotator.recordFunctionClosure(functionDescriptor, closure) - override fun visitVariable(declaration: IrVariable) { - closuresStack.peek()?.declareVariable(declaration.descriptor) - super.visitVariable(declaration) + + override fun visitCall(expression: IrCall) { + expression.acceptChildrenVoid(this) + val descriptor = expression.descriptor + if (descriptor is FunctionDescriptor && DescriptorUtils.isLocal(descriptor)) { + val callClosure = functionClosures[descriptor] + callClosure?.let { + closuresStack.peek()?.addNested(callClosure) + } + } + } } } \ No newline at end of file diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt index e86a373c33e..3246d7c24ec 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/lower/LocalDeclarationsLowering.kt @@ -623,7 +623,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai private fun collectClosures() { - memberDeclaration.acceptChildrenVoid(object : AbstractClosureAnnotator() { + object : AbstractClosureAnnotator() { override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) { localFunctions[functionDescriptor]?.closure = closure } @@ -631,7 +631,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai override fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) { localClasses[classDescriptor]?.closure = closure } - }) + }.annotate(memberDeclaration) } private fun collectLocalDeclarations() {