Skip to content

Commit 20dc62d

Browse files
author
Aleksander Boruch-Gruszecki
committed
Add caching to SmartGADTMap
1 parent b455dad commit 20dc62d

File tree

1 file changed

+55
-18
lines changed

1 file changed

+55
-18
lines changed

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

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -717,13 +717,23 @@ object Contexts {
717717
def derived: GADTMap
718718
}
719719

720-
final class SmartGADTMap(
721-
private[this] var myConstraint: Constraint = new OrderingConstraint(SimpleIdentityMap.Empty, SimpleIdentityMap.Empty, SimpleIdentityMap.Empty),
722-
private[this] var mapping: SimpleIdentityMap[Symbol, TypeVar] = SimpleIdentityMap.Empty,
723-
private[this] var reverseMapping: SimpleIdentityMap[TypeParamRef, Symbol] = SimpleIdentityMap.Empty
720+
final class SmartGADTMap private (
721+
private[this] var myConstraint: Constraint,
722+
private[this] var mapping: SimpleIdentityMap[Symbol, TypeVar],
723+
private[this] var reverseMapping: SimpleIdentityMap[TypeParamRef, Symbol],
724+
private[this] var boundCache: SimpleIdentityMap[Symbol, TypeBounds],
725+
private[this] var dirtyFlag: Boolean
724726
) extends GADTMap with ConstraintHandling {
725727
import dotty.tools.dotc.config.Printers.gadts
726728

729+
def this() = this(
730+
myConstraint = new OrderingConstraint(SimpleIdentityMap.Empty, SimpleIdentityMap.Empty, SimpleIdentityMap.Empty),
731+
mapping = SimpleIdentityMap.Empty,
732+
reverseMapping = SimpleIdentityMap.Empty,
733+
boundCache = SimpleIdentityMap.Empty,
734+
dirtyFlag = false
735+
)
736+
727737
override def debugBoundsDescription(implicit ctx: Context): String = {
728738
val sb = new mutable.StringBuilder
729739
sb ++= constraint.show
@@ -734,6 +744,8 @@ object Contexts {
734744
sb.result
735745
}
736746

747+
private[this] var checkInProgress = false
748+
737749
// TODO: dirty kludge - should this class be an inner class of TyperState instead?
738750
private[this] var myCtx: Context = null
739751
implicit override def ctx = myCtx
@@ -749,9 +761,10 @@ object Contexts {
749761
override def isSubType(tp1: Type, tp2: Type): Boolean = ctx.typeComparer.isSubType(tp1, tp2)
750762
override def isSameType(tp1: Type, tp2: Type): Boolean = ctx.typeComparer.isSameType(tp1, tp2)
751763

752-
private[this] def tvar(sym: Symbol)(implicit ctx: Context): TypeVar = inCtx(ctx) {
753-
val res = mapping(sym) match {
754-
case tv: TypeVar => tv
764+
private[this] def tvar(sym: Symbol)(implicit ctx: Context): TypeVar = {
765+
mapping(sym) match {
766+
case tv: TypeVar =>
767+
tv
755768
case null =>
756769
val res = {
757770
import NameKinds.DepParamName
@@ -769,12 +782,13 @@ object Contexts {
769782
reverseMapping = reverseMapping.updated(res.origin, sym)
770783
res
771784
}
772-
res
773785
}
774786

775787
override def addEmptyBounds(sym: Symbol)(implicit ctx: Context): Unit = tvar(sym)
776788

777-
override def addBound(sym: Symbol, bound: Type, isUpper: Boolean)(implicit ctx: Context): Boolean = inCtx(ctx) {
789+
override def addBound(sym: Symbol, bound: Type, isUpper: Boolean)(implicit ctx: Context): Boolean = try inCtx(ctx) {
790+
dirtyFlag = true
791+
checkInProgress = true
778792
@annotation.tailrec def stripInst(tp: Type): Type = tp match {
779793
case tv: TypeVar =>
780794
val inst = instType(tv)
@@ -795,8 +809,8 @@ object Contexts {
795809

796810
val outerCtx = ctx
797811
val res = {
798-
implicit val ctx : Context =
799-
if (allowNarrowing) outerCtx else outerCtx.fresh.retractMode(Mode.GADTflexible)
812+
// implicit val ctx : Context =
813+
// if (allowNarrowing) outerCtx else outerCtx.fresh.retractMode(Mode.GADTflexible)
800814

801815
// TypeComparer.explain[Boolean](gadts.println) { implicit ctx =>
802816
if (isSubtype) externalizedTp1 frozen_<:< externalizedTp2
@@ -811,6 +825,7 @@ object Contexts {
811825
case tv: TypeVar => tv
812826
case inst =>
813827
gadts.println(i"instantiated: $sym -> $inst")
828+
// return true
814829
return cautiousSubtype(inst, bound, isSubtype = isUpper, allowNarrowing = true)
815830
}
816831

@@ -847,25 +862,47 @@ object Contexts {
847862
i"adding $descr bound $sym $op $bound = $res\t( $symTvar $op $tvarBound )"
848863
}
849864
res
850-
}
865+
} finally checkInProgress = false
851866

852867
override def bounds(sym: Symbol)(implicit ctx: Context): TypeBounds = inCtx(ctx) {
853868
mapping(sym) match {
854869
case null => null
855870
case tv =>
856-
val tb = constraint.fullBounds(tv.origin)
857-
val res = (new TypeVarRemovingMap)(tb).asInstanceOf[TypeBounds]
858-
// gadts.println(i"gadt bounds $sym: $res\t( $tv: $tb )")
871+
def retrieveBounds: TypeBounds = {
872+
val tb = constraint.fullBounds(tv.origin)
873+
(new TypeVarRemovingMap)(tb).asInstanceOf[TypeBounds]
874+
}
875+
val res =
876+
// retrieveBounds
877+
if (checkInProgress || ctx.mode.is(Mode.GADTflexible)) retrieveBounds
878+
else {
879+
if (dirtyFlag) {
880+
dirtyFlag = false
881+
val bounds = retrieveBounds
882+
boundCache = SimpleIdentityMap.Empty.updated(sym, bounds)
883+
bounds
884+
} else boundCache(sym) match {
885+
case tb: TypeBounds =>
886+
tb
887+
case null =>
888+
val bounds = retrieveBounds
889+
boundCache = boundCache.updated(sym, bounds)
890+
bounds
891+
}
892+
}
893+
// gadts.println(i"gadt bounds $sym: $res")
859894
res
860895
}
861896
}
862897

863898
override def contains(sym: Symbol)(implicit ctx: Context): Boolean = mapping(sym) ne null
864899

865900
override def derived: GADTMap = new SmartGADTMap(
866-
this.myConstraint,
867-
this.mapping,
868-
this.reverseMapping
901+
myConstraint,
902+
mapping,
903+
reverseMapping,
904+
boundCache,
905+
dirtyFlag
869906
)
870907

871908
private final class TypeVarInsertingMap extends TypeMap {

0 commit comments

Comments
 (0)