Skip to content

Commit b5e170f

Browse files
authored
bpo-38644: Add _PyEval_EvalCode() (GH-17183)
_PyFunction_Vectorcall() now pass tstate to function calls.
1 parent 0fe0b88 commit b5e170f

File tree

3 files changed

+63
-30
lines changed

3 files changed

+63
-30
lines changed

‎Include/internal/pycore_ceval.h‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ _PyEval_EvalFrame(PyThreadState *tstate, struct _frame *f, int throwflag)
4343
return tstate->interp->eval_frame(f, throwflag);
4444
}
4545

46+
extern PyObject *_PyEval_EvalCode(
47+
PyThreadState *tstate,
48+
PyObject *_co, PyObject *globals, PyObject *locals,
49+
PyObject *const *args, Py_ssize_t argcount,
50+
PyObject *const *kwnames, PyObject *const *kwargs,
51+
Py_ssize_t kwcount, int kwstep,
52+
PyObject *const *defs, Py_ssize_t defcount,
53+
PyObject *kwdefs, PyObject *closure,
54+
PyObject *name, PyObject *qualname);
55+
4656
#ifdef __cplusplus
4757
}
4858
#endif

‎Objects/call.c‎

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -302,13 +302,12 @@ PyCFunction_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
302302
/* --- PyFunction call functions ---------------------------------- */
303303

304304
static PyObject* _Py_HOT_FUNCTION
305-
function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs,
305+
function_code_fastcall(PyThreadState *tstate, PyCodeObject *co,
306+
PyObject *const *args, Py_ssize_t nargs,
306307
PyObject *globals)
307308
{
308-
assert(globals != NULL);
309-
310-
PyThreadState *tstate = _PyThreadState_GET();
311309
assert(tstate != NULL);
310+
assert(globals != NULL);
312311

313312
/* XXX Perhaps we should create a specialized
314313
_PyFrame_New_NoTrack() that doesn't take locals, but does
@@ -344,57 +343,61 @@ PyObject *
344343
_PyFunction_Vectorcall(PyObject *func, PyObject* const* stack,
345344
size_t nargsf, PyObject *kwnames)
346345
{
347-
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
348-
PyObject *globals = PyFunction_GET_GLOBALS(func);
349-
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
350-
PyObject *kwdefs, *closure, *name, *qualname;
351-
PyObject **d;
352-
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
353-
Py_ssize_t nd;
354-
355346
assert(PyFunction_Check(func));
347+
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
348+
356349
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
357350
assert(nargs >= 0);
358-
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
351+
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
359352
assert((nargs == 0 && nkwargs == 0) || stack != NULL);
360353
/* kwnames must only contain strings and all keys must be unique */
361354

355+
PyThreadState *tstate = _PyThreadState_GET();
356+
PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
357+
PyObject *globals = PyFunction_GET_GLOBALS(func);
358+
PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
359+
362360
if (co->co_kwonlyargcount == 0 && nkwargs == 0 &&
363361
(co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE))
364362
{
365363
if (argdefs == NULL && co->co_argcount == nargs) {
366-
return function_code_fastcall(co, stack, nargs, globals);
364+
return function_code_fastcall(tstate, co, stack, nargs, globals);
367365
}
368366
else if (nargs == 0 && argdefs != NULL
369367
&& co->co_argcount == PyTuple_GET_SIZE(argdefs)) {
370368
/* function called with no arguments, but all parameters have
371369
a default value: use default values as arguments .*/
372370
stack = _PyTuple_ITEMS(argdefs);
373-
return function_code_fastcall(co, stack, PyTuple_GET_SIZE(argdefs),
371+
return function_code_fastcall(tstate, co,
372+
stack, PyTuple_GET_SIZE(argdefs),
374373
globals);
375374
}
376375
}
377376

378-
kwdefs = PyFunction_GET_KW_DEFAULTS(func);
379-
closure = PyFunction_GET_CLOSURE(func);
380-
name = ((PyFunctionObject *)func) -> func_name;
381-
qualname = ((PyFunctionObject *)func) -> func_qualname;
377+
PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
378+
PyObject *closure = PyFunction_GET_CLOSURE(func);
379+
PyObject *name = ((PyFunctionObject *)func) -> func_name;
380+
PyObject *qualname = ((PyFunctionObject *)func) -> func_qualname;
382381

382+
PyObject **d;
383+
Py_ssize_t nd;
383384
if (argdefs != NULL) {
384385
d = _PyTuple_ITEMS(argdefs);
385386
nd = PyTuple_GET_SIZE(argdefs);
387+
assert(nd <= INT_MAX);
386388
}
387389
else {
388390
d = NULL;
389391
nd = 0;
390392
}
391-
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
392-
stack, nargs,
393-
nkwargs ? _PyTuple_ITEMS(kwnames) : NULL,
394-
stack + nargs,
395-
nkwargs, 1,
396-
d, (int)nd, kwdefs,
397-
closure, name, qualname);
393+
return _PyEval_EvalCode(tstate,
394+
(PyObject*)co, globals, (PyObject *)NULL,
395+
stack, nargs,
396+
nkwargs ? _PyTuple_ITEMS(kwnames) : NULL,
397+
stack + nargs,
398+
nkwargs, 1,
399+
d, (int)nd, kwdefs,
400+
closure, name, qualname);
398401
}
399402

