Skip to content

Commit 04f0b65

Browse files
oderskyAdriaan Moors
authored and
Adriaan Moors
committed
Attempt #4 to optimize findMember
broke out findMembers as a separate operation to streamline the code. findMember itself still needs to be optimized.
1 parent 0e3c70f commit 04f0b65

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

src/reflect/scala/reflect/internal/Types.scala

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,8 @@ trait Types extends api.Types { self: SymbolTable =>
668668
* Note: unfortunately it doesn't work to exclude DEFERRED this way.
669669
*/
670670
def membersBasedOnFlags(excludedFlags: Long, requiredFlags: Long): List[Symbol] =
671-
findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
671+
findMembers(excludedFlags, requiredFlags)
672+
// findMember(nme.ANYNAME, excludedFlags, requiredFlags, false).alternatives
672673

673674
def memberBasedOnName(name: Name, excludedFlags: Long): Symbol =
674675
findMember(name, excludedFlags, 0, false)
@@ -1016,6 +1017,71 @@ trait Types extends api.Types { self: SymbolTable =>
10161017
if (alts.isEmpty) sym
10171018
else (baseClasses.head.newOverloaded(this, alts))
10181019
}
1020+
1021+
def findMembers(excludedFlags: Long, requiredFlags: Long): List[Symbol] = {
1022+
// if this type contains type variables, put them to sleep for a while -- don't just wipe them out by
1023+
// replacing them by the corresponding type parameter, as that messes up (e.g.) type variables in type refinements
1024+
// without this, the matchesType call would lead to type variables on both sides
1025+
// of a subtyping/equality judgement, which can lead to recursive types being constructed.
1026+
// See (t0851) for a situation where this happens.
1027+
val suspension: List[TypeVar] = if (this.isGround) null else suspendTypeVarsInType(this)
1028+
1029+
Statistics.incCounter(findMembersCount)
1030+
val start = Statistics.pushTimer(typeOpsStack, findMembersNanos)
1031+
1032+
//Console.println("find member " + name.decode + " in " + this + ":" + this.baseClasses)//DEBUG
1033+
var members: Scope = null
1034+
var excluded = excludedFlags | DEFERRED
1035+
var continue = true
1036+
var self: Type = null
1037+
var membertpe: Type = null
1038+
while (continue) {
1039+
continue = false
1040+
val bcs0 = baseClasses
1041+
var bcs = bcs0
1042+
while (!bcs.isEmpty) {
1043+
val decls = bcs.head.info.decls
1044+
var entry = decls.elems
1045+
while (entry ne null) {
1046+
val sym = entry.sym
1047+
if (sym hasAllFlags requiredFlags) {
1048+
val excl = sym.getFlag(excluded)
1049+
if (excl == 0L &&
1050+
(// omit PRIVATE LOCALS unless selector class is contained in class owning the def.
1051+
(bcs eq bcs0) ||
1052+
!sym.isPrivateLocal ||
1053+
(bcs0.head.hasTransOwner(bcs.head)))) {
1054+
if (members eq null) members = newScope
1055+
var prevEntry = members.lookupEntry(sym.name)
1056+
var symtpe: Type = null
1057+
while ((prevEntry ne null) &&
1058+
!((prevEntry.sym eq sym) ||
1059+
(prevEntry.sym.owner ne sym.owner) &&
1060+
!sym.hasFlag(PRIVATE) && {
1061+
if (self eq null) self = this.narrow
1062+
if (symtpe eq null) symtpe = self.memberType(sym)
1063+
self.memberType(prevEntry.sym) matches symtpe
1064+
})) {
1065+
prevEntry = members lookupNextEntry prevEntry
1066+
}
1067+
if (prevEntry eq null) {
1068+
members enter sym
1069+
}
1070+
} else if (excl == DEFERRED) {
1071+
continue = true
1072+
}
1073+
}
1074+
entry = entry.next
1075+
} // while (entry ne null)
1076+
// excluded = excluded | LOCAL
1077+
bcs = bcs.tail
1078+
} // while (!bcs.isEmpty)
1079+
excluded = excludedFlags
1080+
} // while (continue)
1081+
Statistics.popTimer(typeOpsStack, start)
1082+
if (suspension ne null) suspension foreach (_.suspended = false)
1083+
if (members eq null) Nil else members.toList
1084+
}
10191085

10201086
/**
10211087
* 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 =>
11221188
baseClasses.head.newOverloaded(this, members.toList)
11231189
}
11241190
}
1191+
11251192
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
11261193
def skolemsExceptMethodTypeParams: List[Symbol] = {
11271194
var boundSyms: List[Symbol] = List()
@@ -6906,12 +6973,14 @@ object TypesStats {
69066973
val lubCount = Statistics.newCounter ("#toplevel lubs/glbs")
69076974
val nestedLubCount = Statistics.newCounter ("#all lubs/glbs")
69086975
val findMemberCount = Statistics.newCounter ("#findMember ops")
6976+
val findMembersCount = Statistics.newCounter ("#findMembers ops")
69096977
val noMemberCount = Statistics.newSubCounter(" of which not found", findMemberCount)
69106978
val multMemberCount = Statistics.newSubCounter(" of which multiple overloaded", findMemberCount)
69116979
val typerNanos = Statistics.newTimer ("time spent typechecking", "typer")
69126980
val lubNanos = Statistics.newStackableTimer("time spent in lubs", typerNanos)
69136981
val subtypeNanos = Statistics.newStackableTimer("time spent in <:<", typerNanos)
69146982
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
6983+
val findMembersNanos = Statistics.newStackableTimer("time spent in findmembers", typerNanos)
69156984
val asSeenFromNanos = Statistics.newStackableTimer("time spent in asSeenFrom", typerNanos)
69166985
val baseTypeSeqNanos = Statistics.newStackableTimer("time spent in baseTypeSeq", typerNanos)
69176986
val baseClassesNanos = Statistics.newStackableTimer("time spent in baseClasses", typerNanos)

0 commit comments

Comments
 (0)