@@ -1238,8 +1238,10 @@ object SymDenotations {
12381238 private [this ] var myMemberCache : LRUCache [Name , PreDenotation ] = null
12391239 private [this ] var myMemberCachePeriod : Period = Nowhere
12401240
1241- private [this ] var baseTypeRefCache : java.util.HashMap [CachedType , Type ] = null
1242- private [this ] var baseTypeRefValid : RunId = NoRunId
1241+ /** A cache from types T to baseTypeRef(T, C) */
1242+ type BaseTypeRefMap = java.util.HashMap [CachedType , Type ]
1243+ private [this ] var myBaseTypeRefCache : BaseTypeRefMap = null
1244+ private [this ] var myBaseTypeRefCachePeriod : Period = Nowhere
12431245
12441246 private var baseDataCache : BaseData = BaseData .None
12451247 private var memberNamesCache : MemberNames = MemberNames .None
@@ -1252,6 +1254,16 @@ object SymDenotations {
12521254 myMemberCache
12531255 }
12541256
1257+ private def baseTypeRefCache (implicit ctx : Context ): BaseTypeRefMap = {
1258+ if (myBaseTypeRefCachePeriod != ctx.period &&
1259+ (myBaseTypeRefCachePeriod.runId != ctx.runId ||
1260+ ctx.phases(myBaseTypeRefCachePeriod.phaseId).parentsGroup != ctx.phase.parentsGroup)) {
1261+ myBaseTypeRefCache = new BaseTypeRefMap
1262+ myBaseTypeRefCachePeriod = ctx.period
1263+ }
1264+ myBaseTypeRefCache
1265+ }
1266+
12551267 private def invalidateBaseDataCache () = {
12561268 baseDataCache.invalidate()
12571269 baseDataCache = BaseData .None
@@ -1262,14 +1274,19 @@ object SymDenotations {
12621274 memberNamesCache = MemberNames .None
12631275 }
12641276
1265- def invalidateBaseTypeRefCache () =
1266- baseTypeRefCache = new java.util.HashMap [CachedType , Type ]
1277+ def invalidateBaseTypeRefCache () = {
1278+ myBaseTypeRefCache = null
1279+ myBaseTypeRefCachePeriod = Nowhere
1280+ }
12671281
12681282 override def copyCaches (from : SymDenotation , phase : Phase )(implicit ctx : Context ): this .type = {
12691283 from match {
12701284 case from : ClassDenotation =>
12711285 if (from.memberNamesCache.isValidAt(phase)) memberNamesCache = from.memberNamesCache
1272- if (from.baseDataCache.isValidAt(phase)) baseDataCache = from.baseDataCache
1286+ if (from.baseDataCache.isValidAt(phase)) {
1287+ baseDataCache = from.baseDataCache
1288+ myBaseTypeRefCache = from.baseTypeRefCache
1289+ }
12731290 case _ =>
12741291 }
12751292 this
@@ -1381,13 +1398,6 @@ object SymDenotations {
13811398 private def baseClassSet (implicit onBehalf : BaseData , ctx : Context ): BaseClassSet =
13821399 baseData._2
13831400
1384- /** Invalidate baseTypeRefCache, baseClasses and superClassBits on new run */
1385- private def checkBasesUpToDate ()(implicit ctx : Context ) =
1386- if (baseTypeRefValid != ctx.runId) {
1387- invalidateBaseTypeRefCache()
1388- baseTypeRefValid = ctx.runId
1389- }
1390-
13911401 def computeBaseData (implicit onBehalf : BaseData , ctx : Context ): (List [ClassSymbol ], BaseClassSet ) = {
13921402 val seen = mutable.SortedSet [Int ]()
13931403 def addBaseClasses (bcs : List [ClassSymbol ], to : List [ClassSymbol ])
@@ -1571,8 +1581,6 @@ object SymDenotations {
15711581 case _ => bt
15721582 }
15731583
1574- def inCache (tp : Type ) = baseTypeRefCache.containsKey(tp)
1575-
15761584 /** We cannot cache:
15771585 * - type variables which are uninstantiated or whose instances can
15781586 * change, depending on typerstate.
@@ -1581,13 +1589,16 @@ object SymDenotations {
15811589 * and this changes subtyping relations. As a shortcut, we do not
15821590 * cache ErasedValueType at all.
15831591 */
1584- def isCachable (tp : Type ): Boolean = tp match {
1585- case _ : TypeErasure .ErasedValueType => false
1586- case tp : TypeRef if tp.symbol.isClass => true
1587- case tp : TypeVar => tp.inst.exists && inCache(tp.inst)
1588- case tp : TypeProxy => inCache(tp.underlying)
1589- case tp : AndOrType => inCache(tp.tp1) && inCache(tp.tp2)
1590- case _ => true
1592+ def isCachable (tp : Type , btrCache : BaseTypeRefMap ): Boolean = {
1593+ def inCache (tp : Type ) = btrCache.containsKey(tp)
1594+ tp match {
1595+ case _ : TypeErasure .ErasedValueType => false
1596+ case tp : TypeRef if tp.symbol.isClass => true
1597+ case tp : TypeVar => tp.inst.exists && inCache(tp.inst)
1598+ case tp : TypeProxy => inCache(tp.underlying)
1599+ case tp : AndOrType => inCache(tp.tp1) && inCache(tp.tp2)
1600+ case _ => true
1601+ }
15911602 }
15921603
15931604 def computeBaseTypeRefOf (tp : Type ): Type = {
@@ -1622,21 +1633,21 @@ object SymDenotations {
16221633 /* >|>*/ ctx.debugTraceIndented(s " $tp.baseTypeRef( $this) " ) /* <|<*/ {
16231634 tp match {
16241635 case tp : CachedType =>
1636+ val btrCache = baseTypeRefCache
16251637 try {
1626- checkBasesUpToDate()
1627- var basetp = baseTypeRefCache get tp
1638+ var basetp = btrCache get tp
16281639 if (basetp == null ) {
1629- baseTypeRefCache .put(tp, NoPrefix )
1640+ btrCache .put(tp, NoPrefix )
16301641 basetp = computeBaseTypeRefOf(tp)
1631- if (isCachable(tp)) baseTypeRefCache .put(tp, basetp)
1632- else baseTypeRefCache .remove(tp)
1642+ if (isCachable(tp, baseTypeRefCache )) btrCache .put(tp, basetp)
1643+ else btrCache .remove(tp)
16331644 } else if (basetp == NoPrefix )
16341645 throw CyclicReference (this )
16351646 basetp
16361647 }
16371648 catch {
16381649 case ex : Throwable =>
1639- baseTypeRefCache .put(tp, null )
1650+ btrCache .put(tp, null )
16401651 throw ex
16411652 }
16421653 case _ =>
0 commit comments