]> granicus.if.org Git - python/commitdiff
method_call() and slot_tp_new() now uses fast call
authorVictor Stinner <victor.stinner@gmail.com>
Wed, 24 Aug 2016 23:04:14 +0000 (01:04 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Wed, 24 Aug 2016 23:04:14 +0000 (01:04 +0200)
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().

Include/abstract.h
Objects/abstract.c
Objects/classobject.c
Objects/typeobject.c

index 474d7468e7d53a20d594743ae1601666fc7c0a03..ebad84b30e508b542fe46cccc24f4bcfb7b27eb3 100644 (file)
@@ -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);
index c41fe11e3a1ce4674cae47a89069b4e8d4168bf1..9e5405df0a9b18f7b03a219649197ac3d7275bb4 100644 (file)
@@ -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)
 {
index 5e8ac59df25dc9d6960c09702340e94973bcea0e..b0ed02305695da2bf2754e7defadd4a71b1ce5d9 100644 (file)
@@ -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 *
index 63bfd66747739bb4aaf426e1f5b6610bb2666459..9b3d1533e9379c3d395fa5e0fa39ad2ba3540671 100644 (file)
@@ -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