summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala33
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/ICodes.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala8
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala2
9 files changed, 53 insertions, 16 deletions
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index 5c4d44f735..df73feaccc 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -6,6 +6,7 @@
package scala.reflect
package internal
+import scala.collection.{ mutable, immutable }
import util._
abstract class SymbolTable extends /*reflect.generic.Universe
@@ -113,6 +114,38 @@ abstract class SymbolTable extends /*reflect.generic.Universe
}
}
+ object perRunCaches {
+ import java.lang.ref.WeakReference
+
+ // We can allow ourselves a structural type, these methods
+ // amount to a few calls per run at most. This does suggest
+ // a "Clearable" trait may be useful.
+ private type Clearable = {
+ def size: Int
+ def clear(): Unit
+ }
+ // Weak references so the garbage collector will take care of
+ // letting us know when a cache is really out of commission.
+ private val caches = mutable.HashSet[WeakReference[Clearable]]()
+
+ def clearAll() = {
+ if (settings.debug.value) {
+ val size = caches flatMap (ref => Option(ref.get)) map (_.size) sum;
+ log("Clearing " + caches.size + " caches totalling " + size + " entries.")
+ }
+ caches foreach { ref =>
+ val cache = ref.get()
+ if (cache == null)
+ caches -= ref
+ else
+ cache.clear()
+ }
+ }
+
+ 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 }
+ }
+
/** Break into repl debugger if assertion is true. */
// def breakIf(assertion: => Boolean, args: Any*): Unit =
// if (assertion)
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 8704eb4bec..a900af6451 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -38,7 +38,7 @@ trait Symbols /* extends reflect.generic.Symbols*/ { self: SymbolTable =>
/** The original owner of a class. Used by the backend to generate
* EnclosingMethod attributes.
*/
- val originalOwner = mutable.HashMap[Symbol, Symbol]()
+ val originalOwner = perRunCaches.newMap[Symbol, Symbol]()
/** The class for all symbols */
abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name) extends HasFlags /*AbsSymbol */ {
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 7aa987a1ba..36f6b315c2 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1065,6 +1065,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// record dependency data
if (!dependencyAnalysis.off)
dependencyAnalysis.saveDependencyAnalysis()
+
+ // Clear any sets or maps created via perRunCaches.
+ perRunCaches.clearAll()
}
/** Compile list of abstract files. */
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index f615b5fc13..e58f81b3c5 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -47,8 +47,8 @@ abstract class GenICode extends SubComponent {
override def run() {
scalaPrimitives.init
- classes.clear
- super.run
+ classes.clear()
+ super.run()
}
override def apply(unit: CompilationUnit): Unit = {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
index 9c7c9e5010..9553d5cf9b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala
@@ -35,10 +35,10 @@ abstract class ICodes extends AnyRef
with Repository
{
val global: Global
- import global.{ definitions, settings }
+ import global.{ definitions, settings, perRunCaches }
/** The ICode representation of classes */
- val classes = new mutable.HashMap[global.Symbol, IClass]
+ val classes = perRunCaches.newMap[global.Symbol, IClass]()
/** Debugging flag */
def shouldCheckIcode = settings.check contains global.genicode.phaseName
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index e9540dba0d..39eb9be060 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -25,7 +25,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** This map contains a binding (class -> info) if
* the class with this info at phase mixinPhase has been treated for mixin composition
*/
- private val treatedClassInfos = collection.mutable.Map[Symbol, Type]()
+ private val treatedClassInfos = perRunCaches.newMap[Symbol, Type]()
// --------- helper functions -----------------------------------------------
@@ -204,10 +204,10 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
}
/** Map a lazy, mixedin field accessor to it's trait member accessor */
- val initializer = new mutable.HashMap[Symbol, Symbol]
+ val initializer = perRunCaches.newMap[Symbol, Symbol]
/** Deferred bitmaps that will be added during the transformation of a class */
- val deferredBitmaps: collection.mutable.Map[Symbol, List[Tree]] = new collection.mutable.HashMap[Symbol, List[Tree]]
+ val deferredBitmaps = perRunCaches.newMap[Symbol, List[Tree]]()
/** Add all members to be mixed in into a (non-trait-) class
* These are:
@@ -477,7 +477,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* For each class, fields defined by the class come after inherited fields. Mixed-in
* fields count as fields defined by the class itself.
*/
- private val fieldOffset: mutable.Map[Symbol, Int] = new mutable.HashMap[Symbol, Int]
+ private val fieldOffset = perRunCaches.newMap[Symbol, Int]()
/** The first transform; called in a pre-order traversal at phase mixin
* (that is, every node is processed before its children).
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 7dd72e0d10..70976ec3c2 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -182,7 +182,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
/** Map a symbol to additional information on specialization. */
- private val info: mutable.Map[Symbol, SpecializedInfo] = new mutable.HashMap[Symbol, SpecializedInfo]
+ private val info: mutable.Map[Symbol, SpecializedInfo] = perRunCaches.newMap[Symbol, SpecializedInfo]()
/** Has `clazz` any type parameters that need be specialized? */
def hasSpecializedParams(clazz: Symbol) =
@@ -351,7 +351,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// holds mappings from regular type parameter symbols to symbols of
// specialized type parameters which are subtypes of AnyRef
- private val anyrefSpecCache = mutable.Map[Symbol, Symbol]()
+ private val anyrefSpecCache = perRunCaches.newMap[Symbol, Symbol]()
/** Returns the type parameter in the specialized class `cls` that corresponds to type parameter
* `sym` in the original class. It will create it if needed or use the one from the cache.
@@ -375,10 +375,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
)
- // holds mappings from members to the type variables in the class that they were already specialized for,
- // so that they don't get specialized twice (this is for AnyRef specializations)
+ // holds mappings from members to the type variables in the class
+ // that they were already specialized for, so that they don't get
+ // specialized twice (this is for AnyRef specializations)
private val wasSpecializedForTypeVars =
- mutable.Map[Symbol, immutable.Set[Symbol]]() withDefaultValue immutable.Set[Symbol]()
+ perRunCaches.newMap[Symbol, immutable.Set[Symbol]]() withDefaultValue immutable.Set[Symbol]()
/** Type parameters that survive when specializing in the specified environment. */
def survivingParams(params: List[Symbol], env: TypeEnv) =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index 9b0c44155b..44c566030b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -54,7 +54,7 @@ abstract class Duplicators extends Analyzer {
else sym1 eq sym2
}
- private val invalidSyms: mutable.Map[Symbol, Tree] = mutable.HashMap.empty[Symbol, Tree]
+ private val invalidSyms: mutable.Map[Symbol, Tree] = perRunCaches.newMap[Symbol, Tree]()
/** A typer that creates new symbols for all definitions in the given tree
* and updates references to them while re-typechecking. All types in the
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 45663c8bee..6057a77393 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -66,7 +66,7 @@ trait TypeDiagnostics {
/** A map of Positions to addendums - if an error involves a position in
* the map, the addendum should also be printed.
*/
- private var addendums = mutable.Map[Position, () => String]()
+ private var addendums = perRunCaches.newMap[Position, () => String]()
def setAddendum(pos: Position, msg: () => String) =
if (pos != NoPosition)