@@ -174,7 +174,28 @@ object Semantic {
174174 map = map.updated(ref, obj)
175175
176176 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()
178199 }
179200
180201 /** Note: don't use `val` to avoid incorrect sharing */
@@ -311,10 +332,9 @@ object Semantic {
311332 def assume (value : Value , expr : Tree , cacheResult : Boolean )(fun : => Result ): Contextual [Result ] =
312333 val assumeValue : Value =
313334 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` .
315336 last.get(value, expr) match
316337 case ref : ThisRef => ref.ensureObjectExists()
317- case ref : Warm => ref.ensureObjectExists().ensureInit()
318338 case v => v
319339 else
320340 last.put(value, expr, Hot )
@@ -356,7 +376,7 @@ object Semantic {
356376 * - Reset changed flag
357377 * - Reset current cache (last cache already synced in `assume`)
358378 */
359- def iterate () = {
379+ def prepare () = {
360380 changed = false
361381 current = mutable.Map .empty
362382 }
@@ -885,18 +905,20 @@ object Semantic {
885905 case task :: rest =>
886906 checkedTasks = checkedTasks + task
887907
908+ // must be before heap snapshot
909+ task.value.ensureObjectExists()
888910 val heapBefore = heap.snapshot()
889911 val res = doTask(task)
890912 res.errors.foreach(_.issue)
891913
892914 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)
895918 else
896919 cache.commit()
897920 pendingTasks = rest
898-
899- cache.iterate()
921+ cache.prepare()
900922
901923 work()
902924 case _ =>
@@ -907,7 +929,6 @@ object Semantic {
907929 */
908930 private def doTask (task : Task )(using State , Context ): Result = log(" checking " + task) {
909931 val thisRef = task.value
910- thisRef.ensureObjectExists()
911932 val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
912933
913934 val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot ).toMap
0 commit comments