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