aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-10-25 23:00:25 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-10-26 14:24:12 +0000
commit97b3ce60039390a052e9f229e2f61a4c75c8e4bc (patch)
treef701712587b1da7502d338195ef137c7bea1ddc6
parenta643d923911e595cd60439e075a80a36dc85bc32 (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.cpp26
-rw-r--r--sources/shiboken6/libshiboken/bindingmanager.cpp61
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;
}