diff options
author | Araq <rumpf_a@web.de> | 2013-06-28 23:36:43 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-06-28 23:36:43 +0200 |
commit | a8542fbe0654d2236dc25eb42c111b470416b82e (patch) | |
tree | 257db5584d1388d538c1056e65699795578282b7 | |
parent | 976d5b18edf1e650db21c4f5e6990c037ed305a7 (diff) | |
download | Nim-a8542fbe0654d2236dc25eb42c111b470416b82e.tar.gz |
some small performance improvement for the evaluator
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/evals.nim | 89 | ||||
-rw-r--r-- | compiler/transf.nim | 29 |
3 files changed, 69 insertions, 50 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index eee1e1ad2..3456177d3 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -666,6 +666,7 @@ type # (or not in symbol table) # for modules, an unique index corresponding # to the module's fileIdx + # for variables a slot index for the evaluator offset*: int # offset of record field loc*: TLoc diff --git a/compiler/evals.nim b/compiler/evals.nim index 8c05d57fc..1689a37d8 100644 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -23,12 +23,12 @@ when hasFFI: type PStackFrame* = ref TStackFrame - TStackFrame*{.final.} = object - mapping*: TIdNodeTable # mapping from symbols to nodes - prc*: PSym # current prc; proc that is evaluated - call*: PNode - next*: PStackFrame # for stacking - params*: TNodeSeq # parameters passed to the proc + TStackFrame* = object + prc: PSym # current prc; proc that is evaluated + slots: TNodeSeq # parameters passed to the proc + locals; + # parameters come first + call: PNode + next: PStackFrame # for stacking TEvalMode* = enum ## reason for evaluation emRepl, ## evaluate because in REPL mode @@ -67,10 +67,9 @@ const # other idea: use a timeout! -> Wether code compiles depends on the machine # the compiler runs on then! Bad idea! -proc newStackFrame*(): PStackFrame = +proc newStackFrame*(): PStackFrame = new(result) - initIdNodeTable(result.mapping) - result.params = @[] + result.slots = @[] proc newEvalContext*(module: PSym, mode: TEvalMode): PEvalContext = new(result) @@ -291,6 +290,20 @@ proc evalVarValue(c: PEvalContext, n: PNode): PNode = result = evalAux(c, n, {}) if result.kind in {nkType..nkNilLit}: result = result.copyNode +proc setSlot(c: PStackFrame, sym: PSym, val: PNode) = + assert sym.owner == c.prc + var idx = sym.position + if idx == 0: + idx = c.slots.len + if idx == 0: idx = 1 + sym.position = idx + setLen(c.slots, max(idx+1, c.slots.len)) + c.slots[idx] = val + +proc setVar(c: PEvalContext, v: PSym, n: PNode) = + if sfGlobal notin v.flags: setSlot(c.tos, v, n) + else: IdNodeTablePut(c.globals, v, n) + proc evalVar(c: PEvalContext, n: PNode): PNode = for i in countup(0, sonsLen(n) - 1): let a = n.sons[i] @@ -305,7 +318,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode = return raiseCannotEval(c, n.info) for i in 0 .. a.len-3: var v = a.sons[i].sym - IdNodeTablePut(c.tos.mapping, v, result.sons[i]) + setVar(c, v, result.sons[i]) else: if a.sons[2].kind != nkEmpty: result = evalVarValue(c, a.sons[2]) @@ -314,7 +327,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode = result = getNullValue(a.sons[0].typ, a.sons[0].info) if a.sons[0].kind == nkSym: var v = a.sons[0].sym - IdNodeTablePut(c.tos.mapping, v, result) + setVar(c, v, result) else: # assign to a.sons[0]: var x = result @@ -339,21 +352,22 @@ proc aliasNeeded(n: PNode, flags: TEvalFlags): bool = result = efLValue in flags or n.typ == nil or n.typ.kind in {tyExpr, tyStmt, tyTypeDesc} -proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode = +proc evalVariable(c: PStackFrame, sym: PSym, flags: TEvalFlags): PNode = # We need to return a node to the actual value, # which can be modified. + assert sym.position != 0 or skResult == sym.kind var x = c - while x != nil: - if sym.kind == skResult and x.params.len > 0: - result = x.params[0] - if result == nil: result = emptyNode + while x != nil: + if sym.owner == c.prc: + result = x.slots[sym.position] + assert result != nil + if not aliasNeeded(result, flags): + result = copyTree(result) return - result = IdNodeTableGet(x.mapping, sym) - if result != nil and not aliasNeeded(result, flags): - result = copyTree(result) - if result != nil: return x = x.next - #internalError(sym.info, "cannot eval " & sym.name.s) + debug sym.owner + debug c.prc + internalError(sym.info, "cannot eval " & sym.name.s & " " & $sym.position) result = raiseCannotEval(nil, sym.info) #result = emptyNode @@ -385,12 +399,12 @@ proc evalCall(c: PEvalContext, n: PNode): PNode = d.call = n var prc = n.sons[0] let isClosure = prc.kind == nkClosure - setlen(d.params, sonsLen(n) + ord(isClosure)) + setlen(d.slots, sonsLen(n) + ord(isClosure)) if isClosure: #debug prc result = evalAux(c, prc.sons[1], {efLValue}) if isSpecial(result): return - d.params[sonsLen(n)] = result + d.slots[sonsLen(n)] = result result = evalAux(c, prc.sons[0], {}) else: result = evalAux(c, prc, {}) @@ -408,21 +422,21 @@ proc evalCall(c: PEvalContext, n: PNode): PNode = for i in countup(1, sonsLen(n) - 1): result = evalAux(c, n.sons[i], {}) if isSpecial(result): return - d.params[i] = result - if n.typ != nil: d.params[0] = getNullValue(n.typ, n.info) + d.slots[i] = result + if n.typ != nil: d.slots[0] = getNullValue(n.typ, n.info) when hasFFI: if sfImportc in prc.sym.flags and allowFFI in c.features: var newCall = newNodeI(nkCall, n.info, n.len) newCall.sons[0] = evalGlobalVar(c, prc.sym, {}) for i in 1 .. <n.len: - newCall.sons[i] = d.params[i] + newCall.sons[i] = d.slots[i] return callForeignFunction(newCall) pushStackFrame(c, d) result = evalAux(c, prc.sym.getBody, {}) if result.kind == nkExceptBranch: return - if n.typ != nil: result = d.params[0] + if n.typ != nil: result = d.slots[0] popStackFrame(c) proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = @@ -564,8 +578,8 @@ proc evalSym(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = evalGlobalVar(c, s, flags) of skParam: # XXX what about LValue? - if s.position + 1 <% c.tos.params.len: - result = c.tos.params[s.position + 1] + if s.position + 1 <% c.tos.slots.len: + result = c.tos.slots[s.position + 1] of skConst: result = s.ast of skEnumField: result = newIntNodeT(s.position, n) else: result = nil @@ -750,10 +764,12 @@ proc evalProc(c: PEvalContext, n: PNode): PNode = if (resultPos < sonsLen(n)) and (n.sons[resultPos].kind != nkEmpty): var v = n.sons[resultPos].sym result = getNullValue(v.typ, n.info) - IdNodeTablePut(c.tos.mapping, v, result) + if c.tos.slots.len == 0: setLen(c.tos.slots, 1) + c.tos.slots[0] = result + #IdNodeTablePut(c.tos.mapping, v, result) result = evalAux(c, s.getBody, {}) - if result.kind == nkReturnToken: - result = IdNodeTableGet(c.tos.mapping, v) + if result.kind == nkReturnToken: + result = c.tos.slots[0] else: result = evalAux(c, s.getBody, {}) if result.kind == nkReturnToken: @@ -1507,16 +1523,17 @@ proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode = c.callsite = nOrig var s = newStackFrame() s.call = n + s.prc = sym var L = n.safeLen if L == 0: L = 1 - setlen(s.params, L) + setlen(s.slots, L) # return value: - s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0]) + s.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0]) # setup parameters: - for i in 1 .. < L: s.params[i] = setupMacroParam(n.sons[i]) + for i in 1 .. < L: s.slots[i] = setupMacroParam(n.sons[i]) pushStackFrame(c, s) discard eval(c, sym.getBody) - result = s.params[0] + result = s.slots[0] popStackFrame(c) if cyclicTree(result): GlobalError(n.info, errCyclicTree) dec(evalTemplateCounter) diff --git a/compiler/transf.nim b/compiler/transf.nim index a35669e1d..82122d776 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -417,6 +417,15 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto = if skipTypes(formal, abstractInst).kind == tyVar: result = paVarAsgn else: result = paFastAsgn +proc findWrongOwners(c: PTransf, n: PNode) = + if n.kind == nkVarSection: + let x = n.sons[0].sons[0] + if x.kind == nkSym and x.sym.owner != getCurrOwner(c): + internalError(x.info, "bah " & x.sym.name.s & " " & + x.sym.owner.name.s & " " & getCurrOwner(c).name.s) + else: + for i in 0 .. <safeLen(n): findWrongOwners(c, n.sons[i]) + proc transformFor(c: PTransf, n: PNode): PTransNode = # generate access statements for the parameters (unless they are constant) # put mapping from formal parameters to actual parameters @@ -468,6 +477,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = pushInfoContext(n.info) inc(c.inlining) add(result, transform(c, body)) + #findWrongOwners(c, result.pnode) dec(c.inlining) popInfoContext() popTransCon(c) @@ -675,12 +685,12 @@ proc transform(c: PTransf, n: PNode): PTransNode = if cnst != nil and not dontInlineConstant(n, cnst): result = PTransNode(cnst) # do not miss an optimization -proc processTransf(c: PTransf, n: PNode): PNode = +proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode = # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip # this step! We have to rely that the semantic pass transforms too errornous # nodes into an empty node. if passes.skipCodegen(n) or c.fromCache or nfTransf in n.flags: return n - pushTransCon(c, newTransCon(getCurrOwner(c))) + pushTransCon(c, newTransCon(owner)) result = PNode(transform(c, n)) popTransCon(c) incl(result.flags, nfTransf) @@ -691,22 +701,13 @@ proc openTransf(module: PSym, filename: string): PTransf = result.breakSyms = @[] result.module = module -when false: - proc openTransfCached(module: PSym, filename: string, - rd: PRodReader): PPassContext = - result = openTransf(module, filename) - for m in items(rd.methods): methodDef(m, true) - - const transfPass* = makePass(openTransf, openTransfCached, - processTransf, processTransf) # we need to process generics too! - proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = if nfTransf in n.flags or prc.kind in {skTemplate, skMacro}: result = n else: #when useEffectSystem: trackProc(prc, n) var c = openTransf(module, "") - result = processTransf(c, n) + result = processTransf(c, n, prc) if prc.kind != skMacro: # XXX no closures yet for macros: result = liftLambdas(prc, result) @@ -720,7 +721,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode = result = n else: var c = openTransf(module, "") - result = processTransf(c, n) + result = processTransf(c, n, module) result = liftLambdasForTopLevel(module, result) incl(result.flags, nfTransf) @@ -729,5 +730,5 @@ proc transformExpr*(module: PSym, n: PNode): PNode = result = n else: var c = openTransf(module, "") - result = processTransf(c, n) + result = processTransf(c, n, module) incl(result.flags, nfTransf) |