diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6aa93f9cec9d..2f9474a6ad81 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 18671871ae75..ae79bd0fc4b4 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 939cd556a6ec..89e3c52de6ab 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 8477bdaf01ff..41d1d6e8f67b 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)