From ff4988fe1c104125462faa6d68d1f2c957b00727 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 00:36:19 +0100 Subject: Use _PyObject_CallMethodIdObjArgs() Issue #28915: Replace _PyObject_CallMethodId() with _PyObject_CallMethodIdObjArgs() when the format string only use the format 'O' for objects, like "(O)". _PyObject_CallMethodIdObjArgs() avoids the code to parse a format string and avoids the creation of a temporary tuple. --- Objects/descrobject.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Objects/descrobject.c') diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 076e741481..ee356b1bf4 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -804,7 +804,8 @@ mappingproxy_get(mappingproxyobject *pp, PyObject *args) if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def)) return NULL; - return _PyObject_CallMethodId(pp->mapping, &PyId_get, "(OO)", key, def); + return _PyObject_CallMethodIdObjArgs(pp->mapping, &PyId_get, + key, def, NULL); } static PyObject * -- 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/descrobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/descrobject.c') diff --git a/Objects/descrobject.c b/Objects/descrobject.c index ee356b1bf4..090c9cdd04 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1454,7 +1454,7 @@ property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *del) doc = pold->prop_doc ? pold->prop_doc : Py_None; } - new = PyObject_CallFunction(type, "OOOO", get, set, del, doc); + new = PyObject_CallFunctionObjArgs(type, get, set, del, doc, NULL); Py_DECREF(type); if (new == 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/descrobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/descrobject.c') diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 090c9cdd04..ed398919a3 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1173,7 +1173,7 @@ wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds) return (*wk)(self, args, wp->descr->d_wrapped, kwds); } - if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) { + if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_GET_SIZE(kwds) != 0)) { PyErr_Format(PyExc_TypeError, "wrapper %s doesn't take keyword arguments", wp->descr->d_base->name); -- cgit v1.2.1 From b789d9fab8fd9c88b4463b5060034400937e8433 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Jan 2017 10:38:09 +0100 Subject: Optimize methoddescr_call(): avoid temporary PyCFunction Issue #29259, #29263. methoddescr_call() creates a PyCFunction object, call it and the destroy it. Add a new _PyMethodDef_RawFastCallDict() method to avoid the temporary PyCFunction object. --- Objects/descrobject.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'Objects/descrobject.c') diff --git a/Objects/descrobject.c b/Objects/descrobject.c index ed398919a3..a254a2a673 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -210,15 +210,15 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value) } static PyObject * -methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) +methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs) { - Py_ssize_t argc; - PyObject *self, *func, *result, **stack; + Py_ssize_t nargs; + PyObject *self, *result; /* Make sure that the first argument is acceptable as 'self' */ assert(PyTuple_Check(args)); - argc = PyTuple_GET_SIZE(args); - if (argc < 1) { + nargs = PyTuple_GET_SIZE(args); + if (nargs < 1) { PyErr_Format(PyExc_TypeError, "descriptor '%V' of '%.100s' " "object needs an argument", @@ -239,12 +239,10 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) return NULL; } - func = PyCFunction_NewEx(descr->d_method, self, NULL); - if (func == NULL) - return NULL; - stack = &PyTuple_GET_ITEM(args, 1); - result = _PyObject_FastCallDict(func, stack, argc - 1, kwds); - Py_DECREF(func); + result = _PyMethodDef_RawFastCallDict(descr->d_method, self, + &PyTuple_GET_ITEM(args, 1), nargs - 1, + kwargs); + result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL); return result; } -- cgit v1.2.1 From bfeec6d871e3db2e0ddfdef01387913bc19cadd4 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 23 Jan 2017 09:47:21 +0200 Subject: Issue #28999: Use Py_RETURN_NONE, Py_RETURN_TRUE and Py_RETURN_FALSE wherever possible. Patch is writen with Coccinelle. --- Objects/descrobject.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Objects/descrobject.c') diff --git a/Objects/descrobject.c b/Objects/descrobject.c index a254a2a673..3fb34a3d7b 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -419,8 +419,7 @@ static PyObject * member_get_doc(PyMemberDescrObject *descr, void *closure) { if (descr->d_member->doc == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyUnicode_FromString(descr->d_member->doc); } @@ -435,8 +434,7 @@ static PyObject * getset_get_doc(PyGetSetDescrObject *descr, void *closure) { if (descr->d_getset->doc == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyUnicode_FromString(descr->d_getset->doc); } -- cgit v1.2.1 From 99c092a531abf57a8f5c37356dc6971cdfed497a Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Fri, 3 Feb 2017 07:43:03 +0900 Subject: Issue #29263: LOAD_METHOD support for C methods Calling builtin method is at most 10% faster. --- Objects/descrobject.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'Objects/descrobject.c') diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 3fb34a3d7b..20c0d36eca 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -246,6 +246,44 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs) return result; } +// same to methoddescr_call(), but use FASTCALL convention. +PyObject * +_PyMethodDescr_FastCallKeywords(PyObject *descrobj, + PyObject **args, Py_ssize_t nargs, + PyObject *kwnames) +{ + assert(Py_TYPE(descrobj) == &PyMethodDescr_Type); + PyMethodDescrObject *descr = (PyMethodDescrObject *)descrobj; + PyObject *self, *result; + + /* Make sure that the first argument is acceptable as 'self' */ + if (nargs < 1) { + PyErr_Format(PyExc_TypeError, + "descriptor '%V' of '%.100s' " + "object needs an argument", + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name); + return NULL; + } + self = args[0]; + if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self), + (PyObject *)PyDescr_TYPE(descr))) { + PyErr_Format(PyExc_TypeError, + "descriptor '%V' " + "requires a '%.100s' object " + "but received a '%.100s'", + descr_name((PyDescrObject *)descr), "?", + PyDescr_TYPE(descr)->tp_name, + self->ob_type->tp_name); + return NULL; + } + + result = _PyMethodDef_RawFastCallKeywords(descr->d_method, self, + args+1, nargs-1, kwnames); + result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL); + return result; +} + static PyObject * classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds) -- cgit v1.2.1