diff options
author | Martin Odersky <odersky@gmail.com> | 2014-01-30 11:36:24 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-01-30 11:36:24 +0100 |
commit | dfc1a54b614ad64045bcf35f98c030ab04c9f5f2 (patch) | |
tree | 40eaa57991ff7b6293ead57f087d1447f61ef3bf /src/dotty/tools | |
parent | 818d42d20bae1c446e9d540ce801d63b0eb4450a (diff) | |
download | dotty-dfc1a54b614ad64045bcf35f98c030ab04c9f5f2.tar.gz dotty-dfc1a54b614ad64045bcf35f98c030ab04c9f5f2.tar.bz2 dotty-dfc1a54b614ad64045bcf35f98c030ab04c9f5f2.zip |
Performance improvements to NamedType#denot
Diffstat (limited to 'src/dotty/tools')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 77 |
1 files changed, 48 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 9357e8d51..71e38fb8c 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -984,50 +984,67 @@ object Types { assert(prefix.isValueType || (prefix eq NoPrefix)) - private[this] var lastDenotationOrSym: AnyRef = null + private[this] var lastDenotation: Denotation = _ + private[this] var lastSymbol: Symbol = _ + private[this] var checkedPeriod = Nowhere - def knownDenotation: Boolean = lastDenotationOrSym.isInstanceOf[Denotation] + // Invariants: + // (1) checkedPeriod != Nowhere => lastDenotation != null + // (2) lastDenotation != null => lastSymbol != null + + def knownDenotation: Boolean = lastDenotation != null /** The denotation currently denoted by this type */ - final def denot(implicit ctx: Context): Denotation = lastDenotationOrSym match { - case d: Denotation if d.validFor contains ctx.period => d - case _ => computeDenot + final def denot(implicit ctx: Context): Denotation = { + val now = ctx.period + if (checkedPeriod == now) lastDenotation else denotAt(now) + } + + /** A first fall back to do a somewhat more expensive calculation in case the first + * attempt in `denot` does not yield a denotation. + */ + private def denotAt(now: Period)(implicit ctx: Context): Denotation = { + val d = lastDenotation + if (d != null && (d.validFor contains now)) { + checkedPeriod = now + d + } + else computeDenot } + /** A second fallback to recompute the denotation if necessary */ private def computeDenot(implicit ctx: Context): Denotation = { - val denot = lastDenotationOrSym match { + val d = lastDenotation match { + case null => + val sym = lastSymbol + if (sym == null) loadDenot else denotOfSym(sym) case d: SymDenotation if ctx.stillValid(d) => d.current - case d: Denotation => + case d => if (d.validFor.runId == ctx.period.runId) d.current else loadDenot - case sym: Symbol => - val d = sym.denot - val owner = d.owner - if (owner.isTerm) d else d.asSeenFrom(prefix) - case _ => - loadDenot -/* need to do elsewhere as it leads to a cycle in subtyping here. - if (d.exists && !d.symbol.isAliasType && !prefix.isLegalPrefix) { - val ex = new MalformedType(prefix, d, prefix.memberNames(abstractTypeNameFilter)) - if (ctx.checkPrefix) { - ctx.printCreationTrace() - throw ex - } else ctx.log(ex.getMessage) - } -*/ } - lastDenotationOrSym = denot - denot + lastDenotation = d + lastSymbol = d.symbol + d + } + + private def denotOfSym(sym: Symbol)(implicit ctx: Context): Denotation = { + val d = sym.denot + val owner = d.owner + if (owner.isTerm) d else d.asSeenFrom(prefix) } private[dotc] final def withDenot(denot: Denotation): this.type = { - lastDenotationOrSym = denot + lastDenotation = denot + lastSymbol = denot.symbol this } private[dotc] final def withSym(sym: Symbol): this.type = { - lastDenotationOrSym = sym + lastDenotation = null + lastSymbol = sym + checkedPeriod = Nowhere this } @@ -1045,9 +1062,11 @@ object Types { def isType = name.isTypeName def isTerm = name.isTermName - def symbol(implicit ctx: Context): Symbol = lastDenotationOrSym match { - case sym: Symbol => sym - case _ => denot.symbol + def symbol(implicit ctx: Context): Symbol = { + val now = ctx.period + if (checkedPeriod == now || + lastDenotation == null && lastSymbol != null) lastSymbol + else denot.symbol } def info(implicit ctx: Context): Type = denot.info |