diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 8fc4d7563e4..06f5a4c525a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -67,7 +67,7 @@ class JvmBackendContext( val methodSignatureMapper = MethodSignatureMapper(this) internal val innerClassesSupport = JvmInnerClassesSupport(irFactory) - internal val cachedDeclarations = JvmCachedDeclarations(this, state.languageVersionSettings) + internal val cachedDeclarations = JvmCachedDeclarations(this, CachedFieldsForObjectInstances(irFactory, state.languageVersionSettings)) override val mapping: Mapping = DefaultMapping() diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt index c3b93fdf2e1..fae7bffee0b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmCachedDeclarations.kt @@ -32,10 +32,9 @@ import java.util.concurrent.ConcurrentHashMap class JvmCachedDeclarations( private val context: JvmBackendContext, - private val languageVersionSettings: LanguageVersionSettings + val fieldsForObjectInstances: CachedFieldsForObjectInstances, ) { private val singletonFieldDeclarations = ConcurrentHashMap() - private val interfaceCompanionFieldDeclarations = ConcurrentHashMap() private val staticBackingFields = ConcurrentHashMap() private val staticCompanionDeclarations = ConcurrentHashMap>() @@ -58,50 +57,9 @@ class JvmCachedDeclarations( } } - fun getFieldForObjectInstance(singleton: IrClass): IrField = - singletonFieldDeclarations.getOrPut(singleton) { - val originalVisibility = singleton.visibility - val isNotMappedCompanion = singleton.isCompanion && !singleton.isMappedIntrinsicCompanionObject() - val useProperVisibilityForCompanion = - languageVersionSettings.supportsFeature(LanguageFeature.ProperVisibilityForCompanionObjectInstanceField) - && singleton.isCompanion - && !singleton.parentAsClass.isInterface - context.irFactory.buildField { - name = if (isNotMappedCompanion) singleton.name else Name.identifier(JvmAbi.INSTANCE_FIELD) - type = singleton.defaultType - origin = IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE - isFinal = true - isStatic = true - visibility = when { - !useProperVisibilityForCompanion -> DescriptorVisibilities.PUBLIC - originalVisibility == DescriptorVisibilities.PROTECTED -> JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY - else -> originalVisibility - } + fun getFieldForObjectInstance(singleton: IrClass): IrField = fieldsForObjectInstances.getFieldForObjectInstance(singleton) - }.apply { - parent = if (isNotMappedCompanion) singleton.parent else singleton - } - } - - private fun IrClass.isMappedIntrinsicCompanionObject() = - isCompanion && classId?.let { CompanionObjectMapping.isMappedIntrinsicCompanionObjectClassId(it) } == true - - fun getPrivateFieldForObjectInstance(singleton: IrClass): IrField = - if (singleton.isCompanion && singleton.parentAsClass.isJvmInterface) - interfaceCompanionFieldDeclarations.getOrPut(singleton) { - context.irFactory.buildField { - name = Name.identifier("\$\$INSTANCE") - type = singleton.defaultType - origin = JvmLoweredDeclarationOrigin.INTERFACE_COMPANION_PRIVATE_INSTANCE - isFinal = true - isStatic = true - visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY - }.apply { - parent = singleton - } - } - else - getFieldForObjectInstance(singleton) + fun getPrivateFieldForObjectInstance(singleton: IrClass): IrField = fieldsForObjectInstances.getPrivateFieldForObjectInstance(singleton) fun getStaticBackingField(irProperty: IrProperty): IrField? { // Only fields defined directly in objects should be made static. @@ -136,7 +94,7 @@ class JvmCachedDeclarations( } initializer = oldField.initializer?.patchDeclarationParents(this) - oldField.replaceThisByStaticReference(this@JvmCachedDeclarations, oldParent, oldParent.thisReceiver!!) + oldField.replaceThisByStaticReference(fieldsForObjectInstances, oldParent, oldParent.thisReceiver!!) origin = if (irProperty.parentAsClass.isCompanion) JvmLoweredDeclarationOrigin.COMPANION_PROPERTY_BACKING_FIELD else origin } } @@ -315,3 +273,60 @@ class JvmCachedDeclarations( } } } + +/* + This class keeps track of singleton fields for instances of object classes. + */ +class CachedFieldsForObjectInstances( + private val irFactory: IrFactory, + private val languageVersionSettings: LanguageVersionSettings, +) { + private val singletonFieldDeclarations = ConcurrentHashMap() + private val interfaceCompanionFieldDeclarations = ConcurrentHashMap() + + fun getFieldForObjectInstance(singleton: IrClass): IrField = + singletonFieldDeclarations.getOrPut(singleton) { + val originalVisibility = singleton.visibility + val isNotMappedCompanion = singleton.isCompanion && !singleton.isMappedIntrinsicCompanionObject() + val useProperVisibilityForCompanion = + languageVersionSettings.supportsFeature(LanguageFeature.ProperVisibilityForCompanionObjectInstanceField) + && singleton.isCompanion + && !singleton.parentAsClass.isInterface + irFactory.buildField { + name = if (isNotMappedCompanion) singleton.name else Name.identifier(JvmAbi.INSTANCE_FIELD) + type = singleton.defaultType + origin = IrDeclarationOrigin.FIELD_FOR_OBJECT_INSTANCE + isFinal = true + isStatic = true + visibility = when { + !useProperVisibilityForCompanion -> DescriptorVisibilities.PUBLIC + originalVisibility == DescriptorVisibilities.PROTECTED -> JavaDescriptorVisibilities.PROTECTED_STATIC_VISIBILITY + else -> originalVisibility + } + + }.apply { + parent = if (isNotMappedCompanion) singleton.parent else singleton + } + } + + private fun IrClass.isMappedIntrinsicCompanionObject() = + isCompanion && classId?.let { CompanionObjectMapping.isMappedIntrinsicCompanionObjectClassId(it) } == true + + fun getPrivateFieldForObjectInstance(singleton: IrClass): IrField = + if (singleton.isCompanion && singleton.parentAsClass.isJvmInterface) + interfaceCompanionFieldDeclarations.getOrPut(singleton) { + irFactory.buildField { + name = Name.identifier("\$\$INSTANCE") + type = singleton.defaultType + origin = JvmLoweredDeclarationOrigin.INTERFACE_COMPANION_PRIVATE_INSTANCE + isFinal = true + isStatic = true + visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY + }.apply { + parent = singleton + } + } + else + getFieldForObjectInstance(singleton) + +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt index 25c61e8e3c2..1673ee60d2a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/IrUtils.kt @@ -7,10 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.ir import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.lower.IrLoweringContext -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.backend.jvm.JvmCachedDeclarations -import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.JvmSymbols +import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.backend.jvm.codegen.isInlineOnly import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface import org.jetbrains.kotlin.backend.jvm.codegen.representativeUpperBound @@ -232,7 +229,7 @@ fun IrExpression.isSmartcastFromHigherThanNullable(context: JvmBackendContext): } fun IrElement.replaceThisByStaticReference( - cachedDeclarations: JvmCachedDeclarations, + cachedFields: CachedFieldsForObjectInstances, irClass: IrClass, oldThisReceiverParameter: IrValueParameter ) { @@ -242,7 +239,7 @@ fun IrElement.replaceThisByStaticReference( IrGetFieldImpl( expression.startOffset, expression.endOffset, - cachedDeclarations.getPrivateFieldForObjectInstance(irClass).symbol, + cachedFields.getPrivateFieldForObjectInstance(irClass).symbol, irClass.defaultType ) } else super.visitGetValue(expression) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt index 7bfa31302f7..545098f1aee 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStaticAnnotationLowering.kt @@ -87,7 +87,9 @@ private class SingletonObjectJvmStaticTransformer(val context: JvmBackendContext // dispatch receiver parameter is already null for synthetic property annotation methods function.dispatchReceiverParameter?.let { oldDispatchReceiverParameter -> function.dispatchReceiverParameter = null - function.replaceThisByStaticReference(context.cachedDeclarations, declaration, oldDispatchReceiverParameter) + function.replaceThisByStaticReference( + context.cachedDeclarations.fieldsForObjectInstances, declaration, oldDispatchReceiverParameter + ) } } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt index 8369657f151..28d30dbc5a4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/MoveCompanionObjectFieldsLowering.kt @@ -102,7 +102,7 @@ private class MoveOrCopyCompanionObjectFieldsLowering(val context: JvmBackendCon IrAnonymousInitializerImpl(startOffset, endOffset, origin, newSymbol, isStatic = true).apply { parent = newParent body = this@with.body.patchDeclarationParents(newParent) - replaceThisByStaticReference(context.cachedDeclarations, oldParent, oldParent.thisReceiver!!) + replaceThisByStaticReference(context.cachedDeclarations.fieldsForObjectInstances, oldParent, oldParent.thisReceiver!!) } }