[LL FIR] KT-58257 Remove LLFirSession.invalidate

- Due to problematic timing in `LLFirSession.invalidate` when the
  function is called from a read action, it's better to remove the
  function altogether.
- The function's only usage was session invalidation after exceptions
  from resolve when FIR tree guards were turned off. Because FIR tree
  guards are stable enough, the flag that turned them off can be
  removed. This also allows removing `LLFirSession.invalidate`.
- The alternative to removing `LLFirSession.invalidate` would be to
  rewrite session invalidation to be independent of write actions. That
  would require additional locking in `LLFirSessionCache`, which we want
  to avoid.

^KT-59297
This commit is contained in:
Marco Pennekamp
2023-07-18 17:25:28 +02:00
committed by Space Team
parent 03c8654fe3
commit 2ba42b8677
3 changed files with 0 additions and 61 deletions
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.project.structure.llFirMo
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyResolverRunner
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.USE_STATE_KEEPER
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.withOnAirDesignation
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.getContainingFile
@@ -215,8 +214,6 @@ private fun handleExceptionFromResolve(
}
val session = firDeclarationToResolve.llFirSession
invalidateFailedSessionIfNeeded(session)
val moduleData = firDeclarationToResolve.llFirModuleData
val module = moduleData.ktModule
@@ -250,8 +247,6 @@ private fun handleExceptionFromResolve(
}
val session = designation.firFile.llFirSession
invalidateFailedSessionIfNeeded(session)
val moduleData = session.llFirModuleData
val module = moduleData.ktModule
@@ -271,9 +266,3 @@ private fun handleExceptionFromResolve(
withEntry("firDesignationToResolve", designation) { it.toString() }
}
}
private fun invalidateFailedSessionIfNeeded(session: LLFirSession) {
if (!USE_STATE_KEEPER) {
session.invalidate()
}
}
@@ -5,11 +5,8 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.sessions
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.ModificationTracker
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.USE_STATE_KEEPER
import org.jetbrains.kotlin.analysis.project.structure.KtModule
import org.jetbrains.kotlin.fir.BuiltinTypes
import org.jetbrains.kotlin.fir.FirElementWithResolveState
@@ -17,7 +14,6 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.PrivateSessionConstructor
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicLong
@OptIn(PrivateSessionConstructor::class)
@@ -46,31 +42,6 @@ abstract class LLFirSession(
isValid = false
}
fun invalidate() {
val application = ApplicationManager.getApplication()
if (application.isWriteAccessAllowed) {
invalidateInWriteAction()
} else {
// We have to invalidate the session on the EDT per the contract of `LLFirSessionInvalidationService`. The timing here is not
// 100% waterproof, but `LLFirSession.invalidate` is only a workaround for when FIR guards consistency protection (see KT-56503)
// is turned off. The check restricts usage of `invalidate` to this scenario.
check(!USE_STATE_KEEPER) {
"Outside a write action, a session may only be invalidated directly when FIR guards are turned off."
}
// The lambda passed to `invokeLater` might survive beyond project disposal (especially in tests), so me must not capture a hard
// reference to `this` that can leak `project`. A weak reference is appropriate because we do not need to invalidate the session
// when it has already been collected.
val weakSession = WeakReference(this)
application.invokeLater(
{ weakSession.invalidateIfAlive() },
// `ModalityState.any()` can be used because session invalidation does not modify PSI, VFS, or the project model.
ModalityState.any(),
)
}
}
/**
* Creates a [ModificationTracker] which tracks the validity of this session via [isValid].
*/
@@ -91,19 +62,6 @@ abstract class LLFirSession(
}
}
private fun LLFirSession.invalidateInWriteAction() {
if (!isValid) return
LLFirSessionInvalidationService.getInstance(project).invalidate(ktModule)
}
private fun WeakReference<LLFirSession>.invalidateIfAlive() = ApplicationManager.getApplication().runWriteAction {
val session = get() ?: return@runWriteAction
if (session.project.isDisposed) return@runWriteAction
session.invalidateInWriteAction()
}
abstract class LLFirModuleSession(
ktModule: KtModule,
builtinTypes: BuiltinTypes,
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
import com.intellij.openapi.util.registry.Registry
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirElementWithResolveState
import org.jetbrains.kotlin.fir.FirSession
@@ -241,8 +240,6 @@ internal class StateKeeper<in Owner : Any, Context : Any>(val provider: (Owner,
}
}
internal val USE_STATE_KEEPER: Boolean = Registry.`is`("kotlin.analysis.use.state.keeper", true)
/**
* State preserved by a [StateKeeper].
*/
@@ -267,11 +264,6 @@ internal inline fun <Target : FirElementWithResolveState, Context : Any, Result>
prepareTarget: (Target) -> Unit = {},
action: () -> Result,
): Result {
if (!USE_STATE_KEEPER) {
prepareTarget(target)
return action()
}
val onAirAnalysisTarget = target.moduleData.session.onAirAnalysisTarget
if (onAirAnalysisTarget != null && target in onAirAnalysisTarget) {
// Several arrangers reset declaration bodies to lazy ones, and then re-construct the FIR tree from the backing PSI.