Skip to content

Commit f58e721

Browse files
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 e045ba3 commit f58e721

File tree

1 file changed

+70
-1
lines changed

1 file changed

+70
-1
lines changed

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

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

10211087
/**
10221088
* Find member(s) in this type. If several members matching criteria are found, they are
@@ -1123,6 +1189,7 @@ trait Types extends api.Types { self: SymbolTable =>
11231189
baseClasses.head.newOverloaded(this, members.toList)
11241190
}
11251191
}
1192+
11261193
/** The (existential or otherwise) skolems and existentially quantified variables which are free in this type */
11271194
def skolemsExceptMethodTypeParams: List[Symbol] = {
11281195
var boundSyms: List[Symbol] = List()
@@ -6917,12 +6984,14 @@ object TypesStats {
69176984
val lubCount = Statistics.newCounter ("#toplevel lubs/glbs")
69186985
val nestedLubCount = Statistics.newCounter ("#all lubs/glbs")
69196986
val findMemberCount = Statistics.newCounter ("#findMember ops")
6987+
val findMembersCount = Statistics.newCounter ("#findMembers ops")
69206988
val noMemberCount = Statistics.newSubCounter(" of which not found", findMemberCount)
69216989
val multMemberCount = Statistics.newSubCounter(" of which multiple overloaded", findMemberCount)
69226990
val typerNanos = Statistics.newTimer ("time spent typechecking", "typer")
69236991
val lubNanos = Statistics.newStackableTimer("time spent in lubs", typerNanos)
69246992
val subtypeNanos = Statistics.newStackableTimer("time spent in <:<", typerNanos)
69256993
val findMemberNanos = Statistics.newStackableTimer("time spent in findmember", typerNanos)
6994+
val findMembersNanos = Statistics.newStackableTimer("time spent in findmembers", typerNanos)
69266995
val asSeenFromNanos = Statistics.newStackableTimer("time spent in asSeenFrom", typerNanos)
69276996
val baseTypeSeqNanos = Statistics.newStackableTimer("time spent in baseTypeSeq", typerNanos)
69286997
val baseClassesNanos = Statistics.newStackableTimer("time spent in baseClasses", typerNanos)

0 commit comments

Comments
 (0)