@@ -90,7 +90,7 @@ object Semantic {
90
90
*
91
91
* Fields in class body are not initialized.
92
92
*/
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) {
94
94
assert(! populatingParams, " the object is already populating parameters" )
95
95
populatingParams = true
96
96
val tpl = klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
@@ -244,7 +244,7 @@ object Semantic {
244
244
private type Heap = Map [Ref , Objekt ]
245
245
246
246
class Cache {
247
- private val last : CacheStore = mutable.Map .empty
247
+ private var last : CacheStore = mutable.Map .empty
248
248
private var current : CacheStore = mutable.Map .empty
249
249
private val stable : CacheStore = mutable.Map .empty
250
250
private var changed : Boolean = false
@@ -258,8 +258,8 @@ object Semantic {
258
258
*/
259
259
private var heap : Heap = Map .empty
260
260
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
263
263
264
264
def hasChanged = changed
265
265
@@ -305,7 +305,6 @@ object Semantic {
305
305
stable.put(v, e, res)
306
306
}
307
307
}
308
- current = mutable.Map .empty
309
308
310
309
/** Prepare cache for the next iteration
311
310
*
@@ -323,34 +322,16 @@ object Semantic {
323
322
*
324
323
*/
325
324
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
327
331
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
354
335
355
336
def updateObject (ref : Ref , obj : Objekt ) =
356
337
this .heap = this .heap.updated(ref, obj)
@@ -463,11 +444,19 @@ object Semantic {
463
444
464
445
465
446
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)
467
453
468
454
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()
471
460
472
461
def ensureFresh ()(using Cache ): ref.type =
473
462
val obj = Objekt (ref.klass, fields = Map .empty, outers = Map (ref.klass -> ref.outer))
@@ -479,9 +468,9 @@ object Semantic {
479
468
*
480
469
* Invariant: fields are immutable and only set once
481
470
*/
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) {
483
472
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)
485
474
val obj2 = obj.copy(fields = obj.fields.updated(field, value))
486
475
cache.updateObject(ref, obj2)
487
476
}
@@ -490,9 +479,9 @@ object Semantic {
490
479
*
491
480
* Invariant: outers are immutable and only set once
492
481
*/
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) {
494
483
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)
496
485
val obj2 = obj.copy(outers = obj.outers.updated(klass, value))
497
486
cache.updateObject(ref, obj2)
498
487
}
@@ -679,7 +668,7 @@ object Semantic {
679
668
Result (Hot , Errors .empty)
680
669
else
681
670
val outer = Hot
682
- val warm = Warm (klass, outer, ctor, args2).ensureFresh ()
671
+ val warm = Warm (klass, outer, ctor, args2).ensureObjectExists ()
683
672
val argInfos2 = args.zip(args2).map { (argInfo, v) => argInfo.copy(value = v) }
684
673
val res = warm.callConstructor(ctor, argInfos2, source)
685
674
Result (warm, res.errors)
@@ -699,7 +688,7 @@ object Semantic {
699
688
700
689
val argsWidened = args.map(_.value).widenArgs
701
690
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 ()
703
692
val res = warm.callConstructor(ctor, argInfos2, source)
704
693
Result (warm, res.errors)
705
694
0 commit comments