From 96345e5684d825ac75bc2d63f0491f5d19f4d5c6 Mon Sep 17 00:00:00 2001 From: Christian Tismer Date: Sat, 1 Aug 2020 12:14:33 +0200 Subject: feature_select: Apply tiny name switching optimization and cleanup After the big optimization of selectable features, the cached select Id-s can also be used to simplify the case selection. Also, the MSVC glitch with signed bitfields is circumvented by unsigned bitfields. Further a merge error was reverted which killed signature: Clean up and improve readability 3d4d91334 Christian Tismer 10. Jul 2020 at 11:06 Change-Id: I783dc6d73b88016e70c58daeb207f1537fb38f72 Reviewed-by: Cristian Maureira-Fredes --- sources/shiboken2/libshiboken/basewrapper_p.h | 12 +++--- sources/shiboken2/libshiboken/bindingmanager.cpp | 10 +---- sources/shiboken2/libshiboken/signature.cpp | 49 ++++++++++++++++-------- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/sources/shiboken2/libshiboken/basewrapper_p.h b/sources/shiboken2/libshiboken/basewrapper_p.h index 685b4fbe5..482a3ea2a 100644 --- a/sources/shiboken2/libshiboken/basewrapper_p.h +++ b/sources/shiboken2/libshiboken/basewrapper_p.h @@ -130,16 +130,16 @@ struct SbkObjectTypePrivate TypeDiscoveryFuncV2 type_discovery; /// Pointer to a function responsible for deletion of the C++ instance calling the proper destructor. ObjectDestructor cpp_dtor; + /// PYSIDE-1019: Caching the current select Id + unsigned int pyside_reserved_bits : 8; // MSVC has bug with the sign bit! /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. - int is_multicpp : 1; + unsigned int is_multicpp : 1; /// True if this type was defined by the user. - int is_user_type : 1; + unsigned int is_user_type : 1; /// Tells is the type is a value type or an object-type, see BEHAVIOUR_ *constants. // TODO-CONVERTERS: to be deprecated/removed - int type_behaviour : 2; - int delete_in_main_thread : 1; - /// PYSIDE-1019: Caching the current select Id - int pyside_reserved_bits : 9; // MSVC needs the sign bit! Buglet? + unsigned int type_behaviour : 2; + unsigned int delete_in_main_thread : 1; /// C++ name char *original_name; /// Type user data diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp index b35a02ef4..4f8c6068a 100644 --- a/sources/shiboken2/libshiboken/bindingmanager.cpp +++ b/sources/shiboken2/libshiboken/bindingmanager.cpp @@ -274,16 +274,10 @@ SbkObject *BindingManager::retrieveWrapper(const void *cptr) return iter->second; } -static bool mangleNameFlag(PyTypeObject *type) +static inline bool mangleNameFlag(PyTypeObject *type) { // PYSIDE-1019: See if a dict is set with a snake_case bit. - static PyTypeObject *old_dict_type = Py_TYPE(PyType_Type.tp_dict); - auto dict = type->tp_dict; - if (Py_TYPE(dict) == old_dict_type) - return false; - Shiboken::AutoDecRef select_id(PyObject_GetAttr(dict, Shiboken::PyName::select_id())); - auto id = PyInt_AsSsize_t(select_id); - return (id & 1) != 0; + return (SbkObjectType_GetReserved(type) & 1) != 0; } PyObject *BindingManager::getOverride(const void *cptr, PyObject *methodNameCache[2], const char *methodName) diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index 4614a131e..e4dc27ea7 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -653,17 +653,22 @@ _fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp) } } } - // staticmethod has just a __doc__ in the class - assert(strcmp(type->tp_name, "staticmethod") == 0); + PyMemberDef *md = type->tp_members; + if (md != nullptr) + for (; md->name != nullptr; md++) + if (strcmp(md->name, name) == 0) + return 1; + // staticmethod has just a `__doc__` in the class + assert(strcmp(type->tp_name, "staticmethod") == 0 && strcmp(name, "__doc__") == 0); return 0; } static int -add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **old_descr) +add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **doc_descr) { /* - * This function is used to assign a new __signature__ attribute, - * and also to override a __doc__ attribute. + * This function is used to assign a new `__signature__` attribute, + * and also to override a `__doc__` or `__name__` attribute. */ assert(PyType_Check(type)); PyType_Ready(type); @@ -671,9 +676,11 @@ add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **old_descr) for (; gsp->name != nullptr; gsp++) { PyObject *have_descr = PyDict_GetItemString(dict, gsp->name); if (have_descr != nullptr) { - assert(strcmp(gsp->name, "__doc__") == 0); Py_INCREF(have_descr); - *old_descr = have_descr; + if (strcmp(gsp->name, "__doc__") == 0) + *doc_descr = have_descr; + else + assert(false); if (!_fixup_getset(type, gsp->name, gsp)) continue; } @@ -824,7 +831,7 @@ static PyGetSetDef new_PyWrapperDescr_getsets[] = { // // Additionally to the interface via __signature__, we also provide // a general function, which allows for different signature layouts. -// The "modifier" argument is a string that is passed in from loader.py . +// The "modifier" argument is a string that is passed in from 'loader.py'. // Configuration what the modifiers mean is completely in Python. // @@ -909,13 +916,25 @@ PySide_PatchTypes(void) reinterpret_cast(&PyString_Type), "split")); Shiboken::AutoDecRef wrap_descr(PyObject_GetAttrString( reinterpret_cast(Py_TYPE(Py_True)), "__add__")); + // abbreviations for readability + auto md_gs = new_PyMethodDescr_getsets; + auto md_doc = &old_md_doc_descr; + auto cf_gs = new_PyCFunction_getsets; + auto cf_doc = &old_cf_doc_descr; + auto sm_gs = new_PyStaticMethod_getsets; + auto sm_doc = &old_sm_doc_descr; + auto tp_gs = new_PyType_getsets; + auto tp_doc = &old_tp_doc_descr; + auto wd_gs = new_PyWrapperDescr_getsets; + auto wd_doc = &old_wd_doc_descr; + if (meth_descr.isNull() || wrap_descr.isNull() || PyType_Ready(Py_TYPE(meth_descr)) < 0 - || add_more_getsets(PepMethodDescr_TypePtr, new_PyMethodDescr_getsets, &old_md_doc_descr) < 0 - || add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets, &old_cf_doc_descr) < 0 - || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets, &old_sm_doc_descr) < 0 - || add_more_getsets(&PyType_Type, new_PyType_getsets, &old_tp_doc_descr) < 0 - || add_more_getsets(Py_TYPE(wrap_descr), new_PyWrapperDescr_getsets, &old_wd_doc_descr) < 0 + || add_more_getsets(PepMethodDescr_TypePtr, md_gs, md_doc) < 0 + || add_more_getsets(&PyCFunction_Type, cf_gs, cf_doc) < 0 + || add_more_getsets(PepStaticMethod_TypePtr, sm_gs, sm_doc) < 0 + || add_more_getsets(&PyType_Type, tp_gs, tp_doc) < 0 + || add_more_getsets(Py_TYPE(wrap_descr), wd_gs, wd_doc) < 0 ) return -1; #ifndef _WIN32 @@ -1214,8 +1233,8 @@ FinishSignatureInitialization(PyObject *module, const char *signatures[]) * Still, it is not possible to call init phase 2 from here, * because the import is still running. Do it from Python! */ - PySide_PatchTypes(); - if (PySide_FinishSignatures(module, signatures) < 0) { + if ( PySide_PatchTypes() < 0 + || PySide_FinishSignatures(module, signatures) < 0) { PyErr_Print(); PyErr_SetNone(PyExc_ImportError); } -- cgit v1.2.3