Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 62106) +++ Python/ceval.c (working copy) @@ -85,22 +85,6 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *); -/* Forward declarations */ -#ifdef WITH_TSC -static PyObject * call_function(PyObject ***, int, uint64*, uint64*); -#else -static PyObject * call_function(PyObject ***, int); -#endif -static PyObject * fast_function(PyObject *, PyObject ***, int, int, int); -static PyObject * do_call(PyObject *, PyObject ***, int, int); -static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int); -static PyObject * update_keyword_args(PyObject *, int, PyObject ***, - PyObject *); -static PyObject * update_star_args(int, int, PyObject *, PyObject ***); -static PyObject * load_args(PyObject ***, int); -#define CALL_FLAG_VAR 1 -#define CALL_FLAG_KW 2 - #ifdef LLTRACE static int lltrace; static int prtrace(PyObject *, char *); @@ -533,6 +517,9 @@ PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); PyCodeObject *co; + + PyObject *vargs = NULL; + PyObject *vkwds = NULL; /* when tracing we set things up so that @@ -2332,70 +2319,83 @@ PREDICT(END_FINALLY); break; } - - case CALL_FUNCTION: - { - PyObject **sp; - PCALL(PCALL_ALL); - sp = stack_pointer; -#ifdef WITH_TSC - x = call_function(&sp, oparg, &intr0, &intr1); -#else - x = call_function(&sp, oparg); -#endif - stack_pointer = sp; - PUSH(x); - if (x != NULL) - continue; - break; - } - - case CALL_FUNCTION_VAR: case CALL_FUNCTION_KW: + vkwds = POP(); + assert(vkwds); + goto call_function_case; case CALL_FUNCTION_VAR_KW: - { - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int flags = (opcode - CALL_FUNCTION) & 3; - int n = na + 2 * nk; - PyObject **pfunc, *func, **sp; - PCALL(PCALL_ALL); - if (flags & CALL_FLAG_VAR) - n++; - if (flags & CALL_FLAG_KW) - n++; - pfunc = stack_pointer - n - 1; - func = *pfunc; - - 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_DECREF(*pfunc); - *pfunc = self; - na++; - n++; - } else - Py_INCREF(func); - sp = stack_pointer; - READ_TIMESTAMP(intr0); - x = ext_do_call(func, &sp, flags, na, nk); - READ_TIMESTAMP(intr1); - stack_pointer = sp; - Py_DECREF(func); - - while (stack_pointer > pfunc) { - w = POP(); - Py_DECREF(w); - } - PUSH(x); - if (x != NULL) - continue; - break; - } - + vkwds = POP(); + assert(vkwds); + /* fall through */ + case CALL_FUNCTION_VAR: + vargs = POP(); + assert(vargs); + /* fall through */ + call_function_case: + case CALL_FUNCTION: + { + PyObject* func = NULL; + PyObject* kwds = NULL; + PyObject* args = NULL; + PyObject* fastseq = NULL; + int na, nk; + Py_ssize_t nva, i; + x = NULL; + na = oparg & 0xff; + nk = (oparg>>8) & 0xff; + kwds = _PyDict_NewPresized(nk); + if (kwds == NULL) + goto call_function_error; + for (i = 0; i < nk; ++i) { + v = POP(); /* value */ + w = POP(); /* key */ + if (PyDict_SetItem(kwds, w, v) == -1) { + Py_XDECREF(v); + Py_XDECREF(w); + goto call_function_error; + } + } + if (vargs) { + fastseq = PySequence_Fast(vargs, "*args must be a sequence"); + if (fastseq == NULL) + goto call_function_error; + nva = PySequence_Fast_GET_SIZE(fastseq); + } + else + nva = 0; + args = PyTuple_New(na + nva); + if (args == NULL) + goto call_function_error; + for (i = 0; i < na; ++i) { + v = POP(); + PyTuple_SET_ITEM(args, na-i-1, v); + } + func = POP(); + if (vkwds) { + if (PyDict_Merge(kwds, vkwds, 0) == -1) + goto call_function_error; + } + for (; i < na + nva; ++i) { + v = PySequence_Fast_GET_ITEM(fastseq, i-na); + Py_INCREF(v); + PyTuple_SET_ITEM(args, i, v); + } + assert(STACK_LEVEL() >= 0); + x = PyObject_Call(func, args, kwds); + call_function_error: + Py_XDECREF(func); + Py_XDECREF(args); + Py_XDECREF(vargs); + Py_XDECREF(kwds); + Py_XDECREF(vkwds); + Py_XDECREF(fastseq); + vkwds = vargs = NULL; + PUSH(x); + if (x != NULL) + continue; + assert(PyErr_Occurred()); + break; + } case MAKE_FUNCTION: v = POP(); /* code object */ x = PyFunction_New(v, f->f_globals); @@ -2620,6 +2620,7 @@ } /* main loop */ assert(why != WHY_YIELD); + assert(STACK_LEVEL() >= 0); /* Pop remaining stack entries. */ while (!EMPTY()) { v = POP(); @@ -2723,15 +2724,22 @@ } if (argcount > co->co_argcount) { if (!(co->co_flags & CO_VARARGS)) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes %s %d " - "%sargument%s (%d given)", - PyString_AsString(co->co_name), - defcount ? "at most" : "exactly", - co->co_argcount, - kwcount ? "non-keyword " : "", - co->co_argcount == 1 ? "" : "s", - argcount); + PyObject *string; + PyObject *value; + string = PyString_FromFormat("%.200s() takes %s %d " + "%sargument%s (%d given)", + PyString_AsString(co->co_name), + defcount ? "at most" : "exactly", + co->co_argcount, + kwcount ? "non-keyword " : "", + co->co_argcount == 1 ? "" : "s", + argcount); + value = Py_BuildValue("Ossii", string, + defcount ? "at most" : "exactly", + kwcount ? "non-keyword " : "", + co->co_argcount, argcount); + PyErr_SetObject(PyExc_TypeError, value); + Py_XDECREF(string); goto fail; } n = co->co_argcount; @@ -2805,15 +2813,23 @@ int m = co->co_argcount - defcount; for (i = argcount; i < m; i++) { if (GETLOCAL(i) == NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s() takes %s %d " - "%sargument%s (%d given)", - PyString_AsString(co->co_name), - ((co->co_flags & CO_VARARGS) || - defcount) ? "at least" - : "exactly", - m, kwcount ? "non-keyword " : "", - m == 1 ? "" : "s", i); + PyObject *string; + PyObject *value; + string = PyString_FromFormat("%.200s() takes %s %d " + "%sargument%s (%d given)", + PyString_AsString(co->co_name), + ((co->co_flags & CO_VARARGS) || + defcount) ? "at least" + : "exactly", + m, kwcount ? "non-keyword " : "", + m == 1 ? "" : "s", i); + value = Py_BuildValue("Ossii", string, + ((co->co_flags & CO_VARARGS) || + defcount) ? "at least" + : "exactly", kwcount ? "non-keyword " : "", + m, i); + PyErr_SetObject(PyExc_TypeError, value); + Py_XDECREF(string); goto fail; } } @@ -3553,21 +3569,8 @@ } } -static void -err_args(PyObject *func, int flags, int nargs) -{ - if (flags & METH_NOARGS) - PyErr_Format(PyExc_TypeError, - "%.200s() takes no arguments (%d given)", - ((PyCFunctionObject *)func)->m_ml->ml_name, - nargs); - else - PyErr_Format(PyExc_TypeError, - "%.200s() takes exactly one argument (%d given)", - ((PyCFunctionObject *)func)->m_ml->ml_name, - nargs); -} + #define C_TRACE(x, call) \ if (tstate->use_tracing && tstate->c_profilefunc) { \ if (call_trace(tstate->c_profilefunc, \ @@ -3600,355 +3603,6 @@ x = call; \ } -static PyObject * -call_function(PyObject ***pp_stack, int oparg -#ifdef WITH_TSC - , uint64* pintr0, uint64* pintr1 -#endif - ) -{ - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int n = na + 2 * nk; - PyObject **pfunc = (*pp_stack) - n - 1; - PyObject *func = *pfunc; - PyObject *x, *w; - - /* Always dispatch PyCFunction first, because these are - presumed to be the most frequent callable object. - */ - if (PyCFunction_Check(func) && nk == 0) { - int flags = PyCFunction_GET_FLAGS(func); - PyThreadState *tstate = PyThreadState_GET(); - - PCALL(PCALL_CFUNCTION); - if (flags & (METH_NOARGS | METH_O)) { - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - if (flags & METH_NOARGS && na == 0) { - C_TRACE(x, (*meth)(self,NULL)); - } - else if (flags & METH_O && na == 1) { - PyObject *arg = EXT_POP(*pp_stack); - C_TRACE(x, (*meth)(self,arg)); - Py_DECREF(arg); - } - else { - err_args(func, flags, na); - x = NULL; - } - } - else { - PyObject *callargs; - callargs = load_args(pp_stack, na); - READ_TIMESTAMP(*pintr0); - C_TRACE(x, PyCFunction_Call(func,callargs,NULL)); - READ_TIMESTAMP(*pintr1); - Py_XDECREF(callargs); - } - } 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_DECREF(*pfunc); - *pfunc = self; - na++; - n++; - } else - Py_INCREF(func); - READ_TIMESTAMP(*pintr0); - if (PyFunction_Check(func)) - x = fast_function(func, pp_stack, n, na, nk); - else - x = do_call(func, pp_stack, na, nk); - READ_TIMESTAMP(*pintr1); - Py_DECREF(func); - } - - /* 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). - */ - while ((*pp_stack) > pfunc) { - w = EXT_POP(*pp_stack); - Py_DECREF(w); - PCALL(PCALL_POP); - } - return x; -} - -/* The fast_function() function optimize calls for which no argument - tuple is necessary; the objects are passed directly from the stack. - For the simplest case -- a function that takes only positional - arguments and is called with only positional arguments -- it - inlines the most primitive frame setup code from - PyEval_EvalCodeEx(), which vastly reduces the checks that must be - done before evaluating the frame. -*/ - -static PyObject * -fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk) -{ - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject **d = NULL; - int nd = 0; - - PCALL(PCALL_FUNCTION); - PCALL(PCALL_FAST_FUNCTION); - if (argdefs == NULL && co->co_argcount == n && nk==0 && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - PyFrameObject *f; - PyObject *retval = NULL; - PyThreadState *tstate = PyThreadState_GET(); - PyObject **fastlocals, **stack; - int i; - - PCALL(PCALL_FASTER_FUNCTION); - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) - return NULL; - - fastlocals = f->f_localsplus; - stack = (*pp_stack) - n; - - for (i = 0; i < n; i++) { - Py_INCREF(*stack); - fastlocals[i] = *stack++; - } - retval = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return retval; - } - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); - } - return PyEval_EvalCodeEx(co, globals, - (PyObject *)NULL, (*pp_stack)-n, na, - (*pp_stack)-2*nk, nk, d, nd, - PyFunction_GET_CLOSURE(func)); -} - -static PyObject * -update_keyword_args(PyObject *orig_kwdict, int nk, 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); - } - if (kwdict == NULL) - return NULL; - while (--nk >= 0) { - int err; - PyObject *value = EXT_POP(*pp_stack); - PyObject *key = EXT_POP(*pp_stack); - if (PyDict_GetItem(kwdict, key) != NULL) { - PyErr_Format(PyExc_TypeError, - "%.200s%s got multiple values " - "for keyword argument '%.200s'", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - PyString_AsString(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); - return NULL; - } - } - return kwdict; -} - -static PyObject * -update_star_args(int nstack, int nstar, PyObject *stararg, - PyObject ***pp_stack) -{ - PyObject *callargs, *w; - - callargs = PyTuple_New(nstack + nstar); - if (callargs == NULL) { - return NULL; - } - if (nstar) { - int i; - for (i = 0; i < nstar; i++) { - PyObject *a = PyTuple_GET_ITEM(stararg, i); - Py_INCREF(a); - PyTuple_SET_ITEM(callargs, nstack + i, a); - } - } - while (--nstack >= 0) { - w = EXT_POP(*pp_stack); - PyTuple_SET_ITEM(callargs, nstack, w); - } - return callargs; -} - -static PyObject * -load_args(PyObject ***pp_stack, int 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); - } - return args; -} - -static PyObject * -do_call(PyObject *func, PyObject ***pp_stack, int na, int nk) -{ - PyObject *callargs = NULL; - PyObject *kwdict = NULL; - PyObject *result = NULL; - - if (nk > 0) { - kwdict = update_keyword_args(NULL, nk, pp_stack, func); - if (kwdict == NULL) - goto call_fail; - } - callargs = load_args(pp_stack, na); - 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 - PCALL(PCALL_OTHER); -#endif - result = PyObject_Call(func, callargs, kwdict); - call_fail: - Py_XDECREF(callargs); - Py_XDECREF(kwdict); - return result; -} - -static PyObject * -ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) -{ - int nstar = 0; - PyObject *callargs = NULL; - PyObject *stararg = NULL; - PyObject *kwdict = NULL; - PyObject *result = NULL; - - if (flags & CALL_FLAG_KW) { - kwdict = EXT_POP(*pp_stack); - if (!PyDict_Check(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 (flags & CALL_FLAG_VAR) { - stararg = EXT_POP(*pp_stack); - if (!PyTuple_Check(stararg)) { - PyObject *t = NULL; - t = PySequence_Tuple(stararg); - if (t == NULL) { - if (PyErr_ExceptionMatches(PyExc_TypeError)) { - PyErr_Format(PyExc_TypeError, - "%.200s%.200s argument after * " - "must be a sequence, not %200s", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - stararg->ob_type->tp_name); - } - goto ext_call_fail; - } - Py_DECREF(stararg); - stararg = t; - } - nstar = PyTuple_GET_SIZE(stararg); - } - if (nk > 0) { - kwdict = update_keyword_args(kwdict, nk, pp_stack, func); - if (kwdict == NULL) - goto ext_call_fail; - } - callargs = update_star_args(na, 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 - 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 - PCALL(PCALL_OTHER); -#endif - result = 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 PyInt or PyLong or an object with the nb_index slot defined, and store in *pi. Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX, Index: Objects/classobject.c =================================================================== --- Objects/classobject.c (revision 62106) +++ Objects/classobject.c (working copy) @@ -2504,6 +2504,7 @@ static PyObject * instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *self = PyMethod_GET_SELF(func); PyObject *klass = PyMethod_GET_CLASS(func); PyObject *result; @@ -2538,7 +2539,6 @@ self == NULL ? "" : " instance"); return NULL; } - Py_INCREF(arg); } else { Py_ssize_t argcount = PyTuple_Size(arg); @@ -2553,10 +2553,33 @@ Py_XINCREF(v); PyTuple_SET_ITEM(newarg, i+1, v); } - arg = newarg; + result = PyObject_Call((PyObject *)func, newarg, kw); + if (result == 0 && PyErr_ExceptionMatches(PyExc_TypeError)) { + PyObject *type, *value, *traceback; + PyErr_Fetch(&type, &value, &traceback); + if (PyTuple_Check(value)) { + PyObject *string = NULL, *name = NULL; + int given = -1, expected = -1; + char *s1 = "", *s2 = ""; + char clsbuf[256]; + getclassname(klass, clsbuf, sizeof(clsbuf)); + name = PyObject_GetAttrString(func, "__name__"); + PyArg_ParseTuple(value, "Ossii", &string, &s1, &s2, + &expected, &given); + --expected; + --given; + value = PyString_FromFormat("<%.200s object>.%.200s takes" + " %s %d %sargument%s (%d given)", + clsbuf, PyString_AsString(name), + s1, expected, s2, + expected == 1 ? "" : "s", given); + Py_XDECREF(name); + } + PyErr_Restore(type, value, traceback); + } + return result; } result = PyObject_Call((PyObject *)func, arg, kw); - Py_DECREF(arg); return result; }