From 9103b6a51b173d952e776cefb2c7efdeceb3706b Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 8 May 2018 15:21:02 +0200 Subject: [PATCH] Migrate DescriptorsFactory.getOuterThisFieldSymbol() API to symbols --- .../common/descriptors/DescriptorsFactory.kt | 5 +- .../common/lower/InnerClassesLowering.kt | 72 ++++++++++++------- .../ir/backend/js/JsDescriptorsFactory.kt | 26 +++---- .../jvm/descriptors/JvmDescriptorsFactory.kt | 24 ++++--- 4 files changed, 76 insertions(+), 51 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt index bdc41ce79c0..2c800908b36 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/descriptors/DescriptorsFactory.kt @@ -6,8 +6,7 @@ package org.jetbrains.kotlin.backend.common.descriptors import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol @@ -15,7 +14,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol interface DescriptorsFactory { fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol - fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor + fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol fun getSymbolForObjectInstance(singleton: IrClassSymbol): IrFieldSymbol } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt index f1202c3d07e..d4a7c582974 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InnerClassesLowering.kt @@ -8,21 +8,22 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.ClassLoweringPass -import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor +import org.jetbrains.kotlin.descriptors.ValueDescriptor +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl -import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.transformFlat -import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid -import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import java.util.* @@ -34,14 +35,14 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { } private inner class InnerClassTransformer(val irClass: IrClass) { - val classDescriptor = irClass.descriptor - - lateinit var outerThisFieldDescriptor: PropertyDescriptor + lateinit var outerThisField: IrField val oldConstructorParameterToNew = HashMap() + val class2Symbol = HashMap() fun lowerInnerClass() { if (!irClass.descriptor.isInner) return + rememberClassSymbols() createOuterThisField() lowerConstructors() @@ -49,15 +50,33 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { lowerOuterThisReferences() } - private fun createOuterThisField() { - outerThisFieldDescriptor = context.descriptorsFactory.getOuterThisFieldDescriptor(irClass.descriptor) + //TODO: rewrite: this methods is required to 'getClassForImplicitThis' method + private fun rememberClassSymbols() { + var current = irClass.parent as? IrClass + while (current != null) { + class2Symbol[current.descriptor] = current + current = current.parent as? IrClass + } + irClass.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + override fun visitClass(declaration: IrClass) { + return super.visitClass(declaration).also { class2Symbol[declaration.descriptor] = declaration } + } + }) + } + + private fun createOuterThisField() { irClass.declarations.add( IrFieldImpl( irClass.startOffset, irClass.endOffset, FIELD_FOR_OUTER_THIS, - outerThisFieldDescriptor - ) + context.descriptorsFactory.getOuterThisFieldSymbol(irClass) + ).also { + outerThisField = it + } ) } @@ -97,7 +116,7 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { blockBody.statements.add( instanceInitializerIndex, IrSetFieldImpl( - startOffset, endOffset, outerThisFieldDescriptor, + startOffset, endOffset, outerThisField.symbol, IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), IrGetValueImpl(startOffset, endOffset, outerThisValueParameter) ) @@ -131,29 +150,29 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { override fun visitGetValue(expression: IrGetValue): IrExpression { expression.transformChildrenVoid(this) - val implicitThisClass = expression.descriptor.getClassDescriptorForImplicitThis() ?: return expression + val implicitThisClass = expression.symbol.getClassForImplicitThis() ?: return expression - if (implicitThisClass == classDescriptor) return expression + if (implicitThisClass == irClass) return expression val startOffset = expression.startOffset val endOffset = expression.endOffset val origin = expression.origin var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin) - var innerClass = classDescriptor + var innerClass = irClass while (innerClass != implicitThisClass) { - if (!innerClass.isInner) { + if (!innerClass.descriptor.isInner) { // Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is - // should be transformed by closures conversion. return expression } - val outerThisField = context.descriptorsFactory.getOuterThisFieldDescriptor(innerClass) + val outerThisField = context.descriptorsFactory.getOuterThisFieldSymbol(innerClass) irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin) - val outer = innerClass.containingDeclaration - innerClass = outer as? ClassDescriptor ?: + val outer = innerClass.parent + innerClass = outer as? IrClass ?: throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer") } @@ -162,11 +181,12 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass { }) } - private fun ValueDescriptor.getClassDescriptorForImplicitThis(): ClassDescriptor? { - if (this is ReceiverParameterDescriptor) { - val receiverValue = value + private fun IrValueSymbol.getClassForImplicitThis(): IrClass? { + val descriptor1 = this.descriptor + if (descriptor1 is ReceiverParameterDescriptor) { + val receiverValue = descriptor1.value if (receiverValue is ImplicitClassReceiver) { - return receiverValue.classDescriptor + return class2Symbol[receiverValue.classDescriptor]!! } } return null diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt index 949fab538dd..f637c56adba 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsDescriptorsFactory.kt @@ -24,30 +24,32 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.resolve.DescriptorUtils import java.util.* class JsDescriptorsFactory( private val builtIns: KotlinBuiltIns ) : DescriptorsFactory { private val singletonFieldDescriptors = HashMap, IrFieldSymbol>() - private val outerThisDescriptors = HashMap() + private val outerThisFieldSymbols = HashMap() private val innerClassConstructors = HashMap() override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = TODO() - override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = - if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") - else outerThisDescriptors.getOrPut(innerClassDescriptor) { - val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) - ?: throw AssertionError("No containing class for inner class $innerClassDescriptor") + override fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol = + if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}") + else outerThisFieldSymbols.getOrPut(innerClass) { + val outerClass = innerClass.parent as? IrClass + ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}") - PropertyDescriptorImpl.create( - innerClassDescriptor, + IrFieldSymbolImpl(PropertyDescriptorImpl.create( + innerClass.descriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PROTECTED, @@ -63,13 +65,13 @@ class JsDescriptorsFactory( false ).apply { setType( - outerClassDescriptor.defaultType, + outerClass.defaultType, emptyList(), - innerClassDescriptor.thisAsReceiverParameter, + innerClass.descriptor.thisAsReceiverParameter, null as? ReceiverParameterDescriptor ) initialize(null, null) - } + }) } override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt index c4ce1c807bd..b90a233ec2e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmDescriptorsFactory.kt @@ -26,13 +26,15 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi2ir.PsiSourceManager -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.org.objectweb.asm.Opcodes import java.util.* @@ -42,7 +44,7 @@ class JvmDescriptorsFactory( private val builtIns: KotlinBuiltIns ) : DescriptorsFactory { private val singletonFieldDescriptors = HashMap, IrFieldSymbol>() - private val outerThisDescriptors = HashMap() + private val outerThisDescriptors = HashMap() private val innerClassConstructors = HashMap() override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = @@ -63,15 +65,17 @@ class JvmDescriptorsFactory( ) } - override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = - if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") - else outerThisDescriptors.getOrPut(innerClassDescriptor) { - val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) - ?: throw AssertionError("No containing class for inner class $innerClassDescriptor") + override fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol = + if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}") + else outerThisDescriptors.getOrPut(innerClass) { + val outerClass = innerClass.parent as? IrClass + ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}") - JvmPropertyDescriptorImpl.createFinalField( - Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor, - Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE + IrFieldSymbolImpl( + JvmPropertyDescriptorImpl.createFinalField( + Name.identifier("this$0"), outerClass.defaultType, innerClass.descriptor, + Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE + ) ) }