diff options
author | Paul Phillips <paulp@improving.org> | 2011-07-14 01:27:04 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-07-14 01:27:04 +0000 |
commit | 733669230a470b60c2ecc92c666f0871cecf22ef (patch) | |
tree | 70ee5f0e49e348e317bfd9db5d2230b433dada31 /src/compiler/scala/reflect/internal | |
parent | 5e49b4181976f20d28625008a775223dbf8e7f6e (diff) | |
download | scala-733669230a470b60c2ecc92c666f0871cecf22ef.tar.gz scala-733669230a470b60c2ecc92c666f0871cecf22ef.tar.bz2 scala-733669230a470b60c2ecc92c666f0871cecf22ef.zip |
Adding some Sets/Maps to perRunCaches, and elim...
Adding some Sets/Maps to perRunCaches, and eliminating ambiguously named
imports.
Did a tour of the compiler adding a few longer-lived mutable structures
to the per-run cache clearing mechanism. Some of these were not a big
threat, but there is (almost) literally no cost to tracking them and the
fewer mutable structures which are created "lone wolf style" the easier
it is to spot the one playing by his own rules.
While I was at it I followed through on long held ambition to eliminate
the importing of highly ambiguous names like "Map" and "HashSet" from
the mutable and immutable packages. I didn't quite manage elimination
but it's pretty close. Something potentially as pernicious which I
didn't do much about is this import:
import scala.collection._
Imagine coming across that one on lines 407 and 474 of a 1271 file.
That's not cool. Some poor future programmer will be on line 1100 and
use "Map[A, B]" in some function and only after the product has shipped
will it be discovered that the signature is wrong and the rocket will
now be crashing into the mountainside straightaway. No review.
Diffstat (limited to 'src/compiler/scala/reflect/internal')
7 files changed, 38 insertions, 17 deletions
diff --git a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala index bb342cf0e1..38277b5a09 100644 --- a/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/compiler/scala/reflect/internal/BaseTypeSeqs.scala @@ -6,7 +6,7 @@ package scala.reflect package internal // todo implement in terms of BitSet -import scala.collection.mutable.{ListBuffer, BitSet} +import scala.collection.{ mutable, immutable } import math.max import util.Statistics._ @@ -41,7 +41,7 @@ trait BaseTypeSeqs { // (while NoType is in there to indicate a cycle in this BTS, during the execution of // the mergePrefixAndArgs below, the elems get copied without the pending map, // so that NoType's are seen instead of the original type --> spurious compile error) - val pending = new BitSet(length) + val pending = new mutable.BitSet(length) /** The type at i'th position in this sequence; lazy types are returned evaluated. */ def apply(i: Int): Type = @@ -187,7 +187,7 @@ trait BaseTypeSeqs { val tsym = tp.typeSymbol val parents = tp.parents // Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG - val buf = new ListBuffer[Type] + val buf = new mutable.ListBuffer[Type] buf += tsym.tpe var btsSize = 1 if (parents.nonEmpty) { diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 71eb471992..500a5cb428 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -7,7 +7,6 @@ package scala.reflect package internal import scala.collection.{ mutable, immutable } -import scala.collection.mutable.{ HashMap } import Flags._ import PartialFunction._ @@ -503,7 +502,7 @@ trait Definitions extends reflect.api.StandardDefinitions { var Delegate_scalaCallers: List[Symbol] = List() // Symbol -> (Symbol, Type): scalaCaller -> (scalaMethodSym, DelegateType) // var Delegate_scalaCallerInfos: HashMap[Symbol, (Symbol, Type)] = _ - lazy val Delegate_scalaCallerTargets: HashMap[Symbol, Symbol] = new HashMap() + lazy val Delegate_scalaCallerTargets: mutable.HashMap[Symbol, Symbol] = mutable.HashMap() def isCorrespondingDelegate(delegateType: Type, functionType: Type): Boolean = { isSubType(delegateType, DelegateClass.tpe) && diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index ca2b5867ce..32fa88ac15 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -116,6 +116,9 @@ abstract class SymbolTable extends api.Universe object perRunCaches { import java.lang.ref.WeakReference + import scala.tools.util.Signallable + import scala.runtime.ScalaRunTime.stringOf + // We can allow ourselves a structural type, these methods // amount to a few calls per run at most. This does suggest @@ -128,6 +131,25 @@ abstract class SymbolTable extends api.Universe // letting us know when a cache is really out of commission. private val caches = mutable.HashSet[WeakReference[Clearable]]() + private def dumpCaches() { + println(caches.size + " structures are in perRunCaches.") + caches.zipWithIndex foreach { case (ref, index) => + val cache = ref.get() + println("(" + index + ")" + ( + if (cache == null) " has been collected." + else " has " + cache.size + " entries:\n" + stringOf(cache) + )) + } + } + if (settings.debug.value) { + println(Signallable("dump compiler caches")(dumpCaches())) + } + + def recordCache[T <: Clearable](cache: T): T = { + caches += new WeakReference(cache) + cache + } + def clearAll() = { if (settings.debug.value) { val size = caches flatMap (ref => Option(ref.get)) map (_.size) sum; @@ -142,8 +164,9 @@ abstract class SymbolTable extends api.Universe } } - def newMap[K, V]() = { val m = mutable.HashMap[K, V]() ; caches += new WeakReference(m) ; m } - def newSet[K]() = { val s = mutable.HashSet[K]() ; caches += new WeakReference(s) ; s } + def newWeakMap[K, V]() = recordCache(mutable.WeakHashMap[K, V]()) + def newMap[K, V]() = recordCache(mutable.HashMap[K, V]()) + def newSet[K]() = recordCache(mutable.HashSet[K]()) } /** Break into repl debugger if assertion is true. */ diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala index abbe8390a6..afb56d9999 100644 --- a/src/compiler/scala/reflect/internal/TreeInfo.scala +++ b/src/compiler/scala/reflect/internal/TreeInfo.scala @@ -7,7 +7,6 @@ package scala.reflect package internal import Flags._ -import util.HashSet /** This class ... * diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index 70d28d8402..ef80b5d479 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -6,13 +6,10 @@ package scala.reflect package internal -import java.io.{PrintWriter, StringWriter} -import scala.collection.mutable.ListBuffer +import java.io.{ PrintWriter, StringWriter } import Flags._ import api.Modifier -//import scala.tools.nsc.util.{ FreshNameCreator, HashSet, SourceFile } - trait Trees extends api.Trees { self: SymbolTable => // --- modifiers implementation --------------------------------------- diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index bb5608917b..34150069ad 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -9,8 +9,6 @@ package internal import scala.collection.{ mutable, immutable } import scala.ref.WeakReference import mutable.ListBuffer -//import ast.TreeGen -//import util.{ Position, NoPosition } import Flags._ import scala.util.control.ControlThrowable import scala.annotation.tailrec @@ -105,6 +103,9 @@ trait Types extends api.Types { self: SymbolTable => private type UndoLog = List[(TypeVar, TypeConstraint)] private[scala] var log: UndoLog = List() + // register with the auto-clearing cache manager + perRunCaches.recordCache(this) + /** Undo all changes to constraints to type variables upto `limit`. */ private def undoTo(limit: UndoLog) { while ((log ne limit) && log.nonEmpty) { @@ -123,6 +124,7 @@ trait Types extends api.Types { self: SymbolTable => log = Nil } + def size = log.size // `block` should not affect constraints on typevars def undo[T](block: => T): T = { @@ -149,7 +151,7 @@ trait Types extends api.Types { self: SymbolTable => * It makes use of the fact that these two operations depend only on the parents, * not on the refinement. */ - val intersectionWitness = new mutable.WeakHashMap[List[Type], WeakReference[Type]] + val intersectionWitness = perRunCaches.newWeakMap[List[Type], WeakReference[Type]]() //private object gen extends { // val global : Types.this.type = Types.this diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index 1f54edbdc5..6d0b22ac05 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -13,7 +13,8 @@ import java.lang.Double.longBitsToDouble import Flags._ import PickleFormat._ -import collection.mutable.{HashMap, ListBuffer} +import scala.collection.{ mutable, immutable } +import collection.mutable.ListBuffer import annotation.switch /** @author Martin Odersky @@ -57,7 +58,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { private val entries = new Array[AnyRef](index.length) /** A map from symbols to their associated `decls` scopes */ - private val symScopes = new HashMap[Symbol, Scope] + private val symScopes = mutable.HashMap[Symbol, Scope]() //println("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug |