aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2021-02-01 10:42:03 +0000
committerGitHub <noreply@github.com>2021-02-01 10:42:03 +0000
commit0332e569c12d3dc97171546c6dc10e42c27de34b (patch)
tree1ef4cc33b19c2c7f24c157ffdfa61250ea2c9787 /Objects
parentbpo-42504: Ensure that get_config_var('MACOSX_DEPLOYMENT_TARGET') is a string... (diff)
downloadcpython-0332e569c12d3dc97171546c6dc10e42c27de34b.tar.gz
cpython-0332e569c12d3dc97171546c6dc10e42c27de34b.tar.bz2
cpython-0332e569c12d3dc97171546c6dc10e42c27de34b.zip
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.c77
-rw-r--r--Objects/frameobject.c51
-rw-r--r--Objects/funcobject.c4
3 files changed, 31 insertions, 101 deletions
diff --git a/Objects/call.c b/Objects/call.c
index 7972693918b..960c37e1961 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 45a275bd901..57105e1a9eb 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 f839d7b429e..b331c4c4d6e 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);