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. --- Modules/_asynciomodule.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index b65fc02ebd..19503a86f2 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -721,8 +721,7 @@ static PyObject * _asyncio_Future__repr_info_impl(FutureObj *self) /*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/ { - return PyObject_CallFunctionObjArgs( - asyncio_future_repr_info_func, self, NULL); + return _PyObject_CallArg1(asyncio_future_repr_info_func, self); } /*[clinic input] @@ -1535,8 +1534,7 @@ static PyObject * _asyncio_Task__repr_info_impl(TaskObj *self) /*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/ { - return PyObject_CallFunctionObjArgs( - asyncio_task_repr_info_func, self, NULL); + return _PyObject_CallArg1(asyncio_task_repr_info_func, self); } /*[clinic input] @@ -1896,7 +1894,7 @@ task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...) return NULL; } - PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL); + PyObject *e = _PyObject_CallArg1(et, msg); Py_DECREF(msg); if (e == NULL) { return NULL; @@ -1946,7 +1944,7 @@ task_step_impl(TaskObj *task, PyObject *exc) if (!exc) { /* exc was not a CancelledError */ - exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL); + exc = _PyObject_CallNoArg(asyncio_CancelledError); if (!exc) { goto fail; } @@ -2176,7 +2174,7 @@ task_step_impl(TaskObj *task, PyObject *exc) } /* Check if `result` is a generator */ - o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL); + o = _PyObject_CallArg1(inspect_isgenerator, result); if (o == NULL) { /* An exception in inspect.isgenerator */ goto fail; -- cgit v1.2.1 From 777fd0cb30943eb01297d2315c66fa1df791a9b5 Mon Sep 17 00:00:00 2001 From: Yury Selivanov Date: Thu, 1 Dec 2016 11:37:47 -0500 Subject: Merge 3.6 (issue #28843) --- Modules/_asynciomodule.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 19503a86f2..86f191d8f5 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1041,6 +1041,8 @@ FutureIter_throw(futureiterobject *self, PyObject *args) if (PyExceptionClass_Check(type)) { PyErr_NormalizeException(&type, &val, &tb); + /* No need to call PyException_SetTraceback since we'll be calling + PyErr_Restore for `type`, `val`, and `tb`. */ } else if (PyExceptionInstance_Check(type)) { if (val) { PyErr_SetString(PyExc_TypeError, @@ -2001,6 +2003,9 @@ task_step_impl(TaskObj *task, PyObject *exc) if (!ev || !PyObject_TypeCheck(ev, (PyTypeObject *) et)) { PyErr_NormalizeException(&et, &ev, &tb); } + if (tb != NULL) { + PyException_SetTraceback(ev, tb); + } o = future_set_exception((FutureObj*)task, ev); if (!o) { /* An exception in Task.set_exception() */ -- 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(). --- Modules/_asynciomodule.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 86f191d8f5..4e8f74a3c9 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -721,7 +721,8 @@ static PyObject * _asyncio_Future__repr_info_impl(FutureObj *self) /*[clinic end generated code: output=fa69e901bd176cfb input=f21504d8e2ae1ca2]*/ { - return _PyObject_CallArg1(asyncio_future_repr_info_func, self); + return PyObject_CallFunctionObjArgs( + asyncio_future_repr_info_func, self, NULL); } /*[clinic input] @@ -1536,7 +1537,8 @@ static PyObject * _asyncio_Task__repr_info_impl(TaskObj *self) /*[clinic end generated code: output=6a490eb66d5ba34b input=3c6d051ed3ddec8b]*/ { - return _PyObject_CallArg1(asyncio_task_repr_info_func, self); + return PyObject_CallFunctionObjArgs( + asyncio_task_repr_info_func, self, NULL); } /*[clinic input] @@ -1896,7 +1898,7 @@ task_set_error_soon(TaskObj *task, PyObject *et, const char *format, ...) return NULL; } - PyObject *e = _PyObject_CallArg1(et, msg); + PyObject *e = PyObject_CallFunctionObjArgs(et, msg, NULL); Py_DECREF(msg); if (e == NULL) { return NULL; @@ -1946,7 +1948,7 @@ task_step_impl(TaskObj *task, PyObject *exc) if (!exc) { /* exc was not a CancelledError */ - exc = _PyObject_CallNoArg(asyncio_CancelledError); + exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL); if (!exc) { goto fail; } @@ -2179,7 +2181,7 @@ task_step_impl(TaskObj *task, PyObject *exc) } /* Check if `result` is a generator */ - o = _PyObject_CallArg1(inspect_isgenerator, result); + o = PyObject_CallFunctionObjArgs(inspect_isgenerator, result, NULL); if (o == NULL) { /* An exception in inspect.isgenerator */ goto fail; -- 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. --- Modules/_asynciomodule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 4e8f74a3c9..ea02a5e9c0 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -257,7 +257,7 @@ future_get_result(FutureObj *fut, PyObject **result) return -1; } - exc = _PyObject_CallArg1(asyncio_InvalidStateError, msg); + exc = PyObject_CallFunctionObjArgs(asyncio_InvalidStateError, msg, NULL); Py_DECREF(msg); if (exc == NULL) { return -1; @@ -835,7 +835,7 @@ FutureObj_finalize(FutureObj *fut) func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler); if (func != NULL) { - res = _PyObject_CallArg1(func, context); + res = PyObject_CallFunctionObjArgs(func, context, NULL); if (res == NULL) { PyErr_WriteUnraisable(func); } @@ -1731,7 +1731,7 @@ TaskObj_finalize(TaskObj *task) func = _PyObject_GetAttrId(task->task_loop, &PyId_call_exception_handler); if (func != NULL) { - res = _PyObject_CallArg1(func, context); + res = PyObject_CallFunctionObjArgs(func, context, NULL); if (res == NULL) { PyErr_WriteUnraisable(func); } -- cgit v1.2.1 From b729181a504b6aff2461dcbc07c33e902ee90cb0 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 6 Dec 2016 18:45:50 +0100 Subject: Use _PyObject_CallNoArg() Replace: PyObject_CallObject(callable, NULL) with: _PyObject_CallNoArg(callable) --- Modules/_asynciomodule.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index ea02a5e9c0..67794c3fa5 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -141,7 +141,7 @@ future_init(FutureObj *fut, PyObject *loop) _Py_IDENTIFIER(get_debug); if (loop == NULL || loop == Py_None) { - loop = PyObject_CallObject(asyncio_get_event_loop, NULL); + loop = _PyObject_CallNoArg(asyncio_get_event_loop); if (loop == NULL) { return -1; } @@ -158,7 +158,7 @@ future_init(FutureObj *fut, PyObject *loop) } if (PyObject_IsTrue(res)) { Py_CLEAR(res); - fut->fut_source_tb = PyObject_CallObject(traceback_extract_stack, NULL); + fut->fut_source_tb = _PyObject_CallNoArg(traceback_extract_stack); if (fut->fut_source_tb == NULL) { return -1; } @@ -204,7 +204,7 @@ future_set_exception(FutureObj *fut, PyObject *exc) } if (PyExceptionClass_Check(exc)) { - exc_val = PyObject_CallObject(exc, NULL); + exc_val = _PyObject_CallNoArg(exc); if (exc_val == NULL) { return NULL; } @@ -1429,7 +1429,7 @@ _asyncio_Task_current_task_impl(PyTypeObject *type, PyObject *loop) PyObject *res; if (loop == NULL) { - loop = PyObject_CallObject(asyncio_get_event_loop, NULL); + loop = _PyObject_CallNoArg(asyncio_get_event_loop); if (loop == NULL) { return NULL; } @@ -1514,7 +1514,7 @@ _asyncio_Task_all_tasks_impl(PyTypeObject *type, PyObject *loop) PyObject *res; if (loop == NULL) { - loop = PyObject_CallObject(asyncio_get_event_loop, NULL); + loop = _PyObject_CallNoArg(asyncio_get_event_loop); if (loop == NULL) { return NULL; } @@ -2387,7 +2387,7 @@ module_init(void) WITH_MOD("weakref") GET_MOD_ATTR(cls, "WeakSet") - all_tasks = PyObject_CallObject(cls, NULL); + all_tasks = _PyObject_CallNoArg(cls); Py_CLEAR(cls); if (all_tasks == NULL) { goto fail; -- 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) --- Modules/_asynciomodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 67794c3fa5..d8522b9403 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -1948,7 +1948,7 @@ task_step_impl(TaskObj *task, PyObject *exc) if (!exc) { /* exc was not a CancelledError */ - exc = PyObject_CallFunctionObjArgs(asyncio_CancelledError, NULL); + exc = _PyObject_CallNoArg(asyncio_CancelledError); if (!exc) { goto fail; } -- cgit v1.2.1 From c27b3be61e0c5cc22792c71ffd042ce717648e9a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 14:24:02 +0100 Subject: Use _PyObject_CallMethodIdObjArgs() in _asyncio Issue #28915: Replace _PyObject_CallMethodId() with _PyObject_CallMethodIdObjArgs() when the format string was only made of "O" formats, PyObject* arguments. _PyObject_CallMethodIdObjArgs() avoids the creation of a temporary tuple and doesn't have to parse a format string. --- Modules/_asynciomodule.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'Modules/_asynciomodule.c') diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index d8522b9403..ceac7f0039 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -118,8 +118,8 @@ future_schedule_callbacks(FutureObj *fut) PyObject *handle = NULL; PyObject *cb = PyList_GET_ITEM(iters, i); - handle = _PyObject_CallMethodId( - fut->fut_loop, &PyId_call_soon, "OO", cb, fut, NULL); + handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, &PyId_call_soon, + cb, fut, NULL); if (handle == NULL) { Py_DECREF(iters); @@ -283,8 +283,9 @@ static PyObject * future_add_done_callback(FutureObj *fut, PyObject *arg) { if (fut->fut_state != STATE_PENDING) { - PyObject *handle = _PyObject_CallMethodId( - fut->fut_loop, &PyId_call_soon, "OO", arg, fut, NULL); + PyObject *handle = _PyObject_CallMethodIdObjArgs(fut->fut_loop, + &PyId_call_soon, + arg, fut, NULL); if (handle == NULL) { return NULL; @@ -1327,7 +1328,7 @@ _asyncio_Task___init___impl(TaskObj *self, PyObject *coro, PyObject *loop) return -1; } - res = _PyObject_CallMethodId(all_tasks, &PyId_add, "O", self, NULL); + res = _PyObject_CallMethodIdObjArgs(all_tasks, &PyId_add, self, NULL); if (res == NULL) { return -1; } @@ -1838,8 +1839,8 @@ task_call_wakeup(TaskObj *task, PyObject *fut) } else { /* `task` is a subclass of Task */ - return _PyObject_CallMethodId( - (PyObject*)task, &PyId__wakeup, "O", fut, NULL); + return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__wakeup, + fut, NULL); } } @@ -1854,8 +1855,8 @@ task_call_step(TaskObj *task, PyObject *arg) if (arg == NULL) { arg = Py_None; } - return _PyObject_CallMethodId( - (PyObject*)task, &PyId__step, "O", arg, NULL); + return _PyObject_CallMethodIdObjArgs((PyObject*)task, &PyId__step, + arg, NULL); } } @@ -1869,8 +1870,8 @@ task_call_step_soon(TaskObj *task, PyObject *arg) return -1; } - handle = _PyObject_CallMethodId( - task->task_loop, &PyId_call_soon, "O", cb, NULL); + handle = _PyObject_CallMethodIdObjArgs(task->task_loop, &PyId_call_soon, + cb, NULL); Py_DECREF(cb); if (handle == NULL) { return -1; @@ -1965,13 +1966,13 @@ task_step_impl(TaskObj *task, PyObject *exc) result = _PyGen_Send((PyGenObject*)coro, Py_None); } else { - result = _PyObject_CallMethodIdObjArgs( - coro, &PyId_send, Py_None, NULL); + result = _PyObject_CallMethodIdObjArgs(coro, &PyId_send, + Py_None, NULL); } } else { - result = _PyObject_CallMethodIdObjArgs( - coro, &PyId_throw, exc, NULL); + result = _PyObject_CallMethodIdObjArgs(coro, &PyId_throw, + exc, NULL); if (clear_exc) { /* We created 'exc' during this call */ Py_CLEAR(exc); @@ -2135,8 +2136,9 @@ task_step_impl(TaskObj *task, PyObject *exc) if (wrapper == NULL) { goto fail; } - res = _PyObject_CallMethodId( - result, &PyId_add_done_callback, "O", wrapper, NULL); + res = _PyObject_CallMethodIdObjArgs(result, + &PyId_add_done_callback, + wrapper, NULL); Py_DECREF(wrapper); if (res == NULL) { goto fail; -- cgit v1.2.1