mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-16 08:04:20 +00:00
micro optimizations for the evaluation engine
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user