summaryrefslogtreecommitdiff
path: root/Objects/abstract.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r--Objects/abstract.c603
1 files changed, 340 insertions, 263 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c
index d838856d45..6c66b03aec 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -103,7 +103,7 @@ PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
}
return defaultvalue;
}
- result = PyObject_CallFunctionObjArgs(hint, NULL);
+ result = _PyObject_CallNoArg(hint);
Py_DECREF(hint);
if (result == NULL) {
if (PyErr_ExceptionMatches(PyExc_TypeError)) {
@@ -252,14 +252,6 @@ PyObject_DelItemString(PyObject *o, const char *key)
cause issues later on. Don't use these functions in new code.
*/
int
-PyObject_AsCharBuffer(PyObject *obj,
- const char **buffer,
- Py_ssize_t *buffer_len)
-{
- return PyObject_AsReadBuffer(obj, (const void **)buffer, buffer_len);
-}
-
-int
PyObject_CheckReadBuffer(PyObject *obj)
{
PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
@@ -276,9 +268,8 @@ PyObject_CheckReadBuffer(PyObject *obj)
return 1;
}
-int PyObject_AsReadBuffer(PyObject *obj,
- const void **buffer,
- Py_ssize_t *buffer_len)
+static int
+as_read_buffer(PyObject *obj, const void **buffer, Py_ssize_t *buffer_len)
{
Py_buffer view;
@@ -295,6 +286,21 @@ int PyObject_AsReadBuffer(PyObject *obj,
return 0;
}
+int
+PyObject_AsCharBuffer(PyObject *obj,
+ const char **buffer,
+ Py_ssize_t *buffer_len)
+{
+ return as_read_buffer(obj, (const void **)buffer, buffer_len);
+}
+
+int PyObject_AsReadBuffer(PyObject *obj,
+ const void **buffer,
+ Py_ssize_t *buffer_len)
+{
+ return as_read_buffer(obj, buffer, buffer_len);
+}
+
int PyObject_AsWriteBuffer(PyObject *obj,
void **buffer,
Py_ssize_t *buffer_len)
@@ -2167,24 +2173,24 @@ PyMapping_Values(PyObject *o)
/* XXX PyCallable_Check() is in object.c */
PyObject *
-PyObject_CallObject(PyObject *o, PyObject *a)
+PyObject_CallObject(PyObject *callable, PyObject *args)
{
- return PyEval_CallObjectWithKeywords(o, a, NULL);
+ return PyEval_CallObjectWithKeywords(callable, args, NULL);
}
PyObject*
-_Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
+_Py_CheckFunctionResult(PyObject *callable, PyObject *result, const char *where)
{
int err_occurred = (PyErr_Occurred() != NULL);
- assert((func != NULL) ^ (where != NULL));
+ assert((callable != NULL) ^ (where != NULL));
if (result == NULL) {
if (!err_occurred) {
- if (func)
+ if (callable)
PyErr_Format(PyExc_SystemError,
"%R returned NULL without setting an error",
- func);
+ callable);
else
PyErr_Format(PyExc_SystemError,
"%s returned NULL without setting an error",
@@ -2200,10 +2206,10 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
if (err_occurred) {
Py_DECREF(result);
- if (func) {
+ if (callable) {
_PyErr_FormatFromCause(PyExc_SystemError,
"%R returned a result with an error set",
- func);
+ callable);
}
else {
_PyErr_FormatFromCause(PyExc_SystemError,
@@ -2221,36 +2227,49 @@ _Py_CheckFunctionResult(PyObject *func, PyObject *result, const char *where)
}
PyObject *
-PyObject_Call(PyObject *func, PyObject *args, PyObject *kwargs)
+PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
{
ternaryfunc call;
PyObject *result;
/* PyObject_Call() must not be called with an exception set,
- because it may clear it (directly or indirectly) and so the
+ because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(PyTuple_Check(args));
assert(kwargs == NULL || PyDict_Check(kwargs));
- call = func->ob_type->tp_call;
- if (call == NULL) {
- PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
- func->ob_type->tp_name);
- return NULL;
+ if (PyFunction_Check(callable)) {
+ return _PyFunction_FastCallDict(callable,
+ &PyTuple_GET_ITEM(args, 0),
+ PyTuple_GET_SIZE(args),
+ kwargs);
}
+ else if (PyCFunction_Check(callable)) {
+ return PyCFunction_Call(callable, args, kwargs);
+ }
+ else {
+ call = callable->ob_type->tp_call;
+ if (call == NULL) {
+ PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
+ callable->ob_type->tp_name);
+ return NULL;
+ }
- if (Py_EnterRecursiveCall(" while calling a Python object"))
- return NULL;
+ if (Py_EnterRecursiveCall(" while calling a Python object"))
+ return NULL;
- result = (*call)(func, args, kwargs);
+ result = (*call)(callable, args, kwargs);
- Py_LeaveRecursiveCall();
+ Py_LeaveRecursiveCall();
- return _Py_CheckFunctionResult(func, result, NULL);
+ return _Py_CheckFunctionResult(callable, result, NULL);
+ }
}
-PyObject*
+/* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their
+ stack consumption, Disable inlining to optimize the stack consumption. */
+PyObject* _Py_NO_INLINE
_PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
{
PyObject *args;
@@ -2266,71 +2285,127 @@ _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs)
Py_INCREF(item);
PyTuple_SET_ITEM(args, i, item);
}
+ return args;
+}
+PyObject*
+_PyStack_AsTupleSlice(PyObject **stack, Py_ssize_t nargs,
+ Py_ssize_t start, Py_ssize_t end)
+{
+ PyObject *args;
+ Py_ssize_t i;
+
+ assert(0 <= start);
+ assert(end <= nargs);
+ assert(start <= end);
+
+ args = PyTuple_New(end - start);
+ if (args == NULL) {
+ return NULL;
+ }
+
+ for (i=start; i < end; i++) {
+ PyObject *item = stack[i];
+ Py_INCREF(item);
+ PyTuple_SET_ITEM(args, i - start, item);
+ }
return args;
}
PyObject *
-_PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
+_PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs,
PyObject *kwargs)
{
- ternaryfunc call;
- PyObject *result = NULL;
-
/* _PyObject_FastCallDict() must not be called with an exception set,
- because it may clear it (directly or indirectly) and so the
+ because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
- assert(func != NULL);
+ assert(callable != NULL);
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
- if (Py_EnterRecursiveCall(" while calling a Python object")) {
- return NULL;
- }
-
- if (PyFunction_Check(func)) {
- result = _PyFunction_FastCallDict(func, args, nargs, kwargs);
+ if (PyFunction_Check(callable)) {
+ return _PyFunction_FastCallDict(callable, args, nargs, kwargs);
}
- else if (PyCFunction_Check(func)) {
- result = _PyCFunction_FastCallDict(func, args, nargs, kwargs);
+ else if (PyCFunction_Check(callable)) {
+ return _PyCFunction_FastCallDict(callable, args, nargs, kwargs);
}
else {
- PyObject *tuple;
+ PyObject *argstuple, *result;
+ ternaryfunc call;
/* Slow-path: build a temporary tuple */
- call = func->ob_type->tp_call;
+ call = callable->ob_type->tp_call;
if (call == NULL) {
PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
- func->ob_type->tp_name);
- goto exit;
+ callable->ob_type->tp_name);
+ return NULL;
}
- tuple = _PyStack_AsTuple(args, nargs);
- if (tuple == NULL) {
- goto exit;
+ argstuple = _PyStack_AsTuple(args, nargs);
+ if (argstuple == NULL) {
+ return NULL;
+ }
+
+ if (Py_EnterRecursiveCall(" while calling a Python object")) {
+ Py_DECREF(argstuple);
+ return NULL;
}
- result = (*call)(func, tuple, kwargs);
- Py_DECREF(tuple);
+ result = (*call)(callable, argstuple, kwargs);
- result = _Py_CheckFunctionResult(func, result, NULL);
+ Py_LeaveRecursiveCall();
+ Py_DECREF(argstuple);
+
+ result = _Py_CheckFunctionResult(callable, result, NULL);
+ return result;
}
+}
-exit:
- Py_LeaveRecursiveCall();
+/* Positional arguments are obj followed by args:
+ call callable(obj, *args, **kwargs) */
+PyObject *
+_PyObject_FastCall_Prepend(PyObject *callable,
+ PyObject *obj, PyObject **args, Py_ssize_t nargs)
+{
+ PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
+ PyObject **args2;
+ PyObject *result;
+ nargs++;
+ if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
+ args2 = small_stack;
+ }
+ else {
+ args2 = PyMem_Malloc(nargs * sizeof(PyObject *));
+ if (args2 == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ }
+
+ /* use borrowed references */
+ args2[0] = obj;
+ memcpy(&args2[1],
+ args,
+ (nargs - 1)* sizeof(PyObject *));
+
+ result = _PyObject_FastCall(callable, args2, nargs);
+ if (args2 != small_stack) {
+ PyMem_Free(args2);
+ }
return result;
}
-/* Positional arguments are obj followed by args. */
+
+/* Call callable(obj, *args, **kwargs). */
PyObject *
-_PyObject_Call_Prepend(PyObject *func,
+_PyObject_Call_Prepend(PyObject *callable,
PyObject *obj, PyObject *args, PyObject *kwargs)
{
- PyObject *small_stack[8];
+ PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack;
Py_ssize_t argcount;
PyObject *result;
@@ -2355,7 +2430,7 @@ _PyObject_Call_Prepend(PyObject *func,
&PyTuple_GET_ITEM(args, 0),
argcount * sizeof(PyObject *));
- result = _PyObject_FastCallDict(func,
+ result = _PyObject_FastCallDict(callable,
stack, argcount + 1,
kwargs);
if (stack != small_stack) {
@@ -2367,11 +2442,13 @@ _PyObject_Call_Prepend(PyObject *func,
PyObject *
_PyStack_AsDict(PyObject **values, PyObject *kwnames)
{
- Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames);
+ Py_ssize_t nkwargs;
PyObject *kwdict;
Py_ssize_t i;
- kwdict = PyDict_New();
+ assert(kwnames != NULL);
+ nkwargs = PyTuple_GET_SIZE(kwnames);
+ kwdict = _PyDict_NewPresized(nkwargs);
if (kwdict == NULL) {
return NULL;
}
@@ -2379,8 +2456,7 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
for (i = 0; i < nkwargs; i++) {
PyObject *key = PyTuple_GET_ITEM(kwnames, i);
PyObject *value = *values++;
- assert(PyUnicode_CheckExact(key));
- assert(PyDict_GetItem(kwdict, key) == NULL);
+ /* If key already exists, replace it with the new value */
if (PyDict_SetItem(kwdict, key, value)) {
Py_DECREF(kwdict);
return NULL;
@@ -2389,9 +2465,9 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
return kwdict;
}
-PyObject **
+int
_PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
- PyObject **p_kwnames, PyObject *func)
+ PyObject ***p_stack, PyObject **p_kwnames)
{
PyObject **stack, **kwstack;
Py_ssize_t nkwargs;
@@ -2402,27 +2478,27 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
assert(nargs >= 0);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
- nkwargs = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
- if (!nkwargs) {
+ if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) {
+ *p_stack = args;
*p_kwnames = NULL;
- return args;
+ return 0;
}
if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
PyErr_NoMemory();
- return NULL;
+ return -1;
}
stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
if (stack == NULL) {
PyErr_NoMemory();
- return NULL;
+ return -1;
}
kwnames = PyTuple_New(nkwargs);
if (kwnames == NULL) {
PyMem_Free(stack);
- return NULL;
+ return -1;
}
/* Copy position arguments (borrowed references) */
@@ -2441,61 +2517,136 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
i++;
}
+ *p_stack = stack;
*p_kwnames = kwnames;
- return stack;
+ return 0;
}
PyObject *
-_PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs,
+_PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t nargs,
PyObject *kwnames)
{
- PyObject *kwdict, *result;
- Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+ /* _PyObject_FastCallKeywords() must not be called with an exception set,
+ because it can clear it (directly or indirectly) and so the
+ caller loses its exception */
+ assert(!PyErr_Occurred());
assert(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
- assert((nargs == 0 && nkwargs == 0) || stack != NULL);
+
/* kwnames must only contains str strings, no subclass, and all keys must
- be unique: these are implemented in Python/ceval.c and
- _PyArg_ParseStack(). */
+ be unique: these checks are implemented in Python/ceval.c and
+ _PyArg_ParseStackAndKeywords(). */
- if (PyFunction_Check(func)) {
- return _PyFunction_FastCallKeywords(func, stack, nargs, kwnames);
+ if (PyFunction_Check(callable)) {
+ return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames);
}
-
- if (PyCFunction_Check(func)) {
- return _PyCFunction_FastCallKeywords(func, stack, nargs, kwnames);
+ if (PyCFunction_Check(callable)) {
+ return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames);
}
+ else {
+ /* Slow-path: build a temporary tuple for positional arguments and a
+ temporary dictionary for keyword arguments (if any) */
- if (nkwargs > 0) {
- kwdict = _PyStack_AsDict(stack + nargs, kwnames);
- if (kwdict == NULL) {
+ ternaryfunc call;
+ PyObject *argstuple;
+ PyObject *kwdict, *result;
+ Py_ssize_t nkwargs;
+
+ nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
+ assert((nargs == 0 && nkwargs == 0) || stack != NULL);
+
+ call = callable->ob_type->tp_call;
+ if (call == NULL) {
+ PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
+ callable->ob_type->tp_name);
return NULL;
}
- }
- else {
- kwdict = NULL;
- }
- result = _PyObject_FastCallDict(func, stack, nargs, kwdict);
- Py_XDECREF(kwdict);
- return result;
+ argstuple = _PyStack_AsTuple(stack, nargs);
+ if (argstuple == NULL) {
+ return NULL;
+ }
+
+ if (nkwargs > 0) {
+ kwdict = _PyStack_AsDict(stack + nargs, kwnames);
+ if (kwdict == NULL) {
+ Py_DECREF(argstuple);
+ return NULL;
+ }
+ }
+ else {
+ kwdict = NULL;
+ }
+
+ if (Py_EnterRecursiveCall(" while calling a Python object")) {
+ Py_DECREF(argstuple);
+ Py_XDECREF(kwdict);
+ return NULL;
+ }
+
+ result = (*call)(callable, argstuple, kwdict);
+
+ Py_LeaveRecursiveCall();
+
+ Py_DECREF(argstuple);
+ Py_XDECREF(kwdict);
+
+ result = _Py_CheckFunctionResult(callable, result, NULL);
+ return result;
+ }
}
-static PyObject*
-call_function_tail(PyObject *callable, PyObject *args)
+static PyObject *
+_PyObject_CallFunctionVa(PyObject *callable, const char *format,
+ va_list va, int is_size_t)
{
+ PyObject* small_stack[_PY_FASTCALL_SMALL_STACK];
+ const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack);
+ PyObject **stack;
+ Py_ssize_t nargs, i;
PyObject *result;
- assert(args != NULL);
+ if (callable == NULL) {
+ return null_error();
+ }
+
+ if (!format || !*format) {
+ return _PyObject_CallNoArg(callable);
+ }
+
+ if (is_size_t) {
+ stack = _Py_VaBuildStack_SizeT(small_stack, small_stack_len,
+ format, va, &nargs);
+ }
+ else {
+ stack = _Py_VaBuildStack(small_stack, small_stack_len,
+ format, va, &nargs);
+ }
+ if (stack == NULL) {
+ return NULL;
+ }
- if (!PyTuple_Check(args)) {
- result = _PyObject_CallArg1(callable, args);
+ if (nargs == 1 && PyTuple_Check(stack[0])) {
+ /* Special cases for backward compatibility:
+ - PyObject_CallFunction(func, "O", tuple) calls func(*tuple)
+ - PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls
+ func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */
+ PyObject *args = stack[0];
+ result = _PyObject_FastCall(callable,
+ &PyTuple_GET_ITEM(args, 0),
+ PyTuple_GET_SIZE(args));
}
else {
- result = PyObject_Call(callable, args, NULL);
+ result = _PyObject_FastCall(callable, stack, nargs);
}
+ for (i = 0; i < nargs; ++i) {
+ Py_DECREF(stack[i]);
+ }
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
return result;
}
@@ -2503,25 +2654,12 @@ PyObject *
PyObject_CallFunction(PyObject *callable, const char *format, ...)
{
va_list va;
- PyObject *args, *result;
-
- if (callable == NULL) {
- return null_error();
- }
-
- if (!format || !*format) {
- return _PyObject_CallNoArg(callable);
- }
+ PyObject *result;
va_start(va, format);
- args = Py_VaBuildValue(format, va);
+ result = _PyObject_CallFunctionVa(callable, format, va, 0);
va_end(va);
- if (args == NULL) {
- return NULL;
- }
- result = call_function_tail(callable, args);
- Py_DECREF(args);
return result;
}
@@ -2529,289 +2667,227 @@ PyObject *
_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...)
{
va_list va;
- PyObject *args, *result;
-
- if (callable == NULL) {
- return null_error();
- }
-
- if (!format || !*format) {
- return _PyObject_CallNoArg(callable);
- }
+ PyObject *result;
va_start(va, format);
- args = _Py_VaBuildValue_SizeT(format, va);
+ result = _PyObject_CallFunctionVa(callable, format, va, 1);
va_end(va);
- if (args == NULL) {
- return NULL;
- }
- result = call_function_tail(callable, args);
- Py_DECREF(args);
return result;
}
static PyObject*
-callmethod(PyObject* func, const char *format, va_list va, int is_size_t)
+callmethod(PyObject* callable, const char *format, va_list va, int is_size_t)
{
- PyObject *args, *result;
+ assert(callable != NULL);
- assert(func != NULL);
-
- if (!PyCallable_Check(func)) {
- type_error("attribute of type '%.200s' is not callable", func);
+ if (!PyCallable_Check(callable)) {
+ type_error("attribute of type '%.200s' is not callable", callable);
return NULL;
}
- if (!format || !*format) {
- return _PyObject_CallNoArg(func);
- }
-
- if (is_size_t) {
- args = _Py_VaBuildValue_SizeT(format, va);
- }
- else {
- args = Py_VaBuildValue(format, va);
- }
- if (args == NULL) {
- return NULL;
- }
-
- result = call_function_tail(func, args);
- Py_DECREF(args);
- return result;
+ return _PyObject_CallFunctionVa(callable, format, va, is_size_t);
}
PyObject *
-PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...)
+PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{
va_list va;
- PyObject *func = NULL;
- PyObject *retval = NULL;
+ PyObject *callable, *retval;
- if (o == NULL || name == NULL) {
+ if (obj == NULL || name == NULL) {
return null_error();
}
- func = PyObject_GetAttrString(o, name);
- if (func == NULL)
+ callable = PyObject_GetAttrString(obj, name);
+ if (callable == NULL)
return NULL;
va_start(va, format);
- retval = callmethod(func, format, va, 0);
+ retval = callmethod(callable, format, va, 0);
va_end(va);
- Py_DECREF(func);
+
+ Py_DECREF(callable);
return retval;
}
PyObject *
-_PyObject_CallMethodId(PyObject *o, _Py_Identifier *name,
+_PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name,
const char *format, ...)
{
va_list va;
- PyObject *func = NULL;
- PyObject *retval = NULL;
+ PyObject *callable, *retval;
- if (o == NULL || name == NULL) {
+ if (obj == NULL || name == NULL) {
return null_error();
}
- func = _PyObject_GetAttrId(o, name);
- if (func == NULL)
+ callable = _PyObject_GetAttrId(obj, name);
+ if (callable == NULL)
return NULL;
va_start(va, format);
- retval = callmethod(func, format, va, 0);
+ retval = callmethod(callable, format, va, 0);
va_end(va);
- Py_DECREF(func);
+
+ Py_DECREF(callable);
return retval;
}
PyObject *
-_PyObject_CallMethod_SizeT(PyObject *o, const char *name,
+_PyObject_CallMethod_SizeT(PyObject *obj, const char *name,
const char *format, ...)
{
va_list va;
- PyObject *func = NULL;
- PyObject *retval;
+ PyObject *callable, *retval;
- if (o == NULL || name == NULL) {
+ if (obj == NULL || name == NULL) {
return null_error();
}
- func = PyObject_GetAttrString(o, name);
- if (func == NULL)
+ callable = PyObject_GetAttrString(obj, name);
+ if (callable == NULL)
return NULL;
+
va_start(va, format);
- retval = callmethod(func, format, va, 1);
+ retval = callmethod(callable, format, va, 1);
va_end(va);
- Py_DECREF(func);
+
+ Py_DECREF(callable);
return retval;
}
PyObject *
-_PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name,
+_PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name,
const char *format, ...)
{
va_list va;
- PyObject *func = NULL;
- PyObject *retval;
+ PyObject *callable, *retval;
- if (o == NULL || name == NULL) {
+ if (obj == NULL || name == NULL) {
return null_error();
}
- func = _PyObject_GetAttrId(o, name);
- if (func == NULL) {
+ callable = _PyObject_GetAttrId(obj, name);
+ if (callable == NULL) {
return NULL;
}
+
va_start(va, format);
- retval = callmethod(func, format, va, 1);
+ retval = callmethod(callable, format, va, 1);
va_end(va);
- Py_DECREF(func);
+
+ Py_DECREF(callable);
return retval;
}
-static PyObject **
-objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size,
- va_list va, Py_ssize_t *p_nargs)
+static PyObject *
+object_vacall(PyObject *callable, va_list vargs)
{
- Py_ssize_t i, n;
- va_list countva;
+ PyObject *small_stack[_PY_FASTCALL_SMALL_STACK];
PyObject **stack;
+ Py_ssize_t nargs;
+ PyObject *result;
+ Py_ssize_t i;
+ va_list countva;
- /* Count the number of arguments */
- va_copy(countva, va);
+ if (callable == NULL) {
+ return null_error();
+ }
- n = 0;
+ /* Count the number of arguments */
+ va_copy(countva, vargs);
+ nargs = 0;
while (1) {
PyObject *arg = va_arg(countva, PyObject *);
if (arg == NULL) {
break;
}
- n++;
+ nargs++;
}
- *p_nargs = n;
+ va_end(countva);
/* Copy arguments */
- if (n <= small_stack_size) {
+ if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) {
stack = small_stack;
}
else {
- stack = PyMem_Malloc(n * sizeof(stack[0]));
+ stack = PyMem_Malloc(nargs * sizeof(stack[0]));
if (stack == NULL) {
- va_end(countva);
PyErr_NoMemory();
return NULL;
}
}
- for (i = 0; i < n; ++i) {
- stack[i] = va_arg(va, PyObject *);
+ for (i = 0; i < nargs; ++i) {
+ stack[i] = va_arg(vargs, PyObject *);
}
- va_end(countva);
- return stack;
+
+ /* Call the function */
+ result = _PyObject_FastCall(callable, stack, nargs);
+
+ if (stack != small_stack) {
+ PyMem_Free(stack);
+ }
+ return result;
}
PyObject *
PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
{
- PyObject *small_stack[5];
- PyObject **stack;
- Py_ssize_t nargs;
- PyObject *result;
va_list vargs;
+ PyObject *result;
if (callable == NULL || name == NULL) {
return null_error();
}
callable = PyObject_GetAttr(callable, name);
- if (callable == NULL)
+ if (callable == NULL) {
return NULL;
+ }
- /* count the args */
va_start(vargs, name);
- stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
- vargs, &nargs);
+ result = object_vacall(callable, vargs);
va_end(vargs);
- if (stack == NULL) {
- Py_DECREF(callable);
- return NULL;
- }
- result = _PyObject_FastCall(callable, stack, nargs);
Py_DECREF(callable);
- if (stack != small_stack) {
- PyMem_Free(stack);
- }
-
return result;
}
PyObject *
-_PyObject_CallMethodIdObjArgs(PyObject *callable,
- struct _Py_Identifier *name, ...)
+_PyObject_CallMethodIdObjArgs(PyObject *obj,
+ struct _Py_Identifier *name, ...)
{
- PyObject *small_stack[5];
- PyObject **stack;
- Py_ssize_t nargs;
- PyObject *result;
va_list vargs;
+ PyObject *callable, *result;
- if (callable == NULL || name == NULL) {
+ if (obj == NULL || name == NULL) {
return null_error();
}
- callable = _PyObject_GetAttrId(callable, name);
- if (callable == NULL)
+ callable = _PyObject_GetAttrId(obj, name);
+ if (callable == NULL) {
return NULL;
+ }
- /* count the args */
va_start(vargs, name);
- stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
- vargs, &nargs);
+ result = object_vacall(callable, vargs);
va_end(vargs);
- if (stack == NULL) {
- Py_DECREF(callable);
- return NULL;
- }
- result = _PyObject_FastCall(callable, stack, nargs);
Py_DECREF(callable);
- if (stack != small_stack) {
- PyMem_Free(stack);
- }
-
return result;
}
PyObject *
PyObject_CallFunctionObjArgs(PyObject *callable, ...)
{
- PyObject *small_stack[5];
- PyObject **stack;
- Py_ssize_t nargs;
- PyObject *result;
va_list vargs;
+ PyObject *result;
- if (callable == NULL) {
- return null_error();
- }
-
- /* count the args */
va_start(vargs, callable);
- stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack),
- vargs, &nargs);
+ result = object_vacall(callable, vargs);
va_end(vargs);
- if (stack == NULL) {
- return NULL;
- }
-
- result = _PyObject_FastCall(callable, stack, nargs);
- if (stack != small_stack) {
- PyMem_Free(stack);
- }
return result;
}
@@ -3111,7 +3187,8 @@ PyObject *
PyObject_GetIter(PyObject *o)
{
PyTypeObject *t = o->ob_type;
- getiterfunc f = NULL;
+ getiterfunc f;
+
f = t->tp_iter;
if (f == NULL) {
if (PySequence_Check(o))