micro optimizations for the evaluation engine

This commit is contained in:
Araq 2013-02-14 08:41:48 +01:00
commit 1c0c80ef2d
4 changed files with 64 additions and 43 deletions

View file

@ -71,20 +71,23 @@ type
nkDotCall, # used to temporarily flag a nkCall node; nkDotCall, # used to temporarily flag a nkCall node;
# this is used # this is used
# for transforming ``s.len`` to ``len(s)`` # for transforming ``s.len`` to ``len(s)``
nkCommand, # a call like ``p 2, 4`` without parenthesis nkCommand, # a call like ``p 2, 4`` without parenthesis
nkCall, # a call like p(x, y) or an operation like +(a, b) nkCall, # a call like p(x, y) or an operation like +(a, b)
nkCallStrLit, # a call with a string literal nkCallStrLit, # a call with a string literal
# x"abc" has two sons: nkIdent, nkRStrLit # x"abc" has two sons: nkIdent, nkRStrLit
# x"""abc""" has two sons: nkIdent, nkTripleStrLit # 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'' nkExprEqExpr, # a named parameter with equals: ''expr = expr''
nkExprColonExpr, # a named parameter with colon: ''expr: expr'' nkExprColonExpr, # a named parameter with colon: ''expr: expr''
nkIdentDefs, # a definition like `a, b: typeDesc = expr` nkIdentDefs, # a definition like `a, b: typeDesc = expr`
# either typeDesc or expr may be nil; used in # either typeDesc or expr may be nil; used in
# formal parameters, var statements, etc. # formal parameters, var statements, etc.
nkVarTuple, # a ``var (a, b) = expr`` construct 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 nkPar, # syntactic (); may be a tuple constructor
nkCurly, # syntactic {} nkCurly, # syntactic {}
nkCurlyExpr, # an expression like a{i} nkCurlyExpr, # an expression like a{i}
@ -109,7 +112,6 @@ type
nkHiddenStdConv, # an implicit standard type conversion nkHiddenStdConv, # an implicit standard type conversion
nkHiddenSubConv, # an implicit type conversion from a subtype nkHiddenSubConv, # an implicit type conversion from a subtype
# to a supertype # to a supertype
nkHiddenCallConv, # an implicit type conversion via a type converter
nkConv, # a type conversion nkConv, # a type conversion
nkCast, # a type cast nkCast, # a type cast
nkStaticExpr, # a static expr nkStaticExpr, # a static expr

View file

