diff options
author | Victor Stinner <vstinner@python.org> | 2021-02-18 18:20:16 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-18 18:20:16 (GMT) |
commit | 44085a3fc9a150478aec1872dd1079c60dcc42f6 (patch) | |
tree | 1120f81009d599e9d5db25978e25ea4d757bc875 /Objects/funcobject.c | |
parent | cc96231f0a59cc7393943064800ecb6c18892662 (diff) | |
download | cpython-44085a3fc9a150478aec1872dd1079c60dcc42f6.zip cpython-44085a3fc9a150478aec1872dd1079c60dcc42f6.tar.gz cpython-44085a3fc9a150478aec1872dd1079c60dcc42f6.tar.bz2 |
bpo-42990: Refactor _PyFrame_New_NoTrack() (GH-24566)
* Refactor _PyFrame_New_NoTrack() and PyFunction_NewWithQualName()
code.
* PyFrame_New() checks for _PyEval_BuiltinsFromGlobals() failure.
* Fix a ref leak in _PyEval_BuiltinsFromGlobals() error path.
* Complete PyFunction_GetModule() documentation: it returns a
borrowed reference and it can return NULL.
* Move _PyEval_BuiltinsFromGlobals() definition to the internal C
API.
* PyFunction_NewWithQualName() uses _Py_IDENTIFIER() API for the
"__name__" string to make it compatible with subinterpreters.
Diffstat (limited to 'Objects/funcobject.c')
-rw-r--r-- | Objects/funcobject.c | 111 |
1 files changed, 59 insertions, 52 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 523930d..4b92f6c 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -2,83 +2,90 @@ /* Function object implementation */ #include "Python.h" -#include "pycore_object.h" -#include "frameobject.h" -#include "code.h" +#include "pycore_ceval.h" // _PyEval_BuiltinsFromGlobals() +#include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "structmember.h" // PyMemberDef PyObject * PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname) { - PyFunctionObject *op; - PyObject *doc, *consts, *module; - static PyObject *__name__ = NULL; + assert(globals != NULL); + assert(PyDict_Check(globals)); + Py_INCREF(globals); - if (__name__ == NULL) { - __name__ = PyUnicode_InternFromString("__name__"); - if (__name__ == NULL) - return NULL; + PyCodeObject *code_obj = (PyCodeObject *)code; + Py_INCREF(code_obj); + + PyObject *name = code_obj->co_name; + assert(name != NULL); + Py_INCREF(name); + if (!qualname) { + qualname = name; } + Py_INCREF(qualname); - /* __module__: If module name is in globals, use it. - Otherwise, use None. */ - module = PyDict_GetItemWithError(globals, __name__); - if (module) { - Py_INCREF(module); + PyObject *consts = code_obj->co_consts; + assert(PyTuple_Check(consts)); + PyObject *doc; + if (PyTuple_Size(consts) >= 1) { + doc = PyTuple_GetItem(consts, 0); + if (!PyUnicode_Check(doc)) { + doc = Py_None; + } } - else if (PyErr_Occurred()) { - return NULL; + else { + doc = Py_None; + } + Py_INCREF(doc); + + // __module__: Use globals['__name__'] if it exists, or NULL. + _Py_IDENTIFIER(__name__); + PyObject *module = _PyDict_GetItemIdWithError(globals, &PyId___name__); + PyObject *builtins = NULL; + if (module == NULL && PyErr_Occurred()) { + goto error; + } + Py_XINCREF(module); + + builtins = _PyEval_BuiltinsFromGlobals(globals); + if (builtins == NULL) { + goto error; } - op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type); + PyFunctionObject *op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type); if (op == NULL) { - Py_XDECREF(module); - return NULL; + goto error; } /* Note: No failures from this point on, since func_dealloc() does not expect a partially-created object. */ - 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 */ - op->func_kwdefaults = NULL; /* No keyword only defaults */ + op->func_name = name; + op->func_qualname = qualname; + op->func_code = (PyObject*)code_obj; + op->func_defaults = NULL; // No default positional arguments + op->func_kwdefaults = NULL; // No default keyword arguments op->func_closure = NULL; - op->vectorcall = _PyFunction_Vectorcall; - op->func_module = module; - - consts = ((PyCodeObject *)code)->co_consts; - if (PyTuple_Size(consts) >= 1) { - doc = PyTuple_GetItem(consts, 0); - if (!PyUnicode_Check(doc)) - doc = Py_None; - } - else - doc = Py_None; - Py_INCREF(doc); op->func_doc = doc; - op->func_dict = NULL; + op->func_weakreflist = NULL; + op->func_module = module; op->func_annotations = NULL; - - if (qualname) - op->func_qualname = qualname; - else - op->func_qualname = op->func_name; - Py_INCREF(op->func_qualname); + op->vectorcall = _PyFunction_Vectorcall; _PyObject_GC_TRACK(op); return (PyObject *)op; + +error: + Py_DECREF(globals); + Py_DECREF(code_obj); + Py_DECREF(name); + Py_DECREF(qualname); + Py_DECREF(doc); + Py_XDECREF(module); + Py_XDECREF(builtins); + return NULL; } PyObject * |