diff -r c1a698edfa1b Include/abstract.h --- a/Include/abstract.h Tue Aug 23 16:22:35 2016 +0200 +++ b/Include/abstract.h Tue Aug 23 16:53:13 2016 +0200 @@ -292,6 +292,10 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx #define _PyObject_CallArg1(func, arg) \ _PyObject_FastCall((func), &(arg), 1) + PyAPI_FUNC(PyObject *) _PyObject_Call_Preprend(PyObject *func, + PyObject *obj, PyObject *args, + PyObject *kwargs); + PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where); diff -r c1a698edfa1b Objects/abstract.c --- a/Objects/abstract.c Tue Aug 23 16:22:35 2016 +0200 +++ b/Objects/abstract.c Tue Aug 23 16:53:13 2016 +0200 @@ -2309,6 +2309,45 @@ exit: return result; } +/* Positional arguments are obj followed args. */ +PyObject * +_PyObject_Call_Preprend(PyObject *func, + PyObject *obj, PyObject *args, PyObject *kwargs) +{ + PyObject *small_stack[5]; + PyObject **stack; + Py_ssize_t argcount; + PyObject *result; + + assert(PyTuple_Check(args)); + + argcount = PyTuple_GET_SIZE(args); + if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { + stack = small_stack; + } + else { + stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *)); + if (stack == NULL) { + PyErr_NoMemory(); + return NULL; + } + } + + /* use borrowed references */ + stack[0] = obj; + Py_MEMCPY(&stack[1], + &PyTuple_GET_ITEM(args, 0), + argcount * sizeof(PyObject *)); + + result = _PyObject_FastCallDict(func, + stack, argcount + 1, + kwargs); + if (stack != small_stack) { + PyMem_Free(stack); + } + return result; +} + static PyObject* call_function_tail(PyObject *callable, PyObject *args) { diff -r c1a698edfa1b Objects/classobject.c --- a/Objects/classobject.c Tue Aug 23 16:22:35 2016 +0200 +++ b/Objects/classobject.c Tue Aug 23 16:53:13 2016 +0200 @@ -302,34 +302,19 @@ method_traverse(PyMethodObject *im, visi } static PyObject * -method_call(PyObject *func, PyObject *arg, PyObject *kw) +method_call(PyObject *method, PyObject *args, PyObject *kwargs) { - PyObject *self = PyMethod_GET_SELF(func); - PyObject *result; + PyObject *self, *func; - func = PyMethod_GET_FUNCTION(func); + self = PyMethod_GET_SELF(method); if (self == NULL) { PyErr_BadInternalCall(); return NULL; } - else { - Py_ssize_t argcount = PyTuple_Size(arg); - PyObject *newarg = PyTuple_New(argcount + 1); - int i; - if (newarg == NULL) - return NULL; - Py_INCREF(self); - PyTuple_SET_ITEM(newarg, 0, self); - for (i = 0; i < argcount; i++) { - PyObject *v = PyTuple_GET_ITEM(arg, i); - Py_XINCREF(v); - PyTuple_SET_ITEM(newarg, i+1, v); - } - arg = newarg; - } - result = PyObject_Call((PyObject *)func, arg, kw); - Py_DECREF(arg); - return result; + + func = PyMethod_GET_FUNCTION(method); + + return _PyObject_Call_Preprend(func, self, args, kwargs); } static PyObject * diff -r c1a698edfa1b Objects/typeobject.c --- a/Objects/typeobject.c Tue Aug 23 16:22:35 2016 +0200 +++ b/Objects/typeobject.c Tue Aug 23 16:53:13 2016 +0200 @@ -6357,28 +6357,13 @@ static PyObject * slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyObject *func; - PyObject *newargs, *x; - Py_ssize_t i, n; func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__); - if (func == NULL) + if (func == NULL) { return NULL; - assert(PyTuple_Check(args)); - n = PyTuple_GET_SIZE(args); - newargs = PyTuple_New(n+1); - if (newargs == NULL) - return NULL; - Py_INCREF(type); - PyTuple_SET_ITEM(newargs, 0, (PyObject *)type); - for (i = 0; i < n; i++) { - x = PyTuple_GET_ITEM(args, i); - Py_INCREF(x); - PyTuple_SET_ITEM(newargs, i+1, x); - } - x = PyObject_Call(func, newargs, kwds); - Py_DECREF(newargs); - Py_DECREF(func); - return x; + } + + return _PyObject_Call_Preprend(func, (PyObject *)type, args, kwds); } static void