[Python-checkins] bpo-38644: Add _PyEval_EvalCode() (GH-17183)

Victor Stinner webhook-mailer at python.org
Fri Nov 15 19:03:26 EST 2019


https://github.com/python/cpython/commit/b5e170f127b57d5b0a4fb58f316acd6191509dce
commit: b5e170f127b57d5b0a4fb58f316acd6191509dce
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2019-11-16T01:03:22+01:00
summary:

bpo-38644: Add _PyEval_EvalCode() (GH-17183)

_PyFunction_Vectorcall() now pass tstate to function calls.

files:
M Include/internal/pycore_ceval.h
M Objects/call.c
M Python/ceval.c

diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 7adb87214a058..857fc0b2524fe 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -43,6 +43,16 @@ _PyEval_EvalFrame(PyThreadState *tstate, struct _frame *f, int throwflag)
     return tstate->interp->eval_frame(f, throwflag);
 }
 
+extern PyObject *_PyEval_EvalCode(
+    PyThreadState *tstate,
+    PyObject *_co, PyObject *globals, PyObject *locals,
+    PyObject *const *args, Py_ssize_t argcount,
+    PyObject *const *kwnames, PyObject *const *kwargs,
+    Py_ssize_t kwcount, int kwstep,
+    PyObject *const *defs, Py_ssize_t defcount,
+    PyObject *kwdefs, PyObject *closure,
+    PyObject *name, PyObject *qualname);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/Objects/call.c b/Objects/call.c
index ae08d1824468d..0f8cb5aa246b0 100644
--- a/Objects/call.c
+++ b/Objects/call.c
@@ -302,13 +302,12 @@ PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
 /* --- PyFunction call functions ---------------------------------- */
 
 static PyObject* _Py_HOT_FUNCTION
-function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs,
+function_code_fastcall(PyThreadState *tstate, PyCodeObject *co,
+                       PyObject *const *args, Py_ssize_t nargs,
                        PyObject *globals)
 {
-    assert(globals != NULL);
-
-    PyThreadState *tstate = _PyThreadState_GET();
     assert(tstate != NULL);
+    assert(globals != NULL);
 
     /* XXX Perhaps we should create a specialized
        _PyFrame_New_NoTrack() that doesn't take locals, but does
@@ -344,57 +343,61 @@ PyObject *
 _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack,
                        size_t nargsf, PyObject *kwnames)
 {
-    PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
-    PyObject *globals = PyFunction_GET_GLOBALS(func);
-    PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
-    PyObject *kwdefs, *closure, *name, *qualname;
-    PyObject **d;
-    Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
-    Py_ssize_t nd;
-
     assert(PyFunction_Check(func));
+    assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
+
     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     assert(nargs >= 0);
-    assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
+    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 *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(co, stack, nargs, globals);
+            return function_code_fastcall(tstate, co, stack, nargs, globals);
         }
         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(co, stack, PyTuple_GET_SIZE(argdefs),
+            return function_code_fastcall(tstate, co,
+                                          stack, PyTuple_GET_SIZE(argdefs),
                                           globals);
         }
     }
 
-    kwdefs = PyFunction_GET_KW_DEFAULTS(func);
-    closure = PyFunction_GET_CLOSURE(func);
-    name = ((PyFunctionObject *)func) -> func_name;
-    qualname = ((PyFunctionObject *)func) -> func_qualname;
+    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_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
-                                    stack, nargs,
-                                    nkwargs ? _PyTuple_ITEMS(kwnames) : NULL,
-                                    stack + nargs,
-                                    nkwargs, 1,
-                                    d, (int)nd, kwdefs,
-                                    closure, name, qualname);
+    return _PyEval_EvalCode(tstate,
+                (PyObject*)co, globals, (PyObject *)NULL,
+                stack, nargs,
+                nkwargs ? _PyTuple_ITEMS(kwnames) : NULL,
+                stack + nargs,
+                nkwargs, 1,
+                d, (int)nd, kwdefs,
+                closure, name, qualname);
 }
 
 
diff --git a/Python/ceval.c b/Python/ceval.c
index 11d25a53d527a..9f4b43615e28f 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -4045,7 +4045,8 @@ positional_only_passed_as_keyword(PyThreadState *tstate, PyCodeObject *co,
    the test in the if statements in Misc/gdbinit (pystack and pystackv). */
 
 PyObject *
-_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
+_PyEval_EvalCode(PyThreadState *tstate,
+           PyObject *_co, PyObject *globals, PyObject *locals,
            PyObject *const *args, Py_ssize_t argcount,
            PyObject *const *kwnames, PyObject *const *kwargs,
            Py_ssize_t kwcount, int kwstep,
@@ -4053,6 +4054,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
            PyObject *kwdefs, PyObject *closure,
            PyObject *name, PyObject *qualname)
 {
+    assert(tstate != NULL);
+
     PyCodeObject* co = (PyCodeObject*)_co;
     PyFrameObject *f;
     PyObject *retval = NULL;
@@ -4062,9 +4065,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
     Py_ssize_t i, j, n;
     PyObject *kwdict;
 
-    PyThreadState *tstate = _PyThreadState_GET();
-    assert(tstate != NULL);
-
     if (globals == NULL) {
         _PyErr_SetString(tstate, PyExc_SystemError,
                          "PyEval_EvalCodeEx: NULL globals");
@@ -4319,6 +4319,26 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
     return retval;
 }
 
+
+PyObject *
+_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
+           PyObject *const *args, Py_ssize_t argcount,
+           PyObject *const *kwnames, PyObject *const *kwargs,
+           Py_ssize_t kwcount, int kwstep,
+           PyObject *const *defs, Py_ssize_t defcount,
+           PyObject *kwdefs, PyObject *closure,
+           PyObject *name, PyObject *qualname)
+{
+    PyThreadState *tstate = _PyThreadState_GET();
+    return _PyEval_EvalCode(tstate, _co, globals, locals,
+               args, argcount,
+               kwnames, kwargs,
+               kwcount, kwstep,
+               defs, defcount,
+               kwdefs, closure,
+               name, qualname);
+}
+
 PyObject *
 PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
                   PyObject *const *args, int argcount,



More information about the Python-checkins mailing list