summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 3f82afde11..d368ff37f5 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc.symtab
import compat.Platform.currentTime
-import scala.collection.mutable.ListBuffer
+import scala.collection.mutable.{ListBuffer, HashMap}
import scala.tools.nsc.util.{HashSet, Position}
import Flags._
@@ -55,6 +55,13 @@ trait Types requires SymbolTable {
val emptyTypeArray = new Array[Type](0)
+ /** A map from lists to compound types that have the given list as parents.
+ * This is used to avoid duplication in the computation of closure and baseClasses.
+ * It makes use of the fact that these two operations depend only on the parents,
+ * not on the refinement.
+ */
+ var intersectionWitness = new HashMap[List[Type], Type]
+
/** The base class for all types */
abstract class Type {
@@ -763,7 +770,7 @@ trait Types requires SymbolTable {
closurePeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
closureCache = null
- closureCache = computeClosure
+ closureCache = memo[Array[Type], Type](computeClosure, modifyClosure(symbol.tpe))
closureDepthCache = maxDepth(closureCache)
}
//Console.println("closure(" + symbol + ") = " + List.fromArray(closureCache));//DEBUG
@@ -807,7 +814,7 @@ trait Types requires SymbolTable {
baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
baseClassesCache = null
- baseClassesCache = computeBaseClasses
+ baseClassesCache = memo[List[Symbol], Symbol](computeBaseClasses, x => symbol :: x.baseClasses.tail)
}
}
if (baseClassesCache eq null)
@@ -815,6 +822,14 @@ trait Types requires SymbolTable {
baseClassesCache
}
+ def memo[A <: Seq[B], B](op1: => A, op2: Type => A) = intersectionWitness get parents match {
+ case Some(w) =>
+ if (w eq this) op1 else op2(w)
+ case None =>
+ intersectionWitness(parents) = this
+ op1
+ }
+
override def baseType(sym: Symbol): Type = {
val index = closurePos(sym)
if (index >= 0) closure(index) else NoType
@@ -2342,6 +2357,14 @@ trait Types requires SymbolTable {
cl1
}
+ private def modifyClosure(tp: Type)(other: Type): Array[Type] = {
+ val cl = other.closure
+ val cl1 = new Array[Type](cl.length)
+ cl1(0) = tp
+ Array.copy(cl, 1, cl1, 1, cl.length-1)
+ cl1
+ }
+
/** like map2, but returns list `xs' itself - instead of a copy - if function
* <code>f</code> maps all elements to themselves.
*/