diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-10-25 23:00:25 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-10-26 14:24:12 +0000 |
commit | 97b3ce60039390a052e9f229e2f61a4c75c8e4bc (patch) | |
tree | f701712587b1da7502d338195ef137c7bea1ddc6 | |
parent | a643d923911e595cd60439e075a80a36dc85bc32 (diff) |
shiboken6: Refactor multiple inheritance offset calculation
- Avoid std::set allocation by using standard algorithms operating
on the int array instead.
- Fix one-time initialization for hierarchies where all offsets
are 0 by using -2 as magic constant.
- Reduce mutex lock operations by initializing all base addresses in
the wrapper map in one go.
- Reduce mutex lock operations by releasing the base addresses in the
wrapper map in one go.
Task-number: PYSIDE-2506
Change-Id: I7c19b4287a9fcb7a47894b0a06bbeb5698cff7d7
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 1a8923df9c9fbc5c55826fa43ab817ff3f28be0d)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.cpp | 26 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/bindingmanager.cpp | 61 |
2 files changed, 52 insertions, 35 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index a68dc62e4..e56982b6c 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -3991,20 +3991,24 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(TextStream &s, s << "int *\n" << multipleInheritanceInitializerFunctionName(metaClass) << "(const void *cptr)\n" << "{\n" << indent; - s << "static int mi_offsets[] = { "; + s << "static int mi_offsets[] = {-2"; for (qsizetype i = 0; i < ancestors.size(); i++) - s << "-1, "; - s << "-1 };\n" - << "if (mi_offsets[0] == -1) {\n" << indent - << "std::set<int> offsets;\n" - << "const auto *class_ptr = reinterpret_cast<const " << className << " *>(cptr);\n" - << "const auto base = reinterpret_cast<uintptr_t>(class_ptr);\n"; + s << ", 0"; + s << "};\n" + << "if (mi_offsets[0] == -2) {\n" << indent + << "const auto *class_ptr = reinterpret_cast<const " << className << " *>(cptr);\n" + << "const auto base = reinterpret_cast<uintptr_t>(class_ptr);\n" + << "int *p = mi_offsets;\n"; for (const QString &ancestor : ancestors) - s << "offsets.insert(int(" << ancestor << "));\n"; - - s << "\noffsets.erase(0);\n\n" - << "std::copy(offsets.cbegin(), offsets.cend(), mi_offsets);\n" << outdent + s << "*p++ = int(" << ancestor << ");\n"; + s << "std::sort(mi_offsets, p);\n" + << "auto *end = std::unique(mi_offsets, p);\n" + << "*end++ = -1;\n" + << "if (mi_offsets[0] == 0)\n" + << indent + << "std::memmove(&mi_offsets[0], &mi_offsets[1], (end - mi_offsets - 1) * sizeof(int));\n" + << outdent << outdent << "}\nreturn mi_offsets;\n" << outdent << "}\n"; } diff --git a/sources/shiboken6/libshiboken/bindingmanager.cpp b/sources/shiboken6/libshiboken/bindingmanager.cpp index cdb3c311b..a9b87f7f4 100644 --- a/sources/shiboken6/libshiboken/bindingmanager.cpp +++ b/sources/shiboken6/libshiboken/bindingmanager.cpp @@ -118,17 +118,19 @@ struct BindingManager::BindingManagerPrivate { bool destroying; BindingManagerPrivate() : destroying(false) {} - bool releaseWrapper(void *cptr, SbkObject *wrapper); - void assignWrapper(SbkObject *wrapper, const void *cptr); + bool releaseWrapper(void *cptr, SbkObject *wrapper, const int *bases = nullptr); + bool releaseWrapperHelper(void *cptr, SbkObject *wrapper); + + void assignWrapper(SbkObject *wrapper, const void *cptr, const int *bases = nullptr); + void assignWrapperHelper(SbkObject *wrapper, const void *cptr); }; -bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject *wrapper) +inline bool BindingManager::BindingManagerPrivate::releaseWrapperHelper(void *cptr, SbkObject *wrapper) { // The wrapper argument is checked to ensure that the correct wrapper is released. // Returns true if the correct wrapper is found and released. // If wrapper argument is NULL, no such check is performed. - std::lock_guard<std::recursive_mutex> guard(wrapperMapLock); auto iter = wrapperMapper.find(cptr); if (iter != wrapperMapper.end() && (wrapper == nullptr || iter->second == wrapper)) { wrapperMapper.erase(iter); @@ -137,15 +139,41 @@ bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject return false; } -void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject *wrapper, const void *cptr) +bool BindingManager::BindingManagerPrivate::releaseWrapper(void *cptr, SbkObject *wrapper, + const int *bases) { assert(cptr); std::lock_guard<std::recursive_mutex> guard(wrapperMapLock); + const bool result = releaseWrapperHelper(cptr, wrapper); + if (bases != nullptr) { + auto *base = static_cast<uint8_t *>(cptr); + for (const auto *offset = bases; *offset != -1; ++offset) + releaseWrapperHelper(base + *offset, wrapper); + } + return result; +} + +inline void BindingManager::BindingManagerPrivate::assignWrapperHelper(SbkObject *wrapper, + const void *cptr) +{ auto iter = wrapperMapper.find(cptr); if (iter == wrapperMapper.end()) wrapperMapper.insert(std::make_pair(cptr, wrapper)); } +void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject *wrapper, const void *cptr, + const int *bases) +{ + assert(cptr); + std::lock_guard<std::recursive_mutex> guard(wrapperMapLock); + assignWrapperHelper(wrapper, cptr); + if (bases != nullptr) { + const auto *base = static_cast<const uint8_t *>(cptr); + for (const auto *offset = bases; *offset != -1; ++offset) + assignWrapperHelper(wrapper, base + *offset); + } +} + BindingManager::BindingManager() { m_d = new BindingManager::BindingManagerPrivate; @@ -197,15 +225,7 @@ void BindingManager::registerWrapper(SbkObject *pyObj, void *cptr) if (d->mi_init && !d->mi_offsets) d->mi_offsets = d->mi_init(cptr); - m_d->assignWrapper(pyObj, cptr); - if (d->mi_offsets) { - int *offset = d->mi_offsets; - while (*offset != -1) { - if (*offset > 0) - m_d->assignWrapper(pyObj, reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(cptr) + *offset)); - offset++; - } - } + m_d->assignWrapper(pyObj, cptr, d->mi_offsets); } void BindingManager::releaseWrapper(SbkObject *sbkObj) @@ -215,17 +235,10 @@ void BindingManager::releaseWrapper(SbkObject *sbkObj) int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1); void ** cptrs = reinterpret_cast<SbkObject *>(sbkObj)->d->cptr; + const int *mi_offsets = d != nullptr ? d->mi_offsets : nullptr; for (int i = 0; i < numBases; ++i) { - auto *cptr = reinterpret_cast<unsigned char *>(cptrs[i]); - m_d->releaseWrapper(cptr, sbkObj); - if (d && d->mi_offsets) { - int *offset = d->mi_offsets; - while (*offset != -1) { - if (*offset > 0) - m_d->releaseWrapper(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(cptr) + *offset), sbkObj); - offset++; - } - } + if (cptrs[i] != nullptr) + m_d->releaseWrapper(cptrs[i], sbkObj, mi_offsets); } sbkObj->d->validCppObject = false; } |