--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cgen/templates/FastPyFunctionDoCallDerivative Thu Apr 26 11:08:47 2012 -0700 @@ -0,0 +1,68 @@ +<%namespace file="base.impl" import="*"/>\ + + TARGET(FAST_PYFUN_DOCALL_${ arity_str(instr) }) + { + if (oparg != ${ instr.arity() }) goto TARGET_CALL_FUNCTION_SKIP_DISPATCH; + + % for operand,accessor in get_enumerated_args(instr.arity()): + ${operand}= ${accessor}(); + % endfor + + /* guard against inline cache misses */ + if (PyMethod_Check(v) && PyMethod_GET_SELF(v) != NULL) { + ${ dbg_inf_ic_miss(instr) } + goto TARGET_CALL_FUNCTION_SKIP_DISPATCH; + } // if + if (PyFunction_Check(v) || PyCFunction_Check(v)) { + ${ dbg_inf_ic_miss(instr) } + goto TARGET_CALL_FUNCTION_SKIP_DISPATCH; + } // if + register ternaryfunc call= v->ob_type->tp_call; + if (call == NULL) + goto TARGET_CALL_FUNCTION_SKIP_DISPATCH; + + % if instr.arity() > 0: + STACKADJ(-${ instr.arity() }); + % endif + ${ dbg_inf_ic_hit(instr) } + + register PyObject *args= PyTuple_New( ${ instr.arity() } ); +<% ## pass arguments... + i= 0 + revargs= get_enumerated_args(instr.arity()) + revargs.reverse() +%>\ + % for operand, accessor in revargs: + % if operand != 'v': + PyTuple_SET_ITEM(args, ${i}, ${operand}); + <% i+= 1 %>\ + % endif + % endfor + + if (Py_EnterRecursiveCall(" while calling a Python object")) { + x= NULL; + SET_TOP(x); + break; + } // if + + x= (*call)(v, args, NULL); + + Py_LeaveRecursiveCall(); + + if (x == NULL && !PyErr_Occurred()) + PyErr_SetString(PyExc_SystemError, "NULL result without error in PyObject_Call"); + + ## use recursive freeing of tuple container to eliminate + ## the reference counts increased by the argument loading + ## instructions... + Py_XDECREF( args ); + + ## explicit freeing of the code object is necessary... + Py_DECREF(v); + + ## stack management and dispatch... + ${ push_result() } + ${ dispatch() } + } + +