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
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
}
@@ -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<ValueDescriptor, IrValueParameter>()
val class2Symbol = HashMap<ClassDescriptor, IrClass>()
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
@@ -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<IrBindableSymbol<*, *>, IrFieldSymbol>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisFieldSymbols = HashMap<IrClass, IrFieldSymbol>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
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 {
@@ -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<IrBindableSymbol<*, *>, IrFieldSymbol>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisDescriptors = HashMap<IrClass, IrFieldSymbol>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
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
)
)
}