@@ -90,7 +90,7 @@ object Semantic {
9090 *
9191 * Fields in class body are not initialized.
9292 */
93- def populateParams (): Contextual [this .type ] = log(" populating parameters" , printer, (_ : Warm ).objekt.toString) {
93+ private def populateParams (): Contextual [this .type ] = log(" populating parameters" , printer, (_ : Warm ).objekt.toString) {
9494 assert(! populatingParams, " the object is already populating parameters" )
9595 populatingParams = true
9696 val tpl = klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
@@ -244,7 +244,7 @@ object Semantic {
244244 private type Heap = Map [Ref , Objekt ]
245245
246246 class Cache {
247- private val last : CacheStore = mutable.Map .empty
247+ private var last : CacheStore = mutable.Map .empty
248248 private var current : CacheStore = mutable.Map .empty
249249 private val stable : CacheStore = mutable.Map .empty
250250 private var changed : Boolean = false
@@ -258,8 +258,8 @@ object Semantic {
258258 */
259259 private var heap : Heap = Map .empty
260260
261- /** Used to easily revert heap changes . */
262- private var heapBefore : Heap = Map .empty
261+ /** Used to revert heap to last stable heap . */
262+ private var heapStable : Heap = Map .empty
263263
264264 def hasChanged = changed
265265
@@ -305,7 +305,6 @@ object Semantic {
305305 stable.put(v, e, res)
306306 }
307307 }
308- current = mutable.Map .empty
309308
310309 /** Prepare cache for the next iteration
311310 *
@@ -323,34 +322,16 @@ object Semantic {
323322 *
324323 */
325324 def prepareForNextIteration (isStable : Boolean )(using State , Context ) =
326- if isStable then this .commitToStableCache()
325+ if isStable then
326+ this .commitToStableCache()
327+ this .heapStable = this .heap
328+ // If the current iteration is not stable, we need to use `last` for the next iteration,
329+ // which already contains the updated value from the current iteration.
330+ this .last = mutable.Map .empty
327331
328- changed = false
329- current = mutable.Map .empty
330-
331- if ! isStable then revertHeapChanges()
332- heapBefore = this .heap
333-
334- def revertHeapChanges ()(using State , Context ) =
335- printer.println(" reverting heap changes" )
336- this .heap.keys.foreach {
337- case warm : Warm =>
338- if heapBefore.contains(warm) then
339- this .heap = heap.updated(warm, heapBefore(warm))
340- else
341- // We cannot simply remove the object, as the values in the
342- // updated cache may refer to the warm object.
343- given Env = Env .empty
344- given Trace = Trace .empty
345- given Promoted = Promoted .empty
346- printer.println(" resetting " + warm)
347- warm.ensureObjectFreshAndPopulated()
348- case _ =>
349- }
350-
351- // ThisRef objects are not reachable, thus it's fine to leave them in
352- // the heap
353- end revertHeapChanges
332+ this .changed = false
333+ this .current = mutable.Map .empty
334+ this .heap = this .heapStable
354335
355336 def updateObject (ref : Ref , obj : Objekt ) =
356337 this .heap = this .heap.updated(ref, obj)
@@ -463,11 +444,19 @@ object Semantic {
463444
464445
465446 extension (ref : Ref )
466- def objekt (using Cache ): Objekt = cache.getObject(ref)
447+ def objekt : Contextual [Objekt ] =
448+ // TODO: improve performance
449+ ref match
450+ case warm : Warm => warm.ensureObjectExistsAndPopulated()
451+ case _ =>
452+ cache.getObject(ref)
467453
468454 def ensureObjectExists ()(using Cache ): ref.type =
469- if cache.containsObject(ref) then ref
470- else ensureFresh()
455+ if cache.containsObject(ref) then
456+ printer.println(" object " + ref + " already exists" )
457+ ref
458+ else
459+ ensureFresh()
471460
472461 def ensureFresh ()(using Cache ): ref.type =
473462 val obj = Objekt (ref.klass, fields = Map .empty, outers = Map (ref.klass -> ref.outer))
@@ -479,9 +468,9 @@ object Semantic {
479468 *
480469 * Invariant: fields are immutable and only set once
481470 */
482- def updateField (field : Symbol , value : Value )( using Cache , Context ) : Unit = log(" set field " + field + " of " + ref + " to " + value) {
471+ def updateField (field : Symbol , value : Value ): Contextual [ Unit ] = log(" set field " + field + " of " + ref + " to " + value) {
483472 val obj = objekt
484- assert(! obj.hasField(field), field.show + " already init, new = " + value + " , old = " + obj.field(field) + " , ref = " + ref)
473+ assert(! obj.hasField(field) || field.is( Flags . ParamAccessor ) && obj.field(field) == value , field.show + " already init, new = " + value + " , old = " + obj.field(field) + " , ref = " + ref)
485474 val obj2 = obj.copy(fields = obj.fields.updated(field, value))
486475 cache.updateObject(ref, obj2)
487476 }
@@ -490,9 +479,9 @@ object Semantic {
490479 *
491480 * Invariant: outers are immutable and only set once
492481 */
493- def updateOuter (klass : ClassSymbol , value : Value )( using Cache , Context ) : Unit = log(" set outer " + klass + " of " + ref + " to " + value) {
482+ def updateOuter (klass : ClassSymbol , value : Value ): Contextual [ Unit ] = log(" set outer " + klass + " of " + ref + " to " + value) {
494483 val obj = objekt
495- assert(! obj.hasOuter(klass), klass.show + " already has outer, new = " + value + " , old = " + obj.outer(klass) + " , ref = " + ref)
484+ assert(! obj.hasOuter(klass) || obj.outer(klass) == value , klass.show + " already has outer, new = " + value + " , old = " + obj.outer(klass) + " , ref = " + ref)
496485 val obj2 = obj.copy(outers = obj.outers.updated(klass, value))
497486 cache.updateObject(ref, obj2)
498487 }
@@ -679,7 +668,7 @@ object Semantic {
679668 Result (Hot , Errors .empty)
680669 else
681670 val outer = Hot
682- val warm = Warm (klass, outer, ctor, args2).ensureFresh ()
671+ val warm = Warm (klass, outer, ctor, args2).ensureObjectExists ()
683672 val argInfos2 = args.zip(args2).map { (argInfo, v) => argInfo.copy(value = v) }
684673 val res = warm.callConstructor(ctor, argInfos2, source)
685674 Result (warm, res.errors)
@@ -699,7 +688,7 @@ object Semantic {
699688
700689 val argsWidened = args.map(_.value).widenArgs
701690 val argInfos2 = args.zip(argsWidened).map { (argInfo, v) => argInfo.copy(value = v) }
702- val warm = Warm (klass, outer, ctor, argsWidened).ensureFresh ()
691+ val warm = Warm (klass, outer, ctor, argsWidened).ensureObjectExists ()
703692 val res = warm.callConstructor(ctor, argInfos2, source)
704693 Result (warm, res.errors)
705694
0 commit comments