From 759de8623923d17eaca373dcec14899681a52df4 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Mon, 24 Sep 2012 15:09:50 +0200 Subject: 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. --- src/reflect/scala/reflect/internal/Mirrors.scala | 12 +++++++++--- src/reflect/scala/reflect/runtime/JavaMirrors.scala | 13 +++---------- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src') 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] = { -- cgit v1.2.3