From f960c70c68abfa25429303d175f7025b6224a3fe Mon Sep 17 00:00:00 2001 From: Ilya Matveev Date: Wed, 1 Feb 2017 15:47:46 +0300 Subject: [PATCH] backend: Copy AbstractClosureRecorder from Kotlin JVM Copied from org.jetbrains.kotlin.backend.common. AbstractClosureAnnotator --- .../backend/common/AbstractClosureRecorder.kt | 107 ++++++++++++++++++ .../common/lower/LocalDeclarationsLowering.kt | 9 +- 2 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractClosureRecorder.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractClosureRecorder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractClosureRecorder.kt new file mode 100644 index 00000000000..a85fe6878bd --- /dev/null +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/common/AbstractClosureRecorder.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.common + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.resolve.DescriptorUtils +import java.util.* + +abstract class AbstractClosureRecorder : IrElementVisitorVoid { + protected abstract fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) + protected abstract fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) + + private class ClosureBuilder(val owner: DeclarationDescriptor) { + val capturedValues = mutableSetOf() + + fun buildClosure() = Closure(capturedValues.toList()) + + fun addNested(closure: Closure) { + fillInNestedClosure(capturedValues, closure.capturedValues) + } + + private fun fillInNestedClosure(destination: MutableSet, nested: List) { + nested.filterTo(destination) { + it.containingDeclaration != owner + } + } + } + + private val closuresStack = ArrayDeque() + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + val classDescriptor = declaration.descriptor + val closureBuilder = ClosureBuilder(classDescriptor) + + closuresStack.push(closureBuilder) + declaration.acceptChildrenVoid(this) + closuresStack.pop() + + val closure = closureBuilder.buildClosure() + + if (DescriptorUtils.isLocal(classDescriptor)) { + recordClassClosure(classDescriptor, closure) + } + + closuresStack.peek()?.addNested(closure) + } + + override fun visitFunction(declaration: IrFunction) { + val functionDescriptor = declaration.descriptor + val closureBuilder = ClosureBuilder(functionDescriptor) + + closuresStack.push(closureBuilder) + declaration.acceptChildrenVoid(this) + closuresStack.pop() + + val closure = closureBuilder.buildClosure() + + if (DescriptorUtils.isLocal(functionDescriptor)) { + recordFunctionClosure(functionDescriptor, 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) { + val closureBuilder = closuresStack.peek() ?: return + + val variableDescriptor = expression.descriptor + if (variableDescriptor.containingDeclaration != closureBuilder.owner) { + closureBuilder.capturedValues.add(variableDescriptor) + } + + expression.acceptChildrenVoid(this) + } + +} 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 906805305b3..9c9ff1d29a9 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 @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.backend.common.lower -import org.jetbrains.kotlin.backend.common.AbstractClosureAnnotator +import org.jetbrains.kotlin.backend.common.AbstractClosureRecorder import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.Closure import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass @@ -30,10 +30,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid -import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.descriptorUtil.parents import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf @@ -589,7 +586,7 @@ class LocalDeclarationsLowering(val context: BackendContext): DeclarationContain private fun collectClosures() { - memberFunction.acceptChildrenVoid(object : AbstractClosureAnnotator() { + memberFunction.acceptChildrenVoid(object : AbstractClosureRecorder() { override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) { localFunctions[functionDescriptor]?.closure = closure }