From 42279c3b5b3507c93c2adde1cc469716dde709b8 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Tue, 2 Feb 2021 14:12:34 +0300 Subject: [PATCH] IR: introduce IrLock Use a single lock object for synchronization to avoid deadlocks. --- .../kotlin/fir/backend/Fir2IrComponents.kt | 2 + .../fir/backend/Fir2IrComponentsStorage.kt | 4 ++ .../fir/backend/Fir2IrDeclarationStorage.kt | 58 ++++++++++--------- .../fir/lazy/AbstractFir2IrLazyDeclaration.kt | 2 +- .../fir/lazy/AbstractFir2IrLazyFunction.kt | 2 +- .../kotlin/fir/lazy/Fir2IrLazyClass.kt | 6 +- .../kotlin/fir/lazy/Fir2IrLazyConstructor.kt | 6 +- .../kotlin/fir/lazy/Fir2IrLazyProperty.kt | 6 +- .../fir/lazy/Fir2IrLazyPropertyAccessor.kt | 10 ++-- .../fir/lazy/Fir2IrLazySimpleFunction.kt | 10 ++-- .../backend/jvm/codegen/ClassCodegen.kt | 1 - .../src/org/jetbrains/kotlin/ir/IrLock.kt | 11 ++++ .../ir/declarations/lazy/IrLazyClass.kt | 8 +-- .../ir/declarations/lazy/IrLazyConstructor.kt | 2 +- .../lazy/IrLazyDeclarationBase.kt | 4 +- .../ir/declarations/lazy/IrLazyField.kt | 8 +-- .../ir/declarations/lazy/IrLazyFunction.kt | 4 +- .../declarations/lazy/IrLazyFunctionBase.kt | 6 +- .../ir/declarations/lazy/IrLazyProperty.kt | 6 +- .../ir/declarations/lazy/IrLazyTypeAlias.kt | 4 +- .../declarations/lazy/IrLazyTypeParameter.kt | 2 +- .../kotlin/ir/declarations/lazy/lazyUtil.kt | 9 +-- .../ir/util/DeclarationStubGenerator.kt | 4 ++ .../jetbrains/kotlin/ir/util/SymbolTable.kt | 23 ++++---- 24 files changed, 112 insertions(+), 86 deletions(-) create mode 100644 compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrLock.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt index 2a23ed2bad3..076850915bc 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt @@ -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.FakeOverrideGenerator 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.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.util.SymbolTable @@ -22,6 +23,7 @@ interface Fir2IrComponents { val irBuiltIns: IrBuiltIns val builtIns: Fir2IrBuiltIns val irFactory: IrFactory + val lock: IrLock val classifierStorage: Fir2IrClassifierStorage val declarationStorage: Fir2IrDeclarationStorage diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt index 3d59526ecef..b33c529bdc4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer 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.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.util.SymbolTable @@ -36,4 +37,7 @@ class Fir2IrComponentsStorage( override lateinit var annotationGenerator: AnnotationGenerator override lateinit var callGenerator: CallAndReferenceGenerator override lateinit var fakeOverrideGenerator: FakeOverrideGenerator + + override val lock: IrLock + get() = symbolTable.lock } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 2eb5e96a600..e1069bd7e99 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -1145,40 +1145,42 @@ class Fir2IrDeclarationStorage( val fir = firSymbol.fir as F val irParent by lazy { findIrParent(fir) } val signature by lazy { signatureComposer.composeSignature(fir) } - getCachedIrDeclaration(fir) { - // Parent calculation provokes declaration calculation for some members from IrBuiltIns - @Suppress("UNUSED_EXPRESSION") irParent - signature - }?.let { return it.symbol } - val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED - val declarationOrigin = computeDeclarationOrigin(firSymbol, parentOrigin) - // TODO: package fragment members (?) - when (val parent = irParent) { - is Fir2IrLazyClass -> { - assert(parentOrigin != IrDeclarationOrigin.DEFINED) { - "Should not have reference to public API uncached property from source code" + synchronized(symbolTable.lock) { + getCachedIrDeclaration(fir) { + // Parent calculation provokes declaration calculation for some members from IrBuiltIns + @Suppress("UNUSED_EXPRESSION") irParent + signature + }?.let { return it.symbol } + val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED + val declarationOrigin = computeDeclarationOrigin(firSymbol, parentOrigin) + // TODO: package fragment members (?) + when (val parent = irParent) { + is Fir2IrLazyClass -> { + 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 { - return createIrLazyDeclaration(it, parent, declarationOrigin).symbol - } - } - is IrLazyClass -> { - val unwrapped = fir.unwrapFakeOverrides() - if (unwrapped !== fir) { - when (unwrapped) { - is FirSimpleFunction -> { - return getIrFunctionSymbol(unwrapped.symbol) - } - is FirProperty -> { - return getIrPropertySymbol(unwrapped.symbol) + is IrLazyClass -> { + val unwrapped = fir.unwrapFakeOverrides() + if (unwrapped !== fir) { + when (unwrapped) { + is FirSimpleFunction -> { + 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( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt index 2c28c04b4e2..dc07da65980 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyDeclaration.kt @@ -38,7 +38,7 @@ interface AbstractFir2IrLazyDeclaration> = lazyVar { + fun createLazyAnnotations(): ReadWriteProperty> = lazyVar(lock) { fir.annotations.mapNotNull { callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyFunction.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyFunction.kt index b51ea1442f9..814e6d8e526 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyFunction.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/AbstractFir2IrLazyFunction.kt @@ -68,7 +68,7 @@ abstract class AbstractFir2IrLazyFunction( get() = null 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) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index 8e8a49b226e..db8b8979432 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -96,11 +96,11 @@ class Fir2IrLazyClass( override val isFun: Boolean get() = fir.isFun - override var superTypes: List by lazyVar { + override var superTypes: List by lazyVar(lock) { fir.superTypeRefs.map { it.toIrType(typeConverter) } } - override var thisReceiver: IrValueParameter? by lazyVar { + override var thisReceiver: IrValueParameter? by lazyVar(lock) { symbolTable.enterScope(this) val typeArguments = fir.typeParameters.map { IrSimpleTypeImpl( @@ -124,7 +124,7 @@ class Fir2IrLazyClass( .also(fakeOverrideGenerator::bindOverriddenSymbols) } - override val declarations: MutableList by lazyVar { + override val declarations: MutableList by lazyVar(lock) { val result = mutableListOf() val processedNames = mutableSetOf() // NB: it's necessary to take all callables from scope, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt index 54e3ae91eb2..d5e90e03b7c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyConstructor.kt @@ -67,11 +67,11 @@ class Fir2IrLazyConstructor( 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) } - override var dispatchReceiverParameter: IrValueParameter? by lazyVar { + override var dispatchReceiverParameter: IrValueParameter? by lazyVar(lock) { val containingClass = parent as? IrClass val outerClass = containingClass?.parentClassOrNull if (containingClass?.isInner == true && outerClass != null) { @@ -92,7 +92,7 @@ class Fir2IrLazyConstructor( error("Mutating Fir2Ir lazy elements is not possible") } - override var valueParameters: List by lazyVar { + override var valueParameters: List by lazyVar(lock) { declarationStorage.enterScope(this) fir.valueParameters.mapIndexed { index, valueParameter -> declarationStorage.createIrParameter( diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt index 8dc975fe056..620c682c921 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt @@ -86,7 +86,7 @@ class Fir2IrLazyProperty( } @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 val parent = parent 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 Fir2IrLazyPropertyAccessor( 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( components, startOffset, endOffset, when { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt index bec9694e3f3..cef077969ae 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyPropertyAccessor.kt @@ -45,11 +45,11 @@ class Fir2IrLazyPropertyAccessor( override val name: 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) } - override var dispatchReceiverParameter: IrValueParameter? by lazyVar { + override var dispatchReceiverParameter: IrValueParameter? by lazyVar(lock) { val containingClass = parent as? IrClass if (containingClass != null && shouldHaveDispatchReceiver(containingClass, firParentProperty) ) { @@ -57,13 +57,13 @@ class Fir2IrLazyPropertyAccessor( } else null } - override var extensionReceiverParameter: IrValueParameter? by lazyVar { + override var extensionReceiverParameter: IrValueParameter? by lazyVar(lock) { firParentProperty.receiverTypeRef?.let { createThisReceiverParameter(it.toIrType(typeConverter, conversionTypeContext)) } } - override var valueParameters: List by lazyVar { + override var valueParameters: List by lazyVar(lock) { if (!isSetter) emptyList() else { declarationStorage.enterScope(this) @@ -81,7 +81,7 @@ class Fir2IrLazyPropertyAccessor( } } - override var overriddenSymbols: List by lazyVar { + override var overriddenSymbols: List by lazyVar(lock) { firParentProperty.generateOverriddenAccessorSymbols( firParentClass, !isSetter, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt index bd9bc529459..09bd60679e0 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt @@ -37,24 +37,24 @@ class Fir2IrLazySimpleFunction( override val name: Name get() = fir.name - override var returnType: IrType by lazyVar { + override var returnType: IrType by lazyVar(lock) { fir.returnTypeRef.toIrType(typeConverter) } - override var dispatchReceiverParameter: IrValueParameter? by lazyVar { + override var dispatchReceiverParameter: IrValueParameter? by lazyVar(lock) { val containingClass = parent as? IrClass if (containingClass != null && shouldHaveDispatchReceiver(containingClass, fir)) { createThisReceiverParameter(thisType = containingClass.thisReceiver?.type ?: error("No this receiver for containing class")) } else null } - override var extensionReceiverParameter: IrValueParameter? by lazyVar { + override var extensionReceiverParameter: IrValueParameter? by lazyVar(lock) { fir.receiverTypeRef?.let { createThisReceiverParameter(it.toIrType(typeConverter)) } } - override var valueParameters: List by lazyVar { + override var valueParameters: List by lazyVar(lock) { declarationStorage.enterScope(this) fir.valueParameters.mapIndexed { index, valueParameter -> declarationStorage.createIrParameter( @@ -67,7 +67,7 @@ class Fir2IrLazySimpleFunction( } } - override var overriddenSymbols: List by lazyVar { + override var overriddenSymbols: List by lazyVar(lock) { val parent = parent if (isFakeOverride && parent is Fir2IrLazyClass) { fakeOverrideGenerator.calcBaseSymbolsForFakeOverrideFunction( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index ad2f6e3b57d..d2dd80df2e6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -22,7 +22,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility 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.declarations.* import org.jetbrains.kotlin.ir.descriptors.toIrBasedDescriptor diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrLock.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrLock.kt new file mode 100644 index 00000000000..1d641c92231 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrLock.kt @@ -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 \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt index 247675cc629..a2688ccb741 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyClass.kt @@ -47,14 +47,14 @@ class IrLazyClass( override var annotations: List by createLazyAnnotations() - override var thisReceiver: IrValueParameter? by lazyVar { + override var thisReceiver: IrValueParameter? by lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { descriptor.thisAsReceiverParameter.generateReceiverParameterStub().apply { parent = this@IrLazyClass } } } - override val declarations: MutableList by lazyVar { + override val declarations: MutableList by lazyVar(stubGenerator.lock) { ArrayList().also { typeTranslator.buildWithScope(this) { generateChildStubs(descriptor.constructors, it) @@ -68,13 +68,13 @@ class IrLazyClass( } } - override var typeParameters: List by lazyVar { + override var typeParameters: List by lazyVar(stubGenerator.lock) { descriptor.declaredTypeParameters.mapTo(arrayListOf()) { stubGenerator.generateOrGetTypeParameterStub(it) } } - override var superTypes: List by lazyVar { + override var superTypes: List by lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { // TODO get rid of code duplication, see ClassGenerator#generateClass descriptor.typeConstructor.supertypes.mapNotNullTo(arrayListOf()) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt index 81928a1efd8..f712acb9c38 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyConstructor.kt @@ -56,7 +56,7 @@ class IrLazyConstructor( get() = null set(_) = error("We should never need to store metadata of external declarations.") - override var typeParameters: List by lazyVar { + override var typeParameters: List by lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { stubGenerator.symbolTable.withScope(this) { val classTypeParametersCount = descriptor.constructedClass.original.declaredTypeParameters.size diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt index 0bd01779c6a..6218521c3f8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyDeclarationBase.kt @@ -47,11 +47,11 @@ interface IrLazyDeclarationBase : IrDeclaration { } } - fun createLazyAnnotations(): ReadWriteProperty> = lazyVar { + fun createLazyAnnotations(): ReadWriteProperty> = lazyVar(stubGenerator.lock) { descriptor.annotations.mapNotNull(typeTranslator.constantValueGenerator::generateAnnotationConstructorCall).toMutableList() } - fun createLazyParent(): ReadWriteProperty = lazyVar { + fun createLazyParent(): ReadWriteProperty = lazyVar(stubGenerator.lock) { val currentDescriptor = descriptor val containingDeclaration = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyField.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyField.kt index 414072adfe2..3b5f6085863 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyField.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyField.kt @@ -43,17 +43,17 @@ class IrLazyField( override var parent: IrDeclarationParent by createLazyParent() - override var annotations: List by lazyVar { + override var annotations: List by lazyVar(stubGenerator.lock) { descriptor.backingField?.annotations ?.mapNotNullTo(mutableListOf(), typeTranslator.constantValueGenerator::generateAnnotationConstructorCall) ?: mutableListOf() } - override var type: IrType by lazyVar { + override var type: IrType by lazyVar(stubGenerator.lock) { descriptor.type.toIrType() } - override var initializer: IrExpressionBody? by lazyVar { + override var initializer: IrExpressionBody? by lazyVar(stubGenerator.lock) { descriptor.compileTimeInitializer?.let { factory.createExpressionBody( 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 } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt index 1ca7751f7ff..d9c439b5b8e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunction.kt @@ -64,7 +64,7 @@ class IrLazyFunction( get() = null set(_) = error("We should never need to store metadata of external declarations.") - override var typeParameters: List by lazyVar { + override var typeParameters: List by lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { stubGenerator.symbolTable.withScope(this) { val propertyIfAccessor = descriptor.propertyIfAccessor @@ -81,7 +81,7 @@ class IrLazyFunction( } } - override var overriddenSymbols: List by lazyVar { + override var overriddenSymbols: List by lazyVar(stubGenerator.lock) { descriptor.overriddenDescriptors.mapTo(arrayListOf()) { stubGenerator.generateFunctionStub(it.original).symbol } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt index 598d528f8d9..50c29df28c5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyFunctionBase.kt @@ -26,7 +26,7 @@ interface IrLazyFunctionBase : IrLazyDeclarationBase, IrTypeParametersContainer } fun createValueParameters(): ReadWriteProperty> = - lazyVar { + lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { descriptor.valueParameters.mapTo(arrayListOf()) { stubGenerator.generateValueParameterStub(it).apply { parent = this@IrLazyFunctionBase } @@ -38,7 +38,7 @@ interface IrLazyFunctionBase : IrLazyDeclarationBase, IrTypeParametersContainer parameter: ReceiverParameterDescriptor?, functionDispatchReceiver: Boolean = false, ): ReadWriteProperty = - lazyVar { + lazyVar(stubGenerator.lock) { if (functionDispatchReceiver && stubGenerator.extensions.isStaticFunction(descriptor)) null else typeTranslator.buildWithScope(this) { parameter?.generateReceiverParameterStub()?.also { it.parent = this@IrLazyFunctionBase } @@ -46,7 +46,7 @@ interface IrLazyFunctionBase : IrLazyDeclarationBase, IrTypeParametersContainer } fun createReturnType(): ReadWriteProperty = - lazyVar { + lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { descriptor.returnType!!.toIrType() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt index 52b2265fc34..b832b3d04b8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt @@ -50,7 +50,7 @@ class IrLazyProperty( descriptor.compileTimeInitializer != null || descriptor.getter == null || stubGenerator.extensions.isPropertyWithPlatformField(descriptor) - override var backingField: IrField? by lazyVar { + override var backingField: IrField? by lazyVar(stubGenerator.lock) { if (hasBackingField) { stubGenerator.generateFieldStub(descriptor).apply { correspondingPropertySymbol = this@IrLazyProperty.symbol @@ -58,13 +58,13 @@ class IrLazyProperty( } 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 { 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 { correspondingPropertySymbol = this@IrLazyProperty.symbol } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeAlias.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeAlias.kt index 51fcdb47ed4..60c23b81ea9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeAlias.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeAlias.kt @@ -37,13 +37,13 @@ class IrLazyTypeAlias( override var annotations: List by createLazyAnnotations() - override var typeParameters: List by lazyVar { + override var typeParameters: List by lazyVar(stubGenerator.lock) { descriptor.declaredTypeParameters.mapTo(arrayListOf()) { stubGenerator.generateOrGetTypeParameterStub(it) } } - override var expandedType: IrType by lazyVar { + override var expandedType: IrType by lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this) { descriptor.expandedType.toIrType() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt index ab1c7c2a586..e655a998b36 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyTypeParameter.kt @@ -38,7 +38,7 @@ class IrLazyTypeParameter( override var annotations: List by createLazyAnnotations() - override var superTypes: List by lazyVar { + override var superTypes: List by lazyVar(stubGenerator.lock) { typeTranslator.buildWithScope(this.parent as IrTypeParametersContainer) { val descriptor = symbol.descriptor descriptor.upperBounds.mapTo(arrayListOf()) { it.toIrType() } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt index 7551d6f9205..d88e2a05ac8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/lazyUtil.kt @@ -5,12 +5,13 @@ package org.jetbrains.kotlin.ir.declarations.lazy +import org.jetbrains.kotlin.ir.IrLock import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty -fun lazyVar(initializer: () -> T): ReadWriteProperty = SynchronizedLazyVar(initializer) +fun lazyVar(lock: IrLock, initializer: () -> T): ReadWriteProperty = SynchronizedLazyVar(lock, initializer) -private class SynchronizedLazyVar(initializer: () -> T) : ReadWriteProperty { +private class SynchronizedLazyVar(val lock: IrLock, initializer: () -> T) : ReadWriteProperty { @Volatile private var isInitialized = false @@ -23,7 +24,7 @@ private class SynchronizedLazyVar(initializer: () -> T) : ReadWriteProperty(initializer: () -> T) : ReadWriteProperty): T = value override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { - synchronized(this) { + synchronized(lock) { this._value = value isInitialized = true } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt index e9e6411d540..67eb1f32417 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeclarationStubGenerator.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrLock import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* @@ -44,6 +45,9 @@ abstract class DeclarationStubGenerator( ) : IrProvider { protected val lazyTable = symbolTable.lazyWrapper + val lock: IrLock + get() = symbolTable.lock + var unboundSymbolGeneration: Boolean get() = lazyTable.stubGenerator != null set(value) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt index 772745a2631..ad7ef4b5faf 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/SymbolTable.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrLock import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl @@ -62,13 +63,15 @@ interface ReferenceSymbolTable { class SymbolTable( val signaturer: IdSignatureComposer, val irFactory: IrFactory, - val nameProvider: NameProvider = NameProvider.DEFAULT + val nameProvider: NameProvider = NameProvider.DEFAULT, ) : ReferenceSymbolTable { + val lock = IrLock() + @Suppress("LeakingThis") val lazyWrapper = IrLazySymbolTable(this) - private abstract class SymbolTableBase> { + private abstract class SymbolTableBase>(val lock: IrLock) { val unboundSymbols = linkedSetOf() abstract fun get(d: D): S? @@ -76,7 +79,7 @@ class SymbolTable( abstract fun get(sig: IdSignature): S? inline fun declare(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { - synchronized(this) { + synchronized(lock) { @Suppress("UNCHECKED_CAST") val d0 = d.original as D assert(d0 === d) { @@ -97,7 +100,7 @@ class SymbolTable( @OptIn(ObsoleteDescriptorBasedAPI::class) inline fun declare(sig: IdSignature, createSymbol: () -> S, createOwner: (S) -> B): B { - synchronized(this) { + synchronized(lock) { val existing = get(sig) val symbol = if (existing == null) { createSymbol() @@ -113,7 +116,7 @@ class SymbolTable( } inline fun declareIfNotExists(d: D, createSymbol: () -> S, createOwner: (S) -> B): B { - synchronized(this) { + synchronized(lock) { @Suppress("UNCHECKED_CAST") val d0 = d.original as D assert(d0 === d) { @@ -133,7 +136,7 @@ class SymbolTable( } inline fun declare(sig: IdSignature, d: D?, createSymbol: () -> S, createOwner: (S) -> B): B { - synchronized(this) { + synchronized(lock) { @Suppress("UNCHECKED_CAST") val d0 = d?.original as D assert(d0 === d) { @@ -153,7 +156,7 @@ class SymbolTable( } inline fun referenced(d: D, orElse: () -> S): S { - synchronized(this) { + synchronized(lock) { @Suppress("UNCHECKED_CAST") val d0 = d.original as D assert(d0 === d) { @@ -174,7 +177,7 @@ class SymbolTable( @OptIn(ObsoleteDescriptorBasedAPI::class) inline fun referenced(sig: IdSignature, orElse: () -> S): S { - synchronized(this) { + synchronized(lock) { return get(sig) ?: run { val new = orElse() assert(unboundSymbols.add(new)) { @@ -188,7 +191,7 @@ class SymbolTable( } private open inner class FlatSymbolTable> : - SymbolTableBase() { + SymbolTableBase(lock) { val descriptorToSymbol = linkedMapOf() val idSigToSymbol = linkedMapOf() @@ -225,7 +228,7 @@ class SymbolTable( } private inner class ScopedSymbolTable> - : SymbolTableBase() { + : SymbolTableBase(lock) { inner class Scope(val owner: IrSymbol, val parent: Scope?) { private val descriptorToSymbol = linkedMapOf() private val idSigToSymbol = linkedMapOf()