Skip to content

Commit 51aebce

Browse files
committed
Fix handling of baseTypeRef caches.
It's wow subject to the same invalidation as base data caches (except that there's no need for recursive invalidation of caches in subclasses)
1 parent 44b1a9b commit 51aebce

File tree

1 file changed

+38
-27
lines changed

1 file changed

+38
-27
lines changed

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

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)