Skip to content

Commit 6571053

Browse files
authored
Merge pull request #6029 from dotty-staging/try-optimize-ctx
Avoid Context#clone
2 parents 33deb72 + 02ff67a commit 6571053

File tree

4 files changed

+68
-49
lines changed

4 files changed

+68
-49
lines changed

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

Lines changed: 57 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,20 @@ object Contexts {
6868
* of all class fields of type context; allow them only in whitelisted
6969
* classes (which should be short-lived).
7070
*/
71-
abstract class Context extends Periods
72-
with Substituters
73-
with TypeOps
74-
with Phases
75-
with Printers
76-
with Symbols
77-
with SymDenotations
78-
with Reporting
79-
with NamerContextOps
80-
with Plugins
81-
with Cloneable { thiscontext =>
82-
implicit def ctx: Context = this
71+
abstract class Context(val base: ContextBase)
72+
extends Periods
73+
with Substituters
74+
with TypeOps
75+
with Phases
76+
with Printers
77+
with Symbols
78+
with SymDenotations
79+
with Reporting
80+
with NamerContextOps
81+
with Plugins
82+
with Cloneable { thiscontext =>
8383

84-
/** The context base at the root */
85-
val base: ContextBase
84+
implicit def ctx: Context = this
8685

8786
/** All outer contexts, ending in `base.initialCtx` and then `NoContext` */
8887
def outersIterator: Iterator[Context] = new Iterator[Context] {
@@ -94,83 +93,85 @@ object Contexts {
9493
/** The outer context */
9594
private[this] var _outer: Context = _
9695
protected def outer_=(outer: Context): Unit = _outer = outer
97-
def outer: Context = _outer
96+
final def outer: Context = _outer
9897

9998
/** The current context */
10099
private[this] var _period: Period = _
101100
protected def period_=(period: Period): Unit = {
102101
assert(period.firstPhaseId == period.lastPhaseId, period)
103102
_period = period
104103
}
105-
def period: Period = _period
104+
final def period: Period = _period
106105

107106
/** The scope nesting level */
108107
private[this] var _mode: Mode = _
109108
protected def mode_=(mode: Mode): Unit = _mode = mode
110-
def mode: Mode = _mode
109+
final def mode: Mode = _mode
111110

112111
/** The current owner symbol */
113112
private[this] var _owner: Symbol = _
114113
protected def owner_=(owner: Symbol): Unit = _owner = owner
115-
def owner: Symbol = _owner
114+
final def owner: Symbol = _owner
116115

117116
/** The current tree */
118117
private[this] var _tree: Tree[_ >: Untyped]= _
119118
protected def tree_=(tree: Tree[_ >: Untyped]): Unit = _tree = tree
120-
def tree: Tree[_ >: Untyped] = _tree
119+
final def tree: Tree[_ >: Untyped] = _tree
121120

122121
/** The current scope */
123122
private[this] var _scope: Scope = _
124123
protected def scope_=(scope: Scope): Unit = _scope = scope
125-
def scope: Scope = _scope
124+
final def scope: Scope = _scope
126125

127126
/** The current type comparer */
128127
private[this] var _typerState: TyperState = _
129128
protected def typerState_=(typerState: TyperState): Unit = _typerState = typerState
130-
def typerState: TyperState = _typerState
129+
final def typerState: TyperState = _typerState
131130

132131
/** The current type assigner or typer */
133132
private[this] var _typeAssigner: TypeAssigner = _
134133
protected def typeAssigner_=(typeAssigner: TypeAssigner): Unit = _typeAssigner = typeAssigner
135-
def typeAssigner: TypeAssigner = _typeAssigner
134+
final def typeAssigner: TypeAssigner = _typeAssigner
136135

137136
/** The currently active import info */
138137
private[this] var _importInfo: ImportInfo = _
139138
protected def importInfo_=(importInfo: ImportInfo): Unit = _importInfo = importInfo
140-
def importInfo: ImportInfo = _importInfo
139+
final def importInfo: ImportInfo = _importInfo
141140

142141
/** The current bounds in force for type parameters appearing in a GADT */
143142
private[this] var _gadt: GADTMap = _
144143
protected def gadt_=(gadt: GADTMap): Unit = _gadt = gadt
145-
def gadt: GADTMap = _gadt
144+
final def gadt: GADTMap = _gadt
146145

147146
/** The history of implicit searches that are currently active */
148147
private[this] var _searchHistory: SearchHistory = null
149148
protected def searchHistory_= (searchHistory: SearchHistory): Unit = _searchHistory = searchHistory
150-
def searchHistory: SearchHistory = _searchHistory
149+
final def searchHistory: SearchHistory = _searchHistory
151150

152151
/** The current type comparer. This ones updates itself automatically for
153152
* each new context.
154153
*/
155-
private[this] var _typeComparer: TypeComparer = _
156-
protected def typeComparer_=(typeComparer: TypeComparer): Unit = _typeComparer = typeComparer
157-
def typeComparer: TypeComparer = {
158-
if (_typeComparer.ctx ne this)
159-
_typeComparer = _typeComparer.copyIn(this)
154+
private[this] var _typeComparer: TypeComparer = null
155+
protected def typeComparer_=(typeComparer: TypeComparer): Unit = {
156+
assert(typeComparer.ctx eq this)
157+
_typeComparer = typeComparer
158+
}
159+
final def typeComparer: TypeComparer = {
160+
if (_typeComparer == null) _typeComparer = outer.typeComparer.copyIn(this)
160161
_typeComparer
161162
}
162163

163164
/** The current source file */
164165
private[this] var _source: SourceFile = _
165166
protected def source_=(source: SourceFile): Unit = _source = source
166-
def source: SourceFile = _source
167+
final def source: SourceFile = _source
167168

168169
/** A map in which more contextual properties can be stored
169170
* Typically used for attributes that are read and written only in special situations.
170171
*/
171172
private[this] var _moreProperties: Map[Key[Any], Any] = _
172173
protected def moreProperties_=(moreProperties: Map[Key[Any], Any]): Unit = _moreProperties = moreProperties
173-
def moreProperties: Map[Key[Any], Any] = _moreProperties
174+
final def moreProperties: Map[Key[Any], Any] = _moreProperties
174175

175176
def property[T](key: Key[T]): Option[T] =
176177
moreProperties.get(key).asInstanceOf[Option[T]]
@@ -182,7 +183,7 @@ object Contexts {
182183
*/
183184
private var _store: Store = _
184185
protected def store_=(store: Store): Unit = _store = store
185-
def store: Store = _store
186+
final def store: Store = _store
186187

187188
/** The compiler callback implementation, or null if no callback will be called. */
188189
def compilerCallback: CompilerCallback = store(compilerCallbackLoc)
@@ -258,7 +259,7 @@ object Contexts {
258259
* phasedCtxs is array that uses phaseId's as indexes,
259260
* contexts are created only on request and cached in this array
260261
*/
261-
private[this] var phasedCtx: Context = _
262+
private[this] var phasedCtx: Context = this
262263
private[this] var phasedCtxs: Array[Context] = _
263264

264265
/** This context at given phase.
@@ -422,18 +423,28 @@ object Contexts {
422423
base.settings.color.value == "always"
423424

424425
protected def init(outer: Context): this.type = {
425-
this.outer = outer
426-
this.implicitsCache = null
427-
this.phasedCtx = this
428-
this.phasedCtxs = null
429-
this.sourceCtx = null
430-
// See comment related to `creationTrace` in this file
431-
// setCreationTrace()
426+
_outer = outer
427+
_period = outer.period
428+
_mode = outer.mode
429+
_owner = outer.owner
430+
_tree = outer.tree
431+
_scope = outer.scope
432+
_typerState = outer.typerState
433+
_typeAssigner = outer.typeAssigner
434+
_importInfo = outer.importInfo
435+
_gadt = outer.gadt
436+
_searchHistory = outer.searchHistory
437+
_source = outer.source
438+
_moreProperties = outer.moreProperties
439+
_store = outer.store
432440
this
433441
}
434442

435443
/** A fresh clone of this context. */
436-
def fresh: FreshContext = clone.asInstanceOf[FreshContext].init(this)
444+
def fresh: FreshContext = {
445+
util.Stats.record("Context.fresh")
446+
new FreshContext(base).init(this)
447+
}
437448

438449
final def withOwner(owner: Symbol): Context =
439450
if (owner ne this.owner) fresh.setOwner(owner) else this
@@ -508,7 +519,7 @@ object Contexts {
508519
/** A fresh context allows selective modification
509520
* of its attributes using the with... methods.
510521
*/
511-
abstract class FreshContext extends Context {
522+
class FreshContext(base: ContextBase) extends Context(base) {
512523
def setPeriod(period: Period): this.type = { this.period = period; this }
513524
def setMode(mode: Mode): this.type = { this.mode = mode; this }
514525
def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this }
@@ -592,7 +603,7 @@ object Contexts {
592603
/** A class defining the initial context with given context base
593604
* and set of possible settings.
594605
*/
595-
private class InitialContext(val base: ContextBase, settingsGroup: SettingGroup) extends FreshContext {
606+
private class InitialContext(base: ContextBase, settingsGroup: SettingGroup) extends FreshContext(base) {
596607
outer = NoContext
597608
period = InitialPeriod
598609
mode = Mode.None
@@ -608,9 +619,8 @@ object Contexts {
608619
gadt = EmptyGADTMap
609620
}
610621

611-
@sharable object NoContext extends Context {
612-
override def source = NoSource
613-
val base: ContextBase = null
622+
@sharable object NoContext extends Context(null) {
623+
source = NoSource
614624
override val implicits: ContextualImplicits = new ContextualImplicits(Nil, null)(this)
615625
}
616626

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import reporting._
99
import config.Config
1010
import collection.mutable
1111
import java.lang.ref.WeakReference
12+
import util.Stats
1213

1314
import scala.annotation.internal.sharable
1415

@@ -18,6 +19,8 @@ object TyperState {
1819

1920
class TyperState(previous: TyperState /* | Null */) {
2021

22+
Stats.record("typerState")
23+
2124
val id: Int = TyperState.nextId
2225
TyperState.nextId += 1
2326

@@ -138,6 +141,7 @@ class TyperState(previous: TyperState /* | Null */) {
138141
* many parts of dotty itself.
139142
*/
140143
def commit()(implicit ctx: Context): Unit = {
144+
Stats.record("typerState.commit")
141145
val targetState = ctx.typerState
142146
assert(isCommittable)
143147
targetState.constraint =

compiler/src/dotty/tools/dotc/typer/Applications.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ package typer
55
import core._
66
import ast.{Trees, tpd, untpd}
77
import util.Spans._
8-
import util.Stats.track
8+
import util.Stats.{track, record}
99
import util.{SourcePosition, NoSourcePosition, SourceFile}
1010
import Trees.Untyped
1111
import Contexts._
@@ -782,6 +782,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
782782

783783
def realApply(implicit ctx: Context): Tree = track("realApply") {
784784
val originalProto = new FunProto(tree.args, IgnoredProto(pt))(this, tree.isContextual)(argCtx(tree))
785+
record("typedApply")
785786
val fun1 = typedExpr(tree.fun, originalProto)
786787

787788
// Warning: The following lines are dirty and fragile. We record that auto-tupling was demanded as
@@ -916,6 +917,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
916917
def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = track("typedTypeApply") {
917918
val isNamed = hasNamedArg(tree.args)
918919
val typedArgs = if (isNamed) typedNamedArgs(tree.args) else tree.args.mapconserve(typedType(_))
920+
record("typedTypeApply")
919921
handleMeta(typedExpr(tree.fun, PolyProto(typedArgs, pt)) match {
920922
case ExtMethodApply(app) =>
921923
app

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2190,9 +2190,12 @@ class Typer extends Namer
21902190
def tryEither[T](op: Context => T)(fallBack: (T, TyperState) => T)(implicit ctx: Context): T = {
21912191
val nestedCtx = ctx.fresh.setNewTyperState()
21922192
val result = op(nestedCtx)
2193-
if (nestedCtx.reporter.hasErrors)
2193+
if (nestedCtx.reporter.hasErrors) {
2194+
record("tryEither.fallBack")
21942195
fallBack(result, nestedCtx.typerState)
2196+
}
21952197
else {
2198+
record("tryEither.commit")
21962199
nestedCtx.typerState.commit()
21972200
result
21982201
}

0 commit comments

Comments
 (0)