summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-07-12 17:25:17 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-14 12:09:31 +0200
commit0e3c70f2ab7f8b03cd157749f50cc301971cef03 (patch)
treea45c8dd107b53a434b9dcd12c0c7d297fbf56223
parent41f4497cc57f5e010df10a9f5a98c9815c1c36fd (diff)
downloadscala-0e3c70f2ab7f8b03cd157749f50cc301971cef03.tar.gz
scala-0e3c70f2ab7f8b03cd157749f50cc301971cef03.tar.bz2
scala-0e3c70f2ab7f8b03cd157749f50cc301971cef03.zip
Attempt #3 to optimize findMember
Fixed fingerPrinting scheme to work with rehashes, also added finger prints to typedIdent searches.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
-rw-r--r--src/reflect/scala/reflect/internal/Names.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Scopes.scala9
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala12
4 files changed, 23 insertions, 8 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 6aa93f9cec..2f9474a6ad 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4510,6 +4510,8 @@ trait Typers extends Modes with Adaptations with Tags {
assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
errorContainer = tree
}
+
+ val fingerPrint: Long = name.fingerPrint
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
@@ -4548,7 +4550,10 @@ trait Typers extends Modes with Adaptations with Tags {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
pre = cx.enclClass.prefix
- defEntry = cx.scope.lookupEntry(name)
+ defEntry = {
+ val scope = cx.scope
+ if ((fingerPrint & scope.fingerPrints) != 0) scope.lookupEntry(name) else null
+ }
if ((defEntry ne null) && qualifies(defEntry.sym)) {
// Right here is where SI-1987, overloading in package objects, can be
// seen to go wrong. There is an overloaded symbol, but when referring
diff --git a/src/reflect/scala/reflect/internal/Names.scala b/src/reflect/scala/reflect/internal/Names.scala
index 18671871ae..ae79bd0fc4 100644
--- a/src/reflect/scala/reflect/internal/Names.scala
+++ b/src/reflect/scala/reflect/internal/Names.scala
@@ -414,6 +414,9 @@ trait Names extends api.Names {
}
else toString
}
+
+ @inline
+ final def fingerPrint: Long = (1L << start)
/** TODO - find some efficiency. */
def append(ch: Char) = newName("" + this + ch)
diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala
index 939cd556a6..89e3c52de6 100644
--- a/src/reflect/scala/reflect/internal/Scopes.scala
+++ b/src/reflect/scala/reflect/internal/Scopes.scala
@@ -41,15 +41,15 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
* This is necessary because when run from reflection every scope needs to have a
* SynchronizedScope as mixin.
*/
- class Scope protected[Scopes] (initElems: ScopeEntry = null) extends Iterable[Symbol] {
+ class Scope protected[Scopes] (initElems: ScopeEntry = null, initFingerPrints: Long = 0L) extends Iterable[Symbol] {
/** A bitset containing the last 6 bits of the start value of every name
* stored in this scope.
*/
- var fingerPrints: Long = 0L
+ var fingerPrints: Long = initFingerPrints
protected[Scopes] def this(base: Scope) = {
- this(base.elems)
+ this(base.elems, base.fingerPrints)
nestinglevel = base.nestinglevel + 1
}
@@ -119,7 +119,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
* @param sym ...
*/
def enter[T <: Symbol](sym: T): T = {
- fingerPrints |= (1L << sym.name.start)
+ fingerPrints |= sym.name.fingerPrint
enterEntry(newScopeEntry(sym, this))
sym
}
@@ -156,6 +156,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
}
def rehash(sym: Symbol, newname: Name) {
+ fingerPrints |= newname.fingerPrint
if (hashtable ne null) {
val index = sym.name.start & HASHMASK
var e1 = hashtable(index)
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 8477bdaf01..41d1d6e8f6 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -1045,7 +1045,7 @@ trait Types extends api.Types { self: SymbolTable =>
var continue = true
var self: Type = null
var membertpe: Type = null
- val fingerPrint: Long = (1L << name.start)
+ val fingerPrint: Long = name.fingerPrint
while (continue) {
continue = false
val bcs0 = baseClasses
@@ -1612,8 +1612,13 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.baseClassesPeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
- tpe.baseClassesCache = null
- tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ val start = Statistics.pushTimer(typeOpsStack, baseClassesNanos)
+ try {
+ tpe.baseClassesCache = null
+ tpe.baseClassesCache = tpe.memo(computeBaseClasses)(tpe.typeSymbol :: _.baseClasses.tail)
+ } finally {
+ Statistics.popTimer(typeOpsStack, start)
+ }
}
}
if (tpe.baseClassesCache eq null)
@@ -6909,6 +6914,7 @@ object TypesStats {
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
val asSeenFromNanos = Statistics.newStackableTimer("time spent in asSeenFrom", typerNanos)
val baseTypeSeqNanos = Statistics.newStackableTimer("time spent in baseTypeSeq", typerNanos)
+ val baseClassesNanos = Statistics.newStackableTimer("time spent in baseClasses", typerNanos)
val compoundBaseTypeSeqCount = Statistics.newSubCounter(" of which for compound types", baseTypeSeqCount)
val typerefBaseTypeSeqCount = Statistics.newSubCounter(" of which for typerefs", baseTypeSeqCount)
val singletonBaseTypeSeqCount = Statistics.newSubCounter(" of which for singletons", baseTypeSeqCount)