summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c492
1 files changed, 205 insertions, 287 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 75ec7b2..9b9245e 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -109,19 +109,15 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *);
/* Forward declarations */
#ifdef WITH_TSC
-static PyObject * call_function(PyObject ***, int, uint64*, uint64*);
+static PyObject * call_function(PyObject ***, Py_ssize_t, PyObject *, uint64*, uint64*);
#else
-static PyObject * call_function(PyObject ***, int);
+static PyObject * call_function(PyObject ***, Py_ssize_t, PyObject *);
#endif
-static PyObject * fast_function(PyObject *, PyObject **, Py_ssize_t, Py_ssize_t);
-static PyObject * do_call(PyObject *, PyObject ***, Py_ssize_t, Py_ssize_t);
-static PyObject * ext_do_call(PyObject *, PyObject ***, int, Py_ssize_t, Py_ssize_t);
-static PyObject * update_keyword_args(PyObject *, Py_ssize_t, PyObject ***,
- PyObject *);
-static PyObject * update_star_args(Py_ssize_t, Py_ssize_t, PyObject *, PyObject ***);
+static PyObject * fast_function(PyObject *, PyObject ***, Py_ssize_t, PyObject *);
+static PyObject * do_call(PyObject *, PyObject ***, Py_ssize_t, PyObject *);
+static PyObject * do_call_core(PyObject *, PyObject *, PyObject *);
+static PyObject * create_keyword_args(PyObject *, PyObject ***, PyObject *);
static PyObject * load_args(PyObject ***, Py_ssize_t);
-#define CALL_FLAG_VAR 1
-#define CALL_FLAG_KW 2
#ifdef LLTRACE
static int lltrace;
@@ -2659,8 +2655,14 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
TARGET(BUILD_LIST_UNPACK) {
int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK;
Py_ssize_t i;
- PyObject *sum = PyList_New(0);
+ PyObject *sum;
PyObject *return_value;
+
+ if (convert_to_tuple && oparg == 1 && PyTuple_CheckExact(TOP())) {
+ DISPATCH();
+ }
+
+ sum = PyList_New(0);
if (sum == NULL)
goto error;
@@ -2847,29 +2849,25 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
TARGET(BUILD_MAP_UNPACK_WITH_CALL)
TARGET(BUILD_MAP_UNPACK) {
int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL;
- int num_maps;
- int function_location;
Py_ssize_t i;
- PyObject *sum = PyDict_New();
+ PyObject *sum;
+
+ if (with_call && oparg == 1 && PyDict_CheckExact(TOP())) {
+ DISPATCH();
+ }
+
+ sum = PyDict_New();
if (sum == NULL)
goto error;
- if (with_call) {
- num_maps = oparg & 0xff;
- function_location = (oparg>>8) & 0xff;
- }
- else {
- num_maps = oparg;
- }
- for (i = num_maps; i > 0; i--) {
+ for (i = oparg; i > 0; i--) {
PyObject *arg = PEEK(i);
- if (with_call) {
+ if (with_call && PyDict_Size(sum)) {
PyObject *intersection = _PyDictView_Intersect(sum, arg);
if (intersection == NULL) {
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyObject *func = (
- PEEK(function_location + num_maps));
+ PyObject *func = PEEK(2 + oparg);
PyErr_Format(PyExc_TypeError,
"%.200s%.200s argument after ** "
"must be a mapping, not %.200s",
@@ -2884,7 +2882,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
if (PySet_GET_SIZE(intersection)) {
Py_ssize_t idx = 0;
PyObject *key;
- PyObject *func = PEEK(function_location + num_maps);
+ PyObject *func = PEEK(2 + oparg);
Py_hash_t hash;
_PySet_NextEntry(intersection, &idx, &key, &hash);
if (!PyUnicode_Check(key)) {
@@ -2918,7 +2916,7 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
}
}
- while (num_maps--)
+ while (oparg--)
Py_DECREF(POP());
PUSH(sum);
DISPATCH();
@@ -3409,63 +3407,62 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
PCALL(PCALL_ALL);
sp = stack_pointer;
#ifdef WITH_TSC
- res = call_function(&sp, oparg, &intr0, &intr1);
+ res = call_function(&sp, oparg, NULL, &intr0, &intr1);
#else
- res = call_function(&sp, oparg);
+ res = call_function(&sp, oparg, NULL);
#endif
stack_pointer = sp;
PUSH(res);
- if (res == NULL)
+ if (res == NULL) {
goto error;
+ }
DISPATCH();
}
- TARGET(CALL_FUNCTION_VAR)
- TARGET(CALL_FUNCTION_KW)
- TARGET(CALL_FUNCTION_VAR_KW) {
- Py_ssize_t nargs = oparg & 0xff;
- Py_ssize_t nkwargs = (oparg>>8) & 0xff;
- int flags = (opcode - CALL_FUNCTION) & 3;
- Py_ssize_t n;
- PyObject **pfunc, *func, **sp, *res;
+ TARGET(CALL_FUNCTION_KW) {
+ PyObject **sp, *res, *names;
+
+ names = POP();
+ assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg);
PCALL(PCALL_ALL);
+ sp = stack_pointer;
+#ifdef WITH_TSC
+ res = call_function(&sp, oparg, names, &intr0, &intr1);
+#else
+ res = call_function(&sp, oparg, names);
+#endif
+ stack_pointer = sp;
+ PUSH(res);
+ Py_DECREF(names);
- n = nargs + 2 * nkwargs;
- if (flags & CALL_FLAG_VAR) {
- n++;
- }
- if (flags & CALL_FLAG_KW) {
- n++;
+ if (res == NULL) {
+ goto error;
}
- pfunc = stack_pointer - n - 1;
- func = *pfunc;
+ DISPATCH();
+ }
- if (PyMethod_Check(func)
- && PyMethod_GET_SELF(func) != NULL) {
- PyObject *self = PyMethod_GET_SELF(func);
- Py_INCREF(self);
- func = PyMethod_GET_FUNCTION(func);
- Py_INCREF(func);
- Py_SETREF(*pfunc, self);
- nargs++;
- }
- else {
- Py_INCREF(func);
+ TARGET(CALL_FUNCTION_EX) {
+ PyObject *func, *callargs, *kwargs = NULL, *result;
+ PCALL(PCALL_ALL);
+ if (oparg & 0x01) {
+ kwargs = POP();
+ assert(PyDict_CheckExact(kwargs));
}
- sp = stack_pointer;
+ callargs = POP();
+ assert(PyTuple_CheckExact(callargs));
+ func = TOP();
+
READ_TIMESTAMP(intr0);
- res = ext_do_call(func, &sp, flags, nargs, nkwargs);
+ result = do_call_core(func, callargs, kwargs);
READ_TIMESTAMP(intr1);
- stack_pointer = sp;
Py_DECREF(func);
+ Py_DECREF(callargs);
+ Py_XDECREF(kwargs);
- while (stack_pointer > pfunc) {
- PyObject *o = POP();
- Py_DECREF(o);
- }
- PUSH(res);
- if (res == NULL)
+ SET_TOP(result);
+ if (result == NULL) {
goto error;
+ }
DISPATCH();
}
@@ -3950,7 +3947,6 @@ too_many_positional(PyCodeObject *co, Py_ssize_t given, Py_ssize_t defcount,
Py_DECREF(kwonly_sig);
}
-
/* This is gonna seem *real weird*, but if you put some other code between
PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
@@ -3959,6 +3955,7 @@ static PyObject *
_PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, Py_ssize_t argcount,
PyObject **kws, Py_ssize_t kwcount,
+ PyObject *kwnames, PyObject **kwstack,
PyObject **defs, Py_ssize_t defcount,
PyObject *kwdefs, PyObject *closure,
PyObject *name, PyObject *qualname)
@@ -3972,6 +3969,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
Py_ssize_t i, n;
PyObject *kwdict;
+ Py_ssize_t kwcount2 = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames);
assert((kwcount == 0) || (kws != NULL));
@@ -4033,7 +4031,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
}
}
- /* Handle keyword arguments (passed as an array of (key, value)) */
+ /* Handle keyword arguments passed as an array of (key, value) pairs */
for (i = 0; i < kwcount; i++) {
PyObject **co_varnames;
PyObject *keyword = kws[2*i];
@@ -4092,6 +4090,61 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
SETLOCAL(j, value);
}
+ /* Handle keyword arguments passed as keys tuple + values array */
+ for (i = 0; i < kwcount2; i++) {
+ PyObject **co_varnames;
+ PyObject *keyword = PyTuple_GET_ITEM(kwnames, i);
+ PyObject *value = kwstack[i];
+ int j;
+ if (keyword == NULL || !PyUnicode_Check(keyword)) {
+ PyErr_Format(PyExc_TypeError,
+ "%U() keywords must be strings",
+ co->co_name);
+ goto fail;
+ }
+ /* Speed hack: do raw pointer compares. As names are
+ normally interned this should almost always hit. */
+ co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
+ for (j = 0; j < total_args; j++) {
+ PyObject *nm = co_varnames[j];
+ if (nm == keyword)
+ goto kw_found2;
+ }
+ /* Slow fallback, just in case */
+ for (j = 0; j < total_args; j++) {
+ PyObject *nm = co_varnames[j];
+ int cmp = PyObject_RichCompareBool(
+ keyword, nm, Py_EQ);
+ if (cmp > 0)
+ goto kw_found2;
+ else if (cmp < 0)
+ goto fail;
+ }
+ if (j >= total_args && kwdict == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%U() got an unexpected "
+ "keyword argument '%S'",
+ co->co_name,
+ keyword);
+ goto fail;
+ }
+ if (PyDict_SetItem(kwdict, keyword, value) == -1) {
+ goto fail;
+ }
+ continue;
+ kw_found2:
+ if (GETLOCAL(j) != NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "%U() got multiple "
+ "values for argument '%S'",
+ co->co_name,
+ keyword);
+ goto fail;
+ }
+ Py_INCREF(value);
+ SETLOCAL(j, value);
+ }
+
/* Check the number of positional arguments */
if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
too_many_positional(co, argcount, defcount, fastlocals);
@@ -4244,6 +4297,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
return _PyEval_EvalCodeWithName(_co, globals, locals,
args, argcount,
kws, kwcount,
+ NULL, NULL,
defs, defcount,
kwdefs, closure,
NULL, NULL);
@@ -4886,28 +4940,27 @@ if (tstate->use_tracing && tstate->c_profilefunc) { \
}
static PyObject *
-call_function(PyObject ***pp_stack, int oparg
+call_function(PyObject ***pp_stack, Py_ssize_t oparg, PyObject *names
#ifdef WITH_TSC
, uint64* pintr0, uint64* pintr1
#endif
)
{
- Py_ssize_t nargs = oparg & 0xff;
- Py_ssize_t nkwargs = (oparg>>8) & 0xff;
- int n = nargs + 2 * nkwargs;
- PyObject **pfunc = (*pp_stack) - n - 1;
+ PyObject **pfunc = (*pp_stack) - oparg - 1;
PyObject *func = *pfunc;
PyObject *x, *w;
+ Py_ssize_t nk = names == NULL ? 0 : PyTuple_GET_SIZE(names);
+ Py_ssize_t nargs = oparg - nk;
/* Always dispatch PyCFunction first, because these are
presumed to be the most frequent callable object.
*/
- if (PyCFunction_Check(func) && nkwargs == 0) {
+ if (PyCFunction_Check(func)) {
int flags = PyCFunction_GET_FLAGS(func);
PyThreadState *tstate = PyThreadState_GET();
PCALL(PCALL_CFUNCTION);
- if (flags & (METH_NOARGS | METH_O)) {
+ if (names == NULL && flags & (METH_NOARGS | METH_O)) {
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
if (flags & METH_NOARGS && nargs == 0) {
@@ -4928,48 +4981,57 @@ call_function(PyObject ***pp_stack, int oparg
}
}
else {
- PyObject *callargs;
+ PyObject *callargs, *kwdict = NULL;
+ if (names != NULL) {
+ kwdict = create_keyword_args(names, pp_stack, func);
+ if (kwdict == NULL) {
+ x = NULL;
+ goto cfuncerror;
+ }
+ }
callargs = load_args(pp_stack, nargs);
if (callargs != NULL) {
READ_TIMESTAMP(*pintr0);
- C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
+ C_TRACE(x, PyCFunction_Call(func, callargs, kwdict));
READ_TIMESTAMP(*pintr1);
- Py_XDECREF(callargs);
+ Py_DECREF(callargs);
}
else {
x = NULL;
}
+ Py_XDECREF(kwdict);
}
}
else {
- if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
- /* optimize access to bound methods */
- PyObject *self = PyMethod_GET_SELF(func);
- PCALL(PCALL_METHOD);
- PCALL(PCALL_BOUND_METHOD);
- Py_INCREF(self);
- func = PyMethod_GET_FUNCTION(func);
- Py_INCREF(func);
- Py_SETREF(*pfunc, self);
- nargs++;
- n++;
- }
- else {
- Py_INCREF(func);
- }
- READ_TIMESTAMP(*pintr0);
- if (PyFunction_Check(func)) {
- x = fast_function(func, (*pp_stack) - n, nargs, nkwargs);
- }
- else {
- x = do_call(func, pp_stack, nargs, nkwargs);
- }
- READ_TIMESTAMP(*pintr1);
- Py_DECREF(func);
-
- assert((x != NULL) ^ (PyErr_Occurred() != NULL));
+ if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
+ /* optimize access to bound methods */
+ PyObject *self = PyMethod_GET_SELF(func);
+ PCALL(PCALL_METHOD);
+ PCALL(PCALL_BOUND_METHOD);
+ Py_INCREF(self);
+ func = PyMethod_GET_FUNCTION(func);
+ Py_INCREF(func);
+ Py_SETREF(*pfunc, self);
+ nargs++;
+ }
+ else {
+ Py_INCREF(func);
+ }
+
+ READ_TIMESTAMP(*pintr0);
+ if (PyFunction_Check(func)) {
+ x = fast_function(func, pp_stack, nargs, names);
+ } else {
+ x = do_call(func, pp_stack, nargs, names);
+ }
+ READ_TIMESTAMP(*pintr1);
+
+ Py_DECREF(func);
}
+cfuncerror:
+ assert((x != NULL) ^ (PyErr_Occurred() != NULL));
+
/* Clear the stack of the function object. Also removes
the arguments in case they weren't consumed already
(fast_function() and err_args() leave them on the stack).
@@ -4980,7 +5042,6 @@ call_function(PyObject ***pp_stack, int oparg
PCALL(PCALL_POP);
}
- assert((x != NULL) ^ (PyErr_Occurred() != NULL));
return x;
}
@@ -5033,19 +5094,16 @@ _PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t nargs,
/* Similar to _PyFunction_FastCall() but keywords are passed a (key, value)
pairs in stack */
static PyObject *
-fast_function(PyObject *func, PyObject **stack, Py_ssize_t nargs, Py_ssize_t nkwargs)
+fast_function(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, PyObject *names)
{
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;
- int nd;
-
- assert(func != NULL);
- assert(nargs >= 0);
- assert(nkwargs >= 0);
- assert((nargs == 0 && nkwargs == 0) || stack != NULL);
+ Py_ssize_t nkwargs = names == NULL ? 0 : PyTuple_GET_SIZE(names);
+ Py_ssize_t nd;
+ PyObject **stack = (*pp_stack)-nargs-nkwargs;
PCALL(PCALL_FUNCTION);
PCALL(PCALL_FAST_FUNCTION);
@@ -5081,8 +5139,9 @@ fast_function(PyObject *func, PyObject **stack, Py_ssize_t nargs, Py_ssize_t nkw
}
return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
stack, nargs,
- stack + nargs, nkwargs,
- d, nd, kwdefs,
+ NULL, 0,
+ names, stack + nargs,
+ d, (int)nd, kwdefs,
closure, name, qualname);
}
@@ -5166,6 +5225,7 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL,
args, nargs,
k, nk,
+ NULL, NULL,
d, nd, kwdefs,
closure, name, qualname);
Py_XDECREF(kwtuple);
@@ -5173,22 +5233,17 @@ _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
}
static PyObject *
-update_keyword_args(PyObject *orig_kwdict, Py_ssize_t nk, PyObject ***pp_stack,
+create_keyword_args(PyObject *names, PyObject ***pp_stack,
PyObject *func)
{
- PyObject *kwdict = NULL;
- if (orig_kwdict == NULL)
- kwdict = PyDict_New();
- else {
- kwdict = PyDict_Copy(orig_kwdict);
- Py_DECREF(orig_kwdict);
- }
+ Py_ssize_t nk = PyTuple_GET_SIZE(names);
+ PyObject *kwdict = _PyDict_NewPresized(nk);
if (kwdict == NULL)
return NULL;
while (--nk >= 0) {
int err;
PyObject *value = EXT_POP(*pp_stack);
- PyObject *key = EXT_POP(*pp_stack);
+ PyObject *key = PyTuple_GET_ITEM(names, nk);
if (PyDict_GetItem(kwdict, key) != NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s%s got multiple values "
@@ -5196,13 +5251,11 @@ update_keyword_args(PyObject *orig_kwdict, Py_ssize_t nk, PyObject ***pp_stack,
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
key);
- Py_DECREF(key);
Py_DECREF(value);
Py_DECREF(kwdict);
return NULL;
}
err = PyDict_SetItem(kwdict, key, value);
- Py_DECREF(key);
Py_DECREF(value);
if (err) {
Py_DECREF(kwdict);
@@ -5213,183 +5266,51 @@ update_keyword_args(PyObject *orig_kwdict, Py_ssize_t nk, PyObject ***pp_stack,
}
static PyObject *
-update_star_args(Py_ssize_t nstack, Py_ssize_t nstar, PyObject *stararg,
- PyObject ***pp_stack)
+load_args(PyObject ***pp_stack, Py_ssize_t nargs)
{
- PyObject *callargs, *w;
+ PyObject *args = PyTuple_New(nargs);
- if (!nstack) {
- if (!stararg) {
- /* There are no positional arguments on the stack and there is no
- sequence to be unpacked. */
- return PyTuple_New(0);
- }
- if (PyTuple_CheckExact(stararg)) {
- /* No arguments are passed on the stack and the sequence is not a
- tuple subclass so we can just pass the stararg tuple directly
- to the function. */
- Py_INCREF(stararg);
- return stararg;
- }
- }
-
- callargs = PyTuple_New(nstack + nstar);
- if (callargs == NULL) {
+ if (args == NULL) {
return NULL;
}
- if (nstar) {
- Py_ssize_t i;
- for (i = 0; i < nstar; i++) {
- PyObject *arg = PyTuple_GET_ITEM(stararg, i);
- Py_INCREF(arg);
- PyTuple_SET_ITEM(callargs, nstack + i, arg);
- }
- }
-
- while (--nstack >= 0) {
- w = EXT_POP(*pp_stack);
- PyTuple_SET_ITEM(callargs, nstack, w);
- }
- return callargs;
-}
-
-static PyObject *
-load_args(PyObject ***pp_stack, Py_ssize_t na)
-{
- PyObject *args = PyTuple_New(na);
- PyObject *w;
-
- if (args == NULL)
- return NULL;
- while (--na >= 0) {
- w = EXT_POP(*pp_stack);
- PyTuple_SET_ITEM(args, na, w);
+ while (--nargs >= 0) {
+ PyObject *arg= EXT_POP(*pp_stack);
+ PyTuple_SET_ITEM(args, nargs, arg);
}
return args;
}
static PyObject *
-do_call(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, Py_ssize_t nkwargs)
+do_call(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, PyObject *kwnames)
{
- PyObject *callargs = NULL;
- PyObject *kwdict = NULL;
- PyObject *result = NULL;
+ PyObject *callargs, *kwdict, *result;
- if (nkwargs > 0) {
- kwdict = update_keyword_args(NULL, nkwargs, pp_stack, func);
- if (kwdict == NULL)
- goto call_fail;
+ if (kwnames != NULL) {
+ kwdict = create_keyword_args(kwnames, pp_stack, func);
+ if (kwdict == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ kwdict = NULL;
}
+
callargs = load_args(pp_stack, nargs);
- if (callargs == NULL)
- goto call_fail;
-#ifdef CALL_PROFILE
- /* At this point, we have to look at the type of func to
- update the call stats properly. Do it here so as to avoid
- exposing the call stats machinery outside ceval.c
- */
- if (PyFunction_Check(func))
- PCALL(PCALL_FUNCTION);
- else if (PyMethod_Check(func))
- PCALL(PCALL_METHOD);
- else if (PyType_Check(func))
- PCALL(PCALL_TYPE);
- else if (PyCFunction_Check(func))
- PCALL(PCALL_CFUNCTION);
- else
- PCALL(PCALL_OTHER);
-#endif
- if (PyCFunction_Check(func)) {
- PyThreadState *tstate = PyThreadState_GET();
- C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
+ if (callargs == NULL) {
+ Py_XDECREF(kwdict);
+ return NULL;
}
- else
- result = PyObject_Call(func, callargs, kwdict);
-call_fail:
+
+ result = do_call_core(func, callargs, kwdict);
Py_XDECREF(callargs);
Py_XDECREF(kwdict);
return result;
}
static PyObject *
-ext_do_call(PyObject *func, PyObject ***pp_stack, int flags,
- Py_ssize_t nargs, Py_ssize_t nkwargs)
+do_call_core(PyObject *func, PyObject *callargs, PyObject *kwdict)
{
- Py_ssize_t nstar;
- PyObject *callargs = NULL;
- PyObject *stararg = NULL;
- PyObject *kwdict = NULL;
- PyObject *result = NULL;
-
- if (flags & CALL_FLAG_KW) {
- kwdict = EXT_POP(*pp_stack);
- if (!PyDict_CheckExact(kwdict)) {
- PyObject *d;
- d = PyDict_New();
- if (d == NULL)
- goto ext_call_fail;
- if (PyDict_Update(d, kwdict) != 0) {
- Py_DECREF(d);
- /* PyDict_Update raises attribute
- * error (percolated from an attempt
- * to get 'keys' attribute) instead of
- * a type error if its second argument
- * is not a mapping.
- */
- if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s%.200s argument after ** "
- "must be a mapping, not %.200s",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func),
- kwdict->ob_type->tp_name);
- }
- goto ext_call_fail;
- }
- Py_DECREF(kwdict);
- kwdict = d;
- }
- }
-
- if (nkwargs > 0) {
- kwdict = update_keyword_args(kwdict, nkwargs, pp_stack, func);
- if (kwdict == NULL)
- goto ext_call_fail;
- }
-
- if (flags & CALL_FLAG_VAR) {
- stararg = EXT_POP(*pp_stack);
- if (!PyTuple_Check(stararg)) {
- PyObject *t = NULL;
- if (Py_TYPE(stararg)->tp_iter == NULL &&
- !PySequence_Check(stararg)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s%.200s argument after * "
- "must be an iterable, not %.200s",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func),
- stararg->ob_type->tp_name);
- goto ext_call_fail;
- }
- t = PySequence_Tuple(stararg);
- if (t == NULL) {
- goto ext_call_fail;
- }
- Py_DECREF(stararg);
- stararg = t;
- }
- nstar = PyTuple_GET_SIZE(stararg);
- }
- else {
- nstar = 0;
- }
-
- callargs = update_star_args(nargs, nstar, stararg, pp_stack);
- if (callargs == NULL) {
- goto ext_call_fail;
- }
-
#ifdef CALL_PROFILE
/* At this point, we have to look at the type of func to
update the call stats properly. Do it here so as to avoid
@@ -5406,19 +5327,16 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags,
else
PCALL(PCALL_OTHER);
#endif
+
if (PyCFunction_Check(func)) {
+ PyObject *result;
PyThreadState *tstate = PyThreadState_GET();
C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
+ return result;
}
else {
- result = PyObject_Call(func, callargs, kwdict);
+ return PyObject_Call(func, callargs, kwdict);
}
-
-ext_call_fail:
- Py_XDECREF(callargs);
- Py_XDECREF(kwdict);
- Py_XDECREF(stararg);
- return result;
}
/* Extract a slice index from a PyLong or an object with the