diff options
author | Mark Shannon <mark@hotpy.org> | 2021-02-01 10:42:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-01 10:42:03 (GMT) |
commit | 0332e569c12d3dc97171546c6dc10e42c27de34b (patch) | |
tree | 1ef4cc33b19c2c7f24c157ffdfa61250ea2c9787 /Objects | |
parent | 49926cf2bcc8b44d9b8f148d81979ada191dd9d5 (diff) | |
download | cpython-0332e569c12d3dc97171546c6dc10e42c27de34b.zip cpython-0332e569c12d3dc97171546c6dc10e42c27de34b.tar.gz cpython-0332e569c12d3dc97171546c6dc10e42c27de34b.tar.bz2 |
bpo-42990: Further refactoring of PyEval_ functions. (GH-24368)
* Further refactoring of PyEval_EvalCode and friends. Break into make-frame, and eval-frame parts.
* Simplify function vector call using new _PyEval_Vector.
* Remove unused internal functions: _PyEval_EvalCodeWithName and _PyEval_EvalCode.
* Don't use legacy function PyEval_EvalCodeEx.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/call.c | 77 | ||||
-rw-r--r-- | Objects/frameobject.c | 51 | ||||
-rw-r--r-- | Objects/funcobject.c | 4 |
3 files changed, 31 insertions, 101 deletions
diff --git a/Objects/call.c b/Objects/call.c index 7972693..960c37e 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -328,87 +328,24 @@ PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) /* --- PyFunction call functions ---------------------------------- */ -static PyObject* _Py_HOT_FUNCTION -function_code_fastcall(PyThreadState *tstate, PyCodeObject *co, - PyObject *const *args, Py_ssize_t nargs, - PyFunctionObject *func) -{ - assert(tstate != NULL); - assert(func != NULL); - - /* XXX Perhaps we should create a specialized - _PyFrame_New_NoTrack() that doesn't take locals, but does - take builtins without sanity checking them. - */ - PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, func->func_globals, func->func_builtins, NULL); - if (f == NULL) { - return NULL; - } - - PyObject **fastlocals = f->f_localsplus; - - for (Py_ssize_t i = 0; i < nargs; i++) { - Py_INCREF(*args); - fastlocals[i] = *args++; - } - PyObject *result = _PyEval_EvalFrame(tstate, f, 0); - - if (Py_REFCNT(f) > 1) { - Py_DECREF(f); - _PyObject_GC_TRACK(f); - } - else { - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - } - return result; -} - - PyObject * _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, size_t nargsf, PyObject *kwnames) { assert(PyFunction_Check(func)); - assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); - + PyFrameConstructor *f = PyFunction_AS_FRAME_CONSTRUCTOR(func); Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); assert(nargs >= 0); - Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); - assert((nargs == 0 && nkwargs == 0) || stack != NULL); - /* kwnames must only contain strings and all keys must be unique */ - PyThreadState *tstate = _PyThreadState_GET(); - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - - if (co->co_kwonlyargcount == 0 && nkwargs == 0 && - (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) - { - if (argdefs == NULL && co->co_argcount == nargs) { - return function_code_fastcall(tstate, co, stack, nargs, (PyFunctionObject *)func); - } - else if (nargs == 0 && argdefs != NULL - && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { - /* function called with no arguments, but all parameters have - a default value: use default values as arguments .*/ - stack = _PyTuple_ITEMS(argdefs); - return function_code_fastcall(tstate, co, - stack, PyTuple_GET_SIZE(argdefs), - (PyFunctionObject *)func); - } + assert(nargs == 0 || stack != NULL); + if (((PyCodeObject *)f->fc_code)->co_flags & CO_OPTIMIZED) { + return _PyEval_Vector(tstate, f, NULL, stack, nargs, kwnames); + } + else { + return _PyEval_Vector(tstate, f, f->fc_globals, stack, nargs, kwnames); } - - return _PyEval_EvalCode(tstate, - PyFunction_AS_FRAME_CONSTRUCTOR(func), (PyObject *)NULL, - stack, nargs, - nkwargs ? _PyTuple_ITEMS(kwnames) : NULL, - stack + nargs, - nkwargs, 1); } - /* --- More complex call functions -------------------------------- */ /* External interface to call any callable object. diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 45a275b..57105e1 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -816,11 +816,10 @@ frame_alloc(PyCodeObject *code) PyFrameObject* _Py_HOT_FUNCTION -_PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, - PyObject *globals, PyObject *builtins, PyObject *locals) +_PyFrame_New_NoTrack(PyThreadState *tstate, PyFrameConstructor *con, PyObject *locals) { #ifdef Py_DEBUG - if (code == NULL || globals == NULL || builtins == NULL || + if (con == NULL || con->fc_code == NULL || (locals != NULL && !PyMapping_Check(locals))) { PyErr_BadInternalCall(); return NULL; @@ -829,38 +828,21 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, PyFrameObject *back = tstate->frame; - PyFrameObject *f = frame_alloc(code); + PyFrameObject *f = frame_alloc((PyCodeObject *)con->fc_code); if (f == NULL) { return NULL; } f->f_stackdepth = 0; - Py_INCREF(builtins); - f->f_builtins = builtins; + Py_INCREF(con->fc_builtins); + f->f_builtins = con->fc_builtins; Py_XINCREF(back); f->f_back = back; - Py_INCREF(code); - Py_INCREF(globals); - f->f_globals = globals; - /* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */ - if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) == - (CO_NEWLOCALS | CO_OPTIMIZED)) - ; /* f_locals = NULL; will be set by PyFrame_FastToLocals() */ - else if (code->co_flags & CO_NEWLOCALS) { - locals = PyDict_New(); - if (locals == NULL) { - Py_DECREF(f); - return NULL; - } - f->f_locals = locals; - } - else { - if (locals == NULL) { - locals = globals; - } - Py_INCREF(locals); - f->f_locals = locals; - } + Py_INCREF(con->fc_code); + Py_INCREF(con->fc_globals); + f->f_globals = con->fc_globals; + Py_XINCREF(locals); + f->f_locals = locals; f->f_lasti = -1; f->f_lineno = 0; @@ -875,12 +857,23 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, return f; } +/* Legacy API */ PyFrameObject* PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, PyObject *locals) { PyObject *builtins = _PyEval_BuiltinsFromGlobals(globals); - PyFrameObject *f = _PyFrame_New_NoTrack(tstate, code, globals, builtins, locals); + PyFrameConstructor desc = { + .fc_globals = globals, + .fc_builtins = builtins, + .fc_name = code->co_name, + .fc_qualname = code->co_name, + .fc_code = (PyObject *)code, + .fc_defaults = NULL, + .fc_kwdefaults = NULL, + .fc_closure = NULL + }; + PyFrameObject *f = _PyFrame_New_NoTrack(tstate, &desc, locals); Py_DECREF(builtins); if (f) _PyObject_GC_TRACK(f); diff --git a/Objects/funcobject.c b/Objects/funcobject.c index f839d7b..b331c4c 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -575,9 +575,9 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code, globals); - if (newfunc == NULL) + if (newfunc == NULL) { return NULL; - + } if (name != Py_None) { Py_INCREF(name); Py_SETREF(newfunc->func_name, name); |