summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-08-24 23:04:14 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-08-24 23:04:14 (GMT)
commit3f1057a4b62d8c94ae77f34f950b74a45499b218 (patch)
treecb4815a4176534216b519be17cfe84b10ce74b54
parentf7507dd3e8ec84fe025c0ba82a9150275e2af9d9 (diff)
downloadcpython-3f1057a4b62d8c94ae77f34f950b74a45499b218.zip
cpython-3f1057a4b62d8c94ae77f34f950b74a45499b218.tar.gz
cpython-3f1057a4b62d8c94ae77f34f950b74a45499b218.tar.bz2
method_call() and slot_tp_new() now uses fast call
Issue #27841: Add _PyObject_Call_Prepend() helper function to prepend an argument to existing arguments to call a function. This helper uses fast calls. Modify method_call() and slot_tp_new() to use _PyObject_Call_Prepend().
-rw-r--r--Include/abstract.h4
-rw-r--r--Objects/abstract.c39
-rw-r--r--Objects/classobject.c29
-rw-r--r--Objects/typeobject.c23
4 files changed, 55 insertions, 40 deletions
diff --git a/Include/abstract.h b/Include/abstract.h
index 474d746..ebad84b 100644
--- a/Include/abstract.h
+++ b/Include/abstract.h
@@ -309,6 +309,10 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
Py_ssize_t nargs,
Py_ssize_t nkwargs);
+ PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(PyObject *func,
+ PyObject *obj, PyObject *args,
+ PyObject *kwargs);
+
PyAPI_FUNC(PyObject *) _Py_CheckFunctionResult(PyObject *func,
PyObject *result,
const char *where);
diff --git a/Objects/abstract.c b/Objects/abstract.c
index c41fe11..9e5405d 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2388,6 +2388,45 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
return result;
}
+/* Positional arguments are obj followed args. */
+PyObject *
+_PyObject_Call_Prepend(PyObject *func,
+ PyObject *obj, PyObject *args, PyObject *kwargs)
+{
+ PyObject *small_stack[8];
+ 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 --git a/Objects/classobject.c b/Objects/classobject.c
index 5e8ac59..b0ed023 100644
--- a/Objects/classobject.c
+++ b/Objects/classobject.c
@@ -302,34 +302,19 @@ method_traverse(PyMethodObject *im, visitproc visit, void *arg)
}
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_Prepend(func, self, args, kwargs);
}
static PyObject *
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 63bfd66..9b3d153 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -6356,29 +6356,16 @@ slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
static PyObject *
slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
- PyObject *func;
- PyObject *newargs, *x;
- Py_ssize_t i, n;
+ PyObject *func, *result;
func = _PyObject_GetAttrId((PyObject *)type, &PyId___new__);
- if (func == NULL)
- return NULL;
- assert(PyTuple_Check(args));
- n = PyTuple_GET_SIZE(args);
- newargs = PyTuple_New(n+1);
- if (newargs == NULL)
+ if (func == 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);
+
+ result = _PyObject_Call_Prepend(func, (PyObject *)type, args, kwds);
Py_DECREF(func);
- return x;
+ return result;
}
static void