From 4e2f6b4e0c27b2914a11bd18f09170b7686c5f70 Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Wed, 15 Feb 2017 00:16:28 +0900 Subject: [PATCH 1/4] Fix some inefficient call API usage --- Modules/_functoolsmodule.c | 25 ++++++----------------- Modules/_testcapimodule.c | 2 +- Modules/_threadmodule.c | 3 +-- Modules/_tkinter.c | 9 +++------ Objects/abstract.c | 2 +- Objects/fileobject.c | 41 +++++++++++++------------------------- Objects/typeobject.c | 2 +- Objects/weakrefobject.c | 2 +- 8 files changed, 28 insertions(+), 58 deletions(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 4170883368f953..6007de14b0e7ee 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -560,37 +560,25 @@ functools_reduce(PyObject *self, PyObject *args) return NULL; } - if ((args = PyTuple_New(2)) == NULL) - goto Fail; - for (;;) { - PyObject *op2; - - if (args->ob_refcnt > 1) { - Py_DECREF(args); - if ((args = PyTuple_New(2)) == NULL) - goto Fail; - } - - op2 = PyIter_Next(it); + PyObject *op2 = PyIter_Next(it); if (op2 == NULL) { if (PyErr_Occurred()) goto Fail; break; } - if (result == NULL) + if (result == NULL) { result = op2; + } else { - PyTuple_SetItem(args, 0, result); - PyTuple_SetItem(args, 1, op2); - if ((result = PyEval_CallObject(func, args)) == NULL) + PyObject *args[] = {result, op2}; + if ((result = _PyObject_FastCall(func, args, 2)) == NULL) { goto Fail; + } } } - Py_DECREF(args); - if (result == NULL) PyErr_SetString(PyExc_TypeError, "reduce() of empty sequence with no initial value"); @@ -599,7 +587,6 @@ functools_reduce(PyObject *self, PyObject *args) return result; Fail: - Py_XDECREF(args); Py_XDECREF(result); Py_DECREF(it); return NULL; diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 03a4acbc798475..11015df011a5d3 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -3070,7 +3070,7 @@ slot_tp_del(PyObject *self) /* Execute __del__ method, if any. */ del = _PyObject_LookupSpecial(self, &PyId___tp_del__); if (del != NULL) { - res = PyEval_CallObject(del, NULL); + res = _PyObject_CallNoArg(del); if (res == NULL) PyErr_WriteUnraisable(del); else diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c index 8be9306d6a13f8..bf25a19eb25076 100644 --- a/Modules/_threadmodule.c +++ b/Modules/_threadmodule.c @@ -994,8 +994,7 @@ t_bootstrap(void *boot_raw) _PyThreadState_Init(tstate); PyEval_AcquireThread(tstate); nb_threads++; - res = PyEval_CallObjectWithKeywords( - boot->func, boot->args, boot->keyw); + res = PyObject_Call(boot->func, boot->args, boot->keyw); if (res == NULL) { if (PyErr_ExceptionMatches(PyExc_SystemExit)) PyErr_Clear(); diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index f69a4dfed9bd2b..ff11a779fcab39 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -2417,7 +2417,7 @@ PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[ } PyTuple_SET_ITEM(arg, i, s); } - res = PyEval_CallObject(func, arg); + res = PyObject_Call(func, arg, NULL); Py_DECREF(arg); if (res == NULL) @@ -2667,10 +2667,7 @@ FileHandler(ClientData clientData, int mask) func = data->func; file = data->file; - arg = Py_BuildValue("(Oi)", file, (long) mask); - res = PyEval_CallObject(func, arg); - Py_DECREF(arg); - + res = PyObject_CallFunction(func, "Oi", file, (long) mask); if (res == NULL) { errorInCmd = 1; PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd); @@ -2840,7 +2837,7 @@ TimerHandler(ClientData clientData) ENTER_PYTHON - res = PyEval_CallObject(func, NULL); + res = _PyObject_CallNoArg(func); Py_DECREF(func); Py_DECREF(v); /* See Tktt_New() */ diff --git a/Objects/abstract.c b/Objects/abstract.c index 589d9e8fd9b067..4a75b92e1d0895 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -1329,7 +1329,7 @@ PyNumber_Long(PyObject *o) } trunc_func = _PyObject_LookupSpecial(o, &PyId___trunc__); if (trunc_func) { - result = PyEval_CallObject(trunc_func, NULL); + result = _PyObject_CallNoArg(trunc_func); Py_DECREF(trunc_func); if (result == NULL || PyLong_CheckExact(result)) { return result; diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 3c3d46da512f54..0f71944d526ec8 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -49,6 +49,7 @@ PyFile_FromFd(int fd, const char *name, const char *mode, int buffering, const c PyObject * PyFile_GetLine(PyObject *f, int n) { + _Py_IDENTIFIER(readline); PyObject *result; if (f == NULL) { @@ -56,32 +57,18 @@ PyFile_GetLine(PyObject *f, int n) return NULL; } - { - PyObject *reader; - PyObject *args; - _Py_IDENTIFIER(readline); - - reader = _PyObject_GetAttrId(f, &PyId_readline); - if (reader == NULL) - return NULL; - if (n <= 0) - args = PyTuple_New(0); - else - args = Py_BuildValue("(i)", n); - if (args == NULL) { - Py_DECREF(reader); - return NULL; - } - result = PyEval_CallObject(reader, args); - Py_DECREF(reader); - Py_DECREF(args); - if (result != NULL && !PyBytes_Check(result) && - !PyUnicode_Check(result)) { - Py_DECREF(result); - result = NULL; - PyErr_SetString(PyExc_TypeError, - "object.readline() returned non-string"); - } + if (n <= 0) { + result = _PyObject_CallMethodIdObjArgs(f, &PyId_readline, NULL); + } + else { + result = _PyObject_CallMethodId(f, &PyId_readline, "i", n); + } + if (result != NULL && !PyBytes_Check(result) && + !PyUnicode_Check(result)) { + Py_DECREF(result); + result = NULL; + PyErr_SetString(PyExc_TypeError, + "object.readline() returned non-string"); } if (n < 0 && result != NULL && PyBytes_Check(result)) { @@ -197,7 +184,7 @@ PyObject_AsFileDescriptor(PyObject *o) } else if ((meth = _PyObject_GetAttrId(o, &PyId_fileno)) != NULL) { - PyObject *fno = PyEval_CallObject(meth, NULL); + PyObject *fno = _PyObject_CallNoArg(meth); Py_DECREF(meth); if (fno == NULL) return -1; diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f18a79526b27b9..18b67c83258dcb 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4348,7 +4348,7 @@ _common_reduce(PyObject *self, int proto) if (!copyreg) return NULL; - res = PyEval_CallMethod(copyreg, "_reduce_ex", "(Oi)", self, proto); + res = PyObject_CallMethod(copyreg, "_reduce_ex", "Oi", self, proto); Py_DECREF(copyreg); return res; diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index ab6b23525552b8..d12db9185d8611 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -461,7 +461,7 @@ proxy_checkref(PyWeakReference *proxy) WRAP_BINARY(proxy_getattr, PyObject_GetAttr) WRAP_UNARY(proxy_str, PyObject_Str) -WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords) +WRAP_TERNARY(proxy_call, PyObject_Call) static PyObject * proxy_repr(PyWeakReference *proxy) From 4e7d7a476021f3a38e26ee4227385474f031e9d5 Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Thu, 16 Feb 2017 01:06:12 +0900 Subject: [PATCH 2/4] minor style fix --- Modules/_functoolsmodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 6007de14b0e7ee..8a95abef5577b6 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -573,7 +573,8 @@ functools_reduce(PyObject *self, PyObject *args) } else { PyObject *args[] = {result, op2}; - if ((result = _PyObject_FastCall(func, args, 2)) == NULL) { + result = _PyObject_FastCall(func, args, 2); + if (result == NULL) { goto Fail; } } From 706f9e39b2ca4c8fa93f9ca7c6459cf142f973cf Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Thu, 16 Feb 2017 08:36:52 +0900 Subject: [PATCH 3/4] revert functools changes --- Modules/_functoolsmodule.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c index 8a95abef5577b6..4170883368f953 100644 --- a/Modules/_functoolsmodule.c +++ b/Modules/_functoolsmodule.c @@ -560,26 +560,37 @@ functools_reduce(PyObject *self, PyObject *args) return NULL; } + if ((args = PyTuple_New(2)) == NULL) + goto Fail; + for (;;) { - PyObject *op2 = PyIter_Next(it); + PyObject *op2; + + if (args->ob_refcnt > 1) { + Py_DECREF(args); + if ((args = PyTuple_New(2)) == NULL) + goto Fail; + } + + op2 = PyIter_Next(it); if (op2 == NULL) { if (PyErr_Occurred()) goto Fail; break; } - if (result == NULL) { + if (result == NULL) result = op2; - } else { - PyObject *args[] = {result, op2}; - result = _PyObject_FastCall(func, args, 2); - if (result == NULL) { + PyTuple_SetItem(args, 0, result); + PyTuple_SetItem(args, 1, op2); + if ((result = PyEval_CallObject(func, args)) == NULL) goto Fail; - } } } + Py_DECREF(args); + if (result == NULL) PyErr_SetString(PyExc_TypeError, "reduce() of empty sequence with no initial value"); @@ -588,6 +599,7 @@ functools_reduce(PyObject *self, PyObject *args) return result; Fail: + Py_XDECREF(args); Py_XDECREF(result); Py_DECREF(it); return NULL; From 044f9fdf457302d74b7b33d016483295aabe8f2e Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Thu, 16 Feb 2017 08:55:08 +0900 Subject: [PATCH 4/4] remove unused variable. fix inconsistency between arg format and argument. --- Modules/_tkinter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index ff11a779fcab39..1abc0e225e99f9 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -2661,13 +2661,13 @@ static void FileHandler(ClientData clientData, int mask) { FileHandler_ClientData *data = (FileHandler_ClientData *)clientData; - PyObject *func, *file, *arg, *res; + PyObject *func, *file, *res; ENTER_PYTHON func = data->func; file = data->file; - res = PyObject_CallFunction(func, "Oi", file, (long) mask); + res = PyObject_CallFunction(func, "Oi", file, mask); if (res == NULL) { errorInCmd = 1; PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);