@@ -1238,8 +1238,10 @@ object SymDenotations {
1238
1238
private [this ] var myMemberCache : LRUCache [Name , PreDenotation ] = null
1239
1239
private [this ] var myMemberCachePeriod : Period = Nowhere
1240
1240
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
1243
1245
1244
1246
private var baseDataCache : BaseData = BaseData .None
1245
1247
private var memberNamesCache : MemberNames = MemberNames .None
@@ -1252,6 +1254,16 @@ object SymDenotations {
1252
1254
myMemberCache
1253
1255
}
1254
1256
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
+
1255
1267
private def invalidateBaseDataCache () = {
1256
1268
baseDataCache.invalidate()
1257
1269
baseDataCache = BaseData .None
@@ -1262,14 +1274,19 @@ object SymDenotations {
1262
1274
memberNamesCache = MemberNames .None
1263
1275
}
1264
1276
1265
- def invalidateBaseTypeRefCache () =
1266
- baseTypeRefCache = new java.util.HashMap [CachedType , Type ]
1277
+ def invalidateBaseTypeRefCache () = {
1278
+ myBaseTypeRefCache = null
1279
+ myBaseTypeRefCachePeriod = Nowhere
1280
+ }
1267
1281
1268
1282
override def copyCaches (from : SymDenotation , phase : Phase )(implicit ctx : Context ): this .type = {
1269
1283
from match {
1270
1284
case from : ClassDenotation =>
1271
1285
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
+ }
1273
1290
case _ =>
1274
1291
}
1275
1292
this
@@ -1381,13 +1398,6 @@ object SymDenotations {
1381
1398
private def baseClassSet (implicit onBehalf : BaseData , ctx : Context ): BaseClassSet =
1382
1399
baseData._2
1383
1400
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
-
1391
1401
def computeBaseData (implicit onBehalf : BaseData , ctx : Context ): (List [ClassSymbol ], BaseClassSet ) = {
1392
1402
val seen = mutable.SortedSet [Int ]()
1393
1403
def addBaseClasses (bcs : List [ClassSymbol ], to : List [ClassSymbol ])
@@ -1571,8 +1581,6 @@ object SymDenotations {
1571
1581
case _ => bt
1572
1582
}
1573
1583
1574
- def inCache (tp : Type ) = baseTypeRefCache.containsKey(tp)
1575
-
1576
1584
/** We cannot cache:
1577
1585
* - type variables which are uninstantiated or whose instances can
1578
1586
* change, depending on typerstate.
@@ -1581,13 +1589,16 @@ object SymDenotations {
1581
1589
* and this changes subtyping relations. As a shortcut, we do not
1582
1590
* cache ErasedValueType at all.
1583
1591
*/
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
+ }
1591
1602
}
1592
1603
1593
1604
def computeBaseTypeRefOf (tp : Type ): Type = {
@@ -1622,21 +1633,21 @@ object SymDenotations {
1622
1633
/* >|>*/ ctx.debugTraceIndented(s " $tp.baseTypeRef( $this) " ) /* <|<*/ {
1623
1634
tp match {
1624
1635
case tp : CachedType =>
1636
+ val btrCache = baseTypeRefCache
1625
1637
try {
1626
- checkBasesUpToDate()
1627
- var basetp = baseTypeRefCache get tp
1638
+ var basetp = btrCache get tp
1628
1639
if (basetp == null ) {
1629
- baseTypeRefCache .put(tp, NoPrefix )
1640
+ btrCache .put(tp, NoPrefix )
1630
1641
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)
1633
1644
} else if (basetp == NoPrefix )
1634
1645
throw CyclicReference (this )
1635
1646
basetp
1636
1647
}
1637
1648
catch {
1638
1649
case ex : Throwable =>
1639
- baseTypeRefCache .put(tp, null )
1650
+ btrCache .put(tp, null )
1640
1651
throw ex
1641
1652
}
1642
1653
case _ =>
0 commit comments