Skip to content

Commit 15a51d7

Browse files
committed
Address review comments
1 parent 6566756 commit 15a51d7

File tree

2 files changed

+54
-55
lines changed

2 files changed

+54
-55
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Checker extends Phase {
4343
// ignore, we already called `Semantic.check()` in `runOn`
4444
}
4545

46-
class InitTreeTraverser(using State) extends TreeTraverser {
46+
class InitTreeTraverser(using WorkList) extends TreeTraverser {
4747
override def traverse(tree: Tree)(using Context): Unit =
4848
traverseChildren(tree)
4949
tree match {
@@ -56,7 +56,6 @@ class Checker extends Phase {
5656
case tdef: TypeDef if tdef.isClassDef =>
5757
val cls = tdef.symbol.asClass
5858
val thisRef = ThisRef(cls)
59-
given Trace = Trace.empty
6059
if shouldCheckClass(cls) then Semantic.addTask(thisRef)
6160
case _ =>
6261

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

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ object Semantic {
5959
def isHot = this == Hot
6060
def isCold = this == Cold
6161
def isWarm = this.isInstanceOf[Warm]
62+
def isThisRef = this.isInstanceOf[ThisRef]
6263
}
6364

6465
/** A transitively initialized object */
@@ -104,9 +105,6 @@ object Semantic {
104105
def ensureObjectExistsAndPopulated(): Contextual[this.type] =
105106
if cache.containsObject(this) then this
106107
else this.ensureFresh().populateParams()
107-
108-
def ensureObjectFreshAndPopulated(): Contextual[this.type] =
109-
this.ensureFresh().populateParams()
110108
}
111109

112110
/** A function value */
@@ -328,25 +326,37 @@ object Semantic {
328326

329327
/** Prepare cache for the next iteration
330328
*
331-
* 1. Reset changed flag
329+
* 1. Reset changed flag.
332330
*
333-
* 2. Reset current cache (last cache already synced in `assume`)
331+
* 2. Reset current cache (last cache already synced in `assume`).
334332
*
335333
* 3. Revert heap if instable.
336334
*
337335
*/
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) =
346337
this.changed = false
347338
this.current = mutable.Map.empty
348339
this.heap = this.heapStable
349340

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+
350360
def updateObject(ref: Ref, obj: Objekt) =
351361
assert(!this.heapStable.contains(ref))
352362
this.heap = this.heap.updated(ref, obj)
@@ -395,17 +405,10 @@ object Semantic {
395405
value.instantiate(klass, ctor, args, source) ++ errors
396406
}
397407

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 -----------------------------------
406409

407410
/** 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
409412

410413
// ----- Error Handling -----------------------------------
411414

@@ -917,64 +920,62 @@ object Semantic {
917920
cls == defn.ObjectClass
918921

919922
// ----- Work list ---------------------------------------------------
920-
case class Task(value: ThisRef)(val trace: Trace)
923+
case class Task(value: ThisRef)
921924

922925
class WorkList private[Semantic]() {
923926
private var pendingTasks: List[Task] = Nil
924-
private var checkedTasks: Set[Task] = Set.empty
925927

926928
def addTask(task: Task): Unit =
927-
if !checkedTasks.contains(task) then pendingTasks = task :: pendingTasks
929+
if !pendingTasks.contains(task) then pendingTasks = task :: pendingTasks
928930

929931
/** 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)
948935

949936
/** Check an individual class
950937
*
951938
* This method should only be called from the work list scheduler.
952939
*/
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) {
954941
val thisRef = task.value
955942
val tpl = thisRef.klass.defTree.asInstanceOf[TypeDef].rhs.asInstanceOf[Template]
956943

957944
val paramValues = tpl.constr.termParamss.flatten.map(param => param.symbol -> Hot).toMap
958945

959946
given Promoted = Promoted.empty
960-
given Trace = task.trace
947+
given Trace = Trace.empty
961948
given Env = Env(paramValues)
962949

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()
964965
}
965966
}
966967
inline def workList(using wl: WorkList): WorkList = wl
967968

968969
// ----- API --------------------------------
969970

970971
/** 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))
972973

973974
/** Perform check on the work list until it becomes empty
974975
*
975976
* Should only be called once from the checker.
976977
*/
977-
def check()(using State, Context) = workList.work()
978+
def check()(using Cache, WorkList, Context) = workList.work()
978979

979980
/** Perform actions with initial checking state.
980981
*
@@ -984,9 +985,8 @@ object Semantic {
984985
* Semantic.check()
985986
* }
986987
*/
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)
990990
}
991991

992992
// ----- Semantic definition --------------------------------
@@ -1412,7 +1412,7 @@ object Semantic {
14121412
var fieldsChanged = true
14131413

14141414
// 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 {
14161416
case vdef : ValDef if !vdef.symbol.is(Flags.Lazy) && !vdef.rhs.isEmpty =>
14171417
given Env = Env.empty
14181418
val res = eval(vdef.rhs, thisV, klass)
@@ -1423,7 +1423,7 @@ object Semantic {
14231423
case _: MemberDef =>
14241424

14251425
case tree =>
1426-
if fieldsChanged && !thisV.isWarm then thisV.asInstanceOf[ThisRef].tryPromoteCurrentObject
1426+
if fieldsChanged && thisV.isThisRef then thisV.asInstanceOf[ThisRef].tryPromoteCurrentObject
14271427
fieldsChanged = false
14281428

14291429
given Env = Env.empty

0 commit comments

Comments
 (0)