From 2bb3b41348bd965227622294a3cb2eddab5596cb Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 13 Dec 2022 14:45:34 +0100 Subject: [PATCH] [LL FIR] clear implementation details in ValueWithPostCompute after the value is computed to save some memory --- .../api/fir/caches/ValueWithPostCompute.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/ValueWithPostCompute.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/ValueWithPostCompute.kt index 833b1ae9951..3d2ac9ea5c1 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/ValueWithPostCompute.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/caches/ValueWithPostCompute.kt @@ -26,7 +26,8 @@ internal class ValueWithPostCompute( ) { private var _calculate: ((KEY) -> Pair)? = calculate private var _postCompute: ((KEY, VALUE, DATA) -> Unit)? = postCompute - private val lock = ReentrantLock() + private var lock: ReentrantLock? = ReentrantLock() + private var guard: ThreadLocal? = ThreadLocal.withInitial { false } /** * can be in one of the following three states: @@ -41,16 +42,15 @@ internal class ValueWithPostCompute( @Volatile private var value: Any? = ValueIsNotComputed - private val guard = ThreadLocal.withInitial { false } private inline fun recursiveGuarded(body: () -> T): T { - check(!guard.get()) { + check(!guard!!.get()) { "Should not be called recursively" } - guard.set(true) + guard!!.set(true) return try { body() } finally { - guard.set(false) + guard!!.set(false) } } @@ -61,7 +61,7 @@ internal class ValueWithPostCompute( if (stateSnapshot.threadId == Thread.currentThread().id) { return stateSnapshot.value as VALUE } else { - lock.lockWithPCECheck(LOCKING_INTERVAL_MS) { // wait until other thread which holds the lock now computes the value + lock!!.lockWithPCECheck(LOCKING_INTERVAL_MS) { // wait until other thread which holds the lock now computes the value when (val newStateSnapshot = value) { ValueIsNotComputed -> { // if we have a PCE during value computation, then we will enter the critical section with `value == ValueIsNotComputed` @@ -80,7 +80,7 @@ internal class ValueWithPostCompute( } } } - ValueIsNotComputed -> lock.lockWithPCECheck(LOCKING_INTERVAL_MS) { + ValueIsNotComputed -> lock!!.lockWithPCECheck(LOCKING_INTERVAL_MS) { return computeValueWithoutLock() } is ExceptionWasThrownDuringValueComputation -> { @@ -95,7 +95,7 @@ internal class ValueWithPostCompute( @Suppress("UNCHECKED_CAST") // should be called under a synchronized section private fun computeValueWithoutLock(): VALUE { - require(lock.isHeldByCurrentThread) + require(lock!!.isHeldByCurrentThread) // if we entered synchronized section that's mean that the value is not yet calculated and was not started to be calculated // or the some other thread calculated the value while we were waiting to acquire the lock @@ -130,6 +130,8 @@ internal class ValueWithPostCompute( } _calculate = null _postCompute = null + lock = null + guard = null value = calculatedValue return calculatedValue }