static PyObject * function_call(PyObject *func, PyObject *arg, PyObject *kw) { PyObject *result; PyObject *argdefs; PyObject *kwtuple = NULL; PyObject **d, **k; Py_ssize_t nk, nd; argdefs = PyFunction_GET_DEFAULTS(func); if (argdefs != NULL && PyTuple_Check(argdefs)) { d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0); nd = PyTuple_GET_SIZE(argdefs); } else { d = NULL; nd = 0; } if (kw != NULL && PyDict_Check(kw)) { Py_ssize_t pos, i; nk = PyDict_GET_SIZE(kw); kwtuple = PyTuple_New(2*nk); if (kwtuple == NULL) return NULL; k = &PyTuple_GET_ITEM(kwtuple, 0); pos = i = 0; while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); Py_INCREF(k[i+1]); i += 2; } nk = i/2; } else { k = NULL; nk = 0; } result = PyEval_EvalCodeEx( PyFunction_GET_CODE(func), PyFunction_GET_GLOBALS(func), (PyObject *)NULL, &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg), k, nk, d, nd, PyFunction_GET_KW_DEFAULTS(func), PyFunction_GET_CLOSURE(func)); Py_XDECREF(kwtuple); return result; }
static PyObject * fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject **d = NULL; int nd = 0; if (argdefs == NULL && co->co_argcount == n && nk==0 && co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { PyFrameObject *f; PyObject *retval = NULL; PyThreadState *tstate = PyThreadState_GET(); PyObject **fastlocals, **stack; int i; /* XXX Perhaps we should create a specialized PyFrame_New() that doesn't take locals, but does take builtins without sanity checking them. */ f = PyFrame_New(tstate, co, globals, NULL); if (f == NULL) return NULL; fastlocals = f->f_localsplus; stack = (*pp_stack) - n; for (i = 0; i < n; i++) { Py_INCREF(*stack); fastlocals[i] = *stack++; } retval = eval_frame(f); ++tstate->recursion_depth; Py_DECREF(f); --tstate->recursion_depth; return retval; } if (argdefs != NULL) { d = &PyTuple_GET_ITEM(argdefs, 0); nd = ((PyTupleObject *)argdefs)->ob_size; } return PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, (*pp_stack)-n, na, (*pp_stack)-2*nk, nk, d, nd, PyFunction_GET_CLOSURE(func)); }
DEFINEFN vinfo_t* pfunction_simple_call(PsycoObject* po, PyObject* f, vinfo_t* arg, bool allow_inline) { PyObject* glob; PyObject* defl; PyCodeObject* co; vinfo_t* fglobals; vinfo_t* fdefaults; vinfo_t* result; int saved_inlining; /* XXX we capture the code object, so this breaks if someone changes the .func_code attribute of the function later */ co = (PyCodeObject*) PyFunction_GET_CODE(f); if (PyCode_GetNumFree(co) > 0) goto fallback; glob = PyFunction_GET_GLOBALS(f); defl = PyFunction_GET_DEFAULTS(f); Py_INCREF(glob); fglobals = vinfo_new(CompileTime_NewSk(sk_new ((long)glob, SkFlagPyObj))); if (defl == NULL) fdefaults = psyco_vi_Zero(); else { Py_INCREF(defl); fdefaults = vinfo_new(CompileTime_NewSk(sk_new ((long)defl, SkFlagPyObj))); } saved_inlining = po->pr.is_inlining; if (!allow_inline) po->pr.is_inlining = true; result = psyco_call_pyfunc(po, co, fglobals, fdefaults, arg, po->pr.auto_recursion); po->pr.is_inlining = saved_inlining; vinfo_decref(fdefaults, po); vinfo_decref(fglobals, po); return result; fallback: return psyco_generic_call(po, PyFunction_Type.tp_call, CfReturnRef|CfPyErrIfNull, "lvl", (long) f, arg, 0); }
static PyObject* copyrec(PyObject* o) { PyTypeObject* t; PyObject* n; PyObject* key; KeyObject* fkey; if (o == Py_None || o->ob_type == &PyInt_Type || o->ob_type == &PyString_Type) { Py_INCREF(o); return o; } if (ss_next_in_block < 0) { struct key_block* b = (struct key_block*) malloc(sizeof(struct key_block)); if (!b) { PyErr_NoMemory(); goto fail1; } b->next = ss_block; ss_block = b; ss_next_in_block = KEYS_BY_BLOCK - 1; } fkey = ss_block->keys + ss_next_in_block; fkey->ob_refcnt = 1; fkey->ob_type = &keytype; fkey->o = o; key = (PyObject*) fkey; n = PyDict_GetItem(ss_memo, key); if (n) { Py_INCREF(n); return n; } ss_next_in_block--; Py_INCREF(o); /* reference stored in 'fkey->o' */ t = o->ob_type; if (t == &PyTuple_Type) { int i, count = PyTuple_GET_SIZE(o); n = PyTuple_New(count); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; for (i=0; i<count; i++) PyTuple_SET_ITEM(n, i, copyrec(PyTuple_GET_ITEM(o, i))); return n; } if (t == &PyList_Type) { int i, count = PyList_GET_SIZE(o); n = PyList_New(count); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; for (i=0; i<count; i++) PyList_SET_ITEM(n, i, copyrec(PyList_GET_ITEM(o, i))); return n; } if (t == &PyDict_Type) { int i = 0; PyObject* dictkey; PyObject* dictvalue; n = PyDict_New(); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; while (PyDict_Next(o, &i, &dictkey, &dictvalue)) if (PyDict_SetItem(n, copyrec(dictkey), copyrec(dictvalue))) goto fail; return n; } if (t == &PyInstance_Type) { int i = 0; PyObject* dictkey; PyObject* dictvalue; PyObject* dsrc; PyObject* ddest; PyObject* inst_build = PyObject_GetAttr(o, str_inst_build); if (inst_build == NULL) { PyErr_Clear(); goto unmodified; } n = PyObject_CallObject(inst_build, NULL); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; dsrc = ((PyInstanceObject*) o)->in_dict; ddest = ((PyInstanceObject*) n)->in_dict; while (PyDict_Next(dsrc, &i, &dictkey, &dictvalue)) if (PyDict_SetItem(ddest, copyrec(dictkey), copyrec(dictvalue))) goto fail; return n; } if (t == &PyFunction_Type) { int i, count; PyObject* tsrc = PyFunction_GET_DEFAULTS(o); PyObject* tdest; if (!tsrc) goto unmodified; count = PyTuple_GET_SIZE(tsrc); if (count == 0) goto unmodified; n = PyFunction_New(PyFunction_GET_CODE(o), PyFunction_GET_GLOBALS(o)); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; tdest = PyTuple_New(count); if (!tdest) goto fail; for (i=0; i<count; i++) PyTuple_SET_ITEM(tdest, i, copyrec(PyTuple_GET_ITEM(tsrc, i))); i = PyFunction_SetDefaults(n, tdest); Py_DECREF(tdest); if (i) goto fail; return n; } if (t == &PyMethod_Type) { PyObject* x; n = PyMethod_New(PyMethod_GET_FUNCTION(o), PyMethod_GET_SELF(o), PyMethod_GET_CLASS(o)); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; x = copyrec(PyMethod_GET_FUNCTION(n)); Py_DECREF(PyMethod_GET_FUNCTION(n)); PyMethod_GET_FUNCTION(n) = x; x = copyrec(PyMethod_GET_SELF(n)); Py_DECREF(PyMethod_GET_SELF(n)); PyMethod_GET_SELF(n) = x; return n; } if (t == GeneratorType) { n = genbuild(o); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; if (gencopy(n, o)) goto fail; return n; } if (t == &PySeqIter_Type) { n = seqiterbuild(o); if (!n || PyDict_SetItem(ss_memo, key, n)) goto fail; if (seqitercopy(n, o)) goto fail; return n; } ss_next_in_block++; return o; /* reference no longer stored in 'fkey->o' */ unmodified: PyDict_SetItem(ss_memo, key, o); Py_INCREF(o); return o; fail1: n = NULL; fail: Py_INCREF(o); Py_XDECREF(n); return o; }
NUITKA_MAY_BE_UNUSED static PyObject *fast_python_call( PyObject *func, PyObject **args, int count ) { PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE( func ); PyObject *globals = PyFunction_GET_GLOBALS( func ); PyObject *argdefs = PyFunction_GET_DEFAULTS( func ); #if PYTHON_VERSION >= 300 PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS( func ); if ( kwdefs == NULL && argdefs == NULL && co->co_argcount == count && co->co_flags == ( CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE )) #else if ( argdefs == NULL && co->co_argcount == count && co->co_flags == ( CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE )) #endif { PyThreadState *tstate = PyThreadState_GET(); assertObject( globals ); PyFrameObject *frame = PyFrame_New( tstate, co, globals, NULL ); if (unlikely( frame == NULL )) { return NULL; }; for ( int i = 0; i < count; i++ ) { frame->f_localsplus[i] = INCREASE_REFCOUNT( args[i] ); } PyObject *result = PyEval_EvalFrameEx( frame, 0 ); // Frame release protects against recursion as it may lead to variable // destruction. ++tstate->recursion_depth; Py_DECREF( frame ); --tstate->recursion_depth; return result; } PyObject **defaults = NULL; int nd = 0; if ( argdefs != NULL ) { defaults = &PyTuple_GET_ITEM( argdefs, 0 ); nd = int( Py_SIZE( argdefs ) ); } PyObject *result = PyEval_EvalCodeEx( #if PYTHON_VERSION >= 300 (PyObject *)co, #else co, // code object #endif globals, // globals NULL, // no locals args, // args count, // argcount NULL, // kwds 0, // kwcount defaults, // defaults nd, // defcount #if PYTHON_VERSION >= 300 kwdefs, #endif PyFunction_GET_CLOSURE( func ) ); return result; }