From 230a5ff5b12e14426f0897310c4373a4f81b33f5 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 19 Nov 2022 19:00:39 +0100 Subject: [PATCH 1/4] Refactor context - Handle all context state (except caches) in FreshContext. - Drop unsused operations - Make NoContext a simple val instead of an object --- .../src/dotty/tools/dotc/core/Contexts.scala | 185 ++++++++++-------- 1 file changed, 98 insertions(+), 87 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index a6c1a24ebf96..523604661052 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -123,7 +123,9 @@ object Contexts { */ abstract class Context(val base: ContextBase) { thiscontext => - given Context = this + protected given Context = this + + def outer: Context /** All outer contexts, ending in `base.initialCtx` and then `NoContext` */ def outersIterator: Iterator[Context] = new Iterator[Context] { @@ -132,65 +134,20 @@ object Contexts { def next = { val c = current; current = current.outer; c } } - /** The outer context */ - private var _outer: Context = _ - protected def outer_=(outer: Context): Unit = _outer = outer - final def outer: Context = _outer - - /** The current context */ - private var _period: Period = _ - protected def period_=(period: Period): Unit = { - assert(period.firstPhaseId == period.lastPhaseId, period) - _period = period - } - final def period: Period = _period - - /** The scope nesting level */ - private var _mode: Mode = _ - protected def mode_=(mode: Mode): Unit = _mode = mode - final def mode: Mode = _mode - - /** The current owner symbol */ - private var _owner: Symbol = _ - protected def owner_=(owner: Symbol): Unit = _owner = owner - final def owner: Symbol = _owner - - /** The current tree */ - private var _tree: Tree[?]= _ - protected def tree_=(tree: Tree[?]): Unit = _tree = tree - final def tree: Tree[?] = _tree - - /** The current scope */ - private var _scope: Scope = _ - protected def scope_=(scope: Scope): Unit = _scope = scope - final def scope: Scope = _scope - - /** The current typerstate */ - private var _typerState: TyperState = _ - protected def typerState_=(typerState: TyperState): Unit = _typerState = typerState - final def typerState: TyperState = _typerState - - /** The current bounds in force for type parameters appearing in a GADT */ - private var _gadt: GadtConstraint = _ - protected def gadt_=(gadt: GadtConstraint): Unit = _gadt = gadt - final def gadt: GadtConstraint = _gadt - - /** The history of implicit searches that are currently active */ - private var _searchHistory: SearchHistory = _ - protected def searchHistory_= (searchHistory: SearchHistory): Unit = _searchHistory = searchHistory - final def searchHistory: SearchHistory = _searchHistory - - /** The current source file */ - private var _source: SourceFile = _ - protected def source_=(source: SourceFile): Unit = _source = source - final def source: SourceFile = _source + def period: Period + def mode: Mode + def owner: Symbol + def tree: Tree[?] + def scope: Scope + def typerState: TyperState + def gadt: GadtConstraint + def searchHistory: SearchHistory + def source: SourceFile /** A map in which more contextual properties can be stored * Typically used for attributes that are read and written only in special situations. */ - private var _moreProperties: Map[Key[Any], Any] = _ - protected def moreProperties_=(moreProperties: Map[Key[Any], Any]): Unit = _moreProperties = moreProperties - final def moreProperties: Map[Key[Any], Any] = _moreProperties + def moreProperties: Map[Key[Any], Any] def property[T](key: Key[T]): Option[T] = moreProperties.get(key).asInstanceOf[Option[T]] @@ -200,9 +157,7 @@ object Contexts { * Access to store entries is much faster than access to properties, and only * slightly slower than a normal field access would be. */ - private var _store: Store = _ - protected def store_=(store: Store): Unit = _store = store - final def store: Store = _store + def store: Store /** The compiler callback implementation, or null if no callback will be called. */ def compilerCallback: CompilerCallback = store(compilerCallbackLoc) @@ -240,7 +195,7 @@ object Contexts { def typeAssigner: TypeAssigner = store(typeAssignerLoc) /** The new implicit references that are introduced by this scope */ - protected var implicitsCache: ContextualImplicits | Null = null + private var implicitsCache: ContextualImplicits | Null = null def implicits: ContextualImplicits = { if (implicitsCache == null) implicitsCache = { @@ -305,7 +260,6 @@ object Contexts { /** AbstractFile with given path, memoized */ def getFile(name: String): AbstractFile = getFile(name.toTermName) - private var related: SimpleIdentityMap[Phase | SourceFile, Context] | Null = null private def lookup(key: Phase | SourceFile): Context | Null = @@ -491,30 +445,6 @@ object Contexts { /** Is the explicit nulls option set? */ def explicitNulls: Boolean = base.settings.YexplicitNulls.value - /** Initialize all context fields, except typerState, which has to be set separately - * @param outer The outer context - * @param origin The context from which fields are copied - */ - private[Contexts] def init(outer: Context, origin: Context): this.type = { - _outer = outer - _period = origin.period - _mode = origin.mode - _owner = origin.owner - _tree = origin.tree - _scope = origin.scope - _gadt = origin.gadt - _searchHistory = origin.searchHistory - _source = origin.source - _moreProperties = origin.moreProperties - _store = origin.store - this - } - - def reuseIn(outer: Context): this.type = - implicitsCache = null - related = null - init(outer, outer) - /** A fresh clone of this context embedded in this context. */ def fresh: FreshContext = freshOver(this) @@ -565,6 +495,13 @@ object Contexts { def uniques: util.WeakHashSet[Type] = base.uniques def initialize()(using Context): Unit = base.initialize() + + protected def resetCaches(): Unit = + implicitsCache = null + related = null + + /** Reuse this context as a fresh context nested inside `outer` */ + def reuseIn(outer: Context): this.type } /** A condensed context provides only a small memory footprint over @@ -579,6 +516,81 @@ object Contexts { * of its attributes using the with... methods. */ class FreshContext(base: ContextBase) extends Context(base) { + + private var _outer: Context = _ + protected def outer_=(outer: Context): Unit = _outer = outer + def outer: Context = _outer + + private var _period: Period = _ + protected def period_=(period: Period): Unit = + assert(period.firstPhaseId == period.lastPhaseId, period) + _period = period + final def period: Period = _period + + private var _mode: Mode = _ + protected def mode_=(mode: Mode): Unit = _mode = mode + final def mode: Mode = _mode + + private var _owner: Symbol = _ + protected def owner_=(owner: Symbol): Unit = _owner = owner + final def owner: Symbol = _owner + + /** The current tree */ + private var _tree: Tree[?]= _ + protected def tree_=(tree: Tree[?]): Unit = _tree = tree + final def tree: Tree[?] = _tree + + private var _scope: Scope = _ + protected def scope_=(scope: Scope): Unit = _scope = scope + final def scope: Scope = _scope + + private var _typerState: TyperState = _ + protected def typerState_=(typerState: TyperState): Unit = _typerState = typerState + final def typerState: TyperState = _typerState + + private var _gadt: GadtConstraint = _ + protected def gadt_=(gadt: GadtConstraint): Unit = _gadt = gadt + final def gadt: GadtConstraint = _gadt + + private var _searchHistory: SearchHistory = _ + protected def searchHistory_= (searchHistory: SearchHistory): Unit = _searchHistory = searchHistory + final def searchHistory: SearchHistory = _searchHistory + + private var _source: SourceFile = _ + protected def source_=(source: SourceFile): Unit = _source = source + final def source: SourceFile = _source + + private var _moreProperties: Map[Key[Any], Any] = _ + protected def moreProperties_=(moreProperties: Map[Key[Any], Any]): Unit = _moreProperties = moreProperties + final def moreProperties: Map[Key[Any], Any] = _moreProperties + + private var _store: Store = _ + protected def store_=(store: Store): Unit = _store = store + final def store: Store = _store + + /** Initialize all context fields, except typerState, which has to be set separately + * @param outer The outer context + * @param origin The context from which fields are copied + */ + private[Contexts] def init(outer: Context, origin: Context): this.type = { + _outer = outer + _period = origin.period + _mode = origin.mode + _owner = origin.owner + _tree = origin.tree + _scope = origin.scope + _gadt = origin.gadt + _searchHistory = origin.searchHistory + _source = origin.source + _moreProperties = origin.moreProperties + _store = origin.store + this + } + + def reuseIn(outer: Context): this.type = + resetCaches() + init(outer, outer) + def setPeriod(period: Period): this.type = util.Stats.record("Context.setPeriod") this.period = period @@ -627,7 +639,6 @@ object Contexts { util.Stats.record("Context.setStore") this.store = store this - def setImplicits(implicits: ContextualImplicits): this.type = { this.implicitsCache = implicits; this } def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { setSource(compilationUnit.source) @@ -817,7 +828,7 @@ object Contexts { gadt = GadtConstraint.empty } - @sharable object NoContext extends Context((null: ContextBase | Null).uncheckedNN) { + @sharable val NoContext: Context = new FreshContext((null: ContextBase | Null).uncheckedNN) { source = NoSource override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null, false)(this: @unchecked) } From 8989957cdff4f5b83ecab7a7ac1868657c2a931e Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 19 Nov 2022 19:23:44 +0100 Subject: [PATCH 2/4] More Coontext refactorings --- .../src/dotty/tools/dotc/core/Contexts.scala | 155 ++++++++++-------- 1 file changed, 83 insertions(+), 72 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 523604661052..94c70c91b9bf 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -28,6 +28,7 @@ import printing._ import config.{JavaPlatform, SJSPlatform, Platform, ScalaSettings} import classfile.ReusableDataReader import StdNames.nme +import compiletime.uninitialized import scala.annotation.internal.sharable @@ -310,7 +311,7 @@ object Contexts { /** If -Ydebug is on, the top of the stack trace where this context * was created, otherwise `null`. */ - private var creationTrace: Array[StackTraceElement] = _ + private var creationTrace: Array[StackTraceElement] = uninitialized private def setCreationTrace() = creationTrace = (new Throwable).getStackTrace().take(20) @@ -517,55 +518,41 @@ object Contexts { */ class FreshContext(base: ContextBase) extends Context(base) { - private var _outer: Context = _ - protected def outer_=(outer: Context): Unit = _outer = outer + private var _outer: Context = uninitialized def outer: Context = _outer - private var _period: Period = _ - protected def period_=(period: Period): Unit = - assert(period.firstPhaseId == period.lastPhaseId, period) + private var _period: Period = uninitialized _period = period final def period: Period = _period - private var _mode: Mode = _ - protected def mode_=(mode: Mode): Unit = _mode = mode + private var _mode: Mode = uninitialized final def mode: Mode = _mode - private var _owner: Symbol = _ - protected def owner_=(owner: Symbol): Unit = _owner = owner + private var _owner: Symbol = uninitialized final def owner: Symbol = _owner - /** The current tree */ private var _tree: Tree[?]= _ - protected def tree_=(tree: Tree[?]): Unit = _tree = tree final def tree: Tree[?] = _tree - private var _scope: Scope = _ - protected def scope_=(scope: Scope): Unit = _scope = scope + private var _scope: Scope = uninitialized final def scope: Scope = _scope - private var _typerState: TyperState = _ - protected def typerState_=(typerState: TyperState): Unit = _typerState = typerState + private var _typerState: TyperState = uninitialized final def typerState: TyperState = _typerState - private var _gadt: GadtConstraint = _ - protected def gadt_=(gadt: GadtConstraint): Unit = _gadt = gadt + private var _gadt: GadtConstraint = uninitialized final def gadt: GadtConstraint = _gadt - private var _searchHistory: SearchHistory = _ - protected def searchHistory_= (searchHistory: SearchHistory): Unit = _searchHistory = searchHistory + private var _searchHistory: SearchHistory = uninitialized final def searchHistory: SearchHistory = _searchHistory - private var _source: SourceFile = _ - protected def source_=(source: SourceFile): Unit = _source = source + private var _source: SourceFile = uninitialized final def source: SourceFile = _source - private var _moreProperties: Map[Key[Any], Any] = _ - protected def moreProperties_=(moreProperties: Map[Key[Any], Any]): Unit = _moreProperties = moreProperties + private var _moreProperties: Map[Key[Any], Any] = uninitialized final def moreProperties: Map[Key[Any], Any] = _moreProperties - private var _store: Store = _ - protected def store_=(store: Store): Unit = _store = store + private var _store: Store = uninitialized final def store: Store = _store /** Initialize all context fields, except typerState, which has to be set separately @@ -593,51 +580,74 @@ object Contexts { def setPeriod(period: Period): this.type = util.Stats.record("Context.setPeriod") - this.period = period + assert(period.firstPhaseId == period.lastPhaseId, period) + this._period = period this + def setMode(mode: Mode): this.type = util.Stats.record("Context.setMode") - this.mode = mode + this._mode = mode this + def setOwner(owner: Symbol): this.type = util.Stats.record("Context.setOwner") assert(owner != NoSymbol) - this.owner = owner + this._owner = owner this + def setTree(tree: Tree[?]): this.type = util.Stats.record("Context.setTree") - this.tree = tree + this._tree = tree this - def setScope(scope: Scope): this.type = { this.scope = scope; this } + + def setScope(scope: Scope): this.type = + this._scope = scope + this + def setNewScope: this.type = util.Stats.record("Context.setScope") - this.scope = newScope + this._scope = newScope this - def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this } - def setNewTyperState(): this.type = setTyperState(typerState.fresh(committable = true)) - def setExploreTyperState(): this.type = setTyperState(typerState.fresh(committable = false)) - def setReporter(reporter: Reporter): this.type = setTyperState(typerState.fresh().setReporter(reporter)) - def setTyper(typer: Typer): this.type = { this.scope = typer.scope; setTypeAssigner(typer) } + + def setTyperState(typerState: TyperState): this.type = + this._typerState = typerState + this + def setNewTyperState(): this.type = + setTyperState(typerState.fresh(committable = true)) + def setExploreTyperState(): this.type = + setTyperState(typerState.fresh(committable = false)) + def setReporter(reporter: Reporter): this.type = + setTyperState(typerState.fresh().setReporter(reporter)) + + def setTyper(typer: Typer): this.type = + this._scope = typer.scope + setTypeAssigner(typer) + def setGadt(gadt: GadtConstraint): this.type = util.Stats.record("Context.setGadt") - this.gadt = gadt + this._gadt = gadt this - def setFreshGADTBounds: this.type = setGadt(gadt.fresh) + def setFreshGADTBounds: this.type = + setGadt(gadt.fresh) + def setSearchHistory(searchHistory: SearchHistory): this.type = util.Stats.record("Context.setSearchHistory") - this.searchHistory = searchHistory + this._searchHistory = searchHistory this + def setSource(source: SourceFile): this.type = util.Stats.record("Context.setSource") - this.source = source + this._source = source this + private def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = util.Stats.record("Context.setMoreProperties") - this.moreProperties = moreProperties + this._moreProperties = moreProperties this + private def setStore(store: Store): this.type = util.Stats.record("Context.setStore") - this.store = store + this._store = store this def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { @@ -692,6 +702,28 @@ object Contexts { def setDebug: this.type = setSetting(base.settings.Ydebug, true) } + object FreshContext: + /** Defines an initial context with given context base and possible settings. */ + def initial(base: ContextBase, settingsGroup: SettingGroup): Context = + val c = new FreshContext(base) + c._outer = NoContext + c._period = InitialPeriod + c._mode = Mode.None + c._typerState = TyperState.initialState() + c._owner = NoSymbol + c._tree = untpd.EmptyTree + c._moreProperties = Map(MessageLimiter -> DefaultMessageLimiter()) + c._scope = EmptyScope + c._source = NoSource + c._store = initialStore + .updated(settingsStateLoc, settingsGroup.defaultState) + .updated(notNullInfosLoc, Nil) + .updated(compilationUnitLoc, NoCompilationUnit) + c._searchHistory = new SearchRoot + c._gadt = GadtConstraint.empty + c + end FreshContext + given ops: AnyRef with extension (c: Context) def addNotNullInfo(info: NotNullInfo) = @@ -807,30 +839,9 @@ object Contexts { finally ctx.base.comparersInUse = saved end comparing - /** A class defining the initial context with given context base - * and set of possible settings. - */ - private class InitialContext(base: ContextBase, settingsGroup: SettingGroup) extends FreshContext(base) { - outer = NoContext - period = InitialPeriod - mode = Mode.None - typerState = TyperState.initialState() - owner = NoSymbol - tree = untpd.EmptyTree - moreProperties = Map(MessageLimiter -> DefaultMessageLimiter()) - scope = EmptyScope - source = NoSource - store = initialStore - .updated(settingsStateLoc, settingsGroup.defaultState) - .updated(notNullInfosLoc, Nil) - .updated(compilationUnitLoc, NoCompilationUnit) - searchHistory = new SearchRoot - gadt = GadtConstraint.empty - } - @sharable val NoContext: Context = new FreshContext((null: ContextBase | Null).uncheckedNN) { - source = NoSource override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null, false)(this: @unchecked) + setSource(NoSource) } /** A context base defines state and associated methods that exist once per @@ -844,10 +855,10 @@ object Contexts { val settings: ScalaSettings = new ScalaSettings /** The initial context */ - val initialCtx: Context = new InitialContext(this, settings) + val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) /** The platform, initialized by `initPlatform()`. */ - private var _platform: Platform | Null = _ + private var _platform: Platform | Null = uninitialized /** The platform */ def platform: Platform = { @@ -933,18 +944,18 @@ object Contexts { // Phases state - private[core] var phasesPlan: List[List[Phase]] = _ + private[core] var phasesPlan: List[List[Phase]] = uninitialized /** Phases by id */ - private[dotc] var phases: Array[Phase] = _ + private[dotc] var phases: Array[Phase] = uninitialized /** Phases with consecutive Transforms grouped into a single phase, Empty array if fusion is disabled */ private[core] var fusedPhases: Array[Phase] = Array.empty[Phase] /** Next denotation transformer id */ - private[core] var nextDenotTransformerId: Array[Int] = _ + private[core] var nextDenotTransformerId: Array[Int] = uninitialized - private[core] var denotTransformers: Array[DenotTransformer] = _ + private[core] var denotTransformers: Array[DenotTransformer] = uninitialized /** Flag to suppress inlining, set after overflow */ private[dotc] var stopInlining: Boolean = false @@ -978,7 +989,7 @@ object Contexts { private[core] val reusableDataReader = ReusableInstance(new ReusableDataReader()) - private[dotc] var wConfCache: (List[String], WConf) = _ + private[dotc] var wConfCache: (List[String], WConf) = uninitialized def sharedCharArray(len: Int): Array[Char] = while len > charArray.length do From 2c52acd156180491e70ba2da537225f61eb62e75 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 19 Nov 2022 21:07:33 +0100 Subject: [PATCH 3/4] Remove trailing code from previous version --- compiler/src/dotty/tools/dotc/core/Contexts.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index 94c70c91b9bf..f5c1235a8106 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -522,7 +522,6 @@ object Contexts { def outer: Context = _outer private var _period: Period = uninitialized - _period = period final def period: Period = _period private var _mode: Mode = uninitialized From 73ed7f2a6cdf46843b3b91755103096f050af016 Mon Sep 17 00:00:00 2001 From: odersky Date: Sat, 19 Nov 2022 21:29:31 +0100 Subject: [PATCH 4/4] Copy changes to test compiler --- .../dotc/core/Contexts.scala | 289 ++++++++++-------- 1 file changed, 155 insertions(+), 134 deletions(-) diff --git a/tests/pos-with-compiler-cc/dotc/core/Contexts.scala b/tests/pos-with-compiler-cc/dotc/core/Contexts.scala index 4f8157b5ea3c..c37711593c68 100644 --- a/tests/pos-with-compiler-cc/dotc/core/Contexts.scala +++ b/tests/pos-with-compiler-cc/dotc/core/Contexts.scala @@ -28,6 +28,7 @@ import printing._ import config.{JavaPlatform, SJSPlatform, Platform, ScalaSettings} import classfile.ReusableDataReader import StdNames.nme +import compiletime.uninitialized import scala.annotation.internal.sharable @@ -124,7 +125,9 @@ object Contexts { */ abstract class Context(val base: ContextBase) { thiscontext => - given Context = this + protected given Context = this + + def outer: Context /** All outer contexts, ending in `base.initialCtx` and then `NoContext` */ def outersIterator: Iterator[Context] = new Iterator[Context] { @@ -133,65 +136,20 @@ object Contexts { def next = { val c = current; current = current.outer; c } } - /** The outer context */ - private var _outer: Context = _ - protected def outer_=(outer: Context): Unit = _outer = outer - final def outer: Context = _outer - - /** The current context */ - private var _period: Period = _ - protected def period_=(period: Period): Unit = { - assert(period.firstPhaseId == period.lastPhaseId, period) - _period = period - } - final def period: Period = _period - - /** The scope nesting level */ - private var _mode: Mode = _ - protected def mode_=(mode: Mode): Unit = _mode = mode - final def mode: Mode = _mode - - /** The current owner symbol */ - private var _owner: Symbol = _ - protected def owner_=(owner: Symbol): Unit = _owner = owner - final def owner: Symbol = _owner - - /** The current tree */ - private var _tree: Tree[?]= _ - protected def tree_=(tree: Tree[?]): Unit = _tree = tree - final def tree: Tree[?] = _tree - - /** The current scope */ - private var _scope: Scope = _ - protected def scope_=(scope: Scope): Unit = _scope = scope - final def scope: Scope = _scope - - /** The current typerstate */ - private var _typerState: TyperState = _ - protected def typerState_=(typerState: TyperState): Unit = _typerState = typerState - final def typerState: TyperState = _typerState - - /** The current bounds in force for type parameters appearing in a GADT */ - private var _gadt: GadtConstraint = _ - protected def gadt_=(gadt: GadtConstraint): Unit = _gadt = gadt - final def gadt: GadtConstraint = _gadt - - /** The history of implicit searches that are currently active */ - private var _searchHistory: SearchHistory = _ - protected def searchHistory_= (searchHistory: SearchHistory): Unit = _searchHistory = searchHistory - final def searchHistory: SearchHistory = _searchHistory - - /** The current source file */ - private var _source: SourceFile = _ - protected def source_=(source: SourceFile): Unit = _source = source - final def source: SourceFile = _source + def period: Period + def mode: Mode + def owner: Symbol + def tree: Tree[?] + def scope: Scope + def typerState: TyperState + def gadt: GadtConstraint + def searchHistory: SearchHistory + def source: SourceFile /** A map in which more contextual properties can be stored * Typically used for attributes that are read and written only in special situations. */ - private var _moreProperties: Map[Key[Any], Any] = _ - protected def moreProperties_=(moreProperties: Map[Key[Any], Any]): Unit = _moreProperties = moreProperties - final def moreProperties: Map[Key[Any], Any] = _moreProperties + def moreProperties: Map[Key[Any], Any] def property[T](key: Key[T]): Option[T] = moreProperties.get(key).asInstanceOf[Option[T]] @@ -201,9 +159,7 @@ object Contexts { * Access to store entries is much faster than access to properties, and only * slightly slower than a normal field access would be. */ - private var _store: Store = _ - protected def store_=(store: Store): Unit = _store = store - final def store: Store = _store + def store: Store /** The compiler callback implementation, or null if no callback will be called. */ def compilerCallback: CompilerCallback = store(compilerCallbackLoc) @@ -241,7 +197,7 @@ object Contexts { def typeAssigner: TypeAssigner = store(typeAssignerLoc) /** The new implicit references that are introduced by this scope */ - protected var implicitsCache: ContextualImplicits | Null = null + private var implicitsCache: ContextualImplicits | Null = null def implicits: ContextualImplicits = { if (implicitsCache == null) implicitsCache = { @@ -306,7 +262,6 @@ object Contexts { /** AbstractFile with given path, memoized */ def getFile(name: String): AbstractFile = getFile(name.toTermName) - private var related: SimpleIdentityMap[Phase | SourceFile, Context] | Null = null private def lookup(key: Phase | SourceFile): Context | Null = @@ -357,7 +312,7 @@ object Contexts { /** If -Ydebug is on, the top of the stack trace where this context * was created, otherwise `null`. */ - private var creationTrace: Array[StackTraceElement] = _ + private var creationTrace: Array[StackTraceElement] = uninitialized private def setCreationTrace() = creationTrace = (new Throwable).getStackTrace().take(20) @@ -492,30 +447,6 @@ object Contexts { /** Is the explicit nulls option set? */ def explicitNulls: Boolean = base.settings.YexplicitNulls.value - /** Initialize all context fields, except typerState, which has to be set separately - * @param outer The outer context - * @param origin The context from which fields are copied - */ - private[Contexts] def init(outer: Context, origin: Context): this.type = { - _outer = outer - _period = origin.period - _mode = origin.mode - _owner = origin.owner - _tree = origin.tree - _scope = origin.scope - _gadt = origin.gadt - _searchHistory = origin.searchHistory - _source = origin.source - _moreProperties = origin.moreProperties - _store = origin.store - this - } - - def reuseIn(outer: Context): this.type = - implicitsCache = null - related = null - init(outer, outer) - /** A fresh clone of this context embedded in this context. */ def fresh: FreshContext = freshOver(this) @@ -566,6 +497,13 @@ object Contexts { def uniques: util.WeakHashSet[Type] = base.uniques def initialize()(using Context): Unit = base.initialize() + + protected def resetCaches(): Unit = + implicitsCache = null + related = null + + /** Reuse this context as a fresh context nested inside `outer` */ + def reuseIn(outer: Context): this.type } /** A condensed context provides only a small memory footprint over @@ -580,55 +518,137 @@ object Contexts { * of its attributes using the with... methods. */ class FreshContext(base: ContextBase) extends Context(base) { + + private var _outer: Context = uninitialized + def outer: Context = _outer + + private var _period: Period = uninitialized + final def period: Period = _period + + private var _mode: Mode = uninitialized + final def mode: Mode = _mode + + private var _owner: Symbol = uninitialized + final def owner: Symbol = _owner + + private var _tree: Tree[?]= _ + final def tree: Tree[?] = _tree + + private var _scope: Scope = uninitialized + final def scope: Scope = _scope + + private var _typerState: TyperState = uninitialized + final def typerState: TyperState = _typerState + + private var _gadt: GadtConstraint = uninitialized + final def gadt: GadtConstraint = _gadt + + private var _searchHistory: SearchHistory = uninitialized + final def searchHistory: SearchHistory = _searchHistory + + private var _source: SourceFile = uninitialized + final def source: SourceFile = _source + + private var _moreProperties: Map[Key[Any], Any] = uninitialized + final def moreProperties: Map[Key[Any], Any] = _moreProperties + + private var _store: Store = uninitialized + final def store: Store = _store + + /** Initialize all context fields, except typerState, which has to be set separately + * @param outer The outer context + * @param origin The context from which fields are copied + */ + private[Contexts] def init(outer: Context, origin: Context): this.type = { + _outer = outer + _period = origin.period + _mode = origin.mode + _owner = origin.owner + _tree = origin.tree + _scope = origin.scope + _gadt = origin.gadt + _searchHistory = origin.searchHistory + _source = origin.source + _moreProperties = origin.moreProperties + _store = origin.store + this + } + + def reuseIn(outer: Context): this.type = + resetCaches() + init(outer, outer) + def setPeriod(period: Period): this.type = util.Stats.record("Context.setPeriod") - this.period = period + assert(period.firstPhaseId == period.lastPhaseId, period) + this._period = period this + def setMode(mode: Mode): this.type = util.Stats.record("Context.setMode") - this.mode = mode + this._mode = mode this + def setOwner(owner: Symbol): this.type = util.Stats.record("Context.setOwner") assert(owner != NoSymbol) - this.owner = owner + this._owner = owner this + def setTree(tree: Tree[?]): this.type = util.Stats.record("Context.setTree") - this.tree = tree + this._tree = tree + this + + def setScope(scope: Scope): this.type = + this._scope = scope this - def setScope(scope: Scope): this.type = { this.scope = scope; this } + def setNewScope: this.type = util.Stats.record("Context.setScope") - this.scope = newScope + this._scope = newScope + this + + def setTyperState(typerState: TyperState): this.type = + this._typerState = typerState this - def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this } - def setNewTyperState(): this.type = setTyperState(typerState.fresh(committable = true)) - def setExploreTyperState(): this.type = setTyperState(typerState.fresh(committable = false)) - def setReporter(reporter: Reporter): this.type = setTyperState(typerState.fresh().setReporter(reporter)) - def setTyper(typer: Typer): this.type = { this.scope = typer.scope; setTypeAssigner(typer) } + def setNewTyperState(): this.type = + setTyperState(typerState.fresh(committable = true)) + def setExploreTyperState(): this.type = + setTyperState(typerState.fresh(committable = false)) + def setReporter(reporter: Reporter): this.type = + setTyperState(typerState.fresh().setReporter(reporter)) + + def setTyper(typer: Typer): this.type = + this._scope = typer.scope + setTypeAssigner(typer) + def setGadt(gadt: GadtConstraint): this.type = util.Stats.record("Context.setGadt") - this.gadt = gadt + this._gadt = gadt this - def setFreshGADTBounds: this.type = setGadt(gadt.fresh) + def setFreshGADTBounds: this.type = + setGadt(gadt.fresh) + def setSearchHistory(searchHistory: SearchHistory): this.type = util.Stats.record("Context.setSearchHistory") - this.searchHistory = searchHistory + this._searchHistory = searchHistory this + def setSource(source: SourceFile): this.type = util.Stats.record("Context.setSource") - this.source = source + this._source = source this + private def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = util.Stats.record("Context.setMoreProperties") - this.moreProperties = moreProperties + this._moreProperties = moreProperties this + private def setStore(store: Store): this.type = util.Stats.record("Context.setStore") - this.store = store + this._store = store this - def setImplicits(implicits: ContextualImplicits): this.type = { this.implicitsCache = implicits; this } def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { setSource(compilationUnit.source) @@ -682,6 +702,28 @@ object Contexts { def setDebug: this.type = setSetting(base.settings.Ydebug, true) } + object FreshContext: + /** Defines an initial context with given context base and possible settings. */ + def initial(base: ContextBase, settingsGroup: SettingGroup): Context = + val c = new FreshContext(base) + c._outer = NoContext + c._period = InitialPeriod + c._mode = Mode.None + c._typerState = TyperState.initialState() + c._owner = NoSymbol + c._tree = untpd.EmptyTree + c._moreProperties = Map(MessageLimiter -> DefaultMessageLimiter()) + c._scope = EmptyScope + c._source = NoSource + c._store = initialStore + .updated(settingsStateLoc, settingsGroup.defaultState) + .updated(notNullInfosLoc, Nil) + .updated(compilationUnitLoc, NoCompilationUnit) + c._searchHistory = new SearchRoot + c._gadt = GadtConstraint.empty + c + end FreshContext + given ops: AnyRef with extension (c: Context) def addNotNullInfo(info: NotNullInfo) = @@ -797,30 +839,9 @@ object Contexts { finally ctx.base.comparersInUse = saved end comparing - /** A class defining the initial context with given context base - * and set of possible settings. - */ - private class InitialContext(base: ContextBase, settingsGroup: SettingGroup) extends FreshContext(base) { - outer = NoContext - period = InitialPeriod - mode = Mode.None - typerState = TyperState.initialState() - owner = NoSymbol - tree = untpd.EmptyTree - moreProperties = Map(MessageLimiter -> DefaultMessageLimiter()) - scope = EmptyScope - source = NoSource - store = initialStore - .updated(settingsStateLoc, settingsGroup.defaultState) - .updated(notNullInfosLoc, Nil) - .updated(compilationUnitLoc, NoCompilationUnit) - searchHistory = new SearchRoot - gadt = GadtConstraint.empty - } - - @sharable object NoContext extends Context((null: ContextBase | Null).uncheckedNN) { - source = NoSource + @sharable val NoContext: Context = new FreshContext((null: ContextBase | Null).uncheckedNN) { override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null, false)(this: @unchecked) + setSource(NoSource) } /** A context base defines state and associated methods that exist once per @@ -834,10 +855,10 @@ object Contexts { val settings: ScalaSettings = new ScalaSettings /** The initial context */ - val initialCtx: Context = new InitialContext(this, settings) + val initialCtx: Context = FreshContext.initial(this: @unchecked, settings) /** The platform, initialized by `initPlatform()`. */ - private var _platform: Platform | Null = _ + private var _platform: Platform | Null = uninitialized /** The platform */ def platform: Platform = { @@ -923,18 +944,18 @@ object Contexts { // Phases state - private[core] var phasesPlan: List[List[Phase]] = _ + private[core] var phasesPlan: List[List[Phase]] = uninitialized /** Phases by id */ - private[dotc] var phases: Array[Phase] = _ + private[dotc] var phases: Array[Phase] = uninitialized /** Phases with consecutive Transforms grouped into a single phase, Empty array if fusion is disabled */ private[core] var fusedPhases: Array[Phase] = Array.empty[Phase] /** Next denotation transformer id */ - private[core] var nextDenotTransformerId: Array[Int] = _ + private[core] var nextDenotTransformerId: Array[Int] = uninitialized - private[core] var denotTransformers: Array[DenotTransformer] = _ + private[core] var denotTransformers: Array[DenotTransformer] = uninitialized /** Flag to suppress inlining, set after overflow */ private[dotc] var stopInlining: Boolean = false @@ -968,7 +989,7 @@ object Contexts { private[core] val reusableDataReader = ReusableInstance(new ReusableDataReader()) - private[dotc] var wConfCache: (List[String], WConf) = _ + private[dotc] var wConfCache: (List[String], WConf) = uninitialized def sharedCharArray(len: Int): Array[Char] = while len > charArray.length do