summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-09-24 15:09:50 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-09-24 15:09:50 +0200
commit759de8623923d17eaca373dcec14899681a52df4 (patch)
tree58a0a53e205828bb65c9ac6037f414c05e1465e5 /src
parentb403c1d7524ccdfc3455b5bc5d5363fdd9c82bec (diff)
downloadscala-759de8623923d17eaca373dcec14899681a52df4.tar.gz
scala-759de8623923d17eaca373dcec14899681a52df4.tar.bz2
scala-759de8623923d17eaca373dcec14899681a52df4.zip
fixes mirrorThatLoaded in JavaMirrors
`mirrorThatLoaded(sym: Symbol): Mirror` in JavaMirrors used to iterate over `lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]()` to find out what mirror has loaded a certain symbol. It worked okay until yesterday when I noticed failing tests, which crashed when weak references in mirrors were dereferenced with get.get. Apparently some mirrors were collected, and the logic in JavaMirror didn't account for that possibility. When fixing this bug, I noticed that mirrors can become unreachable even if there are still reachable symbols created by those mirrors. That doesn't make sense, therefore I fixed this bug as well by introducing a strong ref from root symbols to the enclosing mirror. Therefore, any active symbol will have a strong reference to the enclosing mirror by the virtue of the owner chain.
Diffstat (limited to 'src')
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala12
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala13
2 files changed, 12 insertions, 13 deletions
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index bde7f7ac51..4836db5db0 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -10,10 +10,15 @@ package internal
import Flags._
trait Mirrors extends api.Mirrors {
- self: SymbolTable =>
+ thisUniverse: SymbolTable =>
override type Mirror >: Null <: RootsBase
+ // root symbols hold a strong reference to the enclosing mirror
+ // this prevents the mirror from being collected
+ // if there are any symbols created by that mirror
+ trait RootSymbol extends Symbol { def mirror: Mirror }
+
abstract class RootsBase(rootOwner: Symbol) extends MirrorOf[Mirrors.this.type] { thisMirror =>
protected[scala] def rootLoader: LazyType
@@ -70,7 +75,7 @@ trait Mirrors extends api.Mirrors {
protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = NoSymbol
- protected def universeMissingHook(owner: Symbol, name: Name): Symbol = self.missingHook(owner, name)
+ protected def universeMissingHook(owner: Symbol, name: Name): Symbol = thisUniverse.missingHook(owner, name)
private[scala] def missingHook(owner: Symbol, name: Name): Symbol = mirrorMissingHook(owner, name) orElse universeMissingHook(owner, name)
@@ -251,10 +256,11 @@ trait Mirrors extends api.Mirrors {
}
// Features common to RootClass and RootPackage, the roots of all
// type and term symbols respectively.
- sealed trait RootSymbol extends WellKnownSymbol {
+ sealed trait RootSymbol extends WellKnownSymbol with thisUniverse.RootSymbol {
final override def isRootSymbol = true
override def owner = rootOwner
override def typeOfThis = thisSym.tpe
+ def mirror = thisMirror.asInstanceOf[Mirror]
}
// This is the package _root_. The actual root cannot be referenced at
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 0d9e90d3a6..2f12ba59a2 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -1236,16 +1236,9 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUnive
override def scopeTransform(owner: Symbol)(op: => Scope): Scope =
if (owner.isPackageClass) owner.info.decls else op
- private lazy val rootToLoader = new WeakHashMap[Symbol, ClassLoader]
-
- override def mirrorThatLoaded(sym: Symbol): Mirror = {
- val root = sym.enclosingRootClass
- def findLoader = {
- val loaders = (mirrors collect { case (cl, ref) if ref.get.get.RootClass == root => cl })
- assert(loaders.nonEmpty, sym)
- loaders.head
- }
- mirrors(rootToLoader getOrElseUpdate(root, findLoader)).get.get
+ override def mirrorThatLoaded(sym: Symbol): Mirror = sym.enclosingRootClass match {
+ case root: RootSymbol => root.mirror
+ case _ => abort(s"${sym}.enclosingRootClass = ${sym.enclosingRootClass}, which is not a RootSymbol")
}
private lazy val syntheticCoreClasses: Map[(String, Name), Symbol] = {