Migrate DescriptorsFactory.getOuterThisFieldSymbol() API to symbols

This commit is contained in:
Mikhael Bogdanov
2018-05-08 15:21:02 +02:00
parent ee98556669
commit 9103b6a51b
4 changed files with 76 additions and 51 deletions
@@ -6,8 +6,7 @@
package org.jetbrains.kotlin.backend.common.descriptors package org.jetbrains.kotlin.backend.common.descriptors
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
@@ -15,7 +14,7 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
interface DescriptorsFactory { interface DescriptorsFactory {
fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol
fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol
fun getSymbolForObjectInstance(singleton: IrClassSymbol): IrFieldSymbol fun getSymbolForObjectInstance(singleton: IrClassSymbol): IrFieldSymbol
} }
@@ -8,21 +8,22 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ClassLoweringPass 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.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
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.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* 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.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
import java.util.* import java.util.*
@@ -34,14 +35,14 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
} }
private inner class InnerClassTransformer(val irClass: IrClass) { private inner class InnerClassTransformer(val irClass: IrClass) {
val classDescriptor = irClass.descriptor lateinit var outerThisField: IrField
lateinit var outerThisFieldDescriptor: PropertyDescriptor
val oldConstructorParameterToNew = HashMap<ValueDescriptor, IrValueParameter>() val oldConstructorParameterToNew = HashMap<ValueDescriptor, IrValueParameter>()
val class2Symbol = HashMap<ClassDescriptor, IrClass>()
fun lowerInnerClass() { fun lowerInnerClass() {
if (!irClass.descriptor.isInner) return if (!irClass.descriptor.isInner) return
rememberClassSymbols()
createOuterThisField() createOuterThisField()
lowerConstructors() lowerConstructors()
@@ -49,15 +50,33 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
lowerOuterThisReferences() lowerOuterThisReferences()
} }
private fun createOuterThisField() { //TODO: rewrite: this methods is required to 'getClassForImplicitThis' method
outerThisFieldDescriptor = context.descriptorsFactory.getOuterThisFieldDescriptor(irClass.descriptor) 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( irClass.declarations.add(
IrFieldImpl( IrFieldImpl(
irClass.startOffset, irClass.endOffset, irClass.startOffset, irClass.endOffset,
FIELD_FOR_OUTER_THIS, 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( blockBody.statements.add(
instanceInitializerIndex, instanceInitializerIndex,
IrSetFieldImpl( IrSetFieldImpl(
startOffset, endOffset, outerThisFieldDescriptor, startOffset, endOffset, outerThisField.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
IrGetValueImpl(startOffset, endOffset, outerThisValueParameter) IrGetValueImpl(startOffset, endOffset, outerThisValueParameter)
) )
@@ -131,29 +150,29 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this) 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 startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
val origin = expression.origin val origin = expression.origin
var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin) var irThis: IrExpression = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin)
var innerClass = classDescriptor var innerClass = irClass
while (innerClass != implicitThisClass) { while (innerClass != implicitThisClass) {
if (!innerClass.isInner) { if (!innerClass.descriptor.isInner) {
// Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is - // Captured 'this' unrelated to inner classes nesting hierarchy, leave it as is -
// should be transformed by closures conversion. // should be transformed by closures conversion.
return expression return expression
} }
val outerThisField = context.descriptorsFactory.getOuterThisFieldDescriptor(innerClass) val outerThisField = context.descriptorsFactory.getOuterThisFieldSymbol(innerClass)
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin) irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin)
val outer = innerClass.containingDeclaration val outer = innerClass.parent
innerClass = outer as? ClassDescriptor ?: innerClass = outer as? IrClass ?:
throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer") 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? { private fun IrValueSymbol.getClassForImplicitThis(): IrClass? {
if (this is ReceiverParameterDescriptor) { val descriptor1 = this.descriptor
val receiverValue = value if (descriptor1 is ReceiverParameterDescriptor) {
val receiverValue = descriptor1.value
if (receiverValue is ImplicitClassReceiver) { if (receiverValue is ImplicitClassReceiver) {
return receiverValue.classDescriptor return class2Symbol[receiverValue.classDescriptor]!!
} }
} }
return null return null
@@ -24,30 +24,32 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl 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.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl 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.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import java.util.* import java.util.*
class JsDescriptorsFactory( class JsDescriptorsFactory(
private val builtIns: KotlinBuiltIns private val builtIns: KotlinBuiltIns
) : DescriptorsFactory { ) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<IrBindableSymbol<*, *>, IrFieldSymbol>() private val singletonFieldDescriptors = HashMap<IrBindableSymbol<*, *>, IrFieldSymbol>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val outerThisFieldSymbols = HashMap<IrClass, IrFieldSymbol>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>() private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = TODO() override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = TODO()
override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = override fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol =
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}")
else outerThisDescriptors.getOrPut(innerClassDescriptor) { else outerThisFieldSymbols.getOrPut(innerClass) {
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) val outerClass = innerClass.parent as? IrClass
?: throw AssertionError("No containing class for inner class $innerClassDescriptor") ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}")
PropertyDescriptorImpl.create( IrFieldSymbolImpl(PropertyDescriptorImpl.create(
innerClassDescriptor, innerClass.descriptor,
Annotations.EMPTY, Annotations.EMPTY,
Modality.FINAL, Modality.FINAL,
Visibilities.PROTECTED, Visibilities.PROTECTED,
@@ -63,13 +65,13 @@ class JsDescriptorsFactory(
false false
).apply { ).apply {
setType( setType(
outerClassDescriptor.defaultType, outerClass.defaultType,
emptyList(), emptyList(),
innerClassDescriptor.thisAsReceiverParameter, innerClass.descriptor.thisAsReceiverParameter,
null as? ReceiverParameterDescriptor null as? ReceiverParameterDescriptor
) )
initialize(null, null) initialize(null, null)
} })
} }
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol { override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol {
@@ -26,13 +26,15 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.ir.SourceManager 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.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl 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.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.PsiSourceManager import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.* import java.util.*
@@ -42,7 +44,7 @@ class JvmDescriptorsFactory(
private val builtIns: KotlinBuiltIns private val builtIns: KotlinBuiltIns
) : DescriptorsFactory { ) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<IrBindableSymbol<*, *>, IrFieldSymbol>() private val singletonFieldDescriptors = HashMap<IrBindableSymbol<*, *>, IrFieldSymbol>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val outerThisDescriptors = HashMap<IrClass, IrFieldSymbol>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>() private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol = override fun getSymbolForEnumEntry(enumEntry: IrEnumEntrySymbol): IrFieldSymbol =
@@ -63,15 +65,17 @@ class JvmDescriptorsFactory(
) )
} }
override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = override fun getOuterThisFieldSymbol(innerClass: IrClass): IrFieldSymbol =
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") if (!innerClass.descriptor.isInner) throw AssertionError("Class is not inner: ${innerClass.dump()}")
else outerThisDescriptors.getOrPut(innerClassDescriptor) { else outerThisDescriptors.getOrPut(innerClass) {
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) val outerClass = innerClass.parent as? IrClass
?: throw AssertionError("No containing class for inner class $innerClassDescriptor") ?: throw AssertionError("No containing class for inner class ${innerClass.dump()}")
JvmPropertyDescriptorImpl.createFinalField( IrFieldSymbolImpl(
Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor, JvmPropertyDescriptorImpl.createFinalField(
Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE Name.identifier("this$0"), outerClass.defaultType, innerClass.descriptor,
Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
)
) )
} }