@@ -272,12 +272,46 @@ object Semantic {
272
272
*/
273
273
274
274
object Cache {
275
- opaque type CacheIn = mutable.Map [Value , EqHashMap [Tree , Value ]]
276
- opaque type CacheOut = mutable.Map [Value , EqHashMap [Tree , Value ]]
275
+ opaque type CacheStore = mutable.Map [Value , EqHashMap [Tree , Value ]]
277
276
278
- class Cache (val in : CacheIn , var out : CacheOut ) {
277
+ class Cache {
278
+ private val in : CacheStore = mutable.Map .empty
279
+ private var out : CacheStore = mutable.Map .empty
280
+ private val global : CacheStore = mutable.Map .empty
279
281
var changed : Boolean = false
280
282
283
+ def contains (value : Value , expr : Tree ) =
284
+ out.contains(value, expr) || global.contains(value, expr)
285
+
286
+ def apply (value : Value , expr : Tree ) =
287
+ if out.contains(value, expr) then out(value)(expr)
288
+ else global(value)(expr)
289
+
290
+ def assume (value : Value , expr : Tree ) =
291
+ val assumeValue = if (in.contains(value, expr)) in.get(value, expr) else Hot
292
+ out.put(value, expr, assumeValue)
293
+ assumeValue
294
+
295
+ def update (value : Value , expr : Tree , result : Value ) =
296
+ out.put(value, expr, result)
297
+
298
+ def remove (value : Value , expr : Tree ) =
299
+ out.remove(value, expr)
300
+
301
+ /** Commit out cache to global cache.
302
+ *
303
+ * Precondition: the out cache reaches fixed point.
304
+ */
305
+ def commit () = {
306
+ out.foreach { (v, m) =>
307
+ m.iterator.foreach { (e, res) =>
308
+ global.put(v, e, res)
309
+ }
310
+ }
311
+
312
+ out = mutable.Map .empty
313
+ }
314
+
281
315
/** Copy out to in and reset out to empty */
282
316
def update () = {
283
317
out.foreach { (v, m) =>
@@ -290,10 +324,10 @@ object Semantic {
290
324
}
291
325
}
292
326
293
- val empty : Cache = new Cache (mutable. Map .empty, mutable. Map .empty )
327
+ val empty : Cache = new Cache ()
294
328
295
- extension (cache : CacheIn | CacheOut )
296
- def contains (value : Value , expr : Tree ): Boolean = cache.contains(value) && cache(value).contains(expr)
329
+ extension (cache : CacheStore )
330
+ def contains (value : Value , expr : Tree ) = cache.contains(value) && cache(value).contains(expr)
297
331
def get (value : Value , expr : Tree ): Value = cache(value)(expr)
298
332
def remove (value : Value , expr : Tree ) = cache(value).remove(expr)
299
333
def put (value : Value , expr : Tree , result : Value ): Unit = {
@@ -793,6 +827,7 @@ object Semantic {
793
827
794
828
if res.errors.nonEmpty || ! cache.changed then
795
829
pendingTasks = rest
830
+ cache.commit()
796
831
else
797
832
// discard heap changes and copy cache.out to cache.in
798
833
cache.update()
@@ -808,7 +843,7 @@ object Semantic {
808
843
*
809
844
* This method should only be called from the work list scheduler.
810
845
*/
811
- private def doTask (task : Task )(using State , Context ): Result = {
846
+ private def doTask (task : Task )(using State , Context ): Result = log( " checking " + task) {
812
847
val thisRef = task
813
848
val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
814
849
@@ -870,17 +905,16 @@ object Semantic {
870
905
* This method only handles cache logic and delegates the work to `cases`.
871
906
*/
872
907
def eval (expr : Tree , thisV : Ref , klass : ClassSymbol , cacheResult : Boolean = false ): Contextual [Result ] = log(" evaluating " + expr.show + " , this = " + thisV.show, printer, res => res.asInstanceOf [Result ].show) {
873
- if (cache.out. contains(thisV, expr)) Result (cache.out.get (thisV, expr), Errors .empty)
908
+ if (cache.contains(thisV, expr)) Result (cache(thisV, expr), Errors .empty)
874
909
else {
875
- val assumeValue = if (cache.in.contains(thisV, expr)) cache.in.get(thisV, expr) else Hot
876
- cache.out.put(thisV, expr, assumeValue)
910
+ val assumeValue = cache.assume(thisV, expr)
877
911
val res = cases(expr, thisV, klass)
878
912
if res.value != assumeValue then
879
913
// println("changed: old = " + assumeValue + ", res = " + res.value)
880
914
cache.changed = true
881
- cache.out.put (thisV, expr, res.value) // must put in cache for termination
915
+ cache.update (thisV, expr, res.value) // must put in cache for termination
882
916
else
883
- if ! cacheResult then cache.out. remove(thisV, expr)
917
+ if ! cacheResult then cache.remove(thisV, expr)
884
918
res
885
919
}
886
920
}
0 commit comments