[FIR IDE] Make fir resolve phase volatile and remove locks
This commit is contained in:
@@ -32,6 +32,7 @@ import kotlin.properties.Delegates
|
||||
class FirJavaClass @FirImplementationDetail internal constructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val name: Name,
|
||||
override val annotations: MutableList<FirAnnotationCall>,
|
||||
|
||||
@@ -37,6 +37,7 @@ class FirJavaConstructor @FirImplementationDetail constructor(
|
||||
override val typeParameters: MutableList<FirTypeParameterRef>,
|
||||
annotationBuilder: () -> List<FirAnnotationCall>,
|
||||
override var status: FirDeclarationStatus,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val dispatchReceiverType: ConeKotlinType?,
|
||||
) : FirConstructor() {
|
||||
|
||||
@@ -36,6 +36,7 @@ class FirJavaField @FirImplementationDetail constructor(
|
||||
override val moduleData: FirModuleData,
|
||||
override val symbol: FirFieldSymbol,
|
||||
override val name: Name,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override var returnTypeRef: FirTypeRef,
|
||||
override var status: FirDeclarationStatus,
|
||||
|
||||
@@ -50,6 +50,7 @@ import kotlin.properties.Delegates
|
||||
class FirJavaMethod @FirImplementationDetail constructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
override var returnTypeRef: FirTypeRef,
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ import kotlin.contracts.contract
|
||||
class FirJavaValueParameter @FirImplementationDetail constructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
override var returnTypeRef: FirTypeRef,
|
||||
|
||||
+1
@@ -55,6 +55,7 @@ internal class FirAnonymousFunctionImpl(
|
||||
override val typeParameters: MutableList<FirTypeParameter>,
|
||||
override var typeRef: FirTypeRef,
|
||||
) : FirAnonymousFunction() {
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase = FirResolvePhase.DECLARATIONS
|
||||
override var status: FirDeclarationStatus = FirResolvedDeclarationStatusImpl.DEFAULT_STATUS_FOR_STATUSLESS_DECLARATIONS
|
||||
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirAnonymousInitializerImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirAnonymousObjectImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirConstructorImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirDefaultSetterValueParameter(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirEnumEntryImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirErrorFunctionImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirErrorPropertyImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
class FirFieldImpl @FirImplementationDetail constructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirFileImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirPrimaryConstructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
open class FirPropertyAccessorImpl @FirImplementationDetail constructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirPropertyImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirRegularClassImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirSimpleFunctionImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirTypeAliasImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirTypeParameterImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
internal class FirValueParameterImpl(
|
||||
override val source: FirSourceElement?,
|
||||
override val moduleData: FirModuleData,
|
||||
@Volatile
|
||||
override var resolvePhase: FirResolvePhase,
|
||||
override val origin: FirDeclarationOrigin,
|
||||
override val attributes: FirDeclarationAttributes,
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
declaration.configure {
|
||||
+symbolWithPackage("fir.symbols", "FirBasedSymbol", "out FirDeclaration")
|
||||
+field("moduleData", firModuleDataType)
|
||||
+field("resolvePhase", resolvePhaseType, withReplace = true).apply { isMutable = true }
|
||||
+field("resolvePhase", resolvePhaseType, withReplace = true).apply { isMutable = true; isVolatile = true }
|
||||
+field("origin", declarationOriginType)
|
||||
+field("attributes", declarationAttributesType)
|
||||
shouldBeAbstractClass()
|
||||
|
||||
+10
-3
@@ -11,6 +11,7 @@ sealed class Field : Importable {
|
||||
abstract val name: String
|
||||
open val arguments = mutableListOf<Importable>()
|
||||
abstract val nullable: Boolean
|
||||
abstract var isVolatile: Boolean
|
||||
open var withReplace: Boolean = false
|
||||
abstract val isFirType: Boolean
|
||||
|
||||
@@ -71,6 +72,7 @@ sealed class Field : Importable {
|
||||
class FieldWithDefault(val origin: Field) : Field() {
|
||||
override val name: String get() = origin.name
|
||||
override val type: String get() = origin.type
|
||||
override var isVolatile: Boolean = origin.isVolatile
|
||||
override val nullable: Boolean get() = origin.nullable
|
||||
override var withReplace: Boolean
|
||||
get() = origin.withReplace
|
||||
@@ -123,7 +125,8 @@ class SimpleField(
|
||||
override val packageName: String?,
|
||||
val customType: Importable? = null,
|
||||
override val nullable: Boolean,
|
||||
override var withReplace: Boolean
|
||||
override var withReplace: Boolean,
|
||||
override var isVolatile: Boolean = false
|
||||
) : Field() {
|
||||
override val isFirType: Boolean = false
|
||||
override val fullQualifiedName: String?
|
||||
@@ -138,7 +141,8 @@ class SimpleField(
|
||||
packageName,
|
||||
customType,
|
||||
nullable,
|
||||
withReplace
|
||||
withReplace,
|
||||
isVolatile
|
||||
).apply {
|
||||
withBindThis = this@SimpleField.withBindThis
|
||||
}
|
||||
@@ -150,7 +154,8 @@ class SimpleField(
|
||||
newType.packageName,
|
||||
customType,
|
||||
nullable,
|
||||
withReplace
|
||||
withReplace,
|
||||
isVolatile
|
||||
).also {
|
||||
it.withBindThis = withBindThis
|
||||
updateFieldsInCopy(it)
|
||||
@@ -170,6 +175,7 @@ class FirField(
|
||||
}
|
||||
|
||||
override val type: String get() = element.type
|
||||
override var isVolatile: Boolean = false
|
||||
override val packageName: String? get() = element.packageName
|
||||
override val isFirType: Boolean = true
|
||||
|
||||
@@ -202,6 +208,7 @@ class FieldList(
|
||||
override val nullable: Boolean
|
||||
get() = false
|
||||
|
||||
override var isVolatile: Boolean = false
|
||||
override var isMutable: Boolean = true
|
||||
|
||||
override fun internalCopy(): Field {
|
||||
|
||||
-1
@@ -37,7 +37,6 @@ fun Element.generateCode(generationPath: File): GeneratedFile {
|
||||
fun SmartPrinter.printElement(element: Element) {
|
||||
with(element) {
|
||||
val isInterface = kind == Kind.Interface || kind == Kind.SealedInterface
|
||||
|
||||
fun abstract() {
|
||||
if (!isInterface) {
|
||||
print("abstract ")
|
||||
|
||||
+7
@@ -6,10 +6,14 @@
|
||||
package org.jetbrains.kotlin.fir.tree.generator.printer
|
||||
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.Field
|
||||
import org.jetbrains.kotlin.fir.tree.generator.model.SimpleField
|
||||
import org.jetbrains.kotlin.util.SmartPrinter
|
||||
|
||||
|
||||
fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: Boolean, end: String) {
|
||||
if (isImplementation && !field.isVal && field.isVolatile) {
|
||||
println("@Volatile")
|
||||
}
|
||||
if (override) {
|
||||
print("override ")
|
||||
}
|
||||
@@ -23,6 +27,9 @@ fun SmartPrinter.printField(field: Field, isImplementation: Boolean, override: B
|
||||
}
|
||||
|
||||
fun SmartPrinter.printFieldWithDefaultInImplementation(field: Field) {
|
||||
if (!field.isVal && field.isVolatile) {
|
||||
println("@Volatile")
|
||||
}
|
||||
val defaultValue = field.defaultValueInImplementation
|
||||
print("override ")
|
||||
if (field.isVal) {
|
||||
|
||||
+2
@@ -73,6 +73,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
|
||||
}
|
||||
println("(")
|
||||
withIndent {
|
||||
|
||||
fieldsWithoutDefault.forEachIndexed { _, field ->
|
||||
printField(field, isImplementation = true, override = true, end = ",")
|
||||
}
|
||||
@@ -89,6 +90,7 @@ fun SmartPrinter.printImplementation(implementation: Implementation) {
|
||||
withIndent {
|
||||
if (isInterface || isAbstract) {
|
||||
allFields.forEach {
|
||||
|
||||
abstract()
|
||||
printField(it, isImplementation = true, override = true, end = "")
|
||||
}
|
||||
|
||||
+9
-11
@@ -25,18 +25,16 @@ internal class IdeFirPhaseManager(
|
||||
symbol: FirBasedSymbol<*>,
|
||||
requiredPhase: FirResolvePhase
|
||||
) {
|
||||
val fir = symbol.fir as FirDeclaration
|
||||
val fir = symbol.fir
|
||||
try {
|
||||
if (fir.resolvePhase < requiredPhase) {
|
||||
lazyDeclarationResolver.lazyResolveDeclaration(
|
||||
firDeclarationToResolve = fir,
|
||||
moduleFileCache = cache,
|
||||
scopeSession = ScopeSession(),
|
||||
toPhase = requiredPhase,
|
||||
checkPCE = true,
|
||||
skipLocalDeclaration = true,
|
||||
)
|
||||
}
|
||||
lazyDeclarationResolver.lazyResolveDeclaration(
|
||||
firDeclarationToResolve = fir,
|
||||
moduleFileCache = cache,
|
||||
scopeSession = ScopeSession(),
|
||||
toPhase = requiredPhase,
|
||||
checkPCE = true,
|
||||
skipLocalDeclaration = true,
|
||||
)
|
||||
} catch (e: Throwable) {
|
||||
sessionInvalidator.invalidate(fir.moduleData.session)
|
||||
throw e
|
||||
|
||||
-16
@@ -13,8 +13,6 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.InternalForInline
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.file.builder.ModuleFileCache
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.ResolveType
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSourcesSession
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.getElementTextInContext
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -50,20 +48,6 @@ abstract class FirModuleResolveState {
|
||||
|
||||
internal abstract fun collectDiagnosticsForFile(ktFile: KtFile, filter: DiagnosticCheckerFilter): Collection<FirPsiDiagnostic>
|
||||
|
||||
internal inline fun <D : FirDeclaration, R> withLock(declaration: D, declarationLockType: DeclarationLockType, action: (D) -> R): R {
|
||||
val originalDeclaration = (declaration as? FirCallableDeclaration)?.unwrapFakeOverrides() ?: declaration
|
||||
val session = originalDeclaration.moduleData.session
|
||||
return when {
|
||||
originalDeclaration.origin == FirDeclarationOrigin.Source && session is FirIdeSourcesSession -> {
|
||||
val cache = session.cache
|
||||
val file = tryGetCachedFirFile(declaration, cache)
|
||||
?: error("Fir file was not found for\n${declaration.render()}\n${(declaration.psi as? KtElement)?.getElementTextInContext()}")
|
||||
cache.firFileLockProvider.withLock(file, declarationLockType) { action(declaration) }
|
||||
}
|
||||
else -> action(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
@InternalForInline
|
||||
abstract fun findSourceFirDeclaration(
|
||||
ktDeclaration: KtDeclaration,
|
||||
|
||||
+2
-26
@@ -125,7 +125,7 @@ fun <D : FirDeclaration, R> D.withFirDeclaration(
|
||||
action: (D) -> R,
|
||||
): R {
|
||||
resolvedFirToPhase(phase, resolveState)
|
||||
return resolveState.withLock(this, DeclarationLockType.READ_LOCK, action)
|
||||
return action(this)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,31 +138,7 @@ fun <D : FirDeclaration, R> D.withFirDeclaration(
|
||||
action: (D) -> R,
|
||||
): R {
|
||||
resolvedFirToType(type, resolveState)
|
||||
return resolveState.withLock(this, DeclarationLockType.READ_LOCK, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes [action] with given [FirDeclaration] under write lock, so resolve **is possible** inside [action]
|
||||
*/
|
||||
fun <D : FirDeclaration, R> D.withFirDeclarationInWriteLock(
|
||||
resolveState: FirModuleResolveState,
|
||||
phase: FirResolvePhase = FirResolvePhase.RAW_FIR,
|
||||
action: (D) -> R,
|
||||
): R {
|
||||
resolvedFirToPhase(phase, resolveState)
|
||||
return resolveState.withLock(this, DeclarationLockType.WRITE_LOCK, action)
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes [action] with given [FirDeclaration] under write lock, so resolve **is possible** inside [action]
|
||||
*/
|
||||
fun <D : FirDeclaration, R> D.withFirDeclarationInWriteLock(
|
||||
resolveState: FirModuleResolveState,
|
||||
resolveType: ResolveType = ResolveType.BodyResolveWithChildren,
|
||||
action: (D) -> R,
|
||||
): R {
|
||||
resolvedFirToType(resolveType, resolveState)
|
||||
return resolveState.withLock(this, DeclarationLockType.WRITE_LOCK, action)
|
||||
return action(this)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+8
-52
@@ -8,66 +8,24 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.file.builder
|
||||
import com.google.common.collect.MapMaker
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.annotations.PrivateForInline
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.DeclarationLockType
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.util.lockWithPCECheck
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
import java.util.concurrent.locks.ReadWriteLock
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
internal class LockProvider<KEY> {
|
||||
private val locks: ConcurrentMap<KEY, ReadWriteLock> = MapMaker().weakKeys().makeMap()
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
private val deadLockGuard = DeadLockGuard()
|
||||
private val locks: ConcurrentMap<KEY, ReentrantLock> = MapMaker().weakKeys().makeMap()
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun getLockFor(key: KEY) = locks.getOrPut(key) { ReentrantReadWriteLock() }
|
||||
private inline fun getLockFor(key: KEY) = locks.getOrPut(key) { ReentrantLock() }
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <R> withReadLock(key: KEY, action: () -> R): R {
|
||||
val readLock = getLockFor(key).readLock()
|
||||
return deadLockGuard.guardReadLock { readLock.withLock { action() } }
|
||||
}
|
||||
inline fun <R> withWriteLock(key: KEY, action: () -> R): R =
|
||||
getLockFor(key).withLock(action)
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <R> withWriteLock(key: KEY, action: () -> R): R {
|
||||
val writeLock = getLockFor(key).writeLock()
|
||||
return deadLockGuard.guardWriteLock { writeLock.withLock { action() } }
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <R> withWriteLockPCECheck(key: KEY, lockingIntervalMs: Long, action: () -> R): R {
|
||||
val writeLock = getLockFor(key).writeLock()
|
||||
return deadLockGuard.guardWriteLock { writeLock.lockWithPCECheck(lockingIntervalMs, action) }
|
||||
}
|
||||
|
||||
inline fun <R> withLock(declaration: KEY, declarationLockType: DeclarationLockType, action: () -> R): R = when (declarationLockType) {
|
||||
DeclarationLockType.READ_LOCK -> withReadLock(declaration, action)
|
||||
DeclarationLockType.WRITE_LOCK -> withWriteLock(declaration, action)
|
||||
}
|
||||
}
|
||||
|
||||
@PrivateForInline
|
||||
internal class DeadLockGuard {
|
||||
private val readLocksCount = ThreadLocal.withInitial { 0 }
|
||||
|
||||
inline fun <R> guardReadLock(action: () -> R): R {
|
||||
readLocksCount.set(readLocksCount.get() + 1)
|
||||
return try {
|
||||
action()
|
||||
} finally {
|
||||
readLocksCount.set(readLocksCount.get() - 1)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <R> guardWriteLock(action: () -> R): R {
|
||||
|
||||
if (readLocksCount.get() > 0) {
|
||||
throw ReadWriteDeadLockException()
|
||||
}
|
||||
return action()
|
||||
}
|
||||
inline fun <R> withWriteLockPCECheck(key: KEY, lockingIntervalMs: Long, action: () -> R): R =
|
||||
getLockFor(key).lockWithPCECheck(lockingIntervalMs, action)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,6 +41,4 @@ internal inline fun <R> LockProvider<FirFile>.runCustomResolveUnderLock(
|
||||
} else {
|
||||
withWriteLock(key = firFile, action = body)
|
||||
}
|
||||
}
|
||||
|
||||
class ReadWriteDeadLockException : IllegalStateException("Acquiring write lock when read lock hold")
|
||||
}
|
||||
-6
@@ -50,12 +50,6 @@ internal abstract class ModuleFileCache {
|
||||
abstract fun getCachedFirFile(ktFile: KtFile): FirFile?
|
||||
|
||||
abstract val firFileLockProvider: LockProvider<FirFile>
|
||||
|
||||
inline fun <D : FirDeclaration, R> withReadLockOn(declaration: D, action: (D) -> R): R {
|
||||
val file = getContainerFirFile(declaration)
|
||||
?: error("No fir file found for\n${declaration.render()}")
|
||||
return firFileLockProvider.withReadLock(file) { action(declaration) }
|
||||
}
|
||||
}
|
||||
|
||||
internal class ModuleFileCacheImpl(override val session: FirSession) : ModuleFileCache() {
|
||||
|
||||
+4
-3
@@ -123,9 +123,10 @@ internal class FileStructure private constructor(
|
||||
toPhase = FirResolvePhase.BODY_RESOLVE,
|
||||
checkPCE = true,
|
||||
)
|
||||
return moduleFileCache.firFileLockProvider.withReadLock(firFile) {
|
||||
FileElementFactory.createFileStructureElement(firDeclaration, declaration, firFile, moduleFileCache.firFileLockProvider)
|
||||
}
|
||||
return FileElementFactory.createFileStructureElement(firDeclaration, declaration, firFile, moduleFileCache.firFileLockProvider)
|
||||
// return moduleFileCache.firFileLockProvider.withReadLock(firFile) {
|
||||
// FileElementFactory.createFileStructureElement(firDeclaration, declaration, firFile, moduleFileCache.firFileLockProvider)
|
||||
// }
|
||||
}
|
||||
|
||||
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) {
|
||||
|
||||
+13
-27
@@ -41,40 +41,26 @@ internal fun FirLazyDeclarationResolver.lazyResolveDeclaration(
|
||||
require(firDeclaration is FirCallableDeclaration) {
|
||||
"CallableReturnType type cannot be applied to ${firDeclaration::class.qualifiedName}"
|
||||
}
|
||||
//Need to be sync
|
||||
if (firDeclaration.returnTypeRef is FirResolvedTypeRef) return
|
||||
val containingFile = firDeclaration.getContainingFile()
|
||||
if (containingFile != null) {
|
||||
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(containingFile, checkPCE) {
|
||||
if (firDeclaration.returnTypeRef !is FirResolvedTypeRef) {
|
||||
lazyResolveDeclaration(
|
||||
firDeclarationToResolve = firDeclaration,
|
||||
moduleFileCache = moduleFileCache,
|
||||
toPhase = FirResolvePhase.TYPES,
|
||||
scopeSession = scopeSession,
|
||||
checkPCE = checkPCE,
|
||||
)
|
||||
}
|
||||
if (firDeclaration.returnTypeRef !is FirResolvedTypeRef) {
|
||||
lazyResolveDeclaration(
|
||||
firDeclarationToResolve = firDeclaration,
|
||||
moduleFileCache = moduleFileCache,
|
||||
toPhase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
|
||||
scopeSession = scopeSession,
|
||||
checkPCE = checkPCE,
|
||||
)
|
||||
}
|
||||
check(firDeclaration.returnTypeRef is FirResolvedTypeRef)
|
||||
}
|
||||
} else {
|
||||
|
||||
if (firDeclaration.resolvePhase < FirResolvePhase.TYPES) {
|
||||
lazyResolveDeclaration(
|
||||
firDeclarationToResolve = firDeclaration,
|
||||
moduleFileCache = moduleFileCache,
|
||||
toPhase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
|
||||
toPhase = FirResolvePhase.TYPES,
|
||||
scopeSession = scopeSession,
|
||||
checkPCE = checkPCE,
|
||||
)
|
||||
}
|
||||
if (firDeclaration.returnTypeRef is FirResolvedTypeRef) return
|
||||
|
||||
lazyResolveDeclaration(
|
||||
firDeclarationToResolve = firDeclaration,
|
||||
moduleFileCache = moduleFileCache,
|
||||
toPhase = FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE,
|
||||
scopeSession = scopeSession,
|
||||
checkPCE = checkPCE,
|
||||
)
|
||||
check(firDeclaration.returnTypeRef is FirResolvedTypeRef)
|
||||
}
|
||||
ResolveType.BodyResolveWithChildren, ResolveType.CallableBodyResolve -> {
|
||||
require(firDeclaration is FirCallableDeclaration || toResolveType != ResolveType.CallableBodyResolve) {
|
||||
|
||||
+13
-4
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationResolveStatus
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
|
||||
@@ -41,6 +42,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
checkPCE: Boolean,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
) {
|
||||
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
|
||||
resolveFileAnnotationsWithoutLock(
|
||||
firFile = firFile,
|
||||
@@ -63,6 +65,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
scopeSession: ScopeSession,
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
) {
|
||||
if (firFile.resolvePhase >= FirResolvePhase.IMPORTS) return
|
||||
lazyResolveFileDeclarationWithoutLock(
|
||||
firFile = firFile,
|
||||
moduleFileCache = moduleFileCache,
|
||||
@@ -116,6 +119,8 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
scopeSession: ScopeSession,
|
||||
checkPCE: Boolean = false,
|
||||
) {
|
||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||
if (firFile.resolvePhase >= toPhase) return
|
||||
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(firFile, checkPCE) {
|
||||
lazyResolveFileDeclarationWithoutLock(
|
||||
firFile = firFile,
|
||||
@@ -136,8 +141,9 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
collector: FirTowerDataContextCollector? = null,
|
||||
) {
|
||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||
if (firFile.resolvePhase >= toPhase) return
|
||||
if (firFile.resolvePhase == FirResolvePhase.RAW_FIR) {
|
||||
val resolvePhase = firFile.resolvePhase
|
||||
if (resolvePhase >= toPhase) return
|
||||
if (resolvePhase == FirResolvePhase.RAW_FIR) {
|
||||
firFile.transform<FirElement, Any?>(FirImportResolveTransformer(firFile.moduleData.session), null)
|
||||
firFile.replaceResolvePhase(FirResolvePhase.IMPORTS)
|
||||
}
|
||||
@@ -245,6 +251,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
|
||||
}
|
||||
|
||||
if (firDeclarationToResolve.resolvePhase >= toPhase) return
|
||||
moduleFileCache.firFileLockProvider.runCustomResolveUnderLock(designation.firFile, checkPCE) {
|
||||
runLazyDesignatedResolveWithoutLock(
|
||||
designation = designation,
|
||||
@@ -263,7 +270,9 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
toPhase: FirResolvePhase,
|
||||
checkPCE: Boolean,
|
||||
) {
|
||||
if (designation.declaration.resolvePhase >= toPhase) return
|
||||
if (toPhase == FirResolvePhase.RAW_FIR) return
|
||||
val declarationResolvePhase = designation.declaration.resolvePhase
|
||||
if (declarationResolvePhase >= toPhase) return
|
||||
|
||||
if (designation.firFile.resolvePhase == FirResolvePhase.RAW_FIR) {
|
||||
lazyResolveFileDeclarationWithoutLock(
|
||||
@@ -275,7 +284,7 @@ internal class FirLazyDeclarationResolver(private val firFileBuilder: FirFileBui
|
||||
)
|
||||
}
|
||||
if (toPhase == FirResolvePhase.IMPORTS) return
|
||||
var currentPhase = maxOf(designation.declaration.resolvePhase, FirResolvePhase.IMPORTS)
|
||||
var currentPhase = maxOf(declarationResolvePhase, FirResolvePhase.IMPORTS)
|
||||
|
||||
while (currentPhase < toPhase) {
|
||||
currentPhase = currentPhase.next
|
||||
|
||||
+4
-55
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.api.withFirDeclarationInWriteLock
|
||||
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.ResolveType
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ValidityTokenOwner
|
||||
import org.jetbrains.kotlin.idea.frontend.api.tokens.ValidityToken
|
||||
@@ -31,16 +30,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
|
||||
?: throw EntityWasGarbageCollectedException("FirElement")
|
||||
val resolveState = resolveStateWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
|
||||
return when (phase) {
|
||||
FirResolvePhase.BODY_RESOLVE -> {
|
||||
/*
|
||||
The BODY_RESOLVE phase is the maximum possible phase we can resolve our declaration to
|
||||
So there is not need to run whole `action` under read lock
|
||||
*/
|
||||
action(fir.withFirDeclaration(resolveState, phase) { it })
|
||||
}
|
||||
else -> fir.withFirDeclaration(resolveState, phase) { action(it) }
|
||||
}
|
||||
return fir.withFirDeclaration(resolveState, phase) { action(it) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,23 +52,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
|
||||
inline fun <R> withFirWithPossibleResolveInside(
|
||||
phase: FirResolvePhase = FirResolvePhase.RAW_FIR,
|
||||
crossinline action: (fir: D) -> R
|
||||
): R {
|
||||
token.assertIsValidAndAccessible()
|
||||
val fir = firWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirElement")
|
||||
val resolveState = resolveStateWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
|
||||
return when (phase) {
|
||||
FirResolvePhase.BODY_RESOLVE -> {
|
||||
/*
|
||||
The BODY_RESOLVE phase is the maximum possible phase we can resolve our declaration to
|
||||
So there is not need to run whole `action` under write lock
|
||||
*/
|
||||
action(fir.withFirDeclarationInWriteLock(resolveState, phase) { it })
|
||||
}
|
||||
else -> fir.withFirDeclarationInWriteLock(resolveState, phase) { action(it) }
|
||||
}
|
||||
}
|
||||
): R = withFir(phase, action)
|
||||
|
||||
/**
|
||||
* Runs [action] with fir element with write action hold
|
||||
@@ -87,23 +61,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
|
||||
inline fun <R> withFirWithPossibleResolveInside(
|
||||
resolveType: ResolveType = ResolveType.NoResolve,
|
||||
crossinline action: (fir: D) -> R
|
||||
): R {
|
||||
token.assertIsValidAndAccessible()
|
||||
val fir = firWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirElement")
|
||||
val resolveState = resolveStateWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
|
||||
return when (resolveType) {
|
||||
ResolveType.BodyResolveWithChildren -> {
|
||||
/*
|
||||
The ResolveType type is the maximum possible phase we can resolve our declaration to
|
||||
So there is not need to run whole `action` under write lock
|
||||
*/
|
||||
action(fir.withFirDeclarationInWriteLock(resolveState, resolveType) { it })
|
||||
}
|
||||
else -> fir.withFirDeclarationInWriteLock(resolveState, resolveType) { action(it) }
|
||||
}
|
||||
}
|
||||
): R = withFir(resolveType, action)
|
||||
|
||||
val resolveState
|
||||
get() = resolveStateWeakRef.get() ?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
|
||||
@@ -119,16 +77,7 @@ internal class FirRefWithValidityCheck<out D : FirDeclaration>(fir: D, resolveSt
|
||||
?: throw EntityWasGarbageCollectedException("FirElement")
|
||||
val resolveState = resolveStateWeakRef.get()
|
||||
?: throw EntityWasGarbageCollectedException("FirModuleResolveState")
|
||||
return when (type) {
|
||||
ResolveType.BodyResolveWithChildren -> {
|
||||
/*
|
||||
The CallableBodyResolve type is the maximum possible phase we can resolve our declaration to
|
||||
So there is not need to run whole `action` under read lock
|
||||
*/
|
||||
action(fir.withFirDeclaration(type, resolveState) { it })
|
||||
}
|
||||
else -> fir.withFirDeclaration(type, resolveState) { action(it) }
|
||||
}
|
||||
return fir.withFirDeclaration(type, resolveState) { action(it) }
|
||||
}
|
||||
|
||||
inline fun <R> withFirAndCache(type: ResolveType, crossinline createValue: (fir: D) -> R) =
|
||||
|
||||
Reference in New Issue
Block a user