400403

‎Python/ceval.c‎

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4045,14 +4045,17 @@ positional_only_passed_as_keyword(PyThreadState *tstate, PyCodeObject *co,
40454045
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
40464046

40474047
PyObject *
4048-
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
4048+
_PyEval_EvalCode(PyThreadState *tstate,
4049+
PyObject *_co, PyObject *globals, PyObject *locals,
40494050
PyObject *const *args, Py_ssize_t argcount,
40504051
PyObject *const *kwnames, PyObject *const *kwargs,
40514052
Py_ssize_t kwcount, int kwstep,
40524053
PyObject *const *defs, Py_ssize_t defcount,
40534054
PyObject *kwdefs, PyObject *closure,
40544055
PyObject *name, PyObject *qualname)
40554056
{
4057+
assert(tstate != NULL);
4058+
40564059
PyCodeObject* co = (PyCodeObject*)_co;
40574060
PyFrameObject *f;
40584061
PyObject *retval = NULL;
@@ -4062,9 +4065,6 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
40624065
Py_ssize_t i, j, n;
40634066
PyObject *kwdict;
40644067

4065-
PyThreadState *tstate = _PyThreadState_GET();
4066-
assert(tstate != NULL);
4067-
40684068
if (globals == NULL) {
40694069
_PyErr_SetString(tstate, PyExc_SystemError,
40704070
"PyEval_EvalCodeEx: NULL globals");
@@ -4319,6 +4319,26 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
43194319
return retval;
43204320
}
43214321

4322+
4323+
PyObject *
4324+
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
4325+
PyObject *const *args, Py_ssize_t argcount,
4326+
PyObject *const *kwnames, PyObject *const *kwargs,
4327+
Py_ssize_t kwcount, int kwstep,
4328+
PyObject *const *defs, Py_ssize_t defcount,
4329+
PyObject *kwdefs, PyObject *closure,
4330+
PyObject *name, PyObject *qualname)
4331+
{
4332+
PyThreadState *tstate = _PyThreadState_GET();
4333+
return _PyEval_EvalCode(tstate, _co, globals, locals,
4334+
args, argcount,
4335+
kwnames, kwargs,
4336+
kwcount, kwstep,
4337+
defs, defcount,
4338+
kwdefs, closure,
4339+
name, qualname);
4340+
}
4341+
43224342
PyObject *
43234343
PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
43244344
PyObject *const *args, int argcount,

0 commit comments

Comments
 (0)