summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-07-06 17:28:04 +0000
committerPaul Phillips <paulp@improving.org>2011-07-06 17:28:04 +0000
commit262114974bfab763b282bf0aa2ec5b902fdd69f5 (patch)
tree02254d5a907ba32866384ef2fb214831dd2a8aaa
parenta21cb1b3759fcb079c9bd21a598cc732d8481072 (diff)
downloadscala-262114974bfab763b282bf0aa2ec5b902fdd69f5.tar.gz
scala-262114974bfab763b282bf0aa2ec5b902fdd69f5.tar.bz2
scala-262114974bfab763b282bf0aa2ec5b902fdd69f5.zip
Created simple infrastructure for creating muta...
Created simple infrastructure for creating mutable sets and maps which are automatically cleared after each compilation run. Since I am not too familiar with the mechanics of the presentation compiler I'm not sure this addresses the problem, or that it doesn't clear something which shouldn't be cleared. Also, this is only a sampling of possible mutable sets and maps: let me know if it does the job and I can expand it. Review by dragos.
-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)