@@ -69,7 +69,7 @@ object Contexts {
69
69
70
70
/** Execute `op` at given phase */
71
71
inline def atPhase [T ](phase : Phase )(inline op : Context ?=> T )(using Context ): T =
72
- atPhase(phase.id)(op )
72
+ op( using ctx.withPhase(phase) )
73
73
74
74
inline def atNextPhase [T ](inline op : Context ?=> T )(using Context ): T =
75
75
atPhase(ctx.phase.next)(op)
@@ -262,7 +262,7 @@ object Contexts {
262
262
263
263
/** Sourcefile corresponding to given abstract file, memoized */
264
264
def getSource (file : AbstractFile , codec : => Codec = Codec (settings.encoding.value)) = {
265
- util.Stats .record(" getSource" )
265
+ util.Stats .record(" Context. getSource" )
266
266
base.sources.getOrElseUpdate(file, new SourceFile (file, codec))
267
267
}
268
268
@@ -285,33 +285,49 @@ object Contexts {
285
285
/** Sourcefile with given path, memoized */
286
286
def getSource (path : String ): SourceFile = getSource(path.toTermName)
287
287
288
- /** Those fields are used to cache phases created in withPhase.
289
- * phasedCtx is first phase with altered phase ever requested.
290
- * phasedCtxs is array that uses phaseId's as indexes,
291
- * contexts are created only on request and cached in this array
292
- */
293
- private var phasedCtx : Context = this
294
- private var phasedCtxs : Array [Context ] = null
288
+ private var related : SimpleIdentityMap [Phase | SourceFile , Context ] = SimpleIdentityMap .Empty
295
289
296
- /** This context at given phase.
297
- * This method will always return a phase period equal to phaseId, thus will never return a fused phase
298
- */
299
- final def withPhase (phaseId : PhaseId ): Context =
300
- if (this .period.phaseId == phaseId) this
301
- else if (phasedCtx.period.phaseId == phaseId) phasedCtx
302
- else if (phasedCtxs != null && phasedCtxs(phaseId) != null ) phasedCtxs(phaseId)
303
- else {
304
- val ctx1 = fresh.setPhase(phaseId)
305
- if (phasedCtx eq this ) phasedCtx = ctx1
306
- else {
307
- if (phasedCtxs == null ) phasedCtxs = new Array [Context ](base.phases.length)
308
- phasedCtxs(phaseId) = ctx1
309
- }
290
+ private def lookup (key : Phase | SourceFile ): Context =
291
+ util.Stats .record(" Context.related.lookup" )
292
+ if related == null then
293
+ related = SimpleIdentityMap .Empty
294
+ null
295
+ else
296
+ related(key)
297
+
298
+ private def withPhase (phase : Phase , pid : PhaseId ): Context =
299
+ util.Stats .record(" Context.withPhase" )
300
+ val curId = phaseId
301
+ if curId == pid then
302
+ this
303
+ else
304
+ var ctx1 = lookup(phase)
305
+ if ctx1 == null then
306
+ util.Stats .record(" Context.withPhase.new" )
307
+ ctx1 = fresh.setPhase(pid)
308
+ related = related.updated(phase, ctx1)
309
+ ctx1
310
+
311
+ final def withPhase (phase : Phase ): Context = withPhase(phase, phase.id)
312
+ final def withPhase (pid : PhaseId ): Context = withPhase(base.phases(pid), pid)
313
+
314
+ final def withSource (source : SourceFile ): Context =
315
+ util.Stats .record(" Context.withSource" )
316
+ if this .source eq source then
317
+ this
318
+ else
319
+ var ctx1 = lookup(source)
320
+ if ctx1 == null then
321
+ util.Stats .record(" Context.withSource.new" )
322
+ ctx1 = fresh.setSource(source)
323
+ related = related.updated(source, ctx1)
310
324
ctx1
311
- }
312
325
313
- final def withPhase (phase : Phase ): Context =
314
- withPhase(phase.id)
326
+ inline def evalAt [T ](phase : Phase )(inline op : Context ?=> T ): T =
327
+ val saved = period
328
+ this .asInstanceOf [FreshContext ].period = Period (runId, phase.id)
329
+ try op(using this )
330
+ finally period = saved
315
331
316
332
// `creationTrace`-related code. To enable, uncomment the code below and the
317
333
// call to `setCreationTrace()` in this file.
@@ -476,8 +492,7 @@ object Contexts {
476
492
477
493
def reuseIn (outer : Context ): this .type =
478
494
implicitsCache = null
479
- phasedCtxs = null
480
- sourceCtx = null
495
+ related = null
481
496
init(outer, outer)
482
497
483
498
/** A fresh clone of this context embedded in this context. */
@@ -491,29 +506,6 @@ object Contexts {
491
506
final def withOwner (owner : Symbol ): Context =
492
507
if (owner ne this .owner) fresh.setOwner(owner) else this
493
508
494
- private var sourceCtx : SimpleIdentityMap [SourceFile , Context ] = null
495
-
496
- final def withSource (source : SourceFile ): Context =
497
- if (source `eq` this .source) this
498
- else if ((source `eq` outer.source) &&
499
- outer.sourceCtx != null &&
500
- (outer.sourceCtx(this .source) `eq` this )) outer
501
- else {
502
- if (sourceCtx == null ) sourceCtx = SimpleIdentityMap .Empty
503
- val prev = sourceCtx(source)
504
- if (prev != null ) prev
505
- else {
506
- val newCtx = fresh.setSource(source)
507
- if (newCtx.compilationUnit == null )
508
- // `source` might correspond to a file not necessarily
509
- // in the current project (e.g. when inlining library code),
510
- // so set `mustExist` to false.
511
- newCtx.setCompilationUnit(CompilationUnit (source, mustExist = false ))
512
- sourceCtx = sourceCtx.updated(source, newCtx)
513
- newCtx
514
- }
515
- }
516
-
517
509
final def withProperty [T ](key : Key [T ], value : Option [T ]): Context =
518
510
if (property(key) == value) this
519
511
else value match {
@@ -732,6 +724,7 @@ object Contexts {
732
724
result
733
725
734
726
inline def comparing [T ](inline op : TypeComparer => T )(using Context ): T =
727
+ util.Stats .record(" comparing" )
735
728
val saved = ctx.base.comparersInUse
736
729
try op(comparer)
737
730
finally ctx.base.comparersInUse = saved
0 commit comments