summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-07-12 18:00:13 +0200
committerAdriaan Moors <adriaan.moors@epfl.ch>2012-07-14 12:09:31 +0200
commit04f0b659efe8565c162b5933ace76e2adf00a16e (patch)
treeeb77e0e4d672ac3b7134659b9969e7349abf46c3 /src/reflect
parent0e3c70f2ab7f8b03cd157749f50cc301971cef03 (diff)
downloadscala-04f0b659efe8565c162b5933ace76e2adf00a16e.tar.gz
scala-04f0b659efe8565c162b5933ace76e2adf00a16e.tar.bz2
scala-04f0b659efe8565c162b5933ace76e2adf00a16e.zip
Attempt #4 to optimize findMember
broke out findMembers as a separate operation to streamline the code. findMember itself still needs to be optimized.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala71
1 files changed, 70 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 41d1d6e8f6..afedf3460e 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -668,7 +668,8 @@ trait Types extends api.Types { self: SymbolTable =>
* Note: unfortunately it doesn't work to exclude DEFERRED this way.
*/
def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] =
- findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
+ findMembers(excludedFlags, requiredFlags)
+// findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
def memberBasedOnName(name: Name, excludedFlags: Long): Symbol =
findMember(name, excludedFlags, 0, false)
@@ -1016,6 +1017,71 @@ trait Types extends api.Types { self: SymbolTable =>
if (alts.isEmpty) sym
else (baseClasses.head.newOverloaded(this, alts))
}
+
+ def findMembers(excludedFlags: Long, requiredFlags: Long): List[Symbol] = {
+ // if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
+ // replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
+ // without this, the matchesType call would lead to type variables on both sides
+ // of a subtyping/equality judgement, which can lead to recursive types being constructed.
+ // See (t0851) for a situation where this happens.
+ val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
+
+ Statistics.incCounter(findMembersCount)
+ val start = Statistics.pushTimer(typeOpsStack, findMembersNanos)
+
+ //Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
+ var members: Scope = null
+ var excluded = excludedFlags | DEFERRED
+ var continue = true
+ var self: Type = null
+ var membertpe: Type = null
+ while (continue) {
+ continue = false
+ val bcs0 = baseClasses
+ var bcs = bcs0
+ while (!bcs.isEmpty) {
+ val decls = bcs.head.info.decls
+ var entry = decls.elems
+ while (entry ne null) {
+ val sym = entry.sym
+ if (sym hasAllFlags requiredFlags) {
+ val excl = sym.getFlag(excluded)
+ if (excl == 0L &&
+ (// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
+ (bcs eq bcs0) ||
+ !sym.isPrivateLocal ||
+ (bcs0.head.hasTransOwner(bcs.head)))) {
+ if (members eq null) members = newScope
+ var prevEntry = members.lookupEntry(sym.name)
+ var symtpe: Type = null
+ while ((prevEntry ne null) &&
+ !((prevEntry.sym eq sym) ||
+ (prevEntry.sym.owner ne sym.owner) &&
+ !sym.hasFlag(PRIVATE) && {
+ if (self eq null) self = this.narrow
+ if (symtpe eq null) symtpe = self.memberType(sym)
+ self.memberType(prevEntry.sym) matches symtpe
+ })) {
+ prevEntry = members lookupNextEntry prevEntry
+ }
+ if (prevEntry eq null) {
+ members enter sym
+ }
+ } else if (excl == DEFERRED) {
+ continue = true
+ }
+ }
+ entry = entry.next
+ } // while (entry ne null)
+ // excluded = excluded | LOCAL
+ bcs = bcs.tail
+ } // while (!bcs.isEmpty)
+ excluded = excludedFlags
+ } // while (continue)
+ Statistics.popTimer(typeOpsStack, start)
+ if (suspension ne null) suspension foreach (_.suspended = false)
+ if (members eq null) Nil else members.toList
+ }
/**
* Find member(s) in this type. If several members matching criteria are found, they are
@@ -1122,6 +1188,7 @@ trait Types extends api.Types { self: SymbolTable =>
baseClasses.head.newOverloaded(this, members.toList)
}
}
+
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
def skolemsExceptMethodTypeParams: List[Symbol] = {
var boundSyms: List[Symbol] = List()
@@ -6906,12 +6973,14 @@ object TypesStats {
val lubCount = Statistics.newCounter ("#toplevel lubs/glbs")
val nestedLubCount = Statistics.newCounter ("#all lubs/glbs")
val findMemberCount = Statistics.newCounter ("#findMember ops")
+ val findMembersCount = Statistics.newCounter ("#findMembers ops")
val noMemberCount = Statistics.newSubCounter(" of which not found", findMemberCount)
val multMemberCount = Statistics.newSubCounter(" of which multiple overloaded", findMemberCount)
val typerNanos = Statistics.newTimer ("time spent typechecking", "typer")
val lubNanos = Statistics.newStackableTimer("time spent in lubs", typerNanos)
val subtypeNanos = Statistics.newStackableTimer("time spent in <:<", typerNanos)
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
+ val findMembersNanos = Statistics.newStackableTimer("time spent in findmembers", 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)