summaryrefslogtreecommitdiffstats
path: root/Objects/abstract.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-08-23 23:14:54 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-08-23 23:14:54 (GMT)
commitdd69564c38de21f2ede269c55fce6db24bb27941 (patch)
tree4ca7943d6efaf2a1a30190233403095b50cee1ae /Objects/abstract.c
parentd48af09043e3f84bc8d3d0e2d9adb4f0be2a70fd (diff)
downloadcpython-dd69564c38de21f2ede269c55fce6db24bb27941.zip
cpython-dd69564c38de21f2ede269c55fce6db24bb27941.tar.gz
cpython-dd69564c38de21f2ede269c55fce6db24bb27941.tar.bz2
PyObject_CallMethodObjArgs() now uses fast call
Issue #27809: * PyObject_CallMethodObjArgs(), _PyObject_CallMethodIdObjArgs() and PyObject_CallFunctionObjArgs() now use fast call to avoid the creation of a temporary tuple * Rename objargs_mktuple() to objargs_mkstack() * objargs_mkstack() now stores objects in a C array using borrowed references, instead of storing arguments into a tuple objargs_mkstack() uses a small buffer allocated on the C stack for 5 arguments or less, or allocates a buffer in the heap memory. Note: this change is different than the change 0e4f26083bbb, I fixed the test to decide if the small stack can be used or not. sizeof(PyObject**) was also replaced with sizeof(stack[0]) since the sizeof() was wrong (but gave the same result).
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r--Objects/abstract.c103
1 files changed, 71 insertions, 32 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 0e67693..6db8c26 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -2499,32 +2499,52 @@ _PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name,
return retval;
}
-static PyObject *
-objargs_mktuple(va_list va)
+static PyObject **
+objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size,
+ va_list va, Py_ssize_t *p_nargs)
{
- int i, n = 0;
+ Py_ssize_t i, n;
va_list countva;
- PyObject *result, *tmp;
+ PyObject **stack;
- Py_VA_COPY(countva, va);
+ /* Count the number of arguments */
+ Py_VA_COPY(countva, va);
- while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
- ++n;
- result = PyTuple_New(n);
- if (result != NULL && n > 0) {
- for (i = 0; i < n; ++i) {
- tmp = (PyObject *)va_arg(va, PyObject *);
- PyTuple_SET_ITEM(result, i, tmp);
- Py_INCREF(tmp);
+ n = 0;
+ while (1) {
+ PyObject *arg = (PyObject *)va_arg(countva, PyObject *);
+ if (arg == NULL) {
+ break;
}
+ n++;
}
- return result;
+ *p_nargs = n;
+
+ /* Copy arguments */
+ if (n <= small_stack_size) {
+ stack = small_stack;
+ }
+ else {
+ stack = PyMem_Malloc(n * sizeof(stack[0]));
+ if (stack == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ }
+
+ for (i = 0; i < n; ++i) {
+ stack[i] = va_arg(va, PyObject *);
+ }
+ return stack;
}
PyObject *
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
{
- PyObject *args, *tmp;
+ PyObject *small_stack[5];
+ PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
va_list vargs;
if (callable == NULL || name == NULL) {
@@ -2537,24 +2557,31 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
/* count the args */
va_start(vargs, name);
- args = objargs_mktuple(vargs);
+ stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
+ vargs, &nargs);
va_end(vargs);
- if (args == NULL) {
+ if (stack == NULL) {
Py_DECREF(callable);
return NULL;
}
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+
+ result = _PyObject_FastCall(callable, stack, nargs);
Py_DECREF(callable);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
- return tmp;
+ return result;
}
PyObject *
_PyObject_CallMethodIdObjArgs(PyObject *callable,
struct _Py_Identifier *name, ...)
{
- PyObject *args, *tmp;
+ PyObject *small_stack[5];
+ PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
va_list vargs;
if (callable == NULL || name == NULL) {
@@ -2567,23 +2594,30 @@ _PyObject_CallMethodIdObjArgs(PyObject *callable,
/* count the args */
va_start(vargs, name);
- args = objargs_mktuple(vargs);
+ stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
+ vargs, &nargs);
va_end(vargs);
- if (args == NULL) {
+ if (stack == NULL) {
Py_DECREF(callable);
return NULL;
}
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+
+ result = _PyObject_FastCall(callable, stack, nargs);
Py_DECREF(callable);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
- return tmp;
+ return result;
}
PyObject *
PyObject_CallFunctionObjArgs(PyObject *callable, ...)
{
- PyObject *args, *tmp;
+ PyObject *small_stack[5];
+ PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
va_list vargs;
if (callable == NULL) {
@@ -2592,14 +2626,19 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...)
/* count the args */
va_start(vargs, callable);
- args = objargs_mktuple(vargs);
+ stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
+ vargs, &nargs);
va_end(vargs);
- if (args == NULL)
+ if (stack == NULL) {
return NULL;
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
+ }
+
+ result = _PyObject_FastCall(callable, stack, nargs);
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
- return tmp;
+ return result;
}