Optimise pickBestCandidate: reduce heap allocations.

This commit is contained in:
Matthew Baulch 2016-08-21 12:41:55 +10:00
commit b0c12a7dc4

View file

@ -40,44 +40,31 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
filter: TSymKinds, filter: TSymKinds,
best, alt: var TCandidate, best, alt: var TCandidate,
errors: var CandidateErrors) = errors: var CandidateErrors) =
while true:
block pickAttempt:
var o: TOverloadIter var o: TOverloadIter
# thanks to the lazy semchecking for operands, we need to iterate over the var sym = initOverloadIter(o, c, headSymbol)
# symbol table *before* any call to 'initCandidate' which might invoke # Thanks to the lazy semchecking for operands, we need to check whether
# semExpr which might modify the symbol table in cases like # 'initCandidate' modifies the symbol table (via semExpr).
# 'init(a, 1, (var b = new(Type2); b))'. # This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
var symx = initOverloadIter(o, c, headSymbol) let counterInitial = c.currentScope.symbols.counter
let symScope = o.lastOverloadScope # Initialise 'best' and 'alt' with the first available symbol
while sym != nil:
var syms: seq[tuple[a: PSym, b: int]] = @[] if sym.kind in filter:
while symx != nil: initCandidate(c, best, sym, initialBinding, o.lastOverloadScope)
if symx.kind in filter: initCandidate(c, alt, sym, initialBinding, o.lastOverloadScope)
syms.add((symx, o.lastOverloadScope))
symx = nextOverloadIter(o, c, headSymbol)
if syms.len == 0:
when false:
if skIterator notin filter:
# also try iterators, but these are 2nd class:
symx = initOverloadIter(o, c, headSymbol)
while symx != nil:
if symx.kind == skIterator:
syms.add((symx, 100))
symx = nextOverloadIter(o, c, headSymbol)
if syms.len == 0: return
else:
return
var z: TCandidate
initCandidate(c, best, syms[0][0], initialBinding, symScope)
initCandidate(c, alt, syms[0][0], initialBinding, symScope)
best.state = csNoMatch best.state = csNoMatch
break
for i in 0 .. <syms.len: else:
let sym = syms[i][0] sym = nextOverloadIter(o, c, headSymbol)
var z: TCandidate
while sym != nil:
if sym.kind notin filter:
sym = nextOverloadIter(o, c, headSymbol)
continue
determineType(c, sym) determineType(c, sym)
initCandidate(c, z, sym, initialBinding, syms[i][1]) initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
if c.currentScope.symbols.counter != counterInitial: break pickAttempt
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
# gDebug = true
matches(c, n, orig, z) matches(c, n, orig, z)
if errors != nil: if errors != nil:
errors.safeAdd((sym, int z.mutabilityProblem)) errors.safeAdd((sym, int z.mutabilityProblem))
@ -94,13 +81,8 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
if cmp < 0: best = z # x is better than the best so far if cmp < 0: best = z # x is better than the best so far
elif cmp == 0: alt = z # x is as good as the best so far elif cmp == 0: alt = z # x is as good as the best so far
else: discard else: discard
#if sym.name.s == "cmp" and (n.info ?? "rstgen.nim") and n.info.line == 516: sym = nextOverloadIter(o, c, headSymbol)
# echo "Matches ", n.info, " ", typeToString(sym.typ) break # pick attempt was successful
# debug sym
# writeMatches(z)
# for i in 1 .. <len(z.call):
# z.call[i].typ.debug
# quit 1
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
# Gives a detailed error message; this is separated from semOverloadedCall, # Gives a detailed error message; this is separated from semOverloadedCall,