@@ -500,7 +500,9 @@ object Contexts {
500
500
implicitsCache = null
501
501
related = null
502
502
503
- /** Reuse this context as a fresh context nested inside `outer` */
503
+ /** Reuse this context as a fresh context nested inside `outer`
504
+ * But keep the typerstate, this one has to be set explicitly if needed.
505
+ */
504
506
def reuseIn (outer : Context ): this .type
505
507
}
506
508
@@ -752,56 +754,40 @@ object Contexts {
752
754
final def retractMode (mode : Mode ): c.type = c.setMode(c.mode &~ mode)
753
755
}
754
756
755
- private def exploreCtx (using Context ): FreshContext =
756
- util.Stats .record(" explore" )
757
- val base = ctx.base
758
- import base ._
759
- val nestedCtx =
760
- if exploresInUse < exploreContexts.size then
761
- exploreContexts(exploresInUse).reuseIn(ctx)
762
- else
763
- val ts = TyperState ()
764
- .setReporter(ExploringReporter ())
765
- .setCommittable(false )
766
- val c = FreshContext (ctx.base).init(ctx, ctx).setTyperState(ts)
767
- exploreContexts += c
768
- c
769
- exploresInUse += 1
770
- val nestedTS = nestedCtx.typerState
771
- nestedTS.init(ctx.typerState, ctx.typerState.constraint)
772
- nestedCtx
773
-
774
- private def wrapUpExplore (ectx : Context ) =
775
- ectx.reporter.asInstanceOf [ExploringReporter ].reset()
776
- ectx.base.exploresInUse -= 1
777
-
757
+ /** Run `op` with a pool-allocated context that has an ExporeTyperState. */
778
758
inline def explore [T ](inline op : Context ?=> T )(using Context ): T =
779
- val ectx = exploreCtx
780
- try op(using ectx) finally wrapUpExplore(ectx)
759
+ exploreInFreshCtx(op)
781
760
761
+ /** Run `op` with a pool-allocated FreshContext that has an ExporeTyperState. */
782
762
inline def exploreInFreshCtx [T ](inline op : FreshContext ?=> T )(using Context ): T =
783
- val ectx = exploreCtx
784
- try op(using ectx) finally wrapUpExplore(ectx)
785
-
786
- private def changeOwnerCtx (owner : Symbol )(using Context ): Context =
787
- val base = ctx.base
788
- import base ._
789
- val nestedCtx =
790
- if changeOwnersInUse < changeOwnerContexts.size then
791
- changeOwnerContexts(changeOwnersInUse).reuseIn(ctx)
792
- else
793
- val c = FreshContext (ctx.base).init(ctx, ctx)
794
- changeOwnerContexts += c
795
- c
796
- changeOwnersInUse += 1
797
- nestedCtx.setOwner(owner).setTyperState(ctx.typerState)
798
-
799
- /** Run `op` in current context, in a reusable context that has the specified owner.
763
+ val pool = ctx.base.exploreContextPool
764
+ val nestedCtx = pool.next()
765
+ try op(using nestedCtx)
766
+ finally
767
+ nestedCtx.typerState.reporter.asInstanceOf [ExploringReporter ].reset()
768
+ pool.free()
769
+
770
+ /** Run `op` with a pool-allocated context that has a fresh typer state.
771
+ * Commit the typer state if `commit` applied to `op`'s result returns true.
800
772
*/
773
+ inline def withFreshTyperState [T ](inline op : Context ?=> T , inline commit : T => Context ?=> Boolean )(using Context ): T =
774
+ val pool = ctx.base.freshTSContextPool
775
+ val nestedCtx = pool.next()
776
+ try
777
+ val result = op(using nestedCtx)
778
+ if commit(result)(using nestedCtx) then
779
+ nestedCtx.typerState.commit()
780
+ nestedCtx.typerState.setCommittable(true )
781
+ result
782
+ finally
783
+ pool.free()
784
+
785
+ /** Run `op` with a pool-allocated context that has the given `owner`. */
801
786
inline def runWithOwner [T ](owner : Symbol )(inline op : Context ?=> T )(using Context ): T =
802
787
if Config .reuseOwnerContexts then
803
- try op(using changeOwnerCtx(owner))
804
- finally ctx.base.changeOwnersInUse -= 1
788
+ val pool = ctx.base.generalContextPool
789
+ try op(using pool.next().setOwner(owner).setTyperState(ctx.typerState))
790
+ finally pool.free()
805
791
else
806
792
op(using ctx.fresh.setOwner(owner))
807
793
@@ -893,6 +879,47 @@ object Contexts {
893
879
allPhases.find(_.period.containsPhaseId(p.id)).getOrElse(NoPhase )
894
880
}
895
881
882
+ class ContextPool :
883
+ protected def fresh ()(using Context ): FreshContext =
884
+ FreshContext (ctx.base).init(ctx, ctx)
885
+
886
+ private var inUse : Int = 0
887
+ private var pool = new mutable.ArrayBuffer [FreshContext ]
888
+
889
+ def next ()(using Context ): FreshContext =
890
+ val base = ctx.base
891
+ import base ._
892
+ val nestedCtx =
893
+ if inUse < pool.size then
894
+ pool(inUse).reuseIn(ctx)
895
+ else
896
+ val c = fresh()
897
+ pool += c
898
+ c
899
+ inUse += 1
900
+ nestedCtx
901
+
902
+ final def free (): Unit =
903
+ inUse -= 1
904
+ end ContextPool
905
+
906
+ class TSContextPool extends ContextPool :
907
+ override def next ()(using Context ) =
908
+ val nextCtx = super .next()
909
+ nextCtx.typerState.init(ctx.typerState, ctx.typerState.constraint)
910
+ nextCtx
911
+
912
+ class FreshTSContextPool extends TSContextPool :
913
+ override protected def fresh ()(using Context ) =
914
+ super .fresh().setTyperState(ctx.typerState.fresh(committable = true ))
915
+
916
+ class ExploreContextPool extends TSContextPool :
917
+ override protected def fresh ()(using Context ) =
918
+ val ts = TyperState ()
919
+ .setReporter(ExploringReporter ())
920
+ .setCommittable(false )
921
+ super .fresh().setTyperState(ts)
922
+
896
923
/** The essential mutable state of a context base, collected into a common class */
897
924
class ContextState {
898
925
// Symbols state
@@ -975,11 +1002,9 @@ object Contexts {
975
1002
976
1003
protected [dotc] val indentTab : String = " "
977
1004
978
- private [Contexts ] val exploreContexts = new mutable.ArrayBuffer [FreshContext ]
979
- private [Contexts ] var exploresInUse : Int = 0
980
-
981
- private [Contexts ] val changeOwnerContexts = new mutable.ArrayBuffer [FreshContext ]
982
- private [Contexts ] var changeOwnersInUse : Int = 0
1005
+ val exploreContextPool = ExploreContextPool ()
1006
+ val freshTSContextPool = FreshTSContextPool ()
1007
+ val generalContextPool = ContextPool ()
983
1008
984
1009
private [Contexts ] val comparers = new mutable.ArrayBuffer [TypeComparer ]
985
1010
private [Contexts ] var comparersInUse : Int = 0
0 commit comments