diff options
author | Mark Shannon <mark@hotpy.org> | 2021-01-29 13:24:55 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-29 13:24:55 (GMT) |
commit | d6c33fbd346765c6a8654dccacb2338006bf2b47 (patch) | |
tree | 857d7b70431dc74ca9b68e5ce1d56953f19f8d77 /Objects | |
parent | 23a567c11ca36eedde0e119443c85cc16075deaf (diff) | |
download | cpython-d6c33fbd346765c6a8654dccacb2338006bf2b47.zip cpython-d6c33fbd346765c6a8654dccacb2338006bf2b47.tar.gz cpython-d6c33fbd346765c6a8654dccacb2338006bf2b47.tar.bz2 |
bpo-42990: Introduce 'frame constructor' struct to simplify API for PyEval_CodeEval and friends (GH-24298)
* Introduce 'frame constructor' to simplify API for frame creation
* Embed struct using a macro to conform to PEP 7
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/call.c | 33 | ||||
-rw-r--r-- | Objects/frameobject.c | 85 | ||||
-rw-r--r-- | Objects/funcobject.c | 13 |
3 files changed, 51 insertions, 80 deletions
diff --git a/Objects/call.c b/Objects/call.c index 1fb85ef..7972693 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -331,16 +331,16 @@ PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs) static PyObject* _Py_HOT_FUNCTION function_code_fastcall(PyThreadState *tstate, PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs, - PyObject *globals) + PyFunctionObject *func) { assert(tstate != NULL); - assert(globals != 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, globals, NULL); + PyFrameObject *f = _PyFrame_New_NoTrack(tstate, co, func->func_globals, func->func_builtins, NULL); if (f == NULL) { return NULL; } @@ -381,14 +381,13 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, PyThreadState *tstate = _PyThreadState_GET(); PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(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, globals); + return function_code_fastcall(tstate, co, stack, nargs, (PyFunctionObject *)func); } else if (nargs == 0 && argdefs != NULL && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { @@ -397,34 +396,16 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack, stack = _PyTuple_ITEMS(argdefs); return function_code_fastcall(tstate, co, stack, PyTuple_GET_SIZE(argdefs), - globals); + (PyFunctionObject *)func); } } - PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func); - PyObject *closure = PyFunction_GET_CLOSURE(func); - PyObject *name = ((PyFunctionObject *)func) -> func_name; - PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname; - - PyObject **d; - Py_ssize_t nd; - if (argdefs != NULL) { - d = _PyTuple_ITEMS(argdefs); - nd = PyTuple_GET_SIZE(argdefs); - assert(nd <= INT_MAX); - } - else { - d = NULL; - nd = 0; - } return _PyEval_EvalCode(tstate, - (PyObject*)co, globals, (PyObject *)NULL, + PyFunction_AS_FRAME_CONSTRUCTOR(func), (PyObject *)NULL, stack, nargs, nkwargs ? _PyTuple_ITEMS(kwnames) : NULL, stack + nargs, - nkwargs, 1, - d, (int)nd, kwdefs, - closure, name, qualname); + nkwargs, 1); } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index 4c5eaa2..45a275b 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -22,7 +22,6 @@ static PyMemberDef frame_memberlist[] = { {NULL} /* Sentinel */ }; - static struct _Py_frame_state * get_frame_state(void) { @@ -816,54 +815,12 @@ frame_alloc(PyCodeObject *code) } -static inline PyObject * -frame_get_builtins(PyFrameObject *back, PyObject *globals) -{ - PyObject *builtins; - - if (back != NULL && back->f_globals == globals) { - /* If we share the globals, we share the builtins. - Save a lookup and a call. */ - builtins = back->f_builtins; - assert(builtins != NULL); - Py_INCREF(builtins); - return builtins; - } - - builtins = _PyDict_GetItemIdWithError(globals, &PyId___builtins__); - if (builtins != NULL && PyModule_Check(builtins)) { - builtins = PyModule_GetDict(builtins); - assert(builtins != NULL); - } - if (builtins != NULL) { - Py_INCREF(builtins); - return builtins; - } - - if (PyErr_Occurred()) { - return NULL; - } - - /* No builtins! Make up a minimal one. - Give them 'None', at least. */ - builtins = PyDict_New(); - if (builtins == NULL) { - return NULL; - } - if (PyDict_SetItemString(builtins, "None", Py_None) < 0) { - Py_DECREF(builtins); - return NULL; - } - return builtins; -} - - PyFrameObject* _Py_HOT_FUNCTION _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, - PyObject *globals, PyObject *locals) + PyObject *globals, PyObject *builtins, PyObject *locals) { #ifdef Py_DEBUG - if (code == NULL || globals == NULL || !PyDict_Check(globals) || + if (code == NULL || globals == NULL || builtins == NULL || (locals != NULL && !PyMapping_Check(locals))) { PyErr_BadInternalCall(); return NULL; @@ -871,18 +828,14 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, #endif PyFrameObject *back = tstate->frame; - PyObject *builtins = frame_get_builtins(back, globals); - if (builtins == NULL) { - return NULL; - } PyFrameObject *f = frame_alloc(code); if (f == NULL) { - Py_DECREF(builtins); return NULL; } f->f_stackdepth = 0; + Py_INCREF(builtins); f->f_builtins = builtins; Py_XINCREF(back); f->f_back = back; @@ -902,8 +855,9 @@ _PyFrame_New_NoTrack(PyThreadState *tstate, PyCodeObject *code, f->f_locals = locals; } else { - if (locals == NULL) + if (locals == NULL) { locals = globals; + } Py_INCREF(locals); f->f_locals = locals; } @@ -925,7 +879,9 @@ PyFrameObject* PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals, PyObject *locals) { - PyFrameObject *f = _PyFrame_New_NoTrack(tstate, code, globals, locals); + PyObject *builtins = _PyEval_BuiltinsFromGlobals(globals); + PyFrameObject *f = _PyFrame_New_NoTrack(tstate, code, globals, builtins, locals); + Py_DECREF(builtins); if (f) _PyObject_GC_TRACK(f); return f; @@ -1223,3 +1179,28 @@ PyFrame_GetBack(PyFrameObject *frame) Py_XINCREF(back); return back; } + +PyObject *_PyEval_BuiltinsFromGlobals(PyObject *globals) { + PyObject *builtins = _PyDict_GetItemIdWithError(globals, &PyId___builtins__); + if (builtins) { + if (PyModule_Check(builtins)) { + builtins = PyModule_GetDict(builtins); + assert(builtins != NULL); + } + } + if (builtins == NULL) { + if (PyErr_Occurred()) { + return NULL; + } + /* No builtins! Make up a minimal one + Give them 'None', at least. */ + builtins = PyDict_New(); + if (builtins == NULL || + PyDict_SetItemString( + builtins, "None", Py_None) < 0) + return NULL; + } + else + Py_INCREF(builtins); + return builtins; +} diff --git a/Objects/funcobject.c b/Objects/funcobject.c index e7961b3..f839d7b 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -3,6 +3,7 @@ #include "Python.h" #include "pycore_object.h" +#include "frameobject.h" #include "code.h" #include "structmember.h" // PyMemberDef @@ -40,8 +41,14 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname op->func_weakreflist = NULL; Py_INCREF(code); op->func_code = code; + assert(globals != NULL); Py_INCREF(globals); op->func_globals = globals; + PyObject *builtins = _PyEval_BuiltinsFromGlobals(globals); + if (builtins == NULL) { + return NULL; + } + op->func_builtins = builtins; op->func_name = ((PyCodeObject *)code)->co_name; Py_INCREF(op->func_name); op->func_defaults = NULL; /* No default arguments */ @@ -592,15 +599,16 @@ func_clear(PyFunctionObject *op) { Py_CLEAR(op->func_code); Py_CLEAR(op->func_globals); - Py_CLEAR(op->func_module); + Py_CLEAR(op->func_builtins); Py_CLEAR(op->func_name); + Py_CLEAR(op->func_qualname); + Py_CLEAR(op->func_module); Py_CLEAR(op->func_defaults); Py_CLEAR(op->func_kwdefaults); Py_CLEAR(op->func_doc); Py_CLEAR(op->func_dict); Py_CLEAR(op->func_closure); Py_CLEAR(op->func_annotations); - Py_CLEAR(op->func_qualname); return 0; } @@ -627,6 +635,7 @@ func_traverse(PyFunctionObject *f, visitproc visit, void *arg) { Py_VISIT(f->func_code); Py_VISIT(f->func_globals); + Py_VISIT(f->func_builtins); Py_VISIT(f->func_module); Py_VISIT(f->func_defaults); Py_VISIT(f->func_kwdefaults); |