@ -451,22 +451,28 @@ proc evalFieldAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
if isSpecial(result): return if isSpecial(result): return
var x = result var x = result
if x.kind != nkPar: return raiseCannotEval(c, n.info) if x.kind != nkPar: return raiseCannotEval(c, n.info)
# this is performance critical:
var field = n.sons[1].sym var field = n.sons[1].sym
for i in countup(0, sonsLen(x) - 1): result = x.sons[field.position]
var it = x.sons[i] if result.kind == nkExprColonExpr: result = result.sons[1]
if it.kind != nkExprColonExpr: if not aliasNeeded(result, flags): result = copyTree(result)
# lookup per index: when false:
result = x.sons[field.position] var field = n.sons[1].sym
if result.kind == nkExprColonExpr: result = result.sons[1] for i in countup(0, sonsLen(x) - 1):
if not aliasNeeded(result, flags): result = copyTree(result) var it = x.sons[i]
return if it.kind != nkExprColonExpr:
#InternalError(it.info, "evalFieldAccess") # lookup per index:
if it.sons[0].sym.name.id == field.name.id: result = x.sons[field.position]
result = x.sons[i].sons[1] if result.kind == nkExprColonExpr: result = result.sons[1]
if not aliasNeeded(result, flags): result = copyTree(result) if not aliasNeeded(result, flags): result = copyTree(result)
return return
stackTrace(c, n, errFieldXNotFound, field.name.s) #InternalError(it.info, "evalFieldAccess")
result = emptyNode 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 = proc evalAsgn(c: PEvalContext, n: PNode): PNode =
var a = n.sons[0] var a = n.sons[0]
@ -1341,13 +1347,22 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
result = emptyNode result = emptyNode
dec(gNestedEvals) dec(gNestedEvals)
if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations) if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
case n.kind # atoms: case n.kind
of nkEmpty: result = n
of nkSym: result = evalSym(c, n, flags) of nkSym: result = evalSym(c, n, flags)
of nkType..nkNilLit: result = copyNode(n) # end of atoms of nkType..nkNilLit:
of nkCall, nkHiddenCallConv, nkCommand, nkCallStrLit, nkInfix, # XXX nkStrLit is VERY common in the traces, so we should avoid
nkPrefix, nkPostfix: # 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) 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: of nkCurly, nkBracket, nkRange:
# flags need to be passed here for mNAddMultiple :-( # flags need to be passed here for mNAddMultiple :-(
# XXX this is not correct in every case! # 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 if isSpecial(result): return
a.sons[i] = result a.sons[i] = result
result = a 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 nkWhenStmt, nkIfStmt, nkIfExpr: result = evalIf(c, n)
of nkWhileStmt: result = evalWhile(c, n) of nkWhileStmt: result = evalWhile(c, n)
of nkCaseStmt: result = evalCase(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) result = raiseCannotEval(c, n.info)
of nkRefTy: of nkRefTy:
result = evalAux(c, n.sons[0], flags) 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) else: InternalError(n.info, "evalAux: " & $n.kind)
if result == nil: if result == nil:
InternalError(n.info, "evalAux: returned nil " & $n.kind) InternalError(n.info, "evalAux: returned nil " & $n.kind)

View file

@ -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 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. 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 cycle collector can be en-/disabled independently from the other parts of
the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The the GC with ``GC_enableMarkAndSweep`` and ``GC_disableMarkAndSweep``. The
compiler analyses the types for their possibility to build cycles, but often 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 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 then break up the cycles explicitly with ``GC_addCycleRoot``. This can be a
very good optimization; the Nimrod compiler itself relies on this optimization very valuable optimization; the Nimrod compiler itself relies on this
trick to improve performance. optimization trick to improve performance. Note that ``GC_addCycleRoot`` is
a quick operation; the root is only registered for the next run of the
To force a full collection call ``GC_fullCollect``. Note that it is generally cycle collector.
better to let the GC do its work and not enforce a full collection.
Realtime support Realtime support

View file

@ -1,7 +1,7 @@
# #
# #
# Nimrod's Runtime Library # Nimrod's Runtime Library
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2013 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -21,9 +21,10 @@ type
nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit, nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit,
nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit, nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit,
nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall, nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall,
nnkCommand, nnkCall, nnkCallStrLit, nnkExprEqExpr, nnkCommand, nnkCall, nnkCallStrLit, nnkInfix,
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkInfix, nnkPrefix, nnkPostfix, nnkHiddenCallConv,
nnkPrefix, nnkPostfix, nnkPar, nnkCurly, nnkCurlyExpr, nnkExprEqExpr,
nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkPar, nnkCurly, nnkCurlyExpr,
nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange,
nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr,
nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted, nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted,
@ -31,7 +32,7 @@ type
nnkClosedSymChoice, nnkClosedSymChoice,
nnkOpenSymChoice, nnkOpenSymChoice,
nnkHiddenStdConv, nnkHiddenStdConv,
nnkHiddenSubConv, nnkHiddenCallConv, nnkConv, nnkCast, nnkStaticExpr, nnkHiddenSubConv, nnkConv, nnkCast, nnkStaticExpr,
nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv,
nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange,
nnkStringToCString, nnkCStringToString, nnkAsgn, nnkStringToCString, nnkCStringToString, nnkAsgn,