@@ -278,7 +278,9 @@ object Semantic {
278
278
private val in : CacheStore = mutable.Map .empty
279
279
private var out : CacheStore = mutable.Map .empty
280
280
private val global : CacheStore = mutable.Map .empty
281
- var changed : Boolean = false
281
+ private var changed : Boolean = false
282
+
283
+ def hasChanged = changed
282
284
283
285
def contains (value : Value , expr : Tree ) =
284
286
out.contains(value, expr) || global.contains(value, expr)
@@ -293,32 +295,31 @@ object Semantic {
293
295
assumeValue
294
296
295
297
def update (value : Value , expr : Tree , result : Value ) =
298
+ this .changed = true
299
+ in.put(value, expr, result)
296
300
out.put(value, expr, result)
297
301
298
302
def remove (value : Value , expr : Tree ) =
299
303
out.remove(value, expr)
300
304
301
- /** Commit out cache to global cache.
305
+ /** Prepare cache for the next iteration
306
+ *
307
+ * - Commit out cache to global cache if unchanged.
308
+ * - Reset changed flag
309
+ * - Reset out cache
302
310
*
303
311
* Precondition: the out cache reaches fixed point.
304
312
*/
305
- def commit () = {
306
- out.foreach { (v, m) =>
307
- m.iterator.foreach { (e, res) =>
308
- global.put(v, e, res)
313
+ def iterate () = {
314
+ if ! changed then
315
+ out.foreach { (v, m) =>
316
+ m.iterator.foreach { (e, res) =>
317
+ global.put(v, e, res)
318
+ }
309
319
}
310
- }
320
+ end if
311
321
312
- out = mutable.Map .empty
313
- }
314
-
315
- /** Copy out to in and reset out to empty */
316
- def update () = {
317
- out.foreach { (v, m) =>
318
- m.iterator.foreach { (e, res) =>
319
- in.put(v, e, res)
320
- }
321
- }
322
+ changed = false
322
323
323
324
out = mutable.Map .empty
324
325
}
@@ -825,16 +826,13 @@ object Semantic {
825
826
val res = doTask(task)
826
827
res.errors.foreach(_.issue)
827
828
828
- if res.errors.nonEmpty || ! cache.changed then
829
- pendingTasks = rest
830
- cache.commit()
831
- else
829
+ if cache.hasChanged && res.errors.isEmpty then
832
830
// discard heap changes and copy cache.out to cache.in
833
- cache.update()
834
831
heap.restore(heapBefore)
832
+ else
833
+ pendingTasks = rest
835
834
836
- // reset change
837
- cache.changed = false
835
+ cache.iterate()
838
836
839
837
work()
840
838
case _ =>
@@ -911,7 +909,6 @@ object Semantic {
911
909
val res = cases(expr, thisV, klass)
912
910
if res.value != assumeValue then
913
911
// println("changed: old = " + assumeValue + ", res = " + res.value)
914
- cache.changed = true
915
912
cache.update(thisV, expr, res.value) // must put in cache for termination
916
913
else
917
914
if ! cacheResult then cache.remove(thisV, expr)
@@ -1336,7 +1333,8 @@ object Semantic {
1336
1333
errorBuffer ++= eval(tree, thisV, klass).errors
1337
1334
}
1338
1335
1339
- Result (thisV, errorBuffer.toList)
1336
+ // The result value is ignored, use Hot to avoid futile fixed point computation
1337
+ Result (Hot , errorBuffer.toList)
1340
1338
}
1341
1339
1342
1340
/** Check that path in path-dependent types are initialized
0 commit comments