aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-02-10 19:17:00 +0100
committerMartin Odersky <odersky@gmail.com>2014-02-10 19:17:00 +0100
commit5870fbb7297b1b4bb70cbcf27cd88d4e12197234 (patch)
tree855fa843dde8b90041629786a22fa7e0187be4b3 /src/dotty/tools/dotc
parent18ae13dcf4f5d40d528e2bcf43a19e84bf475084 (diff)
downloaddotty-5870fbb7297b1b4bb70cbcf27cd88d4e12197234.tar.gz
dotty-5870fbb7297b1b4bb70cbcf27cd88d4e12197234.tar.bz2
dotty-5870fbb7297b1b4bb70cbcf27cd88d4e12197234.zip
New scheme for incremental invalidation of parents.
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/config/Printers.scala1
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala24
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala115
-rw-r--r--src/dotty/tools/dotc/core/Types.scala8
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala9
6 files changed, 87 insertions, 74 deletions
diff --git a/src/dotty/tools/dotc/config/Printers.scala b/src/dotty/tools/dotc/config/Printers.scala
index 67f05c2e7..183ab35b9 100644
--- a/src/dotty/tools/dotc/config/Printers.scala
+++ b/src/dotty/tools/dotc/config/Printers.scala
@@ -21,5 +21,6 @@ object Printers {
val unapp: Printer = noPrinter
val completions = noPrinter
val gadts = noPrinter
+ val incremental = new Printer
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 0d35f3cf9..6cbcd982f 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -17,8 +17,6 @@ import config.Config
import util.common._
import Decorators.SymbolIteratorDecorator
-
-
/** Denotations represent the meaning of symbols and named types.
* The following diagram shows how the principal types of denotations
* and their denoting entities relate to each other. Lines ending in
@@ -463,12 +461,13 @@ object Denotations {
protected def bringForward()(implicit ctx: Context): SingleDenotation = this match {
case denot: SymDenotation if ctx.stillValid(denot) =>
+ if (denot.exists) assert(ctx.runId > validFor.runId)
var d: SingleDenotation = denot
do {
d.validFor = Period(ctx.period.runId, d.validFor.firstPhaseId, d.validFor.lastPhaseId)
d = d.nextInRun
} while (d ne denot)
- initial.copyIfParentInvalid
+ initial.syncWithParents
case _ =>
staleSymbolError
}
@@ -506,7 +505,7 @@ object Denotations {
var startPid = cur.validFor.lastPhaseId + 1
val transformers = ctx.transformersFor(cur)
val transformer = transformers.nextTransformer(startPid)
- next = transformer.transform(cur).copyIfParentInvalid
+ next = transformer.transform(cur).syncWithParents
if (next eq cur)
startPid = cur.validFor.firstPhaseId
else {
@@ -530,14 +529,20 @@ object Denotations {
}
}
- def staleSymbolError(implicit ctx: Context) =
- throw new StaleSymbol(s"stale symbol; $this in ${this.asSymDenotation.owner}, defined in run ${myValidFor.runId}, is referred to in run ${ctx.period.runId}")
+ def staleSymbolError(implicit ctx: Context) = {
+ def ownerMsg = this match {
+ case denot: SymDenotation => s"in ${denot.owner}"
+ case _ => ""
+ }
+ def msg = s"stale symbol; $this#${symbol.id}$ownerMsg, defined in run ${myValidFor.runId}, is referred to in run ${ctx.period.runId}"
+ throw new StaleSymbol(msg)
+ }
/** For ClassDenotations only:
* If caches influenced by parent classes are still valid, the denotation
* itself, otherwise a freshly initialized copy.
*/
- def copyIfParentInvalid(implicit ctx: Context): SingleDenotation = this
+ def syncWithParents(implicit ctx: Context): SingleDenotation = this
override def toString =
if (symbol == NoSymbol) symbol.toString
@@ -759,6 +764,9 @@ object Denotations {
NoSymbol
}
- class StaleSymbol(msg: String) extends Exception(msg)
+ /** An exception for accessing symbols that are no longer valid in current run */
+ class StaleSymbol(msg: => String) extends Exception {
+ override def getMessage() = msg
+ }
}
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index a3e8c4f62..1bb912059 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -30,26 +30,28 @@ trait SymDenotations { this: Context =>
initPrivateWithin: Symbol = NoSymbol)(implicit ctx: Context): SymDenotation = {
val result =
if (symbol.isClass)
- if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin)
- else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin)
+ if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin, ctx.runId)
+ else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin, ctx.runId)
else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin)
- result.firstRunId = ctx.runId
result.validFor = stablePeriod
result
}
- def stillValid(denot: SymDenotation): Boolean = try
+ def stillValid(denot: SymDenotation): Boolean =
if (denot is ValidForever) true
- else if (denot.owner is PackageClass) denot.owner.decls.lookup(denot.name) eq denot.symbol
- else
- stillValid(denot.owner) && (
- (denot.owner.firstRunId == denot.firstRunId) || {
- println(s"no longer valid: $denot, was defined in ${denot.firstRunId}, owner ${denot.owner} was defined in ${denot.owner.firstRunId}")
- false
- })
- catch {
- case ex: StaleSymbol => false
- }
+ else try {
+ val owner = denot.owner.denot
+ def isSelfSym = owner.infoOrCompleter match {
+ case ClassInfo(_, _, _, _, selfInfo) => selfInfo == denot.symbol
+ case _ => false
+ }
+ stillValid(owner) && owner.isClass && (
+ (owner.decls.lookupAll(denot.name) contains denot.symbol)
+ || isSelfSym
+ )
+ } catch {
+ case ex: StaleSymbol => false
+ }
}
object SymDenotations {
@@ -69,8 +71,6 @@ object SymDenotations {
override def hasUniqueSym: Boolean = exists
- private[SymDenotations] var firstRunId: RunId = _
-
// ------ Getting and setting fields -----------------------------
private[this] var myFlags: FlagSet = adaptFlags(initFlags)
@@ -731,8 +731,6 @@ object SymDenotations {
val annotations1 = if (annotations != null) annotations else this.annotations
val d = ctx.SymDenotation(symbol, owner, name, initFlags1, info1, privateWithin1)
d.annotations = annotations1
- d.firstRunId = firstRunId
- // what about validFor?
d
}
}
@@ -745,7 +743,8 @@ object SymDenotations {
name: Name,
initFlags: FlagSet,
initInfo: Type,
- initPrivateWithin: Symbol = NoSymbol)
+ initPrivateWithin: Symbol,
+ initRunId: RunId)
extends SymDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) {
import util.LRUCache
@@ -771,8 +770,9 @@ object SymDenotations {
myTypeParams
}
- private def myClassParents(implicit ctx: Context): List[TypeRef] = info match {
- case classInfo: ClassInfo => classInfo.myClassParents
+ /** The denotations of all parents in this class. */
+ def classParents(implicit ctx: Context): List[TypeRef] = info match {
+ case classInfo: ClassInfo => classInfo.classParents
case _ => Nil
}
@@ -781,51 +781,45 @@ object SymDenotations {
* @see Namer#ClassCompleter
*/
private def isFullyCompleted(implicit ctx: Context): Boolean =
- isCompleted && myClassParents.nonEmpty
-
- /** A key to verify that all caches influenced by parent classes are valid */
- private var parentDenots: List[Denotation] = null
+ isCompleted && classParents.nonEmpty
- /** The denotations of all parents in this class.
- * Note: Always use this method instead of `classInfo.myClassParents`
- * because the latter does not ensure that the `parentDenots` key
- * is up-to-date, which might lead to invalid caches later on.
- */
- def classParents(implicit ctx: Context): List[TypeRef] = {
- val ps = myClassParents
- if (parentDenots == null && ps.nonEmpty) parentDenots = ps map (_.denot)
- ps
- }
+ // ------ syncing inheritance-related info -----------------------------
- /** Are caches influenced by parent classes still valid? */
- private def parentsAreValid(implicit ctx: Context): Boolean =
- parentDenots == null ||
- parentDenots.corresponds(myClassParents map (_.denot))(_ eq _)
-
- private var copied = 0
+ private var firstRunId: RunId = initRunId
/** If caches influenced by parent classes are still valid, the denotation
* itself, otherwise a freshly initialized copy.
*/
- override def copyIfParentInvalid(implicit ctx: Context): SingleDenotation =
- if (!parentsAreValid) {
- println(s"parents of $this are invalid; copying $hashCode, symbol id = ${symbol.id} ...")
- for ((pd1, pd2) <- parentDenots zip (myClassParents map (_.denot)))
- if (pd1 ne pd2) println(s"different: $pd1 != $pd2")
- assert(copied == 0)
- copied += 1
- copySymDenotation()
+ override def syncWithParents(implicit ctx: Context): SingleDenotation = {
+ def isYounger(tref: TypeRef) = tref.symbol.denot match {
+ case denot: ClassDenotation =>
+ if (denot.validFor.runId < ctx.runId) denot.current // syncs with its parents in turn
+ val result = denot.firstRunId > this.firstRunId
+ if (result) incremental.println(s"$denot is younger than $this")
+ result
+ case _ => false
}
- else this
-
- protected override def bringForward()(implicit ctx: Context): SingleDenotation = {
- assert(ctx.runId >= symbol.defRunId, s"$this, defrunid = ${symbol.defRunId}, ctx.runid = ${ctx.runId}")
- if (symbol.defRunId == ctx.runId) symbol.denot
- else {
- val d = super.bringForward()
- symbol.denot = d.asSymDenotation
- d
+ val parentIsYounger = (firstRunId < ctx.runId) && {
+ infoOrCompleter match {
+ case cinfo: ClassInfo => cinfo.classParents exists isYounger
+ case _ => false
+ }
+ }
+ if (parentIsYounger) {
+ incremental.println(s"parents of $this are invalid; symbol id = ${symbol.id}, copying ...\n")
+ invalidateInheritedInfo()
+ firstRunId = ctx.runId
}
+ this
+ }
+
+ /** Invalidate all caches and fields that depend on base classes and their contents */
+ private def invalidateInheritedInfo(): Unit = {
+ myBaseClasses = null
+ mySuperClassBits = null
+ myMemberFingerPrint = FingerPrint.unknown
+ myMemberCache = null
+ memberNamesCache = SimpleMap.Empty
}
// ------ class-specific operations -----------------------------------
@@ -1175,8 +1169,9 @@ object SymDenotations {
name: Name,
initFlags: FlagSet,
initInfo: Type,
- initPrivateWithin: Symbol = NoSymbol)
- extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) {
+ initPrivateWithin: Symbol,
+ initRunId: RunId)
+ extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin, initRunId) {
private[this] var packageObjCache: SymDenotation = _
private[this] var packageObjRunId: RunId = NoRunId
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 28a7f9e67..49b57d32f 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1793,7 +1793,7 @@ object Types {
abstract case class ClassInfo(
prefix: Type,
cls: ClassSymbol,
- myClassParents: List[TypeRef], // to be used only in ClassDenotation!
+ classParents: List[TypeRef],
decls: Scope,
selfInfo: DotClass /* should be: Type | Symbol */) extends CachedGroundType with TypeType {
@@ -1842,10 +1842,10 @@ object Types {
def derivedClassInfo(prefix: Type)(implicit ctx: Context) =
if (prefix eq this.prefix) this
- else ClassInfo(prefix, cls, myClassParents, decls, selfInfo)
+ else ClassInfo(prefix, cls, classParents, decls, selfInfo)
- def derivedClassInfo(prefix: Type = this.prefix, classParents: List[TypeRef] = myClassParents, selfInfo: DotClass = this.selfInfo)(implicit ctx: Context) =
- if ((prefix eq this.prefix) && (classParents eq this.myClassParents) && (selfInfo eq this.selfInfo)) this
+ def derivedClassInfo(prefix: Type = this.prefix, classParents: List[TypeRef] = classParents, selfInfo: DotClass = this.selfInfo)(implicit ctx: Context) =
+ if ((prefix eq this.prefix) && (classParents eq this.classParents) && (selfInfo eq this.selfInfo)) this
else ClassInfo(prefix, cls, classParents, decls, selfInfo)
override def computeHash = doHash(cls, prefix)
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index f40b63bba..a5cbef571 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -343,7 +343,7 @@ trait ImplicitRunInfo { self: RunInfo =>
}
/** A map that counts the number of times an implicit ref was picked */
- val useCount = new mutable.HashMap[TermRef, Int] {
+ val useCount: mutable.Map[TermRef, Int] = new mutable.HashMap[TermRef, Int] { // !!!
override def default(key: TermRef) = 0
}
}
@@ -628,7 +628,7 @@ class SearchHistory(val searchDepth: Int, val seen: Map[ClassSymbol, Int]) {
class TermRefSet(implicit ctx: Context) extends mutable.Traversable[TermRef] {
import collection.JavaConverters._
private val elems = (new java.util.LinkedHashMap[TermSymbol, List[Type]]).asScala
-
+
def += (ref: TermRef): Unit = {
val pre = ref.prefix
val sym = ref.symbol.asTerm
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index bce9d225a..697441ca1 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -63,6 +63,15 @@ class Typer extends Namer with Applications with Implicits {
*/
private var importedFromRoot: Set[Symbol] = Set()
+ /** A denotation exists really if it exists and does not point to a stale symbol.
+ def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean = denot match {
+ case denot: SymDenotation =>
+ denot.ensureCompleted
+ denot.exists && !denot.isAbsent
+ case _ =>
+ true
+ }*/
+
/** A denotation exists really if it exists and does not point to a stale symbol. */
def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean =
try