@@ -59,6 +59,7 @@ object Semantic {
59
59
def isHot = this == Hot
60
60
def isCold = this == Cold
61
61
def isWarm = this .isInstanceOf [Warm ]
62
+ def isThisRef = this .isInstanceOf [ThisRef ]
62
63
}
63
64
64
65
/** A transitively initialized object */
@@ -104,9 +105,6 @@ object Semantic {
104
105
def ensureObjectExistsAndPopulated (): Contextual [this .type ] =
105
106
if cache.containsObject(this ) then this
106
107
else this .ensureFresh().populateParams()
107
-
108
- def ensureObjectFreshAndPopulated (): Contextual [this .type ] =
109
- this .ensureFresh().populateParams()
110
108
}
111
109
112
110
/** A function value */
@@ -328,25 +326,37 @@ object Semantic {
328
326
329
327
/** Prepare cache for the next iteration
330
328
*
331
- * 1. Reset changed flag
329
+ * 1. Reset changed flag.
332
330
*
333
- * 2. Reset current cache (last cache already synced in `assume`)
331
+ * 2. Reset current cache (last cache already synced in `assume`).
334
332
*
335
333
* 3. Revert heap if instable.
336
334
*
337
335
*/
338
- def prepareForNextIteration (isStable : Boolean )(using State , Context ) =
339
- if isStable then
340
- this .commitToStableCache()
341
- this .heapStable = this .heap
342
- // If the current iteration is not stable, we need to use `last` for the next iteration,
343
- // which already contains the updated value from the current iteration.
344
- this .last = mutable.Map .empty
345
-
336
+ def prepareForNextIteration ()(using Context ) =
346
337
this .changed = false
347
338
this .current = mutable.Map .empty
348
339
this .heap = this .heapStable
349
340
341
+ /** Prepare for checking next class
342
+ *
343
+ * 1. Reset changed flag.
344
+ *
345
+ * 2. Commit current cache to stable cache if not changed.
346
+ *
347
+ * 3. Update stable heap if not changed.
348
+ *
349
+ * 4. Reset last cache.
350
+ */
351
+ def prepareForNextClass ()(using Context ) =
352
+ if this .changed then
353
+ this .changed = false
354
+ else
355
+ this .commitToStableCache()
356
+ this .heapStable = this .heap
357
+
358
+ this .last = mutable.Map .empty
359
+
350
360
def updateObject (ref : Ref , obj : Objekt ) =
351
361
assert(! this .heapStable.contains(ref))
352
362
this .heap = this .heap.updated(ref, obj)
@@ -395,17 +405,10 @@ object Semantic {
395
405
value.instantiate(klass, ctor, args, source) ++ errors
396
406
}
397
407
398
- // ----- State --------------------------------------------
399
- /** Global state of the checker */
400
- class State (val cache : Cache , val workList : WorkList )
401
-
402
- given (using s : State ): Cache = s.cache
403
- given (using s : State ): WorkList = s.workList
404
-
405
- inline def state (using s : State ) = s
408
+ // ----- Checker State -----------------------------------
406
409
407
410
/** The state that threads through the interpreter */
408
- type Contextual [T ] = (Env , Context , Trace , Promoted , State ) ?=> T
411
+ type Contextual [T ] = (Env , Context , Trace , Promoted , Cache ) ?=> T
409
412
410
413
// ----- Error Handling -----------------------------------
411
414
@@ -917,64 +920,62 @@ object Semantic {
917
920
cls == defn.ObjectClass
918
921
919
922
// ----- Work list ---------------------------------------------------
920
- case class Task (value : ThisRef )( val trace : Trace )
923
+ case class Task (value : ThisRef )
921
924
922
925
class WorkList private [Semantic ]() {
923
926
private var pendingTasks : List [Task ] = Nil
924
- private var checkedTasks : Set [Task ] = Set .empty
925
927
926
928
def addTask (task : Task ): Unit =
927
- if ! checkedTasks .contains(task) then pendingTasks = task :: pendingTasks
929
+ if ! pendingTasks .contains(task) then pendingTasks = task :: pendingTasks
928
930
929
931
/** Process the worklist until done */
930
- @ tailrec
931
- final def work ()(using State , Context ): Unit =
932
- pendingTasks match
933
- case task :: rest =>
934
- checkedTasks = checkedTasks + task
935
-
936
- task.value.ensureFresh()
937
- val res = doTask(task)
938
- res.errors.foreach(_.issue)
939
-
940
- if cache.hasChanged && res.errors.isEmpty then
941
- cache.prepareForNextIteration(isStable = false )
942
- else
943
- cache.prepareForNextIteration(isStable = true )
944
- pendingTasks = rest
945
-
946
- work()
947
- case _ =>
932
+ final def work ()(using Cache , Context ): Unit =
933
+ for task <- pendingTasks
934
+ do doTask(task)
948
935
949
936
/** Check an individual class
950
937
*
951
938
* This method should only be called from the work list scheduler.
952
939
*/
953
- private def doTask (task : Task )(using State , Context ): Result = log(" checking " + task) {
940
+ private def doTask (task : Task )(using Cache , Context ): Unit = log(" checking " + task) {
954
941
val thisRef = task.value
955
942
val tpl = thisRef.klass.defTree.asInstanceOf [TypeDef ].rhs.asInstanceOf [Template ]
956
943
957
944
val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot ).toMap
958
945
959
946
given Promoted = Promoted .empty
960
- given Trace = task.trace
947
+ given Trace = Trace .empty
961
948
given Env = Env (paramValues)
962
949
963
- eval(tpl, thisRef, thisRef.klass)
950
+ @ tailrec
951
+ def iterate (): Unit = {
952
+ thisRef.ensureFresh()
953
+ val res = eval(tpl, thisRef, thisRef.klass)
954
+ res.errors.foreach(_.issue)
955
+
956
+ if cache.hasChanged && res.errors.isEmpty then
957
+ // code to prepare cache and heap for next iteration
958
+ cache.prepareForNextIteration()
959
+ iterate()
960
+ else
961
+ cache.prepareForNextClass()
962
+ }
963
+
964
+ iterate()
964
965
}
965
966
}
966
967
inline def workList (using wl : WorkList ): WorkList = wl
967
968
968
969
// ----- API --------------------------------
969
970
970
971
/** Add a checking task to the work list */
971
- def addTask (thisRef : ThisRef )(using WorkList , Trace ) = workList.addTask(Task (thisRef)(trace ))
972
+ def addTask (thisRef : ThisRef )(using WorkList ) = workList.addTask(Task (thisRef))
972
973
973
974
/** Perform check on the work list until it becomes empty
974
975
*
975
976
* Should only be called once from the checker.
976
977
*/
977
- def check ()(using State , Context ) = workList.work()
978
+ def check ()(using Cache , WorkList , Context ) = workList.work()
978
979
979
980
/** Perform actions with initial checking state.
980
981
*
@@ -984,9 +985,8 @@ object Semantic {
984
985
* Semantic.check()
985
986
* }
986
987
*/
987
- def withInitialState [T ](work : State ?=> T ): T = {
988
- val initialState = State (new Cache , new WorkList )
989
- work(using initialState)
988
+ def withInitialState [T ](work : (Cache , WorkList ) ?=> T ): T = {
989
+ work(using new Cache , new WorkList )
990
990
}
991
991
992
992
// ----- Semantic definition --------------------------------
@@ -1412,7 +1412,7 @@ object Semantic {
1412
1412
var fieldsChanged = true
1413
1413
1414
1414
// class body
1415
- if ! thisV.isWarm || ! thisV.asInstanceOf [Warm ].isPopulatingParams then tpl.body.foreach {
1415
+ if thisV.isThisRef || ! thisV.asInstanceOf [Warm ].isPopulatingParams then tpl.body.foreach {
1416
1416
case vdef : ValDef if ! vdef.symbol.is(Flags .Lazy ) && ! vdef.rhs.isEmpty =>
1417
1417
given Env = Env .empty
1418
1418
val res = eval(vdef.rhs, thisV, klass)
@@ -1423,7 +1423,7 @@ object Semantic {
1423
1423
case _ : MemberDef =>
1424
1424
1425
1425
case tree =>
1426
- if fieldsChanged && ! thisV.isWarm then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
1426
+ if fieldsChanged && thisV.isThisRef then thisV.asInstanceOf [ThisRef ].tryPromoteCurrentObject
1427
1427
fieldsChanged = false
1428
1428
1429
1429
given Env = Env .empty
0 commit comments