Skip to content

Commit b27d58b

Browse files
committed
Populate class parameters for warm objects in a heap prepare step
1 parent bc98ce8 commit b27d58b

File tree

1 file changed

+30
-9
lines changed

1 file changed

+30
-9
lines changed

compiler/src/dotty/tools/dotc/transform/init/Semantic.scala

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)