From ba86008aac6890c5c4a2c6d30ea8110f228d483e Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Nov 2016 12:16:46 +0200 Subject: Issue #19569: Compiler warnings are now emitted if use most of deprecated functions. --- Objects/abstract.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index f9afece815..beb12c98f6 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -251,14 +251,6 @@ PyObject_DelItemString(PyObject *o, const char *key) /* We release the buffer right after use of this function which could 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) { @@ -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) -- cgit v1.2.1 From 7a82fd02f2c897880626cfcd23cf1e1e966138db Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 29 Nov 2016 18:47:56 +0100 Subject: Uniformize argument names of "call" functions * Callable object: callable, o, callable_object => func * Object for method calls: o => obj * Method name: name or nameid => method Cleanup also the C code: * Don't initialize variables to NULL if they are not used before their first assignement * Add braces for readability --- Objects/abstract.c | 122 +++++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 60 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index beb12c98f6..1a83e93385 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2173,9 +2173,9 @@ PyMapping_Values(PyObject *o) /* XXX PyCallable_Check() is in object.c */ PyObject * -PyObject_CallObject(PyObject *o, PyObject *a) +PyObject_CallObject(PyObject *func, PyObject *args) { - return PyEval_CallObjectWithKeywords(o, a, NULL); + return PyEval_CallObjectWithKeywords(func, args, NULL); } PyObject* @@ -2331,10 +2331,10 @@ exit: return result; } -/* Positional arguments are obj followed args. */ +/* Positional arguments are arg0 followed args: [arg0, *args]. */ PyObject * _PyObject_Call_Prepend(PyObject *func, - PyObject *obj, PyObject *args, PyObject *kwargs) + PyObject *arg0, PyObject *args, PyObject *kwargs) { PyObject *small_stack[8]; PyObject **stack; @@ -2356,7 +2356,7 @@ _PyObject_Call_Prepend(PyObject *func, } /* use borrowed references */ - stack[0] = obj; + stack[0] = arg0; memcpy(&stack[1], &PyTuple_GET_ITEM(args, 0), argcount * sizeof(PyObject *)); @@ -2489,34 +2489,34 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs, } static PyObject* -call_function_tail(PyObject *callable, PyObject *args) +call_function_tail(PyObject *func, PyObject *args) { PyObject *result; assert(args != NULL); if (!PyTuple_Check(args)) { - result = _PyObject_CallArg1(callable, args); + result = _PyObject_CallArg1(func, args); } else { - result = PyObject_Call(callable, args, NULL); + result = PyObject_Call(func, args, NULL); } return result; } PyObject * -PyObject_CallFunction(PyObject *callable, const char *format, ...) +PyObject_CallFunction(PyObject *func, const char *format, ...) { va_list va; PyObject *args, *result; - if (callable == NULL) { + if (func == NULL) { return null_error(); } if (!format || !*format) { - return _PyObject_CallNoArg(callable); + return _PyObject_CallNoArg(func); } va_start(va, format); @@ -2526,23 +2526,23 @@ PyObject_CallFunction(PyObject *callable, const char *format, ...) return NULL; } - result = call_function_tail(callable, args); + result = call_function_tail(func, args); Py_DECREF(args); return result; } PyObject * -_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) +_PyObject_CallFunction_SizeT(PyObject *func, const char *format, ...) { va_list va; PyObject *args, *result; - if (callable == NULL) { + if (func == NULL) { return null_error(); } if (!format || !*format) { - return _PyObject_CallNoArg(callable); + return _PyObject_CallNoArg(func); } va_start(va, format); @@ -2552,7 +2552,7 @@ _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) return NULL; } - result = call_function_tail(callable, args); + result = call_function_tail(func, args); Py_DECREF(args); return result; } @@ -2589,19 +2589,20 @@ callmethod(PyObject* func, const char *format, va_list va, int is_size_t) } PyObject * -PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...) +PyObject_CallMethod(PyObject *obj, const char *method, const char *format, ...) { va_list va; PyObject *func = NULL; PyObject *retval = NULL; - if (o == NULL || name == NULL) { + if (obj == NULL || method == NULL) { return null_error(); } - func = PyObject_GetAttrString(o, name); - if (func == NULL) + func = PyObject_GetAttrString(obj, method); + if (func == NULL) { return NULL; + } va_start(va, format); retval = callmethod(func, format, va, 0); @@ -2611,20 +2612,20 @@ PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...) } PyObject * -_PyObject_CallMethodId(PyObject *o, _Py_Identifier *name, +_PyObject_CallMethodId(PyObject *obj, _Py_Identifier *method, const char *format, ...) { va_list va; - PyObject *func = NULL; - PyObject *retval = NULL; + PyObject *func, *retval; - if (o == NULL || name == NULL) { + if (obj == NULL || method == NULL) { return null_error(); } - func = _PyObject_GetAttrId(o, name); - if (func == NULL) + func = _PyObject_GetAttrId(obj, method); + if (func == NULL) { return NULL; + } va_start(va, format); retval = callmethod(func, format, va, 0); @@ -2634,20 +2635,21 @@ _PyObject_CallMethodId(PyObject *o, _Py_Identifier *name, } PyObject * -_PyObject_CallMethod_SizeT(PyObject *o, const char *name, +_PyObject_CallMethod_SizeT(PyObject *obj, const char *method, const char *format, ...) { va_list va; - PyObject *func = NULL; - PyObject *retval; + PyObject *func, *retval; - if (o == NULL || name == NULL) { + if (obj == NULL || method == NULL) { return null_error(); } - func = PyObject_GetAttrString(o, name); - if (func == NULL) + func = PyObject_GetAttrString(obj, method); + if (func == NULL) { return NULL; + } + va_start(va, format); retval = callmethod(func, format, va, 1); va_end(va); @@ -2656,21 +2658,21 @@ _PyObject_CallMethod_SizeT(PyObject *o, const char *name, } PyObject * -_PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name, +_PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *method, const char *format, ...) { va_list va; - PyObject *func = NULL; - PyObject *retval; + PyObject *func, *retval; - if (o == NULL || name == NULL) { + if (obj == NULL || method == NULL) { return null_error(); } - func = _PyObject_GetAttrId(o, name); + func = _PyObject_GetAttrId(obj, method); if (func == NULL) { return NULL; } + va_start(va, format); retval = callmethod(func, format, va, 1); va_end(va); @@ -2720,34 +2722,34 @@ objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size, } PyObject * -PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) +PyObject_CallMethodObjArgs(PyObject *obj, PyObject *method, ...) { PyObject *small_stack[5]; PyObject **stack; Py_ssize_t nargs; - PyObject *result; + PyObject *func, *result; va_list vargs; - if (callable == NULL || name == NULL) { + if (obj == NULL || method == NULL) { return null_error(); } - callable = PyObject_GetAttr(callable, name); - if (callable == NULL) + func = PyObject_GetAttr(obj, method); + if (func == NULL) return NULL; /* count the args */ - va_start(vargs, name); + va_start(vargs, method); stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack), vargs, &nargs); va_end(vargs); if (stack == NULL) { - Py_DECREF(callable); + Py_DECREF(func); return NULL; } - result = _PyObject_FastCall(callable, stack, nargs); - Py_DECREF(callable); + result = _PyObject_FastCall(func, stack, nargs); + Py_DECREF(func); if (stack != small_stack) { PyMem_Free(stack); } @@ -2756,35 +2758,35 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) } PyObject * -_PyObject_CallMethodIdObjArgs(PyObject *callable, - struct _Py_Identifier *name, ...) +_PyObject_CallMethodIdObjArgs(PyObject *obj, + struct _Py_Identifier *method, ...) { PyObject *small_stack[5]; PyObject **stack; Py_ssize_t nargs; - PyObject *result; + PyObject *func, *result; va_list vargs; - if (callable == NULL || name == NULL) { + if (obj == NULL || method == NULL) { return null_error(); } - callable = _PyObject_GetAttrId(callable, name); - if (callable == NULL) + func = _PyObject_GetAttrId(obj, method); + if (func == NULL) return NULL; /* count the args */ - va_start(vargs, name); + va_start(vargs, method); stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack), vargs, &nargs); va_end(vargs); if (stack == NULL) { - Py_DECREF(callable); + Py_DECREF(func); return NULL; } - result = _PyObject_FastCall(callable, stack, nargs); - Py_DECREF(callable); + result = _PyObject_FastCall(func, stack, nargs); + Py_DECREF(func); if (stack != small_stack) { PyMem_Free(stack); } @@ -2793,7 +2795,7 @@ _PyObject_CallMethodIdObjArgs(PyObject *callable, } PyObject * -PyObject_CallFunctionObjArgs(PyObject *callable, ...) +PyObject_CallFunctionObjArgs(PyObject *func, ...) { PyObject *small_stack[5]; PyObject **stack; @@ -2801,12 +2803,12 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) PyObject *result; va_list vargs; - if (callable == NULL) { + if (func == NULL) { return null_error(); } /* count the args */ - va_start(vargs, callable); + va_start(vargs, func); stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack), vargs, &nargs); va_end(vargs); @@ -2814,7 +2816,7 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) return NULL; } - result = _PyObject_FastCall(callable, stack, nargs); + result = _PyObject_FastCall(func, stack, nargs); if (stack != small_stack) { PyMem_Free(stack); } -- cgit v1.2.1 From cbd0371d81fc46a7a9353ce362ec85ee45ce354b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 30 Nov 2016 12:10:54 +0100 Subject: Backed out changeset 7efddbf1aa70 --- Objects/abstract.c | 122 ++++++++++++++++++++++++++--------------------------- 1 file changed, 60 insertions(+), 62 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 1a83e93385..beb12c98f6 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2173,9 +2173,9 @@ PyMapping_Values(PyObject *o) /* XXX PyCallable_Check() is in object.c */ PyObject * -PyObject_CallObject(PyObject *func, PyObject *args) +PyObject_CallObject(PyObject *o, PyObject *a) { - return PyEval_CallObjectWithKeywords(func, args, NULL); + return PyEval_CallObjectWithKeywords(o, a, NULL); } PyObject* @@ -2331,10 +2331,10 @@ exit: return result; } -/* Positional arguments are arg0 followed args: [arg0, *args]. */ +/* Positional arguments are obj followed args. */ PyObject * _PyObject_Call_Prepend(PyObject *func, - PyObject *arg0, PyObject *args, PyObject *kwargs) + PyObject *obj, PyObject *args, PyObject *kwargs) { PyObject *small_stack[8]; PyObject **stack; @@ -2356,7 +2356,7 @@ _PyObject_Call_Prepend(PyObject *func, } /* use borrowed references */ - stack[0] = arg0; + stack[0] = obj; memcpy(&stack[1], &PyTuple_GET_ITEM(args, 0), argcount * sizeof(PyObject *)); @@ -2489,34 +2489,34 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs, } static PyObject* -call_function_tail(PyObject *func, PyObject *args) +call_function_tail(PyObject *callable, PyObject *args) { PyObject *result; assert(args != NULL); if (!PyTuple_Check(args)) { - result = _PyObject_CallArg1(func, args); + result = _PyObject_CallArg1(callable, args); } else { - result = PyObject_Call(func, args, NULL); + result = PyObject_Call(callable, args, NULL); } return result; } PyObject * -PyObject_CallFunction(PyObject *func, const char *format, ...) +PyObject_CallFunction(PyObject *callable, const char *format, ...) { va_list va; PyObject *args, *result; - if (func == NULL) { + if (callable == NULL) { return null_error(); } if (!format || !*format) { - return _PyObject_CallNoArg(func); + return _PyObject_CallNoArg(callable); } va_start(va, format); @@ -2526,23 +2526,23 @@ PyObject_CallFunction(PyObject *func, const char *format, ...) return NULL; } - result = call_function_tail(func, args); + result = call_function_tail(callable, args); Py_DECREF(args); return result; } PyObject * -_PyObject_CallFunction_SizeT(PyObject *func, const char *format, ...) +_PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) { va_list va; PyObject *args, *result; - if (func == NULL) { + if (callable == NULL) { return null_error(); } if (!format || !*format) { - return _PyObject_CallNoArg(func); + return _PyObject_CallNoArg(callable); } va_start(va, format); @@ -2552,7 +2552,7 @@ _PyObject_CallFunction_SizeT(PyObject *func, const char *format, ...) return NULL; } - result = call_function_tail(func, args); + result = call_function_tail(callable, args); Py_DECREF(args); return result; } @@ -2589,20 +2589,19 @@ callmethod(PyObject* func, const char *format, va_list va, int is_size_t) } PyObject * -PyObject_CallMethod(PyObject *obj, const char *method, const char *format, ...) +PyObject_CallMethod(PyObject *o, const char *name, const char *format, ...) { va_list va; PyObject *func = NULL; PyObject *retval = NULL; - if (obj == NULL || method == NULL) { + if (o == NULL || name == NULL) { return null_error(); } - func = PyObject_GetAttrString(obj, method); - if (func == NULL) { + func = PyObject_GetAttrString(o, name); + if (func == NULL) return NULL; - } va_start(va, format); retval = callmethod(func, format, va, 0); @@ -2612,20 +2611,20 @@ PyObject_CallMethod(PyObject *obj, const char *method, const char *format, ...) } PyObject * -_PyObject_CallMethodId(PyObject *obj, _Py_Identifier *method, +_PyObject_CallMethodId(PyObject *o, _Py_Identifier *name, const char *format, ...) { va_list va; - PyObject *func, *retval; + PyObject *func = NULL; + PyObject *retval = NULL; - if (obj == NULL || method == NULL) { + if (o == NULL || name == NULL) { return null_error(); } - func = _PyObject_GetAttrId(obj, method); - if (func == NULL) { + func = _PyObject_GetAttrId(o, name); + if (func == NULL) return NULL; - } va_start(va, format); retval = callmethod(func, format, va, 0); @@ -2635,21 +2634,20 @@ _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *method, } PyObject * -_PyObject_CallMethod_SizeT(PyObject *obj, const char *method, +_PyObject_CallMethod_SizeT(PyObject *o, const char *name, const char *format, ...) { va_list va; - PyObject *func, *retval; + PyObject *func = NULL; + PyObject *retval; - if (obj == NULL || method == NULL) { + if (o == NULL || name == NULL) { return null_error(); } - func = PyObject_GetAttrString(obj, method); - if (func == NULL) { + func = PyObject_GetAttrString(o, name); + if (func == NULL) return NULL; - } - va_start(va, format); retval = callmethod(func, format, va, 1); va_end(va); @@ -2658,21 +2656,21 @@ _PyObject_CallMethod_SizeT(PyObject *obj, const char *method, } PyObject * -_PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *method, +_PyObject_CallMethodId_SizeT(PyObject *o, _Py_Identifier *name, const char *format, ...) { va_list va; - PyObject *func, *retval; + PyObject *func = NULL; + PyObject *retval; - if (obj == NULL || method == NULL) { + if (o == NULL || name == NULL) { return null_error(); } - func = _PyObject_GetAttrId(obj, method); + func = _PyObject_GetAttrId(o, name); if (func == NULL) { return NULL; } - va_start(va, format); retval = callmethod(func, format, va, 1); va_end(va); @@ -2722,34 +2720,34 @@ objargs_mkstack(PyObject **small_stack, Py_ssize_t small_stack_size, } PyObject * -PyObject_CallMethodObjArgs(PyObject *obj, PyObject *method, ...) +PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) { PyObject *small_stack[5]; PyObject **stack; Py_ssize_t nargs; - PyObject *func, *result; + PyObject *result; va_list vargs; - if (obj == NULL || method == NULL) { + if (callable == NULL || name == NULL) { return null_error(); } - func = PyObject_GetAttr(obj, method); - if (func == NULL) + callable = PyObject_GetAttr(callable, name); + if (callable == NULL) return NULL; /* count the args */ - va_start(vargs, method); + va_start(vargs, name); stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack), vargs, &nargs); va_end(vargs); if (stack == NULL) { - Py_DECREF(func); + Py_DECREF(callable); return NULL; } - result = _PyObject_FastCall(func, stack, nargs); - Py_DECREF(func); + result = _PyObject_FastCall(callable, stack, nargs); + Py_DECREF(callable); if (stack != small_stack) { PyMem_Free(stack); } @@ -2758,35 +2756,35 @@ PyObject_CallMethodObjArgs(PyObject *obj, PyObject *method, ...) } PyObject * -_PyObject_CallMethodIdObjArgs(PyObject *obj, - struct _Py_Identifier *method, ...) +_PyObject_CallMethodIdObjArgs(PyObject *callable, + struct _Py_Identifier *name, ...) { PyObject *small_stack[5]; PyObject **stack; Py_ssize_t nargs; - PyObject *func, *result; + PyObject *result; va_list vargs; - if (obj == NULL || method == NULL) { + if (callable == NULL || name == NULL) { return null_error(); } - func = _PyObject_GetAttrId(obj, method); - if (func == NULL) + callable = _PyObject_GetAttrId(callable, name); + if (callable == NULL) return NULL; /* count the args */ - va_start(vargs, method); + va_start(vargs, name); stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack), vargs, &nargs); va_end(vargs); if (stack == NULL) { - Py_DECREF(func); + Py_DECREF(callable); return NULL; } - result = _PyObject_FastCall(func, stack, nargs); - Py_DECREF(func); + result = _PyObject_FastCall(callable, stack, nargs); + Py_DECREF(callable); if (stack != small_stack) { PyMem_Free(stack); } @@ -2795,7 +2793,7 @@ _PyObject_CallMethodIdObjArgs(PyObject *obj, } PyObject * -PyObject_CallFunctionObjArgs(PyObject *func, ...) +PyObject_CallFunctionObjArgs(PyObject *callable, ...) { PyObject *small_stack[5]; PyObject **stack; @@ -2803,12 +2801,12 @@ PyObject_CallFunctionObjArgs(PyObject *func, ...) PyObject *result; va_list vargs; - if (func == NULL) { + if (callable == NULL) { return null_error(); } /* count the args */ - va_start(vargs, func); + va_start(vargs, callable); stack = objargs_mkstack(small_stack, Py_ARRAY_LENGTH(small_stack), vargs, &nargs); va_end(vargs); @@ -2816,7 +2814,7 @@ PyObject_CallFunctionObjArgs(PyObject *func, ...) return NULL; } - result = _PyObject_FastCall(func, stack, nargs); + result = _PyObject_FastCall(callable, stack, nargs); if (stack != small_stack) { PyMem_Free(stack); } -- cgit v1.2.1 From 366f4ee4da4420842eac26b3fa00c2b01d4515a6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 1 Dec 2016 14:43:22 +0100 Subject: Replace PyObject_CallFunctionObjArgs() with fastcall * PyObject_CallFunctionObjArgs(func, NULL) => _PyObject_CallNoArg(func) * PyObject_CallFunctionObjArgs(func, arg, NULL) => _PyObject_CallArg1(func, arg) PyObject_CallFunctionObjArgs() allocates 40 bytes on the C stack and requires extra work to "parse" C arguments to build a C array of PyObject*. _PyObject_CallNoArg() and _PyObject_CallArg1() are simpler and don't allocate memory on the C stack. This change is part of the fastcall project. The change on listsort() is related to the issue #23507. --- Objects/abstract.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index beb12c98f6..2f238ed0f1 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)) { @@ -716,7 +716,7 @@ PyObject_Format(PyObject *obj, PyObject *format_spec) } /* And call it. */ - result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); + result = _PyObject_CallArg1(meth, format_spec); Py_DECREF(meth); if (result && !PyUnicode_Check(result)) { @@ -3011,7 +3011,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) Py_DECREF(checker); return ok; } - res = PyObject_CallFunctionObjArgs(checker, inst, NULL); + res = _PyObject_CallArg1(checker, inst); Py_LeaveRecursiveCall(); Py_DECREF(checker); if (res != NULL) { @@ -3085,7 +3085,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls) Py_DECREF(checker); return ok; } - res = PyObject_CallFunctionObjArgs(checker, derived, NULL); + res = _PyObject_CallArg1(checker, derived); Py_LeaveRecursiveCall(); Py_DECREF(checker); if (res != NULL) { -- cgit v1.2.1 From 39ae5bedd90f9caf9a78efa82f4d11e838933b3a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 4 Dec 2016 22:59:09 +0100 Subject: Backed out changeset b9c9691c72c5 Issue #28858: The change b9c9691c72c5 introduced a regression. It seems like _PyObject_CallArg1() uses more stack memory than PyObject_CallFunctionObjArgs(). --- Objects/abstract.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 2f238ed0f1..beb12c98f6 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_CallNoArg(hint); + result = PyObject_CallFunctionObjArgs(hint, NULL); Py_DECREF(hint); if (result == NULL) { if (PyErr_ExceptionMatches(PyExc_TypeError)) { @@ -716,7 +716,7 @@ PyObject_Format(PyObject *obj, PyObject *format_spec) } /* And call it. */ - result = _PyObject_CallArg1(meth, format_spec); + result = PyObject_CallFunctionObjArgs(meth, format_spec, NULL); Py_DECREF(meth); if (result && !PyUnicode_Check(result)) { @@ -3011,7 +3011,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) Py_DECREF(checker); return ok; } - res = _PyObject_CallArg1(checker, inst); + res = PyObject_CallFunctionObjArgs(checker, inst, NULL); Py_LeaveRecursiveCall(); Py_DECREF(checker); if (res != NULL) { @@ -3085,7 +3085,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls) Py_DECREF(checker); return ok; } - res = _PyObject_CallArg1(checker, derived); + res = PyObject_CallFunctionObjArgs(checker, derived, NULL); Py_LeaveRecursiveCall(); Py_DECREF(checker); if (res != NULL) { -- cgit v1.2.1 From 40273ec4f37c65c13a09d0ac23b08c99ebe2f1a3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 5 Dec 2016 17:04:32 +0100 Subject: Issue #28858: Remove _PyObject_CallArg1() macro Replace _PyObject_CallArg1(func, arg) with PyObject_CallFunctionObjArgs(func, arg, NULL) Using the _PyObject_CallArg1() macro increases the usage of the C stack, which was unexpected and unwanted. PyObject_CallFunctionObjArgs() doesn't have this issue. --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index beb12c98f6..a6a58db591 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2496,7 +2496,7 @@ call_function_tail(PyObject *callable, PyObject *args) assert(args != NULL); if (!PyTuple_Check(args)) { - result = _PyObject_CallArg1(callable, args); + result = PyObject_CallFunctionObjArgs(callable, args, NULL); } else { result = PyObject_Call(callable, args, NULL); -- cgit v1.2.1 From 647e75b25047cd0bf6a780e929db7a67de4cca75 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Dec 2016 16:27:24 +0100 Subject: Uniformize argument names of "call" functions Issue #28838: Rename parameters of the "calls" functions of the Python C API. * Rename 'callable_object' and 'func' to 'callable': any Python callable object is accepted, not only Python functions * Rename 'method' and 'nameid' to 'name' (method name) * Rename 'o' to 'obj' * Move, fix and update documentation of PyObject_CallXXX() functions in abstract.h * Update also the documentaton of the C API (update parameter names) --- Objects/abstract.c | 148 ++++++++++++++++++++++++++++------------------------- 1 file changed, 78 insertions(+), 70 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index a6a58db591..4cd96368b4 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2173,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", @@ -2206,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, @@ -2227,7 +2227,7 @@ _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; @@ -2239,21 +2239,21 @@ PyObject_Call(PyObject *func, PyObject *args, PyObject *kwargs) assert(PyTuple_Check(args)); assert(kwargs == NULL || PyDict_Check(kwargs)); - 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); + callable->ob_type->tp_name); return NULL; } if (Py_EnterRecursiveCall(" while calling a Python object")) return NULL; - result = (*call)(func, args, kwargs); + result = (*call)(callable, args, kwargs); Py_LeaveRecursiveCall(); - return _Py_CheckFunctionResult(func, result, NULL); + return _Py_CheckFunctionResult(callable, result, NULL); } PyObject* @@ -2277,7 +2277,7 @@ _PyStack_AsTuple(PyObject **stack, Py_ssize_t nargs) } 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; @@ -2288,7 +2288,7 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, 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)); @@ -2297,20 +2297,20 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, return NULL; } - if (PyFunction_Check(func)) { - result = _PyFunction_FastCallDict(func, args, nargs, kwargs); + if (PyFunction_Check(callable)) { + result = _PyFunction_FastCallDict(callable, args, nargs, kwargs); } - else if (PyCFunction_Check(func)) { - result = _PyCFunction_FastCallDict(func, args, nargs, kwargs); + else if (PyCFunction_Check(callable)) { + result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs); } else { PyObject *tuple; /* 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); + callable->ob_type->tp_name); goto exit; } @@ -2319,10 +2319,10 @@ _PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, goto exit; } - result = (*call)(func, tuple, kwargs); + result = (*call)(callable, tuple, kwargs); Py_DECREF(tuple); - result = _Py_CheckFunctionResult(func, result, NULL); + result = _Py_CheckFunctionResult(callable, result, NULL); } exit: @@ -2331,9 +2331,10 @@ exit: return result; } -/* Positional arguments are obj followed args. */ +/* Positional arguments are obj followed 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]; @@ -2361,7 +2362,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) { @@ -2452,7 +2453,7 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, } 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; @@ -2465,12 +2466,12 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs, be unique: these are implemented in Python/ceval.c and _PyArg_ParseStack(). */ - 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); } if (nkwargs > 0) { @@ -2483,7 +2484,7 @@ _PyObject_FastCallKeywords(PyObject *func, PyObject **stack, Py_ssize_t nargs, kwdict = NULL; } - result = _PyObject_FastCallDict(func, stack, nargs, kwdict); + result = _PyObject_FastCallDict(callable, stack, nargs, kwdict); Py_XDECREF(kwdict); return result; } @@ -2558,19 +2559,19 @@ _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) } 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(func != NULL); + assert(callable != 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); + return _PyObject_CallNoArg(callable); } if (is_size_t) { @@ -2583,98 +2584,104 @@ callmethod(PyObject* func, const char *format, va_list va, int is_size_t) return NULL; } - result = call_function_tail(func, args); + result = call_function_tail(callable, args); Py_DECREF(args); return result; } 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 *callable = NULL; PyObject *retval = NULL; - 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 *callable = NULL; PyObject *retval = NULL; - 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 *callable = NULL; PyObject *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 *callable = NULL; PyObject *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; } @@ -2756,20 +2763,21 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) } PyObject * -_PyObject_CallMethodIdObjArgs(PyObject *callable, - struct _Py_Identifier *name, ...) +_PyObject_CallMethodIdObjArgs(PyObject *obj, + struct _Py_Identifier *name, ...) { PyObject *small_stack[5]; PyObject **stack; + PyObject *callable; Py_ssize_t nargs; PyObject *result; va_list vargs; - if (callable == NULL || name == NULL) { + if (obj == NULL || name == NULL) { return null_error(); } - callable = _PyObject_GetAttrId(callable, name); + callable = _PyObject_GetAttrId(obj, name); if (callable == NULL) return NULL; -- cgit v1.2.1 From a95a307d2cbb7fc1c778691f142e0c21c05fd5bc Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Dec 2016 18:46:19 +0100 Subject: Use _PyObject_CallNoArg() Replace: PyObject_CallFunctionObjArgs(callable, NULL) with: _PyObject_CallNoArg(callable) --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 4cd96368b4..24948dbfea 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)) { -- cgit v1.2.1 From fe6bb6b27a48ae671bb2c0d888b3e6d3aacce06b Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Dec 2016 18:49:15 +0100 Subject: Fix typo in a comment of abstract.c --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 24948dbfea..034209ccd4 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2463,7 +2463,7 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg 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 + be unique: these checks are implemented in Python/ceval.c and _PyArg_ParseStack(). */ if (PyFunction_Check(callable)) { -- cgit v1.2.1 From 7b1d78db28c9f6983ffe6a4a5600684efd5ca379 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 7 Dec 2016 00:37:38 +0100 Subject: _PyObject_FastCallKeywords() now calls directly tp_call _PyObject_FastCallKeywords() doesn't call _PyObject_FastCallDict() anymore: call directly tp_call. --- Objects/abstract.c | 60 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 15 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 034209ccd4..9b4c124ac3 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2456,12 +2456,9 @@ PyObject * _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); - 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 checks are implemented in Python/ceval.c and _PyArg_ParseStack(). */ @@ -2469,24 +2466,57 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg if (PyFunction_Check(callable)) { return _PyFunction_FastCallKeywords(callable, 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 *argtuple; + PyObject *kwdict, *result; + Py_ssize_t nkwargs; + + result = NULL; + nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); + assert((nargs == 0 && nkwargs == 0) || stack != NULL); + + if (Py_EnterRecursiveCall(" while calling a Python object")) { return NULL; } - } - else { - kwdict = NULL; - } - result = _PyObject_FastCallDict(callable, stack, nargs, kwdict); - Py_XDECREF(kwdict); - return result; + call = callable->ob_type->tp_call; + if (call == NULL) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", + callable->ob_type->tp_name); + goto exit; + } + + argtuple = _PyStack_AsTuple(stack, nargs); + if (argtuple == NULL) { + goto exit; + } + + if (nkwargs > 0) { + kwdict = _PyStack_AsDict(stack + nargs, kwnames); + if (kwdict == NULL) { + Py_DECREF(argtuple); + goto exit; + } + } + else { + kwdict = NULL; + } + + result = (*call)(callable, argtuple, kwdict); + Py_DECREF(argtuple); + Py_XDECREF(kwdict); + + exit: + Py_LeaveRecursiveCall(); + return result; + } } static PyObject* -- cgit v1.2.1 From 3eefbce427a8dbc88d9f1bf2490ef97484f63395 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 00:21:55 +0100 Subject: Add _PyObject_FastCallVa() helper Issue #28915: Add _PyObject_FastCallVa() helper to factorize code of functions: * PyObject_CallFunctionObjArgs() * PyObject_CallMethodObjArgs() * _PyObject_CallMethodIdObjArgs() Inline objargs_mkstack() into _PyObject_FastCallVa(), remove objargs_mkstack(). --- Objects/abstract.c | 108 ++++++++++++++++++----------------------------------- 1 file changed, 37 insertions(+), 71 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 9b4c124ac3..b2cf07c08f 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2715,80 +2715,77 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, 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 * +_PyObject_FastCallVa(PyObject *callable, va_list vargs) { - Py_ssize_t i, n; - va_list countva; + PyObject *small_stack[5]; 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 = _PyObject_FastCallVa(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; } @@ -2796,66 +2793,35 @@ PyObject * _PyObject_CallMethodIdObjArgs(PyObject *obj, struct _Py_Identifier *name, ...) { - PyObject *small_stack[5]; - PyObject **stack; - PyObject *callable; - Py_ssize_t nargs; - PyObject *result; va_list vargs; + PyObject *callable, *result; if (obj == NULL || name == NULL) { return null_error(); } callable = _PyObject_GetAttrId(obj, 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 = _PyObject_FastCallVa(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 = _PyObject_FastCallVa(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; } -- cgit v1.2.1 From 7414b6dc42b094fd694321a85f375ddb4a8c0e19 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 00:22:56 +0100 Subject: Add _PyObject_CallFunctionVa() helper Issue #28915: Add _PyObject_CallFunctionVa() helper to factorize code of functions: * PyObject_CallFunction() * _PyObject_CallFunction_SizeT() * callmethod() --- Objects/abstract.c | 83 +++++++++++++++++++----------------------------------- 1 file changed, 29 insertions(+), 54 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index b2cf07c08f..4f59f04731 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2519,20 +2519,39 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg } } -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 *result; + PyObject *args, *result; - assert(args != NULL); + if (callable == NULL) { + return null_error(); + } + + if (!format || !*format) { + return _PyObject_CallNoArg(callable); + } + + if (is_size_t) { + args = Py_VaBuildValue(format, va); + } + else { + args = _Py_VaBuildValue_SizeT(format, va); + } + if (args == NULL) { + return NULL; + } if (!PyTuple_Check(args)) { - result = PyObject_CallFunctionObjArgs(callable, args, NULL); + PyObject *stack[1] = {args}; + result = _PyObject_FastCall(callable, stack, 1); } else { result = PyObject_Call(callable, args, NULL); } + Py_DECREF(args); return result; } @@ -2540,25 +2559,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; } @@ -2566,33 +2572,18 @@ 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* callable, const char *format, va_list va, int is_size_t) { - PyObject *args, *result; - assert(callable != NULL); if (!PyCallable_Check(callable)) { @@ -2600,23 +2591,7 @@ callmethod(PyObject* callable, const char *format, va_list va, int is_size_t) return NULL; } - if (!format || !*format) { - return _PyObject_CallNoArg(callable); - } - - 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(callable, args); - Py_DECREF(args); - return result; + return _PyObject_CallFunctionVa(callable, format, va, is_size_t); } PyObject * -- cgit v1.2.1 From 5524988027d357d99d03c6edf84dcf2216293e75 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 00:31:47 +0100 Subject: _PyObject_CallFunctionVa() uses fast call Issue #28915: Use _Py_VaBuildStack() to build a C array of PyObject* and then use _PyObject_FastCall(). The function has a special case if the stack only contains one parameter and the parameter is a tuple: "unpack" the tuple of arguments in this case. --- Objects/abstract.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 4f59f04731..5c3344cb38 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2523,7 +2523,12 @@ static PyObject * _PyObject_CallFunctionVa(PyObject *callable, const char *format, va_list va, int is_size_t) { - PyObject *args, *result; + PyObject* small_stack[5]; + /*const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack);*/ + const Py_ssize_t small_stack_len = 0; + PyObject **stack; + Py_ssize_t nargs, i; + PyObject *result; if (callable == NULL) { return null_error(); @@ -2534,24 +2539,35 @@ _PyObject_CallFunctionVa(PyObject *callable, const char *format, } if (is_size_t) { - args = Py_VaBuildValue(format, va); + stack = _Py_VaBuildStack(small_stack, small_stack_len, format, va, &nargs); } else { - args = _Py_VaBuildValue_SizeT(format, va); + stack = _Py_VaBuildStack_SizeT(small_stack, small_stack_len, format, va, &nargs); } - if (args == NULL) { + if (stack == NULL) { return NULL; } - if (!PyTuple_Check(args)) { - PyObject *stack[1] = {args}; - result = _PyObject_FastCall(callable, stack, 1); + if (nargs == 1 && PyTuple_Check(stack[0])) { + /* Special cases: + - 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); } - Py_DECREF(args); + for (i = 0; i < nargs; ++i) { + Py_DECREF(stack[i]); + } + if (stack != small_stack) { + PyMem_Free(stack); + } return result; } -- cgit v1.2.1 From cb8c62febe743a22d57f0d431340c0dd8e504fb2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 00:40:33 +0100 Subject: Add _PyObject_VaCallFunctionObjArgs() private function Issue #28915: Similar to _PyObject_CallFunctionObjArgs() but use va_list to pass arguments. --- Objects/abstract.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 5c3344cb38..2c5057d133 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2706,8 +2706,8 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, return retval; } -static PyObject * -_PyObject_FastCallVa(PyObject *callable, va_list vargs) +PyObject * +_PyObject_VaCallFunctionObjArgs(PyObject *callable, va_list vargs) { PyObject *small_stack[5]; PyObject **stack; @@ -2773,7 +2773,7 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) } va_start(vargs, name); - result = _PyObject_FastCallVa(callable, vargs); + result = _PyObject_VaCallFunctionObjArgs(callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -2797,7 +2797,7 @@ _PyObject_CallMethodIdObjArgs(PyObject *obj, } va_start(vargs, name); - result = _PyObject_FastCallVa(callable, vargs); + result = _PyObject_VaCallFunctionObjArgs(callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -2811,7 +2811,7 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) PyObject *result; va_start(vargs, callable); - result = _PyObject_FastCallVa(callable, vargs); + result = _PyObject_VaCallFunctionObjArgs(callable, vargs); va_end(vargs); return result; -- cgit v1.2.1 From 26fbec2e01a2eeac7a59ea585f6fa35e175224de Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 16:22:32 +0100 Subject: Use PyObject_CallFunctionObjArgs() Issue #28915: Replace PyObject_CallFunction() with PyObject_CallFunctionObjArgs() when the format string was only made of "O" formats, PyObject* arguments. PyObject_CallFunctionObjArgs() avoids the creation of a temporary tuple and doesn't have to parse a format string. --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 2c5057d133..d3b9ec0d19 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2549,7 +2549,7 @@ _PyObject_CallFunctionVa(PyObject *callable, const char *format, } if (nargs == 1 && PyTuple_Check(stack[0])) { - /* Special cases: + /* 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) */ -- cgit v1.2.1 From 5d3bfadae1b16e75a2e93c0dc7836855b15a1a73 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 17:08:59 +0100 Subject: Remove useless variable initialization Don't initialize variables which are not used before they are assigned. --- Objects/abstract.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index d3b9ec0d19..8892e3ed52 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2614,8 +2614,7 @@ PyObject * PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...) { va_list va; - PyObject *callable = NULL; - PyObject *retval = NULL; + PyObject *callable, *retval; if (obj == NULL || name == NULL) { return null_error(); @@ -2638,8 +2637,7 @@ _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name, const char *format, ...) { va_list va; - PyObject *callable = NULL; - PyObject *retval = NULL; + PyObject *callable, *retval; if (obj == NULL || name == NULL) { return null_error(); @@ -2662,8 +2660,7 @@ _PyObject_CallMethod_SizeT(PyObject *obj, const char *name, const char *format, ...) { va_list va; - PyObject *callable = NULL; - PyObject *retval; + PyObject *callable, *retval; if (obj == NULL || name == NULL) { return null_error(); @@ -2686,8 +2683,7 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, const char *format, ...) { va_list va; - PyObject *callable = NULL; - PyObject *retval; + PyObject *callable, *retval; if (obj == NULL || name == NULL) { return null_error(); @@ -3112,7 +3108,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)) -- cgit v1.2.1 From 1e1106c76b9a36dd487704231fde7561a61607d7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Dec 2016 12:36:50 +0100 Subject: Fix _PyObject_CallFunctionVa(), use the small stack Issue #28915. Oops, I disabled the small stack to test both code paths. It's now fixed. --- Objects/abstract.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 8447fdbc24..7da97ac8a8 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2524,8 +2524,7 @@ _PyObject_CallFunctionVa(PyObject *callable, const char *format, va_list va, int is_size_t) { PyObject* small_stack[5]; - /*const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack);*/ - const Py_ssize_t small_stack_len = 0; + const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack); PyObject **stack; Py_ssize_t nargs, i; PyObject *result; -- cgit v1.2.1 From cff69a956b4ce78ad7c4318ada06f07959dd8023 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Dec 2016 12:40:53 +0100 Subject: Add _PY_FASTCALL_SMALL_STACK constant Issue #28870: Add a new _PY_FASTCALL_SMALL_STACK constant, size of "small stacks" allocated on the C stack to pass positional arguments to _PyObject_FastCall(). _PyObject_Call_Prepend() now uses a small stack of 5 arguments (40 bytes) instead of 8 (64 bytes), since it is modified to use _PY_FASTCALL_SMALL_STACK. --- Objects/abstract.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 7da97ac8a8..351c6eb56b 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2337,7 +2337,7 @@ PyObject * _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; @@ -2523,7 +2523,7 @@ static PyObject * _PyObject_CallFunctionVa(PyObject *callable, const char *format, va_list va, int is_size_t) { - PyObject* small_stack[5]; + 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; @@ -2704,7 +2704,7 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, PyObject * _PyObject_VaCallFunctionObjArgs(PyObject *callable, va_list vargs) { - PyObject *small_stack[5]; + PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; Py_ssize_t nargs; PyObject *result; -- cgit v1.2.1 From 15f6772cc70245d61451cf16f64da47b36389c67 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Dec 2016 16:59:40 +0100 Subject: Use _PyDict_NewPresized() in _PyStack_AsDict() Issue #27810. --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 351c6eb56b..67b163d7b7 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2378,7 +2378,7 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames) PyObject *kwdict; Py_ssize_t i; - kwdict = PyDict_New(); + kwdict = _PyDict_NewPresized(nkwargs); if (kwdict == NULL) { return NULL; } -- cgit v1.2.1 From f22b56b777f7134b5c4e6c9caa9249e92c4f4fd9 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 16 Dec 2016 16:18:57 +0200 Subject: Issue #28959: Added private macro PyDict_GET_SIZE for retrieving the size of dict. --- Objects/abstract.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 67b163d7b7..8d1eddc093 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2409,8 +2409,7 @@ _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_kwnames = NULL; return args; } -- cgit v1.2.1 From a8ccebab461e0c74a522f55fc25bef949d34ef29 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 11 Jan 2017 00:07:40 +0100 Subject: call_method() now uses _PyObject_FastCall() Issue #29233: Replace the inefficient _PyObject_VaCallFunctionObjArgs() with _PyObject_FastCall() in call_method() and call_maybe(). Only a few functions call call_method() and call it with a fixed number of arguments. Avoid the complex and expensive _PyObject_VaCallFunctionObjArgs() function, replace it with an array allocated on the stack with the exact number of argumlents. It reduces the stack consumption, bytes per call, before => after: test_python_call: 1168 => 1152 (-16 B) test_python_getitem: 1344 => 1008 (-336 B) test_python_iterator: 1568 => 1232 (-336 B) Remove the _PyObject_VaCallFunctionObjArgs() function which became useless. Rename it to object_vacall() and make it private. --- Objects/abstract.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 8d1eddc093..93bf87fa88 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2700,8 +2700,8 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, return retval; } -PyObject * -_PyObject_VaCallFunctionObjArgs(PyObject *callable, va_list vargs) +static PyObject * +object_vacall(PyObject *callable, va_list vargs) { PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; @@ -2767,7 +2767,7 @@ PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) } va_start(vargs, name); - result = _PyObject_VaCallFunctionObjArgs(callable, vargs); + result = object_vacall(callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -2791,7 +2791,7 @@ _PyObject_CallMethodIdObjArgs(PyObject *obj, } va_start(vargs, name); - result = _PyObject_VaCallFunctionObjArgs(callable, vargs); + result = object_vacall(callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -2805,7 +2805,7 @@ PyObject_CallFunctionObjArgs(PyObject *callable, ...) PyObject *result; va_start(vargs, callable); - result = _PyObject_VaCallFunctionObjArgs(callable, vargs); + result = object_vacall(callable, vargs); va_end(vargs); return result; -- cgit v1.2.1 From 3106ff9ad570b650a3afee6ebc4adc7430c5eca2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 11 Jan 2017 01:07:03 +0100 Subject: Disable _PyStack_AsTuple() inlining Issue #29234: Inlining _PyStack_AsTuple() into callers increases their stack consumption, Disable inlining to optimize the stack consumption. Add _Py_NO_INLINE: use __attribute__((noinline)) of GCC and Clang. It reduces the stack consumption, bytes per call, before => after: test_python_call: 1040 => 976 (-64 B) test_python_getitem: 976 => 912 (-64 B) test_python_iterator: 1120 => 1056 (-64 B) => total: 3136 => 2944 (- 192 B) --- Objects/abstract.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 93bf87fa88..5726160c08 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2256,7 +2256,9 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) 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; -- cgit v1.2.1 From 7e1c513a9ea54b50e4c3b947208d1306aba5362f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 16 Jan 2017 23:50:53 +0100 Subject: Add _PyStack_AsTupleSlice() helper --- Objects/abstract.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 5726160c08..bba946e8ef 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2274,7 +2274,30 @@ _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; } -- cgit v1.2.1 From 271403abe36069797ac332e1c6eae3473878db20 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Jan 2017 01:29:01 +0100 Subject: Rename _PyArg_ParseStack to _PyArg_ParseStackAndKeywords Issue #29286. --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index bba946e8ef..48fdf6541a 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2485,7 +2485,7 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg /* kwnames must only contains str strings, no subclass, and all keys must be unique: these checks are implemented in Python/ceval.c and - _PyArg_ParseStack(). */ + _PyArg_ParseStackAndKeywords(). */ if (PyFunction_Check(callable)) { return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); -- cgit v1.2.1 From 36b536afbf9f8adfc6511521bb8596ad7762a247 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Jan 2017 01:57:29 +0100 Subject: _PyStack_UnpackDict() now returns -1 on error Issue #29286. Change _PyStack_UnpackDict() prototype to be able to notify of failure when args is NULL. --- Objects/abstract.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 48fdf6541a..ee50f02057 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2421,9 +2421,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 *func) { PyObject **stack, **kwstack; Py_ssize_t nkwargs; @@ -2435,25 +2435,26 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, assert(kwargs == NULL || PyDict_CheckExact(kwargs)); 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) */ @@ -2472,8 +2473,9 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, i++; } + *p_stack = stack; *p_kwnames = kwnames; - return stack; + return 0; } PyObject * -- cgit v1.2.1 From e44ae9a7fd3a32fc03338559f82679db3e6f79fd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jan 2017 10:31:46 +0100 Subject: Remove unused func parameter of _PyStack_UnpackDict() Issue #29259. --- Objects/abstract.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index ee50f02057..682263d7bc 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2423,7 +2423,7 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames) int _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, - PyObject ***p_stack, PyObject **p_kwnames, PyObject *func) + PyObject ***p_stack, PyObject **p_kwnames) { PyObject **stack, **kwstack; Py_ssize_t nkwargs; -- cgit v1.2.1 From 1e87b169d0aabb2b52f5d642b96dbb60b41310f1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jan 2017 11:27:22 +0100 Subject: _PyObject_FastCallKeywords() now checks the result Issue ##27830, Issue #29259. --- Objects/abstract.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 682263d7bc..4b32fedccf 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2539,6 +2539,8 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg Py_DECREF(argtuple); Py_XDECREF(kwdict); + result = _Py_CheckFunctionResult(callable, result, NULL); + exit: Py_LeaveRecursiveCall(); return result; -- cgit v1.2.1 From 74d6d9a64feed656f54ca069e3ccc6e4bf1db270 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jan 2017 14:06:38 +0100 Subject: _PyObject_FastCallKeywords() now checks !PyErr_Occurred() Issue #29259. All other functions calling functions start with the similar assertion. --- Objects/abstract.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 4b32fedccf..1132b842ca 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2482,6 +2482,11 @@ PyObject * _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t nargs, PyObject *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)); -- cgit v1.2.1 From 4a6bc8201521488a56ced3d3825e21915f681fae Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jan 2017 14:12:51 +0100 Subject: Rephrase !PyErr_Occurred() comment: may=>can Issue #29259. --- Objects/abstract.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 1132b842ca..7b1f196891 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2233,7 +2233,7 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) 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)); @@ -2309,7 +2309,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, 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()); -- cgit v1.2.1 From abe9d8370c190416822dbc329872de805219caf6 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jan 2017 18:06:32 +0100 Subject: _PyStack_AsDict() now checks kwnames != NULL Issue #29259. --- Objects/abstract.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 7b1f196891..58640323dc 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2399,10 +2399,12 @@ _PyObject_Call_Prepend(PyObject *callable, 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; + assert(kwnames != NULL); + nkwargs = PyTuple_GET_SIZE(kwnames); kwdict = _PyDict_NewPresized(nkwargs); if (kwdict == NULL) { return NULL; -- cgit v1.2.1 From df457ae79fffb23d438ddd780dd0fbbb60062299 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 24 Jan 2017 15:05:30 +0100 Subject: Issue #29360: _PyStack_AsDict() doesn't check kwnames Remove two assertions which can fail on legit code. Keyword arguments are checked later with better tests and raise a regular (TypeError) exception. --- Objects/abstract.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Objects/abstract.c') diff --git a/Objects/abstract.c b/Objects/abstract.c index 58640323dc..1e394f865a 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2413,8 +2413,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; -- cgit v1.2.1