From 5d858465b6ebdafa05f86309457848cc26913b6a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 20 Nov 2016 10:16:47 +0200 Subject: Added the const qualifier to char* variables that refer to readonly internal UTF-8 represenatation of Unicode objects. --- Objects/typeobject.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 606e08e449..af09271680 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1624,7 +1624,7 @@ consistent method resolution\norder (MRO) for bases"); i = 0; while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) { PyObject *name = class_name(k); - char *name_str; + const char *name_str; if (name != NULL) { name_str = PyUnicode_AsUTF8(name); if (name_str == NULL) @@ -2572,7 +2572,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) PyObject *doc = _PyDict_GetItemId(dict, &PyId___doc__); if (doc != NULL && PyUnicode_Check(doc)) { Py_ssize_t len; - char *doc_str; + const char *doc_str; char *tp_doc; doc_str = PyUnicode_AsUTF8(doc); -- 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/typeobject.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 186c57016c..3cff904894 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1425,15 +1425,16 @@ _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) as lookup_method to cache the interned name string object. */ static PyObject * -call_method(PyObject *o, _Py_Identifier *nameid, const char *format, ...) +call_method(PyObject *obj, _Py_Identifier *method, const char *format, ...) { va_list va; - PyObject *func = NULL, *retval; + PyObject *func, *retval; - func = lookup_maybe(o, nameid); + func = lookup_maybe(obj, method); if (func == NULL) { - if (!PyErr_Occurred()) - PyErr_SetObject(PyExc_AttributeError, nameid->object); + if (!PyErr_Occurred()) { + PyErr_SetObject(PyExc_AttributeError, method->object); + } return NULL; } @@ -1465,12 +1466,12 @@ call_method(PyObject *o, _Py_Identifier *nameid, const char *format, ...) /* Clone of call_method() that returns NotImplemented when the lookup fails. */ static PyObject * -call_maybe(PyObject *o, _Py_Identifier *nameid, const char *format, ...) +call_maybe(PyObject *obj, _Py_Identifier *method, const char *format, ...) { va_list va; - PyObject *func = NULL, *retval; + PyObject *func, *retval; - func = lookup_maybe(o, nameid); + func = lookup_maybe(obj, method); if (func == NULL) { if (!PyErr_Occurred()) Py_RETURN_NOTIMPLEMENTED; -- 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/typeobject.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3cff904894..186c57016c 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1425,16 +1425,15 @@ _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) as lookup_method to cache the interned name string object. */ static PyObject * -call_method(PyObject *obj, _Py_Identifier *method, const char *format, ...) +call_method(PyObject *o, _Py_Identifier *nameid, const char *format, ...) { va_list va; - PyObject *func, *retval; + PyObject *func = NULL, *retval; - func = lookup_maybe(obj, method); + func = lookup_maybe(o, nameid); if (func == NULL) { - if (!PyErr_Occurred()) { - PyErr_SetObject(PyExc_AttributeError, method->object); - } + if (!PyErr_Occurred()) + PyErr_SetObject(PyExc_AttributeError, nameid->object); return NULL; } @@ -1466,12 +1465,12 @@ call_method(PyObject *obj, _Py_Identifier *method, const char *format, ...) /* Clone of call_method() that returns NotImplemented when the lookup fails. */ static PyObject * -call_maybe(PyObject *obj, _Py_Identifier *method, const char *format, ...) +call_maybe(PyObject *o, _Py_Identifier *nameid, const char *format, ...) { va_list va; - PyObject *func, *retval; + PyObject *func = NULL, *retval; - func = lookup_maybe(obj, method); + func = lookup_maybe(o, nameid); if (func == NULL) { if (!PyErr_Occurred()) Py_RETURN_NOTIMPLEMENTED; -- 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/typeobject.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 186c57016c..a9f352046c 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3487,9 +3487,7 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) sorted = _PyDict_GetItemId(builtins, &PyId_sorted); if (sorted == NULL) goto error; - sorted_methods = PyObject_CallFunctionObjArgs(sorted, - abstract_methods, - NULL); + sorted_methods = _PyObject_CallArg1(sorted, abstract_methods); if (sorted_methods == NULL) goto error; comma = _PyUnicode_FromId(&comma_id); @@ -6193,7 +6191,7 @@ call_attribute(PyObject *self, PyObject *attr, PyObject *name) else attr = descr; } - res = PyObject_CallFunctionObjArgs(attr, name, NULL); + res = _PyObject_CallArg1(attr, name); Py_XDECREF(descr); return res; } -- 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/typeobject.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a9f352046c..186c57016c 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3487,7 +3487,9 @@ object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) sorted = _PyDict_GetItemId(builtins, &PyId_sorted); if (sorted == NULL) goto error; - sorted_methods = _PyObject_CallArg1(sorted, abstract_methods); + sorted_methods = PyObject_CallFunctionObjArgs(sorted, + abstract_methods, + NULL); if (sorted_methods == NULL) goto error; comma = _PyUnicode_FromId(&comma_id); @@ -6191,7 +6193,7 @@ call_attribute(PyObject *self, PyObject *attr, PyObject *name) else attr = descr; } - res = _PyObject_CallArg1(attr, name); + res = PyObject_CallFunctionObjArgs(attr, name, NULL); Py_XDECREF(descr); return res; } -- 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/typeobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0af153481a..d9699ef1ba 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -5873,7 +5873,7 @@ slot_sq_item(PyObject *self, Py_ssize_t i) goto error; } - retval = _PyObject_CallArg1(func, ival); + retval = PyObject_CallFunctionObjArgs(func, ival, NULL); Py_DECREF(func); Py_DECREF(ival); return retval; @@ -5914,7 +5914,7 @@ slot_sq_contains(PyObject *self, PyObject *value) return -1; } if (func != NULL) { - res = _PyObject_CallArg1(func, value); + res = PyObject_CallFunctionObjArgs(func, value, NULL); Py_DECREF(func); if (res != NULL) { result = PyObject_IsTrue(res); @@ -6284,7 +6284,7 @@ slot_tp_richcompare(PyObject *self, PyObject *other, int op) PyErr_Clear(); Py_RETURN_NOTIMPLEMENTED; } - res = _PyObject_CallArg1(func, other); + res = PyObject_CallFunctionObjArgs(func, other, NULL); Py_DECREF(func); return res; } -- cgit v1.2.1 From 9a6cf6cff587281c54dc45951ff3f24e1385cc18 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 5 Dec 2016 18:23:27 +0100 Subject: Use directly _PyObject_GenericSetAttrWithDict() Modify type_setattro() to call directly _PyObject_GenericSetAttrWithDict() instead of PyObject_GenericSetAttr(). PyObject_GenericSetAttr() is a thin wrapper to _PyObject_GenericSetAttrWithDict(). --- Objects/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index d9699ef1ba..f3e718b5e6 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3082,7 +3082,7 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) type->tp_name); return -1; } - if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0) + if (_PyObject_GenericSetAttrWithDict((PyObject *)type, name, value, NULL) < 0) return -1; return update_slot(type, name); } -- 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/typeobject.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index f3e718b5e6..0fcdd7d2fc 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1425,15 +1425,15 @@ _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) as lookup_method to cache the interned name string object. */ static PyObject * -call_method(PyObject *o, _Py_Identifier *nameid, const char *format, ...) +call_method(PyObject *obj, _Py_Identifier *name, const char *format, ...) { va_list va; PyObject *func = NULL, *retval; - func = lookup_maybe(o, nameid); + func = lookup_maybe(obj, name); if (func == NULL) { if (!PyErr_Occurred()) - PyErr_SetObject(PyExc_AttributeError, nameid->object); + PyErr_SetObject(PyExc_AttributeError, name->object); return NULL; } @@ -1465,12 +1465,12 @@ call_method(PyObject *o, _Py_Identifier *nameid, const char *format, ...) /* Clone of call_method() that returns NotImplemented when the lookup fails. */ static PyObject * -call_maybe(PyObject *o, _Py_Identifier *nameid, const char *format, ...) +call_maybe(PyObject *obj, _Py_Identifier *name, const char *format, ...) { va_list va; PyObject *func = NULL, *retval; - func = lookup_maybe(o, nameid); + func = lookup_maybe(obj, name); if (func == NULL) { if (!PyErr_Occurred()) Py_RETURN_NOTIMPLEMENTED; -- 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) --- Objects/typeobject.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0fcdd7d2fc..1758de2032 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1856,7 +1856,7 @@ mro_invoke(PyTypeObject *type) PyObject *mro_meth = lookup_method((PyObject *)type, &PyId_mro); if (mro_meth == NULL) return NULL; - mro_result = PyObject_CallObject(mro_meth, NULL); + mro_result = _PyObject_CallNoArg(mro_meth); Py_DECREF(mro_meth); } else { @@ -4032,7 +4032,7 @@ _PyObject_GetState(PyObject *obj, int required) Py_DECREF(slotnames); } else { /* getstate != NULL */ - state = PyObject_CallObject(getstate, NULL); + state = _PyObject_CallNoArg(getstate); Py_DECREF(getstate); if (state == NULL) return NULL; @@ -4057,7 +4057,7 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs) __getnewargs_ex__ on the object. */ getnewargs_ex = _PyObject_LookupSpecial(obj, &PyId___getnewargs_ex__); if (getnewargs_ex != NULL) { - PyObject *newargs = PyObject_CallObject(getnewargs_ex, NULL); + PyObject *newargs = _PyObject_CallNoArg(getnewargs_ex); Py_DECREF(getnewargs_ex); if (newargs == NULL) { return -1; @@ -4110,7 +4110,7 @@ _PyObject_GetNewArguments(PyObject *obj, PyObject **args, PyObject **kwargs) __getnewargs__ instead. */ getnewargs = _PyObject_LookupSpecial(obj, &PyId___getnewargs__); if (getnewargs != NULL) { - *args = PyObject_CallObject(getnewargs, NULL); + *args = _PyObject_CallNoArg(getnewargs); Py_DECREF(getnewargs); if (*args == NULL) { return -1; @@ -4362,7 +4362,7 @@ object_reduce_ex(PyObject *self, PyObject *args) override = (clsreduce != objreduce); Py_DECREF(clsreduce); if (override) { - res = PyObject_CallObject(reduce, NULL); + res = _PyObject_CallNoArg(reduce); Py_DECREF(reduce); return res; } -- cgit v1.2.1 From 260454930cfe21d8d987c17804740347b4829ee5 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 9 Dec 2016 00:41:46 +0100 Subject: Use _PyObject_FastCallVa() in type slots Issue #28915: Replace Py_VaBuildValue()+PyObject_Call() with _PyObject_FastCallVa() to avoid the creation of temporary tuple. --- Objects/typeobject.c | 131 ++++++++++++++++++++------------------------------- 1 file changed, 50 insertions(+), 81 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index c7f49b7321..88493b5afc 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1420,15 +1420,15 @@ _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) return lookup_maybe(self, attrid); } -/* A variation of PyObject_CallMethod that uses lookup_method() +/* A variation of PyObject_CallMethodObjArgs that uses lookup_method() instead of PyObject_GetAttrString(). This uses the same convention as lookup_method to cache the interned name string object. */ static PyObject * -call_method(PyObject *obj, _Py_Identifier *name, const char *format, ...) +call_method(PyObject *obj, _Py_Identifier *name, ...) { va_list va; - PyObject *func = NULL, *retval; + PyObject *func, *retval; func = lookup_maybe(obj, name); if (func == NULL) { @@ -1437,25 +1437,9 @@ call_method(PyObject *obj, _Py_Identifier *name, const char *format, ...) return NULL; } - if (format && *format) { - PyObject *args; - - va_start(va, format); - args = Py_VaBuildValue(format, va); - va_end(va); - - if (args == NULL) { - Py_DECREF(func); - return NULL; - } - assert(PyTuple_Check(args)); - - retval = PyObject_Call(func, args, NULL); - Py_DECREF(args); - } - else { - retval = _PyObject_CallNoArg(func); - } + va_start(va, name); + retval = _PyObject_VaCallFunctionObjArgs(func, va); + va_end(va); Py_DECREF(func); @@ -1465,10 +1449,10 @@ call_method(PyObject *obj, _Py_Identifier *name, const char *format, ...) /* Clone of call_method() that returns NotImplemented when the lookup fails. */ static PyObject * -call_maybe(PyObject *obj, _Py_Identifier *name, const char *format, ...) +call_maybe(PyObject *obj, _Py_Identifier *name, ...) { va_list va; - PyObject *func = NULL, *retval; + PyObject *func, *retval; func = lookup_maybe(obj, name); if (func == NULL) { @@ -1477,25 +1461,9 @@ call_maybe(PyObject *obj, _Py_Identifier *name, const char *format, ...) return NULL; } - if (format && *format) { - PyObject *args; - - va_start(va, format); - args = Py_VaBuildValue(format, va); - va_end(va); - - if (args == NULL) { - Py_DECREF(func); - return NULL; - } - assert(PyTuple_Check(args)); - - retval = PyObject_Call(func, args, NULL); - Py_DECREF(args); - } - else { - retval = _PyObject_CallNoArg(func); - } + va_start(va, name); + retval = _PyObject_VaCallFunctionObjArgs(func, va); + va_end(va); Py_DECREF(func); @@ -5736,12 +5704,12 @@ FUNCNAME(PyObject *self) \ return call_method(self, &id, NULL); \ } -#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \ +#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE) \ static PyObject * \ FUNCNAME(PyObject *self, ARG1TYPE arg1) \ { \ _Py_static_string(id, OPSTR); \ - return call_method(self, &id, "(" ARGCODES ")", arg1); \ + return call_method(self, &id, arg1, NULL); \ } /* Boolean helper for SLOT1BINFULL(). @@ -5794,20 +5762,20 @@ FUNCNAME(PyObject *self, PyObject *other) \ if (do_other && \ PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self)) && \ method_is_overloaded(self, other, &rop_id)) { \ - r = call_maybe(other, &rop_id, "(O)", self); \ + r = call_maybe(other, &rop_id, self, NULL); \ if (r != Py_NotImplemented) \ return r; \ Py_DECREF(r); \ do_other = 0; \ } \ - r = call_maybe(self, &op_id, "(O)", other); \ + r = call_maybe(self, &op_id, other, NULL); \ if (r != Py_NotImplemented || \ Py_TYPE(other) == Py_TYPE(self)) \ return r; \ Py_DECREF(r); \ } \ if (do_other) { \ - return call_maybe(other, &rop_id, "(O)", self); \ + return call_maybe(other, &rop_id, self, NULL); \ } \ Py_RETURN_NOTIMPLEMENTED; \ } @@ -5815,14 +5783,6 @@ FUNCNAME(PyObject *self, PyObject *other) \ #define SLOT1BIN(FUNCNAME, SLOTNAME, OPSTR, ROPSTR) \ SLOT1BINFULL(FUNCNAME, FUNCNAME, SLOTNAME, OPSTR, ROPSTR) -#define SLOT2(FUNCNAME, OPSTR, ARG1TYPE, ARG2TYPE, ARGCODES) \ -static PyObject * \ -FUNCNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \ -{ \ - _Py_static_string(id, #OPSTR); \ - return call_method(self, &id, "(" ARGCODES ")", arg1, arg2); \ -} - static Py_ssize_t slot_sq_length(PyObject *self) { @@ -5887,13 +5847,22 @@ static int slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) { PyObject *res; + PyObject *index_obj; + + index_obj = PyLong_FromSsize_t(index); + if (index_obj == NULL) { + return -1; + } if (value == NULL) - res = call_method(self, &PyId___delitem__, "(n)", index); + res = call_method(self, &PyId___delitem__, index_obj, NULL); else - res = call_method(self, &PyId___setitem__, "(nO)", index, value); - if (res == NULL) + res = call_method(self, &PyId___setitem__, index_obj, value, NULL); + Py_DECREF(index_obj); + + if (res == NULL) { return -1; + } Py_DECREF(res); return 0; } @@ -5931,7 +5900,7 @@ slot_sq_contains(PyObject *self, PyObject *value) #define slot_mp_length slot_sq_length -SLOT1(slot_mp_subscript, "__getitem__", PyObject *, "O") +SLOT1(slot_mp_subscript, "__getitem__", PyObject *) static int slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) @@ -5939,9 +5908,9 @@ slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) PyObject *res; if (value == NULL) - res = call_method(self, &PyId___delitem__, "(O)", key); + res = call_method(self, &PyId___delitem__, key, NULL); else - res = call_method(self, &PyId___setitem__, "(OO)", key, value); + res = call_method(self, &PyId___setitem__, key, value, NULL); if (res == NULL) return -1; @@ -5973,7 +5942,7 @@ slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) slot_nb_power, so check before calling self.__pow__. */ if (Py_TYPE(self)->tp_as_number != NULL && Py_TYPE(self)->tp_as_number->nb_power == slot_nb_power) { - return call_method(self, &PyId___pow__, "(OO)", other, modulus); + return call_method(self, &PyId___pow__, other, modulus, NULL); } Py_RETURN_NOTIMPLEMENTED; } @@ -6053,28 +6022,28 @@ SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__") SLOT0(slot_nb_int, "__int__") SLOT0(slot_nb_float, "__float__") -SLOT1(slot_nb_inplace_add, "__iadd__", PyObject *, "O") -SLOT1(slot_nb_inplace_subtract, "__isub__", PyObject *, "O") -SLOT1(slot_nb_inplace_multiply, "__imul__", PyObject *, "O") -SLOT1(slot_nb_inplace_matrix_multiply, "__imatmul__", PyObject *, "O") -SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *, "O") +SLOT1(slot_nb_inplace_add, "__iadd__", PyObject *) +SLOT1(slot_nb_inplace_subtract, "__isub__", PyObject *) +SLOT1(slot_nb_inplace_multiply, "__imul__", PyObject *) +SLOT1(slot_nb_inplace_matrix_multiply, "__imatmul__", PyObject *) +SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *) /* Can't use SLOT1 here, because nb_inplace_power is ternary */ static PyObject * slot_nb_inplace_power(PyObject *self, PyObject * arg1, PyObject *arg2) { _Py_IDENTIFIER(__ipow__); - return call_method(self, &PyId___ipow__, "(" "O" ")", arg1); + return call_method(self, &PyId___ipow__, arg1, NULL); } -SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *, "O") -SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *, "O") -SLOT1(slot_nb_inplace_and, "__iand__", PyObject *, "O") -SLOT1(slot_nb_inplace_xor, "__ixor__", PyObject *, "O") -SLOT1(slot_nb_inplace_or, "__ior__", PyObject *, "O") +SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *) +SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *) +SLOT1(slot_nb_inplace_and, "__iand__", PyObject *) +SLOT1(slot_nb_inplace_xor, "__ixor__", PyObject *) +SLOT1(slot_nb_inplace_or, "__ior__", PyObject *) SLOT1BIN(slot_nb_floor_divide, nb_floor_divide, "__floordiv__", "__rfloordiv__") SLOT1BIN(slot_nb_true_divide, nb_true_divide, "__truediv__", "__rtruediv__") -SLOT1(slot_nb_inplace_floor_divide, "__ifloordiv__", PyObject *, "O") -SLOT1(slot_nb_inplace_true_divide, "__itruediv__", PyObject *, "O") +SLOT1(slot_nb_inplace_floor_divide, "__ifloordiv__", PyObject *) +SLOT1(slot_nb_inplace_true_divide, "__itruediv__", PyObject *) static PyObject * slot_tp_repr(PyObject *self) @@ -6184,7 +6153,7 @@ slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * slot_tp_getattro(PyObject *self, PyObject *name) { - return call_method(self, &PyId___getattribute__, "(O)", name); + return call_method(self, &PyId___getattribute__, name, NULL); } static PyObject * @@ -6256,9 +6225,9 @@ slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value) _Py_IDENTIFIER(__setattr__); if (value == NULL) - res = call_method(self, &PyId___delattr__, "(O)", name); + res = call_method(self, &PyId___delattr__, name, NULL); else - res = call_method(self, &PyId___setattr__, "(OO)", name, value); + res = call_method(self, &PyId___setattr__, name, value, NULL); if (res == NULL) return -1; Py_DECREF(res); @@ -6359,9 +6328,9 @@ slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value) _Py_IDENTIFIER(__set__); if (value == NULL) - res = call_method(self, &PyId___delete__, "(O)", target); + res = call_method(self, &PyId___delete__, target, NULL); else - res = call_method(self, &PyId___set__, "(OO)", target, value); + res = call_method(self, &PyId___set__, target, value, NULL); if (res == NULL) return -1; Py_DECREF(res); -- 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/typeobject.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 391eed3156..37f0082587 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -902,7 +902,7 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) if (type == &PyType_Type && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && (kwds == NULL || - (PyDict_Check(kwds) && PyDict_Size(kwds) == 0))) + (PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) == 0))) return obj; /* If the returned object is not an instance of type, @@ -1585,7 +1585,7 @@ set_mro_error(PyObject *to_merge, int *remain) } } } - n = PyDict_Size(set); + n = PyDict_GET_SIZE(set); off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \ consistent method resolution\norder (MRO) for bases"); @@ -2187,7 +2187,7 @@ type_init(PyObject *cls, PyObject *args, PyObject *kwds) assert(kwds == NULL || PyDict_Check(kwds)); if (kwds != NULL && PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 && - PyDict_Check(kwds) && PyDict_Size(kwds) != 0) { + PyDict_Check(kwds) && PyDict_GET_SIZE(kwds) != 0) { PyErr_SetString(PyExc_TypeError, "type.__init__() takes no keyword arguments"); return -1; @@ -2272,7 +2272,7 @@ type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds) Note: We don't call PyType_CheckExact as that also allows subclasses */ if (metatype == &PyType_Type) { const Py_ssize_t nargs = PyTuple_GET_SIZE(args); - const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds); + const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_GET_SIZE(kwds); if (nargs == 1 && nkwds == 0) { PyObject *x = PyTuple_GET_ITEM(args, 0); @@ -3416,7 +3416,7 @@ static int excess_args(PyObject *args, PyObject *kwds) { return PyTuple_GET_SIZE(args) || - (kwds && PyDict_Check(kwds) && PyDict_Size(kwds)); + (kwds && PyDict_Check(kwds) && PyDict_GET_SIZE(kwds)); } static int @@ -3894,7 +3894,7 @@ _PyObject_GetState(PyObject *obj, int required) We also return None if the dict is empty to make the behavior consistent regardless whether the dict was initialized or not. This make unit testing easier. */ - if (dict != NULL && *dict != NULL && PyDict_Size(*dict) > 0) { + if (dict != NULL && *dict != NULL && PyDict_GET_SIZE(*dict)) { state = *dict; } else { @@ -3983,7 +3983,7 @@ _PyObject_GetState(PyObject *obj, int required) /* If we found some slot attributes, pack them in a tuple along the original attribute dictionary. */ - if (PyDict_Size(slots) > 0) { + if (PyDict_GET_SIZE(slots) > 0) { PyObject *state2; state2 = PyTuple_Pack(2, state, slots); @@ -4175,7 +4175,7 @@ reduce_newobj(PyObject *obj) return NULL; } hasargs = (args != NULL); - if (kwargs == NULL || PyDict_Size(kwargs) == 0) { + if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) { _Py_IDENTIFIER(__newobj__); PyObject *cls; Py_ssize_t i, n; -- 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/typeobject.c | 100 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 39 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 37f0082587..05fc7b88d3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -1425,9 +1425,9 @@ _PyObject_LookupSpecial(PyObject *self, _Py_Identifier *attrid) as lookup_method to cache the interned name string object. */ static PyObject * -call_method(PyObject *obj, _Py_Identifier *name, ...) +call_method(PyObject *obj, _Py_Identifier *name, + PyObject **args, Py_ssize_t nargs) { - va_list va; PyObject *func, *retval; func = lookup_maybe(obj, name); @@ -1437,10 +1437,7 @@ call_method(PyObject *obj, _Py_Identifier *name, ...) return NULL; } - va_start(va, name); - retval = _PyObject_VaCallFunctionObjArgs(func, va); - va_end(va); - + retval = _PyObject_FastCall(func, args, nargs); Py_DECREF(func); return retval; @@ -1449,9 +1446,9 @@ call_method(PyObject *obj, _Py_Identifier *name, ...) /* Clone of call_method() that returns NotImplemented when the lookup fails. */ static PyObject * -call_maybe(PyObject *obj, _Py_Identifier *name, ...) +call_maybe(PyObject *obj, _Py_Identifier *name, + PyObject **args, Py_ssize_t nargs) { - va_list va; PyObject *func, *retval; func = lookup_maybe(obj, name); @@ -1461,10 +1458,7 @@ call_maybe(PyObject *obj, _Py_Identifier *name, ...) return NULL; } - va_start(va, name); - retval = _PyObject_VaCallFunctionObjArgs(func, va); - va_end(va); - + retval = _PyObject_FastCall(func, args, nargs); Py_DECREF(func); return retval; @@ -5701,15 +5695,16 @@ static PyObject * \ FUNCNAME(PyObject *self) \ { \ _Py_static_string(id, OPSTR); \ - return call_method(self, &id, NULL); \ + return call_method(self, &id, NULL, 0); \ } #define SLOT1(FUNCNAME, OPSTR, ARG1TYPE) \ static PyObject * \ FUNCNAME(PyObject *self, ARG1TYPE arg1) \ { \ + PyObject* stack[1] = {arg1}; \ _Py_static_string(id, OPSTR); \ - return call_method(self, &id, arg1, NULL); \ + return call_method(self, &id, stack, 1); \ } /* Boolean helper for SLOT1BINFULL(). @@ -5751,6 +5746,7 @@ method_is_overloaded(PyObject *left, PyObject *right, struct _Py_Identifier *nam static PyObject * \ FUNCNAME(PyObject *self, PyObject *other) \ { \ + PyObject* stack[1]; \ _Py_static_string(op_id, OPSTR); \ _Py_static_string(rop_id, ROPSTR); \ int do_other = Py_TYPE(self) != Py_TYPE(other) && \ @@ -5762,20 +5758,23 @@ FUNCNAME(PyObject *self, PyObject *other) \ if (do_other && \ PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self)) && \ method_is_overloaded(self, other, &rop_id)) { \ - r = call_maybe(other, &rop_id, self, NULL); \ + stack[0] = self; \ + r = call_maybe(other, &rop_id, stack, 1); \ if (r != Py_NotImplemented) \ return r; \ Py_DECREF(r); \ do_other = 0; \ } \ - r = call_maybe(self, &op_id, other, NULL); \ + stack[0] = other; \ + r = call_maybe(self, &op_id, stack, 1); \ if (r != Py_NotImplemented || \ Py_TYPE(other) == Py_TYPE(self)) \ return r; \ Py_DECREF(r); \ } \ if (do_other) { \ - return call_maybe(other, &rop_id, self, NULL); \ + stack[0] = self; \ + return call_maybe(other, &rop_id, stack, 1); \ } \ Py_RETURN_NOTIMPLEMENTED; \ } @@ -5786,7 +5785,7 @@ FUNCNAME(PyObject *self, PyObject *other) \ static Py_ssize_t slot_sq_length(PyObject *self) { - PyObject *res = call_method(self, &PyId___len__, NULL); + PyObject *res = call_method(self, &PyId___len__, NULL, 0); Py_ssize_t len; if (res == NULL) @@ -5846,6 +5845,7 @@ error: static int slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) { + PyObject *stack[2]; PyObject *res; PyObject *index_obj; @@ -5854,10 +5854,14 @@ slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value) return -1; } - if (value == NULL) - res = call_method(self, &PyId___delitem__, index_obj, NULL); - else - res = call_method(self, &PyId___setitem__, index_obj, value, NULL); + stack[0] = index_obj; + if (value == NULL) { + res = call_method(self, &PyId___delitem__, stack, 1); + } + else { + stack[1] = value; + res = call_method(self, &PyId___setitem__, stack, 2); + } Py_DECREF(index_obj); if (res == NULL) { @@ -5905,12 +5909,17 @@ SLOT1(slot_mp_subscript, "__getitem__", PyObject *) static int slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { + PyObject *stack[2]; PyObject *res; - if (value == NULL) - res = call_method(self, &PyId___delitem__, key, NULL); - else - res = call_method(self, &PyId___setitem__, key, value, NULL); + stack[0] = key; + if (value == NULL) { + res = call_method(self, &PyId___delitem__, stack, 1); + } + else { + stack[1] = value; + res = call_method(self, &PyId___setitem__, stack, 2); + } if (res == NULL) return -1; @@ -5942,7 +5951,8 @@ slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus) slot_nb_power, so check before calling self.__pow__. */ if (Py_TYPE(self)->tp_as_number != NULL && Py_TYPE(self)->tp_as_number->nb_power == slot_nb_power) { - return call_method(self, &PyId___pow__, other, modulus, NULL); + PyObject* stack[2] = {other, modulus}; + return call_method(self, &PyId___pow__, stack, 2); } Py_RETURN_NOTIMPLEMENTED; } @@ -6009,7 +6019,7 @@ static PyObject * slot_nb_index(PyObject *self) { _Py_IDENTIFIER(__index__); - return call_method(self, &PyId___index__, NULL); + return call_method(self, &PyId___index__, NULL, 0); } @@ -6031,8 +6041,9 @@ SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *) static PyObject * slot_nb_inplace_power(PyObject *self, PyObject * arg1, PyObject *arg2) { + PyObject *stack[1] = {arg1}; _Py_IDENTIFIER(__ipow__); - return call_method(self, &PyId___ipow__, arg1, NULL); + return call_method(self, &PyId___ipow__, stack, 1); } SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *) SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *) @@ -6153,7 +6164,8 @@ slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * slot_tp_getattro(PyObject *self, PyObject *name) { - return call_method(self, &PyId___getattribute__, name, NULL); + PyObject *stack[1] = {name}; + return call_method(self, &PyId___getattribute__, stack, 1); } static PyObject * @@ -6220,14 +6232,19 @@ slot_tp_getattr_hook(PyObject *self, PyObject *name) static int slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value) { + PyObject *stack[2]; PyObject *res; _Py_IDENTIFIER(__delattr__); _Py_IDENTIFIER(__setattr__); - if (value == NULL) - res = call_method(self, &PyId___delattr__, name, NULL); - else - res = call_method(self, &PyId___setattr__, name, value, NULL); + stack[0] = name; + if (value == NULL) { + res = call_method(self, &PyId___delattr__, stack, 1); + } + else { + stack[1] = value; + res = call_method(self, &PyId___setattr__, stack, 2); + } if (res == NULL) return -1; Py_DECREF(res); @@ -6295,7 +6312,7 @@ static PyObject * slot_tp_iternext(PyObject *self) { _Py_IDENTIFIER(__next__); - return call_method(self, &PyId___next__, NULL); + return call_method(self, &PyId___next__, NULL, 0); } static PyObject * @@ -6323,14 +6340,19 @@ slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type) static int slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value) { + PyObject* stack[2]; PyObject *res; _Py_IDENTIFIER(__delete__); _Py_IDENTIFIER(__set__); - if (value == NULL) - res = call_method(self, &PyId___delete__, target, NULL); - else - res = call_method(self, &PyId___set__, target, value, NULL); + stack[0] = target; + if (value == NULL) { + res = call_method(self, &PyId___delete__, stack, 1); + } + else { + stack[1] = value; + res = call_method(self, &PyId___set__, stack, 2); + } if (res == NULL) return -1; Py_DECREF(res); -- cgit v1.2.1 From 55d565ff6a595485dcb3065529ada04c84e5505e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 16 Jan 2017 23:52:00 +0100 Subject: type_prepare() now uses fast call (METH_FASTCALL) --- Objects/typeobject.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 05fc7b88d3..a521177210 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3112,7 +3112,8 @@ type_subclasses(PyTypeObject *type, PyObject *args_ignored) } static PyObject * -type_prepare(PyObject *self, PyObject *args, PyObject *kwds) +type_prepare(PyObject *self, PyObject **args, Py_ssize_t nargs, + PyObject *kwnames) { return PyDict_New(); } @@ -3216,7 +3217,7 @@ static PyMethodDef type_methods[] = { {"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS, PyDoc_STR("__subclasses__() -> list of immediate subclasses")}, {"__prepare__", (PyCFunction)type_prepare, - METH_VARARGS | METH_KEYWORDS | METH_CLASS, + METH_FASTCALL | METH_CLASS, PyDoc_STR("__prepare__() -> dict\n" "used to create the namespace for the class statement")}, {"__instancecheck__", type___instancecheck__, METH_O, -- 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/typeobject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index a521177210..0fdff318b8 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -887,7 +887,7 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds) #ifdef Py_DEBUG /* type_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()); #endif -- 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/typeobject.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 0fdff318b8..bf6d3f12c3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -140,8 +140,7 @@ _PyType_GetDocFromInternalDoc(const char *name, const char *internal_doc) const char *doc = _PyType_DocWithoutSignature(name, internal_doc); if (!doc || *doc == '\0') { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyUnicode_FromString(doc); @@ -158,8 +157,7 @@ _PyType_GetTextSignatureFromInternalDoc(const char *name, const char *internal_d else end = NULL; if (!end) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* back "end" up until it points just past the final ')' */ @@ -761,8 +759,7 @@ static PyObject * type_dict(PyTypeObject *type, void *context) { if (type->tp_dict == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyDictProxy_New(type->tp_dict); } @@ -5330,8 +5327,7 @@ wrap_sq_setitem(PyObject *self, PyObject *args, void *wrapped) res = (*func)(self, i, value); if (res == -1 && PyErr_Occurred()) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -5351,8 +5347,7 @@ wrap_sq_delitem(PyObject *self, PyObject *args, void *wrapped) res = (*func)(self, i, NULL); if (res == -1 && PyErr_Occurred()) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* XXX objobjproc is a misnomer; should be objargpred */ @@ -5385,8 +5380,7 @@ wrap_objobjargproc(PyObject *self, PyObject *args, void *wrapped) res = (*func)(self, key, value); if (res == -1 && PyErr_Occurred()) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -5402,8 +5396,7 @@ wrap_delitem(PyObject *self, PyObject *args, void *wrapped) res = (*func)(self, key, NULL); if (res == -1 && PyErr_Occurred()) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* Helper to check for object.__setattr__ or __delattr__ applied to a type. @@ -5440,8 +5433,7 @@ wrap_setattr(PyObject *self, PyObject *args, void *wrapped) res = (*func)(self, name, value); if (res < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -5459,8 +5451,7 @@ wrap_delattr(PyObject *self, PyObject *args, void *wrapped) res = (*func)(self, name, NULL); if (res < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -5571,8 +5562,7 @@ wrap_descr_set(PyObject *self, PyObject *args, void *wrapped) ret = (*func)(self, obj, value); if (ret < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -5588,8 +5578,7 @@ wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped) ret = (*func)(self, obj, NULL); if (ret < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -5599,8 +5588,7 @@ wrap_init(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds) if (func(self, args, kwds) < 0) return NULL; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * -- cgit v1.2.1 From 47aa45aa2e4dba5e37f848ca3144a0c298e64e00 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 25 Jan 2017 23:33:27 +0100 Subject: Issue #29358: Add postcondition checks on types --- Objects/typeobject.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index bf6d3f12c3..8d22051486 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -121,6 +121,22 @@ skip_signature(const char *doc) return NULL; } +#ifdef Py_DEBUG +static int +_PyType_CheckConsistency(PyTypeObject *type) +{ + if (!(type->tp_flags & Py_TPFLAGS_READY)) { + /* don't check types before PyType_Ready() */ + return 1; + } + + assert(!(type->tp_flags & Py_TPFLAGS_READYING)); + assert(type->tp_mro != NULL && PyTuple_Check(type->tp_mro)); + assert(type->tp_dict != NULL); + return 1; +} +#endif + static const char * _PyType_DocWithoutSignature(const char *name, const char *internal_doc) { @@ -719,6 +735,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) Py_DECREF(old_bases); Py_DECREF(old_base); + assert(_PyType_CheckConsistency(type)); return res; undo: @@ -752,6 +769,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context) Py_DECREF(old_base); } + assert(_PyType_CheckConsistency(type)); return -1; } @@ -3034,6 +3052,7 @@ type_getattro(PyTypeObject *type, PyObject *name) static int type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) { + int res; if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) { PyErr_Format( PyExc_TypeError, @@ -3043,7 +3062,9 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value) } if (_PyObject_GenericSetAttrWithDict((PyObject *)type, name, value, NULL) < 0) return -1; - return update_slot(type, name); + res = update_slot(type, name); + assert(_PyType_CheckConsistency(type)); + return res; } extern void @@ -4851,7 +4872,7 @@ PyType_Ready(PyTypeObject *type) Py_ssize_t i, n; if (type->tp_flags & Py_TPFLAGS_READY) { - assert(type->tp_dict != NULL); + assert(_PyType_CheckConsistency(type)); return 0; } assert((type->tp_flags & Py_TPFLAGS_READYING) == 0); @@ -5045,9 +5066,9 @@ PyType_Ready(PyTypeObject *type) } /* All done -- set the ready flag */ - assert(type->tp_dict != NULL); type->tp_flags = (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY; + assert(_PyType_CheckConsistency(type)); return 0; error: -- cgit v1.2.1 From db58e46a50818a49b606b66d404f4c272e84ba2e Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Sat, 28 Jan 2017 16:35:44 +0900 Subject: Issue #29383: reduce temporary interned unicode add_methods(), add_members(), and add_getset() used PyDict_SetItemString() to register descriptor to the type's dict. So descr_new() and PyDict_SetItemString() creates interned unicode from same C string. This patch takes interned unicode from descriptor, and use PyDict_SetItem() instead of PyDict_SetItemString(). python_startup_no_site: default: Median +- std dev: 12.7 ms +- 0.1 ms patched: Median +- std dev: 12.5 ms +- 0.1 ms --- Objects/typeobject.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'Objects/typeobject.c') diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 8d22051486..0193192102 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4539,6 +4539,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) for (; meth->ml_name != NULL; meth++) { PyObject *descr; int err; + int isdescr = 1; if (PyDict_GetItemString(dict, meth->ml_name) && !(meth->ml_flags & METH_COEXIST)) continue; @@ -4555,6 +4556,7 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) if (cfunc == NULL) return -1; descr = PyStaticMethod_New(cfunc); + isdescr = 0; // PyStaticMethod is not PyDescrObject Py_DECREF(cfunc); } else { @@ -4562,7 +4564,12 @@ add_methods(PyTypeObject *type, PyMethodDef *meth) } if (descr == NULL) return -1; - err = PyDict_SetItemString(dict, meth->ml_name, descr); + if (isdescr) { + err = PyDict_SetItem(dict, PyDescr_NAME(descr), descr); + } + else { + err = PyDict_SetItemString(dict, meth->ml_name, descr); + } Py_DECREF(descr); if (err < 0) return -1; @@ -4582,7 +4589,7 @@ add_members(PyTypeObject *type, PyMemberDef *memb) descr = PyDescr_NewMember(type, memb); if (descr == NULL) return -1; - if (PyDict_SetItemString(dict, memb->name, descr) < 0) { + if (PyDict_SetItem(dict, PyDescr_NAME(descr), descr) < 0) { Py_DECREF(descr); return -1; } @@ -4604,7 +4611,7 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp) if (descr == NULL) return -1; - if (PyDict_SetItemString(dict, gsp->name, descr) < 0) { + if (PyDict_SetItem(dict, PyDescr_NAME(descr), descr) < 0) { Py_DECREF(descr); return -1; } -- cgit v1.2.1