summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 5d5221b2e4..958689debc 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -212,6 +212,9 @@ static _PyInterpreterFrame *
_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
PyObject *locals, PyObject* const* args,
size_t argcount, PyObject *kwnames);
+static _PyInterpreterFrame *
+_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
+ PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs);
static void
_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame);
@@ -1501,6 +1504,49 @@ fail:
return NULL;
}
+/* Same as _PyEvalFramePushAndInit but takes an args tuple and kwargs dict.
+ Steals references to func, callargs and kwargs.
+*/
+static _PyInterpreterFrame *
+_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
+ PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs)
+{
+ bool has_dict = (kwargs != NULL && PyDict_GET_SIZE(kwargs) > 0);
+ PyObject *kwnames = NULL;
+ PyObject *const *newargs;
+ if (has_dict) {
+ newargs = _PyStack_UnpackDict(tstate, _PyTuple_ITEMS(callargs), nargs, kwargs, &kwnames);
+ if (newargs == NULL) {
+ Py_DECREF(func);
+ goto error;
+ }
+ }
+ else {
+ newargs = &PyTuple_GET_ITEM(callargs, 0);
+ /* We need to incref all our args since the new frame steals the references. */
+ for (Py_ssize_t i = 0; i < nargs; ++i) {
+ Py_INCREF(PyTuple_GET_ITEM(callargs, i));
+ }
+ }
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)func, locals,
+ newargs, nargs, kwnames
+ );
+ if (has_dict) {
+ _PyStack_UnpackDict_FreeNoDecRef(newargs, kwnames);
+ }
+ /* No need to decref func here because the reference has been stolen by
+ _PyEvalFramePushAndInit.
+ */
+ Py_DECREF(callargs);
+ Py_XDECREF(kwargs);
+ return new_frame;
+error:
+ Py_DECREF(callargs);
+ Py_XDECREF(kwargs);
+ return NULL;
+}
+
PyObject *
_PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func,
PyObject *locals,