Skip to content

Commit

Permalink
Attempt #3 to optimize findMember
Browse files Browse the repository at this point in the history
Fixed fingerPrinting scheme to work with rehashes, also added finger prints to typedIdent searches.
  • Loading branch information
odersky authored and adriaanm committed Jul 14, 2012
1 parent 41f4497 commit 0e3c70f
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 8 deletions.
7 changes: 6 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/Typers.scala
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/reflect/scala/reflect/internal/Names.scala
Expand Up @@ -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)
Expand Down
9 changes: 5 additions & 4 deletions src/reflect/scala/reflect/internal/Scopes.scala
Expand Up @@ -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
}

Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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)
Expand Down
12 changes: 9 additions & 3 deletions src/reflect/scala/reflect/internal/Types.scala
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 0e3c70f

Please sign in to comment.