Skip to content

Commit 8b78497

Browse files
authored
Merge pull request #3375 from dotty-staging/change-context
Make rarely updated context fields elements of the store
2 parents 03d660a + 9542f66 commit 8b78497

File tree

7 files changed

+101
-126
lines changed

7 files changed

+101
-126
lines changed

compiler/src/dotty/tools/dotc/config/Config.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ object Config {
170170
* dotty itself only causes small pending names lists to be generated (we measured
171171
* at max 6 elements) and these lists are never searched with contains.
172172
*/
173-
final val LogPendingFindMemberThreshold = 10
173+
final val LogPendingFindMemberThreshold = 9
174174

175175
/** Maximal number of outstanding recursive calls to findMember before backing out
176176
* when findMemberLimit is set.

compiler/src/dotty/tools/dotc/config/PathResolver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ class PathResolver(implicit ctx: Context) {
263263
val cp = AggregateClassPath(containers.toIndexedSeq)
264264

265265
if (settings.Ylogcp.value) {
266-
Console.println("Classpath built from " + settings.toConciseString(ctx.sstate))
266+
Console.println("Classpath built from " + settings.toConciseString(ctx.settingsState))
267267
Console.println("Defaults: " + PathResolver.Defaults)
268268
Console.println("Calculated: " + Calculated)
269269

compiler/src/dotty/tools/dotc/config/Settings.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,9 @@ object Settings {
180180

181181
object Setting {
182182
implicit class SettingDecorator[T](val setting: Setting[T]) extends AnyVal {
183-
def value(implicit ctx: Context): T = setting.valueIn(ctx.sstate)
184-
def update(x: T)(implicit ctx: Context): SettingsState = setting.updateIn(ctx.sstate, x)
185-
def isDefault(implicit ctx: Context): Boolean = setting.isDefaultIn(ctx.sstate)
183+
def value(implicit ctx: Context): T = setting.valueIn(ctx.settingsState)
184+
def update(x: T)(implicit ctx: Context): SettingsState = setting.updateIn(ctx.settingsState, x)
185+
def isDefault(implicit ctx: Context): Boolean = setting.isDefaultIn(ctx.settingsState)
186186
}
187187
}
188188

@@ -248,7 +248,7 @@ object Settings {
248248
}
249249

250250
def processArguments(arguments: List[String], processAll: Boolean)(implicit ctx: Context): ArgsSummary =
251-
processArguments(ArgsSummary(ctx.sstate, arguments, Nil, Nil), processAll, Nil)
251+
processArguments(ArgsSummary(ctx.settingsState, arguments, Nil, Nil), processAll, Nil)
252252

253253
def publish[T](settingf: Int => Setting[T]): Setting[T] = {
254254
val setting = settingf(_allSettings.length)

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 86 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ import xsbti.AnalysisCallback
3636

3737
object Contexts {
3838

39+
private val (compilerCallbackLoc, store1) = Store.empty.newLocation[CompilerCallback]()
40+
private val (sbtCallbackLoc, store2) = store1.newLocation[AnalysisCallback]()
41+
private val (printerFnLoc, store3) = store2.newLocation[Context => Printer](new RefinedPrinter(_))
42+
private val (settingsStateLoc, store4) = store3.newLocation[SettingsState]()
43+
private val (freshNamesLoc, store5) = store4.newLocation[FreshNameCreator](new FreshNameCreator.Default)
44+
private val (compilationUnitLoc, store6) = store5.newLocation[CompilationUnit]()
45+
private val (runInfoLoc, store7) = store6.newLocation[RunInfo]()
46+
private val initialStore = store7
47+
3948
/** A context is passed basically everywhere in dotc.
4049
* This is convenient but carries the risk of captured contexts in
4150
* objects that turn into space leaks. To combat this risk, here are some
@@ -82,18 +91,6 @@ object Contexts {
8291
protected def outer_=(outer: Context) = _outer = outer
8392
def outer: Context = _outer
8493

85-
/** The compiler callback implementation, or null if no callback will be called. */
86-
private[this] var _compilerCallback: CompilerCallback = _
87-
protected def compilerCallback_=(callback: CompilerCallback) =
88-
_compilerCallback = callback
89-
def compilerCallback: CompilerCallback = _compilerCallback
90-
91-
/** The sbt callback implementation if we are run from sbt, null otherwise */
92-
private[this] var _sbtCallback: AnalysisCallback = _
93-
protected def sbtCallback_=(callback: AnalysisCallback) =
94-
_sbtCallback = callback
95-
def sbtCallback: AnalysisCallback = _sbtCallback
96-
9794
/** The current context */
9895
private[this] var _period: Period = _
9996
protected def period_=(period: Period) = {
@@ -107,31 +104,11 @@ object Contexts {
107104
protected def mode_=(mode: Mode) = _mode = mode
108105
def mode: Mode = _mode
109106

110-
/** The current type comparer */
111-
private[this] var _typerState: TyperState = _
112-
protected def typerState_=(typerState: TyperState) = _typerState = typerState
113-
def typerState: TyperState = _typerState
114-
115-
/** The current plain printer */
116-
private[this] var _printerFn: Context => Printer = _
117-
protected def printerFn_=(printerFn: Context => Printer) = _printerFn = printerFn
118-
def printerFn: Context => Printer = _printerFn
119-
120107
/** The current owner symbol */
121108
private[this] var _owner: Symbol = _
122109
protected def owner_=(owner: Symbol) = _owner = owner
123110
def owner: Symbol = _owner
124111

125-
/** The current settings values */
126-
private[this] var _sstate: SettingsState = _
127-
protected def sstate_=(sstate: SettingsState) = _sstate = sstate
128-
def sstate: SettingsState = _sstate
129-
130-
/** The current compilation unit */
131-
private[this] var _compilationUnit: CompilationUnit = _
132-
protected def compilationUnit_=(compilationUnit: CompilationUnit) = _compilationUnit = compilationUnit
133-
def compilationUnit: CompilationUnit = _compilationUnit
134-
135112
/** The current tree */
136113
private[this] var _tree: Tree[_ >: Untyped]= _
137114
protected def tree_=(tree: Tree[_ >: Untyped]) = _tree = tree
@@ -142,6 +119,11 @@ object Contexts {
142119
protected def scope_=(scope: Scope) = _scope = scope
143120
def scope: Scope = _scope
144121

122+
/** The current type comparer */
123+
private[this] var _typerState: TyperState = _
124+
protected def typerState_=(typerState: TyperState) = _typerState = typerState
125+
def typerState: TyperState = _typerState
126+
145127
/** The current type assigner or typer */
146128
private[this] var _typeAssigner: TypeAssigner = _
147129
protected def typeAssigner_=(typeAssigner: TypeAssigner) = _typeAssigner = typeAssigner
@@ -153,34 +135,19 @@ object Contexts {
153135
protected def importInfo_=(importInfo: ImportInfo) = _importInfo = importInfo
154136
def importInfo: ImportInfo = _importInfo
155137

156-
/** The current compiler-run specific Info */
157-
private[this] var _runInfo: RunInfo = _
158-
protected def runInfo_=(runInfo: RunInfo) = _runInfo = runInfo
159-
def runInfo: RunInfo = _runInfo
160-
161138
/** The current bounds in force for type parameters appearing in a GADT */
162139
private[this] var _gadt: GADTMap = _
163140
protected def gadt_=(gadt: GADTMap) = _gadt = gadt
164141
def gadt: GADTMap = _gadt
165142

166-
/**The current fresh name creator */
167-
private[this] var _freshNames: FreshNameCreator = _
168-
protected def freshNames_=(freshNames: FreshNameCreator) = _freshNames = freshNames
169-
def freshNames: FreshNameCreator = _freshNames
170-
171-
/** A store that can be used by sub-components */
172-
private var _store: Store = _
173-
protected def store_=(store: Store) = _store = store
174-
def store: Store = _store
175-
176-
/** A map in which more contextual properties can be stored */
177-
private[this] var _moreProperties: Map[Key[Any], Any] = _
178-
protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties
179-
def moreProperties: Map[Key[Any], Any] = _moreProperties
180-
181-
def property[T](key: Key[T]): Option[T] =
182-
moreProperties.get(key).asInstanceOf[Option[T]]
143+
/** The history of implicit searches that are currently active */
144+
private[this] var _searchHistory: SearchHistory = null
145+
protected def searchHistory_= (searchHistory: SearchHistory) = _searchHistory = searchHistory
146+
def searchHistory: SearchHistory = _searchHistory
183147

148+
/** The current type comparer. This ones updates itself automatically for
149+
* each new context.
150+
*/
184151
private[this] var _typeComparer: TypeComparer = _
185152
protected def typeComparer_=(typeComparer: TypeComparer) = _typeComparer = typeComparer
186153
def typeComparer: TypeComparer = {
@@ -189,13 +156,45 @@ object Contexts {
189156
_typeComparer
190157
}
191158

192-
/** Number of findMember calls on stack */
193-
private[core] var findMemberCount: Int = 0
159+
/** A map in which more contextual properties can be stored
160+
* Typically used for attributes that are read and written only in special situations.
161+
*/
162+
private[this] var _moreProperties: Map[Key[Any], Any] = _
163+
protected def moreProperties_=(moreProperties: Map[Key[Any], Any]) = _moreProperties = moreProperties
164+
def moreProperties: Map[Key[Any], Any] = _moreProperties
194165

195-
/** List of names which have a findMemberCall on stack,
196-
* after Config.LogPendingFindMemberThreshold is reached.
166+
def property[T](key: Key[T]): Option[T] =
167+
moreProperties.get(key).asInstanceOf[Option[T]]
168+
169+
/** A store that can be used by sub-components.
170+
* Typically used for attributes that are defined only once per compilation unit.
171+
* Access to store entries is much faster than access to properties, and only
172+
* slightly slower than a normal field access would be.
197173
*/
198-
private[core] var pendingMemberSearches: List[Name] = Nil
174+
private var _store: Store = _
175+
protected def store_=(store: Store) = _store = store
176+
def store: Store = _store
177+
178+
/** The compiler callback implementation, or null if no callback will be called. */
179+
def compilerCallback: CompilerCallback = store(compilerCallbackLoc)
180+
181+
/** The sbt callback implementation if we are run from sbt, null otherwise */
182+
def sbtCallback: AnalysisCallback = store(sbtCallbackLoc)
183+
184+
/** The current plain printer */
185+
def printerFn: Context => Printer = store(printerFnLoc)
186+
187+
/** The current settings values */
188+
def settingsState: SettingsState = store(settingsStateLoc)
189+
190+
/** The current fresh name creator */
191+
def freshNames: FreshNameCreator = store(freshNamesLoc)
192+
193+
/** The current compilation unit */
194+
def compilationUnit: CompilationUnit = store(compilationUnitLoc)
195+
196+
/** The current compiler-run specific Info */
197+
def runInfo: RunInfo = store(runInfoLoc)
199198

200199
/** The new implicit references that are introduced by this scope */
201200
protected var implicitsCache: ContextualImplicits = null
@@ -222,11 +221,6 @@ object Contexts {
222221
implicitsCache
223222
}
224223

225-
/** The history of implicit searches that are currently active */
226-
private[this] var _searchHistory: SearchHistory = null
227-
protected def searchHistory_= (searchHistory: SearchHistory) = _searchHistory = searchHistory
228-
def searchHistory: SearchHistory = _searchHistory
229-
230224
/** Those fields are used to cache phases created in withPhase.
231225
* phasedCtx is first phase with altered phase ever requested.
232226
* phasedCtxs is array that uses phaseId's as indexes,
@@ -383,26 +377,6 @@ object Contexts {
383377
def useColors: Boolean =
384378
base.settings.color.value == "always"
385379

386-
/** A condensed context containing essential information of this but
387-
* no outer contexts except the initial context.
388-
private[this] var _condensed: CondensedContext = null
389-
def condensed: CondensedContext = {
390-
if (_condensed eq outer.condensed)
391-
_condensed = base.initialCtx.fresh
392-
.withPeriod(period)
393-
.withNewMode(mode)
394-
// typerState and its constraint is not preserved in condensed
395-
// reporter is always ThrowingReporter
396-
.withPrinterFn(printerFn)
397-
.withOwner(owner)
398-
.withSettings(sstate)
399-
// tree is not preserved in condensed
400-
.withRunInfo(runInfo)
401-
.withMoreProperties(moreProperties)
402-
_condensed
403-
}
404-
*/
405-
406380
protected def init(outer: Context): this.type = {
407381
this.outer = outer
408382
this.implicitsCache = null
@@ -447,31 +421,32 @@ object Contexts {
447421
abstract class FreshContext extends Context {
448422
def setPeriod(period: Period): this.type = { this.period = period; this }
449423
def setMode(mode: Mode): this.type = { this.mode = mode; this }
450-
def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
451-
def setSbtCallback(callback: AnalysisCallback): this.type = { this.sbtCallback = callback; this }
452-
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
453-
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.fresh().setReporter(reporter))
454-
def setNewTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(true))
455-
def setExploreTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(false))
456-
def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
457424
def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this }
458-
def setSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
459-
def setCompilationUnit(compilationUnit: CompilationUnit): this.type = { this.compilationUnit = compilationUnit; this }
460425
def setTree(tree: Tree[_ >: Untyped]): this.type = { this.tree = tree; this }
461426
def setScope(scope: Scope): this.type = { this.scope = scope; this }
462427
def setNewScope: this.type = { this.scope = newScope; this }
428+
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
429+
def setNewTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(true))
430+
def setExploreTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(false))
431+
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.fresh().setReporter(reporter))
463432
def setTypeAssigner(typeAssigner: TypeAssigner): this.type = { this.typeAssigner = typeAssigner; this }
464433
def setTyper(typer: Typer): this.type = { this.scope = typer.scope; setTypeAssigner(typer) }
465434
def setImportInfo(importInfo: ImportInfo): this.type = { this.importInfo = importInfo; this }
466-
def setImplicits(implicits: ContextualImplicits): this.type = { this.implicitsCache = implicits; this }
467-
def setRunInfo(runInfo: RunInfo): this.type = { this.runInfo = runInfo; this }
468435
def setGadt(gadt: GADTMap): this.type = { this.gadt = gadt; this }
469436
def setFreshGADTBounds: this.type = setGadt(new GADTMap(gadt.bounds))
470-
def setTypeComparerFn(tcfn: Context => TypeComparer): this.type = { this.typeComparer = tcfn(this); this }
471437
def setSearchHistory(searchHistory: SearchHistory): this.type = { this.searchHistory = searchHistory; this }
472-
def setFreshNames(freshNames: FreshNameCreator): this.type = { this.freshNames = freshNames; this }
473-
def setStore(store: Store): this.type = { this.store = store; this }
474-
def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = { this.moreProperties = moreProperties; this }
438+
def setTypeComparerFn(tcfn: Context => TypeComparer): this.type = { this.typeComparer = tcfn(this); this }
439+
private def setMoreProperties(moreProperties: Map[Key[Any], Any]): this.type = { this.moreProperties = moreProperties; this }
440+
private def setStore(store: Store): this.type = { this.store = store; this }
441+
def setImplicits(implicits: ContextualImplicits): this.type = { this.implicitsCache = implicits; this }
442+
443+
def setCompilerCallback(callback: CompilerCallback): this.type = updateStore(compilerCallbackLoc, callback)
444+
def setSbtCallback(callback: AnalysisCallback): this.type = updateStore(sbtCallbackLoc, callback)
445+
def setPrinterFn(printer: Context => Printer): this.type = updateStore(printerFnLoc, printer)
446+
def setSettings(settingsState: SettingsState): this.type = updateStore(settingsStateLoc, settingsState)
447+
def setCompilationUnit(compilationUnit: CompilationUnit): this.type = updateStore(compilationUnitLoc, compilationUnit)
448+
def setRunInfo(runInfo: RunInfo): this.type = updateStore(runInfoLoc, runInfo)
449+
def setFreshNames(freshNames: FreshNameCreator): this.type = updateStore(freshNamesLoc, freshNames)
475450

476451
def setProperty[T](key: Key[T], value: T): this.type =
477452
setMoreProperties(moreProperties.updated(key, value))
@@ -498,7 +473,7 @@ object Contexts {
498473
def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end))
499474

500475
def setSetting[T](setting: Setting[T], value: T): this.type =
501-
setSettings(setting.updateIn(sstate, value))
476+
setSettings(setting.updateIn(settingsState, value))
502477

503478
def setDebug = setSetting(base.settings.debug, true)
504479
}
@@ -526,15 +501,13 @@ object Contexts {
526501
period = InitialPeriod
527502
mode = Mode.None
528503
typerState = new TyperState(null)
529-
printerFn = new RefinedPrinter(_)
530504
owner = NoSymbol
531-
sstate = settings.defaultState
532505
tree = untpd.EmptyTree
533506
typeAssigner = TypeAssigner
534-
runInfo = new RunInfo(this)
535-
freshNames = new FreshNameCreator.Default
536507
moreProperties = Map.empty
537-
store = Store.empty
508+
store = initialStore
509+
.updated(settingsStateLoc, settings.defaultState)
510+
.updated(runInfoLoc, new RunInfo(this))
538511
typeComparer = new TypeComparer(this)
539512
searchHistory = new SearchHistory(0, Map())
540513
gadt = EmptyGADTMap
@@ -628,6 +601,14 @@ object Contexts {
628601
/** A map that associates label and size of all uniques sets */
629602
def uniquesSizes: Map[String, Int] = uniqueSets.mapValues(_.size)
630603

604+
/** Number of findMember calls on stack */
605+
private[core] var findMemberCount: Int = 0
606+
607+
/** List of names which have a findMemberCall on stack,
608+
* after Config.LogPendingFindMemberThreshold is reached.
609+
*/
610+
private[core] var pendingMemberSearches: List[Name] = Nil
611+
631612
/** The number of recursive invocation of underlying on a NamedType
632613
* during a controlled operation.
633614
*/

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
328328
object TypeOps {
329329
@sharable var track = false // !!!DEBUG
330330

331-
/** When a property with this key is set in a context, it limit the number
331+
/** When a property with this key is set in a context, it limits the number
332332
* of recursive member searches. If the limit is reached, findMember returns
333333
* NoDenotation.
334334
*/

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -632,16 +632,14 @@ object Types {
632632
go(l) & (go(r), pre, safeIntersection = ctx.pendingMemberSearches.contains(name))
633633
}
634634

635-
{ val recCount = ctx.findMemberCount + 1
636-
ctx.findMemberCount = recCount
637-
if (recCount >= Config.LogPendingFindMemberThreshold) {
638-
ctx.pendingMemberSearches = name :: ctx.pendingMemberSearches
639-
if (ctx.property(TypeOps.findMemberLimit).isDefined &&
640-
ctx.findMemberCount > Config.PendingFindMemberLimit)
641-
return NoDenotation
642-
}
635+
val recCount = ctx.findMemberCount
636+
if (recCount >= Config.LogPendingFindMemberThreshold) {
637+
if (ctx.property(TypeOps.findMemberLimit).isDefined &&
638+
ctx.findMemberCount > Config.PendingFindMemberLimit)
639+
return NoDenotation
640+
ctx.pendingMemberSearches = name :: ctx.pendingMemberSearches
643641
}
644-
642+
ctx.findMemberCount = recCount + 1
645643
//assert(ctx.findMemberCount < 20)
646644
try go(this)
647645
catch {
@@ -650,10 +648,9 @@ object Types {
650648
throw ex // DEBUG
651649
}
652650
finally {
653-
val recCount = ctx.findMemberCount
654651
if (recCount >= Config.LogPendingFindMemberThreshold)
655652
ctx.pendingMemberSearches = ctx.pendingMemberSearches.tail
656-
ctx.findMemberCount = recCount - 1
653+
ctx.findMemberCount = recCount
657654
}
658655
}
659656

0 commit comments

Comments
 (0)