diff options
author | Araq <rumpf_a@web.de> | 2013-02-14 08:41:48 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-02-14 08:41:48 +0100 |
commit | 1c0c80ef2dba09bb50c470a013f3bdb9391620a7 (patch) | |
tree | 66011812d64f1f2f3c933d601ca72d647302c274 | |
parent | 0f2aa053d9e9bcbe67238c498ed96f27c8d737db (diff) | |
download | Nim-1c0c80ef2dba09bb50c470a013f3bdb9391620a7.tar.gz |
micro optimizations for the evaluation engine
-rwxr-xr-x | compiler/ast.nim | 10 | ||||
-rwxr-xr-x | compiler/evals.nim | 70 | ||||
-rw-r--r-- | doc/gc.txt | 16 | ||||
-rwxr-xr-x | lib/core/macros.nim | 11 |
4 files changed, 64 insertions, 43 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 107489094..4fa3617d7 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -71,20 +71,23 @@ type nkDotCall, # used to temporarily flag a nkCall node; # this is used # for transforming ``s.len`` to ``len(s)`` + nkCommand, # a call like ``p 2, 4`` without parenthesis nkCall, # a call like p(x, y) or an operation like +(a, b) nkCallStrLit, # a call with a string literal # x"abc" has two sons: nkIdent, nkRStrLit # x"""abc""" has two sons: nkIdent, nkTripleStrLit + nkInfix, # a call like (a + b) + nkPrefix, # a call like !a + nkPostfix, # something like a! (also used for visibility) + nkHiddenCallConv, # an implicit type conversion via a type converter + nkExprEqExpr, # a named parameter with equals: ''expr = expr'' nkExprColonExpr, # a named parameter with colon: ''expr: expr'' nkIdentDefs, # a definition like `a, b: typeDesc = expr` # either typeDesc or expr may be nil; used in # formal parameters, var statements, etc. nkVarTuple, # a ``var (a, b) = expr`` construct - nkInfix, # a call like (a + b) - nkPrefix, # a call like !a - nkPostfix, # something like a! (also used for visibility) nkPar, # syntactic (); may be a tuple constructor nkCurly, # syntactic {} nkCurlyExpr, # an expression like a{i} @@ -109,7 +112,6 @@ type nkHiddenStdConv, # an implicit standard type conversion nkHiddenSubConv, # an implicit type conversion from a subtype # to a supertype - nkHiddenCallConv, # an implicit type conversion via a type converter nkConv, # a type conversion nkCast, # a type cast nkStaticExpr, # a static expr diff --git a/compiler/evals.nim b/compiler/evals.nim index 4b83cb703..c6e0e947f 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -444,29 +444,35 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = stackTrace(c, n, errIndexOutOfBounds) else: stackTrace(c, n, errNilAccess) -proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = +proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = # a real field access; proc calls have already been transformed # XXX: field checks! result = evalAux(c, n.sons[0], flags) - if isSpecial(result): return + if isSpecial(result): return var x = result if x.kind != nkPar: return raiseCannotEval(c, n.info) + # this is performance critical: var field = n.sons[1].sym - for i in countup(0, sonsLen(x) - 1): - var it = x.sons[i] - if it.kind != nkExprColonExpr: - # lookup per index: - result = x.sons[field.position] - if result.kind == nkExprColonExpr: result = result.sons[1] - if not aliasNeeded(result, flags): result = copyTree(result) - return - #InternalError(it.info, "evalFieldAccess") - if it.sons[0].sym.name.id == field.name.id: - result = x.sons[i].sons[1] - if not aliasNeeded(result, flags): result = copyTree(result) - return - stackTrace(c, n, errFieldXNotFound, field.name.s) - result = emptyNode + result = x.sons[field.position] + if result.kind == nkExprColonExpr: result = result.sons[1] + if not aliasNeeded(result, flags): result = copyTree(result) + when false: + var field = n.sons[1].sym + for i in countup(0, sonsLen(x) - 1): + var it = x.sons[i] + if it.kind != nkExprColonExpr: + # lookup per index: + result = x.sons[field.position] + if result.kind == nkExprColonExpr: result = result.sons[1] + if not aliasNeeded(result, flags): result = copyTree(result) + return + #InternalError(it.info, "evalFieldAccess") + if it.sons[0].sym.name.id == field.name.id: + result = x.sons[i].sons[1] + if not aliasNeeded(result, flags): result = copyTree(result) + return + stackTrace(c, n, errFieldXNotFound, field.name.s) + result = emptyNode proc evalAsgn(c: PEvalContext, n: PNode): PNode = var a = n.sons[0] @@ -1341,14 +1347,23 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = emptyNode dec(gNestedEvals) if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations) - case n.kind # atoms: - of nkEmpty: result = n + case n.kind of nkSym: result = evalSym(c, n, flags) - of nkType..nkNilLit: result = copyNode(n) # end of atoms - of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkInfix, - nkPrefix, nkPostfix: + of nkType..nkNilLit: + # XXX nkStrLit is VERY common in the traces, so we should avoid + # the 'copyNode' here. However, for now we cannot do this for unknown + # reasons. + result = n.copyNode + of nkAsgn, nkFastAsgn: result = evalAsgn(c, n) + of nkCommand..nkHiddenCallConv: result = evalMagicOrCall(c, n) - of nkCurly, nkBracket, nkRange: + of nkDotExpr: result = evalFieldAccess(c, n, flags) + of nkBracketExpr: + result = evalArrayAccess(c, n, flags) + of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags) + of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags) + of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n) + of nkCurly, nkBracket, nkRange: # flags need to be passed here for mNAddMultiple :-( # XXX this is not correct in every case! var a = copyNode(n) @@ -1370,12 +1385,6 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = if isSpecial(result): return a.sons[i] = result result = a - of nkBracketExpr: result = evalArrayAccess(c, n, flags) - of nkDotExpr: result = evalFieldAccess(c, n, flags) - of nkDerefExpr, nkHiddenDeref: result = evalDeref(c, n, flags) - of nkAddr, nkHiddenAddr: result = evalAddr(c, n, flags) - of nkHiddenStdConv, nkHiddenSubConv, nkConv: result = evalConv(c, n) - of nkAsgn, nkFastAsgn: result = evalAsgn(c, n) of nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n) of nkWhileStmt: result = evalWhile(c, n) of nkCaseStmt: result = evalCase(c, n) @@ -1414,6 +1423,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode = result = raiseCannotEval(c, n.info) of nkRefTy: result = evalAux(c, n.sons[0], flags) + of nkEmpty: + # nkEmpty occurs once in each trace that I looked at + result = n else: InternalError(n.info, "evalAux: " & $n.kind) if result == nil: InternalError(n.info, "evalAux: returned nil " & $n.kind) diff --git a/doc/gc.txt b/doc/gc.txt index 975a89308..854f9ce2a 100644 --- a/doc/gc.txt +++ b/doc/gc.txt @@ -22,6 +22,13 @@ delta-subgraph of the heap that changed since its last run. The GC is only triggered in a memory allocation operation. It it not triggered by some timer and does not run in a background thread. +To force a full collection call ``GC_fullCollect``. Note that it is generally +better to let the GC do its work and not enforce a full collection. + + +Cycle collector +=============== + The cycle collector can be en-/disabled independently from the other parts of the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The compiler analyses the types for their possibility to build cycles, but often @@ -30,11 +37,10 @@ it is necessary to help this analysis with the ``acyclic`` pragma (see You can also use the ``acyclic`` pragma for data that is cyclic in reality and then break up the cycles explicitly with ``GC_addCycleRoot``. This can be a -very good optimization; the Nimrod compiler itself relies on this optimization -trick to improve performance. - -To force a full collection call ``GC_fullCollect``. Note that it is generally -better to let the GC do its work and not enforce a full collection. +very valuable optimization; the Nimrod compiler itself relies on this +optimization trick to improve performance. Note that ``GC_addCycleRoot`` is +a quick operation; the root is only registered for the next run of the +cycle collector. Realtime support diff --git a/lib/core/macros.nim b/lib/core/macros.nim index bf7510a92..b72279777 100755 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2013 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -21,9 +21,10 @@ type nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit, nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit, nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall, - nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr, - nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix, - nnkPrefix, nnkPostfix, nnkPar, nnkCurly, nnkCurlyExpr, + nnkCommand, nnkCall, nnkCallStrLit, nnkInfix, + nnkPrefix, nnkPostfix, nnkHiddenCallConv, + nnkExprEqExpr, + nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkPar, nnkCurly, nnkCurlyExpr, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted, @@ -31,7 +32,7 @@ type nnkClosedSymChoice, nnkOpenSymChoice, nnkHiddenStdConv, - nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkStaticExpr, + nnkHiddenSubConv, nnkConv, nnkCast, nnkStaticExpr, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString, nnkAsgn, |