summaryrefslogtreecommitdiffstats
path: root/Objects/abstract.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-08-23 22:01:56 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-08-23 22:01:56 (GMT)
commite62b85260542df5a7cb0c5b47507875ca7ffff23 (patch)
treecd6692cc4880940693e88244462ce85161aec43c /Objects/abstract.c
parenta9ba1ab21b44abea9775b076573f9c69c9e7153a (diff)
downloadcpython-e62b85260542df5a7cb0c5b47507875ca7ffff23.zip
cpython-e62b85260542df5a7cb0c5b47507875ca7ffff23.tar.gz
cpython-e62b85260542df5a7cb0c5b47507875ca7ffff23.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.
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..14021ba 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 (small_stack_size <= n) {
+ stack = small_stack;
+ }
+ else {
+ stack = PyMem_Malloc(n * sizeof(PyObject**));
+ 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;
}