JVM_IR: refactor JvmSharedVariablesManager

This commit is contained in:
pyos
2020-03-02 14:51:59 +01:00
committed by Dmitry Petrov
parent ed96b81a42
commit 68745ec43f
3 changed files with 66 additions and 177 deletions
@@ -407,9 +407,6 @@ fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
thisReceiverDescriptor.bind(valueParameter) thisReceiverDescriptor.bind(valueParameter)
valueParameter.parent = this valueParameter.parent = this
} }
assert(typeParameters.isEmpty())
assert(descriptor.declaredTypeParameters.isEmpty())
} }
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -69,7 +69,7 @@ class JvmBackendContext(
val methodSignatureMapper = MethodSignatureMapper(this) val methodSignatureMapper = MethodSignatureMapper(this)
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper, state.languageVersionSettings) override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(methodSignatureMapper, state.languageVersionSettings)
override val sharedVariablesManager = JvmSharedVariablesManager(state.module, builtIns, irBuiltIns) override val sharedVariablesManager = JvmSharedVariablesManager(state.module, irBuiltIns)
override val mapping: Mapping = DefaultMapping() override val mapping: Mapping = DefaultMapping()
@@ -6,45 +6,27 @@
package org.jetbrains.kotlin.backend.jvm.descriptors package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager
import org.jetbrains.kotlin.backend.common.ir.addChild import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.descriptors.WrappedTypeParameterDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor
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.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
private val SHARED_VARIABLE_ORIGIN = object : IrDeclarationOriginImpl("SHARED_VARIABLE_ORIGIN") {}
private val SHARED_VARIABLE_CONSTRUCTOR_CALL_ORIGIN = object : IrStatementOriginImpl("SHARED_VARIABLE_CONSTRUCTOR_CALL") {}
class JvmSharedVariablesManager( class JvmSharedVariablesManager(
module: ModuleDescriptor, module: ModuleDescriptor,
val builtIns: KotlinBuiltIns,
val irBuiltIns: IrBuiltIns val irBuiltIns: IrBuiltIns
) : SharedVariablesManager { ) : SharedVariablesManager {
private val jvmInternalPackage = IrExternalPackageFragmentImpl( private val jvmInternalPackage = IrExternalPackageFragmentImpl(
@@ -53,106 +35,44 @@ class JvmSharedVariablesManager(
) )
) )
private val refNamespaceClass = buildClass { private val refNamespaceClass = jvmInternalPackage.addClass {
name = Name.identifier("Ref") name = Name.identifier("Ref")
}.apply {
parent = jvmInternalPackage
jvmInternalPackage.addChild(this)
superTypes += irBuiltIns.anyType
} }
private abstract class RefProvider { private class RefProvider(val refClass: IrClass, elementType: IrType) {
abstract val elementType: IrType val refConstructor = refClass.addConstructor {
abstract val refClass: IrClass origin = IrDeclarationOrigin.IR_BUILTINS_STUB
abstract fun getRefType(valueType: IrType): IrSimpleType
// Have to initialize fields lazily in order to refer to refClass.
val refConstructor: IrConstructor by lazy {
buildConstructor {
origin = SHARED_VARIABLE_ORIGIN
returnType = refClass.defaultType
}.apply {
parent = refClass
refClass.addMember(this)
}
} }
val elementField: IrField by lazy { val elementField = refClass.addField {
buildField { origin = IrDeclarationOrigin.IR_BUILTINS_STUB
origin = SHARED_VARIABLE_ORIGIN name = Name.identifier("element")
name = Name.identifier("element") type = elementType
type = elementType
}.apply {
parent = refClass
refClass.addMember(this)
}
} }
} }
private inner class PrimitiveRefProvider(override val elementType: IrType) : RefProvider() {
override val refClass = buildClass {
origin = SHARED_VARIABLE_ORIGIN
name = Name.identifier(elementType.classOrNull!!.owner.name.asString() + "Ref")
}.apply {
parent = refNamespaceClass
refNamespaceClass.addMember(this)
superTypes += irBuiltIns.anyType
thisReceiver = buildValueParameter {
type = IrSimpleTypeImpl(symbol, hasQuestionMark = false, arguments = emptyList(), annotations = emptyList())
name = Name.identifier("$this")
}.also {
it.parent = this
}
}
override fun getRefType(valueType: IrType) = refClass.defaultType
}
private val primitiveRefProviders = irBuiltIns.primitiveIrTypes.associate { primitiveType -> private val primitiveRefProviders = irBuiltIns.primitiveIrTypes.associate { primitiveType ->
primitiveType.classifierOrFail to PrimitiveRefProvider(primitiveType) val refClass = refNamespaceClass.addClass {
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
name = Name.identifier(primitiveType.classOrNull!!.owner.name.asString() + "Ref")
}.apply {
createImplicitParameterDeclarationWithWrappedDescriptor()
}
primitiveType.classifierOrFail to RefProvider(refClass, primitiveType)
} }
private val objectRefProvider = object : RefProvider() { private val objectRefProvider = run {
override val refClass = buildClass { val refClass = refNamespaceClass.addClass {
origin = SHARED_VARIABLE_ORIGIN origin = IrDeclarationOrigin.IR_BUILTINS_STUB
name = Name.identifier("ObjectRef") name = Name.identifier("ObjectRef")
}.apply { }.apply {
val irClass = this addTypeParameter {
typeParameters += name = Name.identifier("T")
IrTypeParameterImpl( superTypes.add(irBuiltIns.anyNType)
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
SHARED_VARIABLE_ORIGIN,
IrTypeParameterSymbolImpl(WrappedTypeParameterDescriptor()),
Name.identifier("T"),
index = 0,
variance = Variance.INVARIANT,
isReified = false
).apply {
(descriptor as WrappedTypeParameterDescriptor).bind(this)
parent = irClass
superTypes.add(irBuiltIns.anyNType)
}
parent = refNamespaceClass
refNamespaceClass.addMember(this)
superTypes += irBuiltIns.anyType
thisReceiver = buildValueParameter {
type = IrSimpleTypeImpl(
symbol,
hasQuestionMark = false,
arguments = listOf(
makeTypeProjection(typeParameters[0].defaultType, Variance.INVARIANT)
),
annotations = emptyList()
)
name = Name.identifier("$this")
}.also {
it.parent = this
} }
createImplicitParameterDeclarationWithWrappedDescriptor()
} }
RefProvider(refClass, refClass.typeParameters[0].defaultType)
override val elementType = refClass.typeParameters[0].defaultType
override fun getRefType(valueType: IrType) = refClass.typeWith(valueType)
} }
private fun getProvider(valueType: IrType): RefProvider = private fun getProvider(valueType: IrType): RefProvider =
@@ -161,85 +81,57 @@ class JvmSharedVariablesManager(
else else
objectRefProvider objectRefProvider
private fun getElementFieldSymbol(valueType: IrType): IrFieldSymbol {
return getProvider(valueType).elementField.symbol
}
override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable { override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable {
val valueType = originalDeclaration.type val valueType = originalDeclaration.type
val provider = getProvider(valueType) val provider = getProvider(valueType)
val refType = provider.getRefType(valueType) val typeArguments = provider.refClass.typeParameters.map { valueType }
val refConstructor = provider.refConstructor val refType = provider.refClass.typeWith(typeArguments)
val refConstructorCall = IrConstructorCallImpl.fromSymbolOwner(refType, provider.refConstructor.symbol).apply {
val refConstructorCall = IrConstructorCallImpl.fromSymbolOwner( typeArguments.forEachIndexed(::putTypeArgument)
refType,
refConstructor.symbol,
SHARED_VARIABLE_CONSTRUCTOR_CALL_ORIGIN
).apply {
List(refConstructor.parentAsClass.typeParameters.size) { i ->
putTypeArgument(i, valueType)
}
} }
return with(originalDeclaration) {
return IrVariableImpl( IrVariableImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin, startOffset, endOffset, origin, IrVariableSymbolImpl(WrappedVariableDescriptor()), name, refType,
IrVariableSymbolImpl(WrappedVariableDescriptor()), isVar = false, // writes are remapped to field stores
originalDeclaration.name, isConst = false, // const vals could not possibly require ref wrappers
refType, isLateinit = false
originalDeclaration.isVar, ).apply {
originalDeclaration.isConst, (descriptor as WrappedVariableDescriptor).bind(this)
isLateinit = false initializer = refConstructorCall
).apply { }
(descriptor as WrappedVariableDescriptor).bind(this)
initializer = refConstructorCall
parent = originalDeclaration.parent
} }
} }
override fun defineSharedValue( override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable): IrStatement {
originalDeclaration: IrVariable,
sharedVariableDeclaration: IrVariable
): IrStatement {
val initializer = originalDeclaration.initializer ?: return sharedVariableDeclaration val initializer = originalDeclaration.initializer ?: return sharedVariableDeclaration
val initializationStatement = with(initializer) {
val valueType = originalDeclaration.type IrSetVariableImpl(startOffset, endOffset, irBuiltIns.unitType, originalDeclaration.symbol, this, null)
}
val sharedVariableInitialization = IrSetFieldImpl( val sharedVariableInitialization = setSharedValue(sharedVariableDeclaration.symbol, initializationStatement)
initializer.startOffset, initializer.endOffset, return with(originalDeclaration) {
getElementFieldSymbol(valueType), IrCompositeImpl(
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDeclaration.symbol), startOffset, endOffset, irBuiltIns.unitType, null,
initializer, listOf(sharedVariableDeclaration, sharedVariableInitialization)
irBuiltIns.unitType )
) }
return IrCompositeImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, irBuiltIns.unitType, null,
listOf(sharedVariableDeclaration, sharedVariableInitialization)
)
} }
override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression = override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression =
IrTypeOperatorCallImpl( with(originalGet) {
UNDEFINED_OFFSET, UNDEFINED_OFFSET, val provider = getProvider(symbol.owner.type)
originalGet.type, val receiver = IrGetValueImpl(startOffset, endOffset, sharedVariableSymbol)
IrTypeOperator.IMPLICIT_CAST, IrGetFieldImpl(startOffset, endOffset, provider.elementField.symbol, type, receiver, origin)
originalGet.type, }
IrGetFieldImpl(
originalGet.startOffset, originalGet.endOffset,
getElementFieldSymbol(originalGet.symbol.owner.type),
originalGet.type,
IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableSymbol),
originalGet.origin
)
)
override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression = override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetVariable): IrExpression =
IrSetFieldImpl( with(originalSet) {
originalSet.startOffset, originalSet.endOffset, val provider = getProvider(symbol.owner.type)
getElementFieldSymbol(originalSet.symbol.owner.type), val receiver = IrGetValueImpl(startOffset, endOffset, sharedVariableSymbol)
IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol), IrSetFieldImpl(startOffset, endOffset, provider.elementField.symbol, receiver, value, type, origin)
originalSet.value, }
originalSet.type, }
originalSet.origin
) private inline fun IrDeclarationContainer.addClass(builder: IrClassBuilder.() -> Unit) = buildClass(builder).also {
it.parent = this
declarations += it
} }