diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-08-25 16:35:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-08-25 16:35:33 +0200 |
commit | 56c31a51d0fe15b3e039701b99fbe869fe933d11 (patch) | |
tree | b8e582c6a31b4567ccfb093bc8e6fe901a899e40 | |
parent | f1e4d8ed74549a868be58c15fc8cfe04159c52fd (diff) | |
parent | b0c12a7dc4065372960a696907947812b4c01e0d (diff) | |
download | Nim-56c31a51d0fe15b3e039701b99fbe869fe933d11.tar.gz |
Merge pull request #4633 from mbaulch/pickbestcand_faster_inlined
Optimise pickBestCandidate: reduce heap allocations.
-rw-r--r-- | compiler/semcall.nim | 104 |
1 files changed, 43 insertions, 61 deletions
diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 97209167d..b83872fe9 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -40,67 +40,49 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, filter: TSymKinds, best, alt: var TCandidate, errors: var CandidateErrors) = - var o: TOverloadIter - # thanks to the lazy semchecking for operands, we need to iterate over the - # symbol table *before* any call to 'initCandidate' which might invoke - # semExpr which might modify the symbol table in cases like - # 'init(a, 1, (var b = new(Type2); b))'. - var symx = initOverloadIter(o, c, headSymbol) - let symScope = o.lastOverloadScope - - var syms: seq[tuple[a: PSym, b: int]] = @[] - while symx != nil: - if symx.kind in filter: - 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 - - for i in 0 .. <syms.len: - let sym = syms[i][0] - determineType(c, sym) - initCandidate(c, z, sym, initialBinding, syms[i][1]) - - #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140: - # gDebug = true - matches(c, n, orig, z) - if errors != nil: - errors.safeAdd((sym, int z.mutabilityProblem)) - if z.errors != nil: - for err in z.errors: - 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 + while true: + block pickAttempt: + var o: TOverloadIter + var sym = initOverloadIter(o, c, headSymbol) + # Thanks to the lazy semchecking for operands, we need to check whether + # 'initCandidate' modifies the symbol table (via semExpr). + # This can occur in cases like 'init(a, 1, (var b = new(Type2); b))' + let counterInitial = c.currentScope.symbols.counter + # Initialise 'best' and 'alt' with the first available symbol + while sym != nil: + if sym.kind in filter: + initCandidate(c, best, sym, initialBinding, o.lastOverloadScope) + initCandidate(c, alt, sym, initialBinding, o.lastOverloadScope) + best.state = csNoMatch + break + else: + 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) + initCandidate(c, z, sym, initialBinding, o.lastOverloadScope) + if c.currentScope.symbols.counter != counterInitial: break pickAttempt + matches(c, n, orig, z) + if errors != nil: + errors.safeAdd((sym, int z.mutabilityProblem)) + if z.errors != nil: + for err in z.errors: + 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 + sym = nextOverloadIter(o, c, headSymbol) + break # pick attempt was successful proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = # Gives a detailed error message; this is separated from semOverloadedCall, |