IR: introduce IrLock

Use a single lock object for synchronization to avoid deadlocks.
This commit is contained in:
Georgy Bronnikov
2021-02-02 14:12:34 +03:00
parent 215556511e
commit 42279c3b5b
24 changed files with 112 additions and 86 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator
import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.ir.IrLock
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
@@ -22,6 +23,7 @@ interface Fir2IrComponents {
val irBuiltIns: IrBuiltIns val irBuiltIns: IrBuiltIns
val builtIns: Fir2IrBuiltIns val builtIns: Fir2IrBuiltIns
val irFactory: IrFactory val irFactory: IrFactory
val lock: IrLock
val classifierStorage: Fir2IrClassifierStorage val classifierStorage: Fir2IrClassifierStorage
val declarationStorage: Fir2IrDeclarationStorage val declarationStorage: Fir2IrDeclarationStorage
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer
import org.jetbrains.kotlin.fir.signaturer.FirMangler import org.jetbrains.kotlin.fir.signaturer.FirMangler
import org.jetbrains.kotlin.ir.IrLock
import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
@@ -36,4 +37,7 @@ class Fir2IrComponentsStorage(
override lateinit var annotationGenerator: AnnotationGenerator override lateinit var annotationGenerator: AnnotationGenerator
override lateinit var callGenerator: CallAndReferenceGenerator override lateinit var callGenerator: CallAndReferenceGenerator
override lateinit var fakeOverrideGenerator: FakeOverrideGenerator override lateinit var fakeOverrideGenerator: FakeOverrideGenerator
override val lock: IrLock
get() = symbolTable.lock
} }
@@ -1145,40 +1145,42 @@ class Fir2IrDeclarationStorage(
val fir = firSymbol.fir as F val fir = firSymbol.fir as F
val irParent by lazy { findIrParent(fir) } val irParent by lazy { findIrParent(fir) }
val signature by lazy { signatureComposer.composeSignature(fir) } val signature by lazy { signatureComposer.composeSignature(fir) }
getCachedIrDeclaration(fir) { synchronized(symbolTable.lock) {
// Parent calculation provokes declaration calculation for some members from IrBuiltIns getCachedIrDeclaration(fir) {
@Suppress("UNUSED_EXPRESSION") irParent // Parent calculation provokes declaration calculation for some members from IrBuiltIns
signature @Suppress("UNUSED_EXPRESSION") irParent
}?.let { return it.symbol } signature
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED }?.let { return it.symbol }
val declarationOrigin = computeDeclarationOrigin(firSymbol, parentOrigin) val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
// TODO: package fragment members (?) val declarationOrigin = computeDeclarationOrigin(firSymbol, parentOrigin)
when (val parent = irParent) { // TODO: package fragment members (?)
is Fir2IrLazyClass -> { when (val parent = irParent) {
assert(parentOrigin != IrDeclarationOrigin.DEFINED) { is Fir2IrLazyClass -> {
"Should not have reference to public API uncached property from source code" assert(parentOrigin != IrDeclarationOrigin.DEFINED) {
"Should not have reference to public API uncached property from source code"
}
signature?.let {
return createIrLazyDeclaration(it, parent, declarationOrigin).symbol
}
} }
signature?.let { is IrLazyClass -> {
return createIrLazyDeclaration(it, parent, declarationOrigin).symbol val unwrapped = fir.unwrapFakeOverrides()
} if (unwrapped !== fir) {
} when (unwrapped) {
is IrLazyClass -> { is FirSimpleFunction -> {
val unwrapped = fir.unwrapFakeOverrides() return getIrFunctionSymbol(unwrapped.symbol)
if (unwrapped !== fir) { }
when (unwrapped) { is FirProperty -> {
is FirSimpleFunction -> { return getIrPropertySymbol(unwrapped.symbol)
return getIrFunctionSymbol(unwrapped.symbol) }
}
is FirProperty -> {
return getIrPropertySymbol(unwrapped.symbol)
} }
} }
} }
} }
return createIrDeclaration(irParent, declarationOrigin).apply {
(this as IrDeclaration).setAndModifyParent(irParent)
}.symbol
} }
return createIrDeclaration(irParent, declarationOrigin).apply {
(this as IrDeclaration).setAndModifyParent(irParent)
}.symbol
} }
private fun computeDeclarationOrigin( private fun computeDeclarationOrigin(
@@ -38,7 +38,7 @@ interface AbstractFir2IrLazyDeclaration<F : FirMemberDeclaration, D : IrDeclarat
} }
} }
fun createLazyAnnotations(): ReadWriteProperty<Any?, List<IrConstructorCall>> = lazyVar { fun createLazyAnnotations(): ReadWriteProperty<Any?, List<IrConstructorCall>> = lazyVar(lock) {
fir.annotations.mapNotNull { fir.annotations.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
} }
@@ -68,7 +68,7 @@ abstract class AbstractFir2IrLazyFunction<F : FirMemberDeclaration>(
get() = null get() = null
set(_) = error("We should never need to store body of external functions.") set(_) = error("We should never need to store body of external functions.")
override var visibility: DescriptorVisibility by lazyVar { override var visibility: DescriptorVisibility by lazyVar(lock) {
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility) components.visibilityConverter.convertToDescriptorVisibility(fir.visibility)
} }
@@ -96,11 +96,11 @@ class Fir2IrLazyClass(
override val isFun: Boolean override val isFun: Boolean
get() = fir.isFun get() = fir.isFun
override var superTypes: List<IrType> by lazyVar { override var superTypes: List<IrType> by lazyVar(lock) {
fir.superTypeRefs.map { it.toIrType(typeConverter) } fir.superTypeRefs.map { it.toIrType(typeConverter) }
} }
override var thisReceiver: IrValueParameter? by lazyVar { override var thisReceiver: IrValueParameter? by lazyVar(lock) {
symbolTable.enterScope(this) symbolTable.enterScope(this)
val typeArguments = fir.typeParameters.map { val typeArguments = fir.typeParameters.map {
IrSimpleTypeImpl( IrSimpleTypeImpl(
@@ -124,7 +124,7 @@ class Fir2IrLazyClass(
.also(fakeOverrideGenerator::bindOverriddenSymbols) .also(fakeOverrideGenerator::bindOverriddenSymbols)
} }
override val declarations: MutableList<IrDeclaration> by lazyVar { override val declarations: MutableList<IrDeclaration> by lazyVar(lock) {
val result = mutableListOf<IrDeclaration>() val result = mutableListOf<IrDeclaration>()
val processedNames = mutableSetOf<Name>() val processedNames = mutableSetOf<Name>()
// NB: it's necessary to take all callables from scope, // NB: it's necessary to take all callables from scope,
@@ -67,11 +67,11 @@ class Fir2IrLazyConstructor(
error("Mutating Fir2Ir lazy elements is not possible") error("Mutating Fir2Ir lazy elements is not possible")
} }
override var returnType: IrType by lazyVar { override var returnType: IrType by lazyVar(lock) {
fir.returnTypeRef.toIrType(typeConverter) fir.returnTypeRef.toIrType(typeConverter)
} }
override var dispatchReceiverParameter: IrValueParameter? by lazyVar { override var dispatchReceiverParameter: IrValueParameter? by lazyVar(lock) {
val containingClass = parent as? IrClass val containingClass = parent as? IrClass
val outerClass = containingClass?.parentClassOrNull val outerClass = containingClass?.parentClassOrNull
if (containingClass?.isInner == true && outerClass != null) { if (containingClass?.isInner == true && outerClass != null) {
@@ -92,7 +92,7 @@ class Fir2IrLazyConstructor(
error("Mutating Fir2Ir lazy elements is not possible") error("Mutating Fir2Ir lazy elements is not possible")
} }
override var valueParameters: List<IrValueParameter> by lazyVar { override var valueParameters: List<IrValueParameter> by lazyVar(lock) {
declarationStorage.enterScope(this) declarationStorage.enterScope(this)
fir.valueParameters.mapIndexed { index, valueParameter -> fir.valueParameters.mapIndexed { index, valueParameter ->
declarationStorage.createIrParameter( declarationStorage.createIrParameter(
@@ -86,7 +86,7 @@ class Fir2IrLazyProperty(
} }
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
override var backingField: IrField? by lazyVar { override var backingField: IrField? by lazyVar(lock) {
// TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself // TODO: this checks are very preliminary, FIR resolve should determine backing field presence itself
val parent = parent val parent = parent
when { when {
@@ -126,7 +126,7 @@ class Fir2IrLazyProperty(
} }
} }
override var getter: IrSimpleFunction? by lazyVar { override var getter: IrSimpleFunction? by lazyVar(lock) {
if (fir.isConst) return@lazyVar null if (fir.isConst) return@lazyVar null
Fir2IrLazyPropertyAccessor( Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset, components, startOffset, endOffset,
@@ -155,7 +155,7 @@ class Fir2IrLazyProperty(
} }
} }
override var setter: IrSimpleFunction? by lazyVar { override var setter: IrSimpleFunction? by lazyVar(lock) {
if (!fir.isVar) null else Fir2IrLazyPropertyAccessor( if (!fir.isVar) null else Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset, components, startOffset, endOffset,
when { when {
@@ -45,11 +45,11 @@ class Fir2IrLazyPropertyAccessor(
override val name: Name override val name: Name
get() = Name.special("<${if (isSetter) "set" else "get"}-${firParentProperty.name}>") get() = Name.special("<${if (isSetter) "set" else "get"}-${firParentProperty.name}>")
override var returnType: IrType by lazyVar { override var returnType: IrType by lazyVar(lock) {
if (isSetter) irBuiltIns.unitType else firParentProperty.returnTypeRef.toIrType(typeConverter, conversionTypeContext) if (isSetter) irBuiltIns.unitType else firParentProperty.returnTypeRef.toIrType(typeConverter, conversionTypeContext)
} }
override var dispatchReceiverParameter: IrValueParameter? by lazyVar { override var dispatchReceiverParameter: IrValueParameter? by lazyVar(lock) {
val containingClass = parent as? IrClass val containingClass = parent as? IrClass
if (containingClass != null && shouldHaveDispatchReceiver(containingClass, firParentProperty) if (containingClass != null && shouldHaveDispatchReceiver(containingClass, firParentProperty)
) { ) {
@@ -57,13 +57,13 @@ class Fir2IrLazyPropertyAccessor(
} else null } else null
} }
override var extensionReceiverParameter: IrValueParameter? by lazyVar { override var extensionReceiverParameter: IrValueParameter? by lazyVar(lock) {
firParentProperty.receiverTypeRef?.let { firParentProperty.receiverTypeRef?.let {
createThisReceiverParameter(it.toIrType(typeConverter, conversionTypeContext)) createThisReceiverParameter(it.toIrType(typeConverter, conversionTypeContext))
} }
} }
override var valueParameters: List<IrValueParameter> by lazyVar { override var valueParameters: List<IrValueParameter> by lazyVar(lock) {
if (!isSetter) emptyList() if (!isSetter) emptyList()
else { else {
declarationStorage.enterScope(this) declarationStorage.enterScope(this)
@@ -81,7 +81,7 @@ class Fir2IrLazyPropertyAccessor(
} }
} }
override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar { override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar(lock) {
firParentProperty.generateOverriddenAccessorSymbols( firParentProperty.generateOverriddenAccessorSymbols(
firParentClass, firParentClass,
!isSetter, !isSetter,
@@ -37,24 +37,24 @@ class Fir2IrLazySimpleFunction(
override val name: Name override val name: Name
get() = fir.name get() = fir.name
override var returnType: IrType by lazyVar { override var returnType: IrType by lazyVar(lock) {
fir.returnTypeRef.toIrType(typeConverter) fir.returnTypeRef.toIrType(typeConverter)
} }
override var dispatchReceiverParameter: IrValueParameter? by lazyVar { override var dispatchReceiverParameter: IrValueParameter? by lazyVar(lock) {
val containingClass = parent as? IrClass val containingClass = parent as? IrClass
if (containingClass != null && shouldHaveDispatchReceiver(containingClass, fir)) { if (containingClass != null && shouldHaveDispatchReceiver(containingClass, fir)) {
createThisReceiverParameter(thisType = containingClass.thisReceiver?.type ?: error("No this receiver for containing class")) createThisReceiverParameter(thisType = containingClass.thisReceiver?.type ?: error("No this receiver for containing class"))
} else null } else null
} }
override var extensionReceiverParameter: IrValueParameter? by lazyVar { override var extensionReceiverParameter: IrValueParameter? by lazyVar(lock) {
fir.receiverTypeRef?.let { fir.receiverTypeRef?.let {
createThisReceiverParameter(it.toIrType(typeConverter)) createThisReceiverParameter(it.toIrType(typeConverter))
} }
} }
override var valueParameters: List<IrValueParameter> by lazyVar { override var valueParameters: List<IrValueParameter> by lazyVar(lock) {
declarationStorage.enterScope(this) declarationStorage.enterScope(this)
fir.valueParameters.mapIndexed { index, valueParameter -> fir.valueParameters.mapIndexed { index, valueParameter ->
declarationStorage.createIrParameter( declarationStorage.createIrParameter(
@@ -67,7 +67,7 @@ class Fir2IrLazySimpleFunction(
} }
} }
override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar { override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar(lock) {
val parent = parent val parent = parent
if (isFakeOverride && parent is Fir2IrLazyClass) { if (isFakeOverride && parent is Fir2IrLazyClass) {
fakeOverrideGenerator.calcBaseSymbolsForFakeOverrideFunction( fakeOverrideGenerator.calcBaseSymbolsForFakeOverrideFunction(
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrLock
import org.jetbrains.kotlin.ir.builders.declarations.addFunction import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor
@@ -0,0 +1,11 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir
/*
Lock protecting accesses to global IR structures during by-file lowerings.
*/
class IrLock
@@ -47,14 +47,14 @@ class IrLazyClass(
override var annotations: List<IrConstructorCall> by createLazyAnnotations() override var annotations: List<IrConstructorCall> by createLazyAnnotations()
override var thisReceiver: IrValueParameter? by lazyVar { override var thisReceiver: IrValueParameter? by lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
descriptor.thisAsReceiverParameter.generateReceiverParameterStub().apply { parent = this@IrLazyClass } descriptor.thisAsReceiverParameter.generateReceiverParameterStub().apply { parent = this@IrLazyClass }
} }
} }
override val declarations: MutableList<IrDeclaration> by lazyVar { override val declarations: MutableList<IrDeclaration> by lazyVar(stubGenerator.lock) {
ArrayList<IrDeclaration>().also { ArrayList<IrDeclaration>().also {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
generateChildStubs(descriptor.constructors, it) generateChildStubs(descriptor.constructors, it)
@@ -68,13 +68,13 @@ class IrLazyClass(
} }
} }
override var typeParameters: List<IrTypeParameter> by lazyVar { override var typeParameters: List<IrTypeParameter> by lazyVar(stubGenerator.lock) {
descriptor.declaredTypeParameters.mapTo(arrayListOf()) { descriptor.declaredTypeParameters.mapTo(arrayListOf()) {
stubGenerator.generateOrGetTypeParameterStub(it) stubGenerator.generateOrGetTypeParameterStub(it)
} }
} }
override var superTypes: List<IrType> by lazyVar { override var superTypes: List<IrType> by lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
// TODO get rid of code duplication, see ClassGenerator#generateClass // TODO get rid of code duplication, see ClassGenerator#generateClass
descriptor.typeConstructor.supertypes.mapNotNullTo(arrayListOf()) { descriptor.typeConstructor.supertypes.mapNotNullTo(arrayListOf()) {
@@ -56,7 +56,7 @@ class IrLazyConstructor(
get() = null get() = null
set(_) = error("We should never need to store metadata of external declarations.") set(_) = error("We should never need to store metadata of external declarations.")
override var typeParameters: List<IrTypeParameter> by lazyVar { override var typeParameters: List<IrTypeParameter> by lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
stubGenerator.symbolTable.withScope(this) { stubGenerator.symbolTable.withScope(this) {
val classTypeParametersCount = descriptor.constructedClass.original.declaredTypeParameters.size val classTypeParametersCount = descriptor.constructedClass.original.declaredTypeParameters.size
@@ -47,11 +47,11 @@ interface IrLazyDeclarationBase : IrDeclaration {
} }
} }
fun createLazyAnnotations(): ReadWriteProperty<Any?, List<IrConstructorCall>> = lazyVar { fun createLazyAnnotations(): ReadWriteProperty<Any?, List<IrConstructorCall>> = lazyVar(stubGenerator.lock) {
descriptor.annotations.mapNotNull(typeTranslator.constantValueGenerator::generateAnnotationConstructorCall).toMutableList() descriptor.annotations.mapNotNull(typeTranslator.constantValueGenerator::generateAnnotationConstructorCall).toMutableList()
} }
fun createLazyParent(): ReadWriteProperty<Any?, IrDeclarationParent> = lazyVar { fun createLazyParent(): ReadWriteProperty<Any?, IrDeclarationParent> = lazyVar(stubGenerator.lock) {
val currentDescriptor = descriptor val currentDescriptor = descriptor
val containingDeclaration = val containingDeclaration =
@@ -43,17 +43,17 @@ class IrLazyField(
override var parent: IrDeclarationParent by createLazyParent() override var parent: IrDeclarationParent by createLazyParent()
override var annotations: List<IrConstructorCall> by lazyVar { override var annotations: List<IrConstructorCall> by lazyVar(stubGenerator.lock) {
descriptor.backingField?.annotations descriptor.backingField?.annotations
?.mapNotNullTo(mutableListOf(), typeTranslator.constantValueGenerator::generateAnnotationConstructorCall) ?.mapNotNullTo(mutableListOf(), typeTranslator.constantValueGenerator::generateAnnotationConstructorCall)
?: mutableListOf() ?: mutableListOf()
} }
override var type: IrType by lazyVar { override var type: IrType by lazyVar(stubGenerator.lock) {
descriptor.type.toIrType() descriptor.type.toIrType()
} }
override var initializer: IrExpressionBody? by lazyVar { override var initializer: IrExpressionBody? by lazyVar(stubGenerator.lock) {
descriptor.compileTimeInitializer?.let { descriptor.compileTimeInitializer?.let {
factory.createExpressionBody( factory.createExpressionBody(
typeTranslator.constantValueGenerator.generateConstantValueAsExpression(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it) typeTranslator.constantValueGenerator.generateConstantValueAsExpression(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it)
@@ -61,7 +61,7 @@ class IrLazyField(
} }
} }
override var correspondingPropertySymbol: IrPropertySymbol? by lazyVar { override var correspondingPropertySymbol: IrPropertySymbol? by lazyVar(stubGenerator.lock) {
stubGenerator.generatePropertyStub(descriptor).symbol stubGenerator.generatePropertyStub(descriptor).symbol
} }
@@ -64,7 +64,7 @@ class IrLazyFunction(
get() = null get() = null
set(_) = error("We should never need to store metadata of external declarations.") set(_) = error("We should never need to store metadata of external declarations.")
override var typeParameters: List<IrTypeParameter> by lazyVar { override var typeParameters: List<IrTypeParameter> by lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
stubGenerator.symbolTable.withScope(this) { stubGenerator.symbolTable.withScope(this) {
val propertyIfAccessor = descriptor.propertyIfAccessor val propertyIfAccessor = descriptor.propertyIfAccessor
@@ -81,7 +81,7 @@ class IrLazyFunction(
} }
} }
override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar { override var overriddenSymbols: List<IrSimpleFunctionSymbol> by lazyVar(stubGenerator.lock) {
descriptor.overriddenDescriptors.mapTo(arrayListOf()) { descriptor.overriddenDescriptors.mapTo(arrayListOf()) {
stubGenerator.generateFunctionStub(it.original).symbol stubGenerator.generateFunctionStub(it.original).symbol
} }
@@ -26,7 +26,7 @@ interface IrLazyFunctionBase : IrLazyDeclarationBase, IrTypeParametersContainer
} }
fun createValueParameters(): ReadWriteProperty<Any?, List<IrValueParameter>> = fun createValueParameters(): ReadWriteProperty<Any?, List<IrValueParameter>> =
lazyVar { lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
descriptor.valueParameters.mapTo(arrayListOf()) { descriptor.valueParameters.mapTo(arrayListOf()) {
stubGenerator.generateValueParameterStub(it).apply { parent = this@IrLazyFunctionBase } stubGenerator.generateValueParameterStub(it).apply { parent = this@IrLazyFunctionBase }
@@ -38,7 +38,7 @@ interface IrLazyFunctionBase : IrLazyDeclarationBase, IrTypeParametersContainer
parameter: ReceiverParameterDescriptor?, parameter: ReceiverParameterDescriptor?,
functionDispatchReceiver: Boolean = false, functionDispatchReceiver: Boolean = false,
): ReadWriteProperty<Any?, IrValueParameter?> = ): ReadWriteProperty<Any?, IrValueParameter?> =
lazyVar { lazyVar(stubGenerator.lock) {
if (functionDispatchReceiver && stubGenerator.extensions.isStaticFunction(descriptor)) null if (functionDispatchReceiver && stubGenerator.extensions.isStaticFunction(descriptor)) null
else typeTranslator.buildWithScope(this) { else typeTranslator.buildWithScope(this) {
parameter?.generateReceiverParameterStub()?.also { it.parent = this@IrLazyFunctionBase } parameter?.generateReceiverParameterStub()?.also { it.parent = this@IrLazyFunctionBase }
@@ -46,7 +46,7 @@ interface IrLazyFunctionBase : IrLazyDeclarationBase, IrTypeParametersContainer
} }
fun createReturnType(): ReadWriteProperty<Any?, IrType> = fun createReturnType(): ReadWriteProperty<Any?, IrType> =
lazyVar { lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
descriptor.returnType!!.toIrType() descriptor.returnType!!.toIrType()
} }
@@ -50,7 +50,7 @@ class IrLazyProperty(
descriptor.compileTimeInitializer != null || descriptor.getter == null || descriptor.compileTimeInitializer != null || descriptor.getter == null ||
stubGenerator.extensions.isPropertyWithPlatformField(descriptor) stubGenerator.extensions.isPropertyWithPlatformField(descriptor)
override var backingField: IrField? by lazyVar { override var backingField: IrField? by lazyVar(stubGenerator.lock) {
if (hasBackingField) { if (hasBackingField) {
stubGenerator.generateFieldStub(descriptor).apply { stubGenerator.generateFieldStub(descriptor).apply {
correspondingPropertySymbol = this@IrLazyProperty.symbol correspondingPropertySymbol = this@IrLazyProperty.symbol
@@ -58,13 +58,13 @@ class IrLazyProperty(
} else null } else null
} }
override var getter: IrSimpleFunction? by lazyVar { override var getter: IrSimpleFunction? by lazyVar(stubGenerator.lock) {
descriptor.getter?.let { stubGenerator.generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply { descriptor.getter?.let { stubGenerator.generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingPropertySymbol = this@IrLazyProperty.symbol correspondingPropertySymbol = this@IrLazyProperty.symbol
} }
} }
override var setter: IrSimpleFunction? by lazyVar { override var setter: IrSimpleFunction? by lazyVar(stubGenerator.lock) {
descriptor.setter?.let { stubGenerator.generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply { descriptor.setter?.let { stubGenerator.generateFunctionStub(it, createPropertyIfNeeded = false) }?.apply {
correspondingPropertySymbol = this@IrLazyProperty.symbol correspondingPropertySymbol = this@IrLazyProperty.symbol
} }
@@ -37,13 +37,13 @@ class IrLazyTypeAlias(
override var annotations: List<IrConstructorCall> by createLazyAnnotations() override var annotations: List<IrConstructorCall> by createLazyAnnotations()
override var typeParameters: List<IrTypeParameter> by lazyVar { override var typeParameters: List<IrTypeParameter> by lazyVar(stubGenerator.lock) {
descriptor.declaredTypeParameters.mapTo(arrayListOf()) { descriptor.declaredTypeParameters.mapTo(arrayListOf()) {
stubGenerator.generateOrGetTypeParameterStub(it) stubGenerator.generateOrGetTypeParameterStub(it)
} }
} }
override var expandedType: IrType by lazyVar { override var expandedType: IrType by lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this) { typeTranslator.buildWithScope(this) {
descriptor.expandedType.toIrType() descriptor.expandedType.toIrType()
} }
@@ -38,7 +38,7 @@ class IrLazyTypeParameter(
override var annotations: List<IrConstructorCall> by createLazyAnnotations() override var annotations: List<IrConstructorCall> by createLazyAnnotations()
override var superTypes: List<IrType> by lazyVar { override var superTypes: List<IrType> by lazyVar(stubGenerator.lock) {
typeTranslator.buildWithScope(this.parent as IrTypeParametersContainer) { typeTranslator.buildWithScope(this.parent as IrTypeParametersContainer) {
val descriptor = symbol.descriptor val descriptor = symbol.descriptor
descriptor.upperBounds.mapTo(arrayListOf()) { it.toIrType() } descriptor.upperBounds.mapTo(arrayListOf()) { it.toIrType() }
@@ -5,12 +5,13 @@
package org.jetbrains.kotlin.ir.declarations.lazy package org.jetbrains.kotlin.ir.declarations.lazy
import org.jetbrains.kotlin.ir.IrLock
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
fun <T> lazyVar(initializer: () -> T): ReadWriteProperty<Any?, T> = SynchronizedLazyVar(initializer) fun <T> lazyVar(lock: IrLock, initializer: () -> T): ReadWriteProperty<Any?, T> = SynchronizedLazyVar(lock, initializer)
private class SynchronizedLazyVar<T>(initializer: () -> T) : ReadWriteProperty<Any?, T> { private class SynchronizedLazyVar<T>(val lock: IrLock, initializer: () -> T) : ReadWriteProperty<Any?, T> {
@Volatile @Volatile
private var isInitialized = false private var isInitialized = false
@@ -23,7 +24,7 @@ private class SynchronizedLazyVar<T>(initializer: () -> T) : ReadWriteProperty<A
get() { get() {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
if (isInitialized) return _value as T if (isInitialized) return _value as T
synchronized(this) { synchronized(lock) {
if (!isInitialized) { if (!isInitialized) {
_value = initializer!!() _value = initializer!!()
isInitialized = true isInitialized = true
@@ -39,7 +40,7 @@ private class SynchronizedLazyVar<T>(initializer: () -> T) : ReadWriteProperty<A
override fun getValue(thisRef: Any?, property: KProperty<*>): T = value override fun getValue(thisRef: Any?, property: KProperty<*>): T = value
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
synchronized(this) { synchronized(lock) {
this._value = value this._value = value
isInitialized = true isInitialized = true
} }
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrLock
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -44,6 +45,9 @@ abstract class DeclarationStubGenerator(
) : IrProvider { ) : IrProvider {
protected val lazyTable = symbolTable.lazyWrapper protected val lazyTable = symbolTable.lazyWrapper
val lock: IrLock
get() = symbolTable.lock
var unboundSymbolGeneration: Boolean var unboundSymbolGeneration: Boolean
get() = lazyTable.stubGenerator != null get() = lazyTable.stubGenerator != null
set(value) { set(value) {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.util package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrLock
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
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
@@ -62,13 +63,15 @@ interface ReferenceSymbolTable {
class SymbolTable( class SymbolTable(
val signaturer: IdSignatureComposer, val signaturer: IdSignatureComposer,
val irFactory: IrFactory, val irFactory: IrFactory,
val nameProvider: NameProvider = NameProvider.DEFAULT val nameProvider: NameProvider = NameProvider.DEFAULT,
) : ReferenceSymbolTable { ) : ReferenceSymbolTable {
val lock = IrLock()
@Suppress("LeakingThis") @Suppress("LeakingThis")
val lazyWrapper = IrLazySymbolTable(this) val lazyWrapper = IrLazySymbolTable(this)
private abstract class SymbolTableBase<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> { private abstract class SymbolTableBase<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>(val lock: IrLock) {
val unboundSymbols = linkedSetOf<S>() val unboundSymbols = linkedSetOf<S>()
abstract fun get(d: D): S? abstract fun get(d: D): S?
@@ -76,7 +79,7 @@ class SymbolTable(
abstract fun get(sig: IdSignature): S? abstract fun get(sig: IdSignature): S?
inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B {
synchronized(this) { synchronized(lock) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val d0 = d.original as D val d0 = d.original as D
assert(d0 === d) { assert(d0 === d) {
@@ -97,7 +100,7 @@ class SymbolTable(
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
inline fun declare(sig: IdSignature, createSymbol: () -> S, createOwner: (S) -> B): B { inline fun declare(sig: IdSignature, createSymbol: () -> S, createOwner: (S) -> B): B {
synchronized(this) { synchronized(lock) {
val existing = get(sig) val existing = get(sig)
val symbol = if (existing == null) { val symbol = if (existing == null) {
createSymbol() createSymbol()
@@ -113,7 +116,7 @@ class SymbolTable(
} }
inline fun declareIfNotExists(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { inline fun declareIfNotExists(d: D, createSymbol: () -> S, createOwner: (S) -> B): B {
synchronized(this) { synchronized(lock) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val d0 = d.original as D val d0 = d.original as D
assert(d0 === d) { assert(d0 === d) {
@@ -133,7 +136,7 @@ class SymbolTable(
} }
inline fun declare(sig: IdSignature, d: D?, createSymbol: () -> S, createOwner: (S) -> B): B { inline fun declare(sig: IdSignature, d: D?, createSymbol: () -> S, createOwner: (S) -> B): B {
synchronized(this) { synchronized(lock) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val d0 = d?.original as D val d0 = d?.original as D
assert(d0 === d) { assert(d0 === d) {
@@ -153,7 +156,7 @@ class SymbolTable(
} }
inline fun referenced(d: D, orElse: () -> S): S { inline fun referenced(d: D, orElse: () -> S): S {
synchronized(this) { synchronized(lock) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val d0 = d.original as D val d0 = d.original as D
assert(d0 === d) { assert(d0 === d) {
@@ -174,7 +177,7 @@ class SymbolTable(
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
inline fun referenced(sig: IdSignature, orElse: () -> S): S { inline fun referenced(sig: IdSignature, orElse: () -> S): S {
synchronized(this) { synchronized(lock) {
return get(sig) ?: run { return get(sig) ?: run {
val new = orElse() val new = orElse()
assert(unboundSymbols.add(new)) { assert(unboundSymbols.add(new)) {
@@ -188,7 +191,7 @@ class SymbolTable(
} }
private open inner class FlatSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> : private open inner class FlatSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> :
SymbolTableBase<D, B, S>() { SymbolTableBase<D, B, S>(lock) {
val descriptorToSymbol = linkedMapOf<D, S>() val descriptorToSymbol = linkedMapOf<D, S>()
val idSigToSymbol = linkedMapOf<IdSignature, S>() val idSigToSymbol = linkedMapOf<IdSignature, S>()
@@ -225,7 +228,7 @@ class SymbolTable(
} }
private inner class ScopedSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>> private inner class ScopedSymbolTable<D : DeclarationDescriptor, B : IrSymbolOwner, S : IrBindableSymbol<D, B>>
: SymbolTableBase<D, B, S>() { : SymbolTableBase<D, B, S>(lock) {
inner class Scope(val owner: IrSymbol, val parent: Scope?) { inner class Scope(val owner: IrSymbol, val parent: Scope?) {
private val descriptorToSymbol = linkedMapOf<D, S>() private val descriptorToSymbol = linkedMapOf<D, S>()
private val idSigToSymbol = linkedMapOf<IdSignature, S>() private val idSigToSymbol = linkedMapOf<IdSignature, S>()