summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2021-01-29 13:24:55 (GMT)
committerGitHub <noreply@github.com>2021-01-29 13:24:55 (GMT)
commitd6c33fbd346765c6a8654dccacb2338006bf2b47 (patch)
tree857d7b70431dc74ca9b68e5ce1d56953f19f8d77 /Objects
parent23a567c11ca36eedde0e119443c85cc16075deaf (diff)
downloadcpython-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.c33
-rw-r--r--Objects/frameobject.c85
-rw-r--r--Objects/funcobject.c13
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);