@@ -174,7 +174,28 @@ object Semantic {
174
174
map = map.updated(ref, obj)
175
175
176
176
def snapshot (): Heap = new Heap (map)
177
- def restore (h : Heap ) = this .map = h.map
177
+
178
+ /** Recompute the newly created warm objects with the updated cache.
179
+ *
180
+ * The computation only covers class parameters and outers. Class fields are ignored and
181
+ * are lazily evaluated and cached.
182
+ *
183
+ * The method must be called after the call `Cache.prepare()`.
184
+ */
185
+ def prepare (heapBefore : Heap )(using State , Context ) =
186
+ this .map.keys.foreach {
187
+ case thisRef : ThisRef =>
188
+ this .map = this .map - thisRef
189
+ case warm : Warm if ! heapBefore.contains(warm) =>
190
+ this .map = this .map - warm
191
+ given Env = Env .empty
192
+ given Trace = Trace .empty
193
+ given Promoted = Promoted .empty
194
+ warm.ensureObjectExists().ensureInit()
195
+ case _ =>
196
+ }
197
+
198
+ override def toString () = map.toString()
178
199
}
179
200
180
201
/** Note: don't use `val` to avoid incorrect sharing */
@@ -311,10 +332,9 @@ object Semantic {
311
332
def assume (value : Value , expr : Tree , cacheResult : Boolean )(fun : => Result ): Contextual [Result ] =
312
333
val assumeValue : Value =
313
334
if last.contains(value, expr) then
314
- // Due to heap reverting, the object corresponding to a reference may not exist in the heap.
335
+ // The object corresponding to ThisRef may not exist in the heap. See `Heap.prepare` .
315
336
last.get(value, expr) match
316
337
case ref : ThisRef => ref.ensureObjectExists()
317
- case ref : Warm => ref.ensureObjectExists().ensureInit()
318
338
case v => v
319
339
else
320
340
last.put(value, expr, Hot )
@@ -356,7 +376,7 @@ object Semantic {
356
376
* - Reset changed flag
357
377
* - Reset current cache (last cache already synced in `assume`)
358
378
*/
359
- def iterate () = {
379
+ def prepare () = {
360
380
changed = false
361
381
current = mutable.Map .empty
362
382
}
@@ -885,18 +905,20 @@ object Semantic {
885
905
case task :: rest =>
886
906
checkedTasks = checkedTasks + task
887
907
908
+ // must be before heap snapshot
909
+ task.value.ensureObjectExists()
888
910
val heapBefore = heap.snapshot()
889
911
val res = doTask(task)
890
912
res.errors.foreach(_.issue)
891
913
892
914
if cache.hasChanged && res.errors.isEmpty then
893
- // discard heap changes
894
- heap.restore(heapBefore)
915
+ // must call cache.prepare() first
916
+ cache.prepare()
917
+ heap.prepare(heapBefore)
895
918
else
896
919
cache.commit()
897
920
pendingTasks = rest
898
-
899
- cache.iterate()
921
+ cache.prepare()
900
922
901
923
work()
902
924
case _ =>
@@ -907,7 +929,6 @@ object Semantic {
907
929
*/
908
930
private def doTask (task : Task )(using State , Context ): Result = log(" checking " + task) {
909
931
val thisRef = task.value
910
- thisRef.ensureObjectExists()
911
932
val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
912
933
913
934
val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot ).toMap
0 commit comments