micro optimizations for the evaluation engine
This commit is contained in:
parent
0f2aa053d9
commit
1c0c80ef2d
4 changed files with 64 additions and 43 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -451,22 +451,28 @@ proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
|
|||
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,13 +1347,22 @@ 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 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!
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
16
doc/gc.txt
16
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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue