diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-04-24 13:51:11 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-04-25 13:02:03 +0200 |
commit | ae23c335e0988111e58feef75df1d50b697359aa (patch) | |
tree | f137cedc2a1b85cf7c030fbee7ea8091e1015464 | |
parent | ce2959ec5135965ef67476274a8b4a57c897f4cf (diff) |
Revert "Lazy Load: Fix polymorphic classes by identifying lazy groups"
This reverts commit 9f09e1dda0f167432110a22db6f9a5accf800734.
Let's try to make the dependency graph lazy.
Revert the change, excluding the test bits.
Task-number: PYSIDE-2404
Task-number: PYSIDE-2675
Pick-to: 6.7
Change-Id: I0d28678f09834a09255dce28862e0970d68ac9fa
Reviewed-by: Adrian Herrmann <adrian.herrmann@qt.io>
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.cpp | 66 | ||||
-rw-r--r-- | sources/shiboken6/generator/shiboken/cppgenerator.h | 3 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkmodule.cpp | 181 | ||||
-rw-r--r-- | sources/shiboken6/libshiboken/sbkmodule.h | 5 |
4 files changed, 21 insertions, 234 deletions
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp index 037209dfb..ad4071c35 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp +++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp @@ -5769,18 +5769,6 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(TextStream &s, const Generato } } -// Note: This is an incomplete function that does not work without a -// surrounding functionality. It's purpose is to make sure that exactly -// this expression always is used, although the first clause is never true in PySide. -// Without it can create false positives. -static AbstractMetaClassCPtr getPolymorphicBaseClass(const AbstractMetaClassCPtr &metaClass) -{ - auto baseClass = metaClass; - while (!baseClass->typeEntry()->isPolymorphicBase() && baseClass->baseClass()) - baseClass = baseClass->baseClass(); - return baseClass; -} - void CppGenerator::replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr &metaClass, QString *id) { @@ -5790,7 +5778,9 @@ void CppGenerator::replacePolymorphicIdPlaceHolders(const AbstractMetaClassCPtr id->replace("%1"_L1, replacement); } if (id->contains("%B"_L1)) { - auto baseClass = getPolymorphicBaseClass(metaClass); + auto baseClass = metaClass; + while (!baseClass->typeEntry()->isPolymorphicBase() && baseClass->baseClass()) + baseClass = baseClass->baseClass(); QString replacement = " reinterpret_cast< "_L1 + m_gsp + baseClass->qualifiedCppName() + " *>(cptr)"_L1; id->replace("%B"_L1, replacement); @@ -6019,15 +6009,19 @@ void CppGenerator::writeNbBoolFunction(const GeneratorContext &context, void CppGenerator::writeInitFunc(TextStream &declStr, TextStream &callStr, const QString &initFunctionName, const TypeEntryCPtr &enclosingEntry, - const QString &pythonName, - const QString &lazyGroup) + const QString &pythonName, bool lazy) { - const QString functionName = "init_"_L1 + initFunctionName; const bool hasParent = enclosingEntry && enclosingEntry->type() != TypeEntry::TypeSystemType; declStr << "PyTypeObject *" << functionName << "(PyObject *" << (hasParent ? "enclosingClass" : "module") << ");\n"; - if (hasParent) { + + if (!lazy) { + const QString enclosing = hasParent + ? "reinterpret_cast<PyObject *>("_L1 + cpythonTypeNameExt(enclosingEntry) + u')' + : "module"_L1; + callStr << functionName << '(' << enclosing << ");\n"; + } else if (hasParent) { const QString &enclosingName = enclosingEntry->name(); const auto parts = QStringView{enclosingName}.split(u"::", Qt::SkipEmptyParts); callStr << "Shiboken::Module::AddTypeCreationFunction(" @@ -6039,13 +6033,9 @@ void CppGenerator::writeInitFunc(TextStream &declStr, TextStream &callStr, } callStr << "\");\n"; } else { - const char *funcName = lazyGroup.isEmpty() - ? "AddTypeCreationFunction" : "AddGroupedTypeCreationFunction"; - callStr << "Shiboken::Module::" << funcName << "(module, \"" - << pythonName << "\", " << functionName; - if (!lazyGroup.isEmpty()) - callStr << ", \"" << lazyGroup << "\""; - callStr << ");\n"; + callStr << "Shiboken::Module::AddTypeCreationFunction(" + << "module, \"" << pythonName << "\", " + << "init_" << initFunctionName << ");\n"; } } @@ -6062,12 +6052,6 @@ static void writeSubModuleHandling(TextStream &s, const QString &moduleName, << indent << "return nullptr;\n" << outdent << outdent << "}\n"; } -static AbstractMetaClassCPtr getLazyGroupBaseClass(const AbstractMetaClassCPtr &metaClass) -{ - return needsTypeDiscoveryFunction(metaClass) && !isQObject(metaClass) - ? getPolymorphicBaseClass(metaClass) : nullptr; -} - bool CppGenerator::finishGeneration() { //Generate CPython wrapper file @@ -6099,18 +6083,6 @@ bool CppGenerator::finishGeneration() s_globalFunctionDef << methodDefinitionEntries(overloadData); } - // Collect the lazy group base classes first, because we need to add - // these base classes into the group, too. - std::set<AbstractMetaClassCPtr> lazyGroupBaseClasses{}; - for (const auto &cls : api().classes()){ - auto te = cls->typeEntry(); - if (shouldGenerate(te)) { - auto lazyGroupCls = getLazyGroupBaseClass(cls); - if (lazyGroupCls) - lazyGroupBaseClasses.insert(lazyGroupCls); - } - } - AbstractMetaClassCList classesWithStaticFields; for (const auto &cls : api().classes()){ auto te = cls->typeEntry(); @@ -6120,17 +6092,9 @@ bool CppGenerator::finishGeneration() s_classInitDecl << te->configCondition() << '\n'; s_classPythonDefines << te->configCondition() << '\n'; } - auto lazyGroupCls = getLazyGroupBaseClass(cls); - if (!lazyGroupCls) { - auto it = lazyGroupBaseClasses.find(cls); - if (it != lazyGroupBaseClasses.end()) - lazyGroupCls = cls; - } writeInitFunc(s_classInitDecl, s_classPythonDefines, getSimpleClassInitFunctionName(cls), - targetLangEnclosingEntry(te), cls->name(), - lazyGroupCls ? lazyGroupCls->typeEntry()->qualifiedTargetLangName() - : QString()); + targetLangEnclosingEntry(te), cls->name()); if (cls->hasStaticFields()) { s_classInitDecl << "PyTypeObject *" << getSimpleClassStaticFieldsInitFunctionName(cls) << "(PyObject *module);\n"; diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.h b/sources/shiboken6/generator/shiboken/cppgenerator.h index 6c20d9d78..1ad576895 100644 --- a/sources/shiboken6/generator/shiboken/cppgenerator.h +++ b/sources/shiboken6/generator/shiboken/cppgenerator.h @@ -63,8 +63,7 @@ private: static void writeInitFunc(TextStream &declStr, TextStream &callStr, const QString &initFunctionName, const TypeEntryCPtr &enclosingEntry, - const QString &pythonName, - const QString &lazyGroup = {}); + const QString &pythonName, bool lazy = true); static void writeCacheResetNative(TextStream &s, const GeneratorContext &classContext); void writeConstructorNative(TextStream &s, const GeneratorContext &classContext, const AbstractMetaFunctionCPtr &func) const; diff --git a/sources/shiboken6/libshiboken/sbkmodule.cpp b/sources/shiboken6/libshiboken/sbkmodule.cpp index 428ebc5f0..4153df27f 100644 --- a/sources/shiboken6/libshiboken/sbkmodule.cpp +++ b/sources/shiboken6/libshiboken/sbkmodule.cpp @@ -31,82 +31,6 @@ static ModuleTypesMap moduleTypes; static ModuleConvertersMap moduleConverters; static ModuleToFuncsMap moduleToFuncs; -/***************************************************************************** - - How Do Lazy Groups Work? - ------------------------ - -When polymorphic classes are in use, then we have to deal with classes -which might not yet be visible. They are located by type discovery functions. - -In order to allow these functions to do their work, the needed classes -must be existent in time. That is what lazy groups are doing: - - They provide the minimum set of sufficient classes that might be - needed by the type discovery functions. - -Lazy groups are determined by the cppgenerator when polymorphic functions -are analyzed. They are communicated to sbkmodule by a LazyGroup parameter. - - -The Idea --------- - -When the creating functions of a module are collected for lazy evaluation, -we build a data structure that keeps the lazy groups together. In this -phase, there is no other special action. - -As soon as a single element of a group gets used by getattr, the whole action -takes place: - -- All elements in the same group are touched by getattr as well, meaning -- The whole group becomes existent at once. - -After that action, a group is not evaluated again because it is switched -to immediate mode. - - -Importing Another Module ------------------------- - -If a group has not been touched and a new module with new group members -is added, the elements are simply accumulated in the group as before. - -If a group has already been touched, then it is in immediate mode, and all -new elements must be created as well. - - -The Implementation ------------------- - -There is a structure LazyPool which contains - - - classToGroup members->group n:1 - - - groupState groups->state 1:1 - -The classToGroup is the central structure that controls group membership. -The groupState enum makes sure that the group members are initialized -together at once and only once. - -*****************************************************************************/ - -/// Lazy Groups -/// -/// Accumulated in lists, but completely incarnated if a member is accessed. -struct LazyGroupStructure { - enum State { - NoGroup, // No group at all - FirstSeen, // Seen first by getattr - Handled // Normal processing like no group - }; - - std::unordered_map<std::string, std::string> classToGroup; - std::unordered_map<std::string, State> groupState; -}; - -static LazyGroupStructure LazyPool; - namespace Shiboken { namespace Module @@ -175,8 +99,7 @@ static PyTypeObject *incarnateType(PyObject *module, const char *name, Py_INCREF(res); PyModule_AddObject(module, name, res); // steals reference // - remove the entry, if not by something cleared. - funcIter = nameToFunc.find(name); - if (funcIter != nameToFunc.end()) + if (!nameToFunc.empty()) nameToFunc.erase(funcIter); // - return the PyTypeObject. return type; @@ -221,34 +144,10 @@ void resolveLazyClasses(PyObject *module) // PYSIDE-2404: Override the gettattr function of modules. static getattrofunc origModuleGetattro{}; -static LazyGroupStructure::State getGroupStateAndLock(const std::string &groupName) -{ - if (groupName.empty()) - return LazyGroupStructure::NoGroup; - - auto stateIt = LazyPool.groupState.find(groupName); - if (stateIt == LazyPool.groupState.end()) { - LazyPool.groupState.insert(std::make_pair(groupName, LazyGroupStructure::FirstSeen)); - return LazyGroupStructure::FirstSeen; - } - - auto result = stateIt->second; - if (stateIt->second == LazyGroupStructure::FirstSeen) - stateIt->second = LazyGroupStructure::Handled; - return result; -} - -static std::string getGroupName(const std::string &key) -{ - auto git = LazyPool.classToGroup.find(key); - return git != LazyPool.classToGroup.end() ? git->second : std::string{}; -} - // PYSIDE-2404: Use the patched module getattr to do on-demand initialization. // This modifies _all_ modules but should have no impact. static PyObject *PyModule_lazyGetAttro(PyObject *module, PyObject *name) { - static auto *sysModules = PyImport_GetModuleDict(); // - check if the attribute is present and return it. auto *attr = PyObject_GenericGetAttr(module, name); // - we handle AttributeError, only. @@ -262,19 +161,9 @@ static PyObject *PyModule_lazyGetAttro(PyObject *module, PyObject *name) if (tableIter == moduleToFuncs.end()) return origModuleGetattro(module, name); + // - locate the name and retrieve the generating function const char *attrNameStr = Shiboken::String::toCString(name); - auto key = std::string(PyModule_GetName(module)) + '.' + attrNameStr; - - // - see if we have a group. Initializes the process if seen first. - const auto &groupName = getGroupName(key); - auto state = getGroupStateAndLock(groupName); - - // - retrieve the generating function auto &nameToFunc = tableIter->second; - - // - make sure that the state gets past possible action - getGroupStateAndLock(groupName); - // - create the real type (incarnateType checks this) auto *type = incarnateType(module, attrNameStr, nameToFunc); auto *ret = reinterpret_cast<PyObject *>(type); @@ -284,31 +173,6 @@ static PyObject *PyModule_lazyGetAttro(PyObject *module, PyObject *name) return origModuleGetattro(module, name); } - if (state != LazyPool.FirstSeen) - return ret; - - // The state is now FirstSeen. So we are the one instance who handles it - // and no one else again. - // This was crucial to avoid duplication in recursive calls. - - // - incarnate the whole group - for (auto it = LazyPool.classToGroup.cbegin(), end = LazyPool.classToGroup.cend(); - it != end; ++it) { - if (it->second == groupName) { - // - obtain the module name - std::string_view names(it->first); - const bool usePySide = names.compare(0, 8, "PySide6.") == 0; - auto dotPos = usePySide ? names.find('.', 8) : names.find('.'); - auto startPos = dotPos + 1; - AutoDecRef modName(String::fromCppStringView(names.substr(0, dotPos))); - module = PyDict_GetItem(sysModules, modName); - assert(module != nullptr); - // - isolate the type name - auto typeName = names.substr(startPos); - // - create the type - PyModule_lazyGetAttro(module, String::fromCString(typeName.data())); - } - } return ret; } @@ -428,24 +292,9 @@ static bool shouldLazyLoad(PyObject *module) return std::strncmp(modName, "PySide6.", 8) == 0; } -static bool groupMaterialized(const char *group) -{ - auto iter = LazyPool.groupState.find(group); - return iter != LazyPool.groupState.end(); -} - -static void addToGroup(PyObject *module, const char *shortName, const char *group) -{ - auto name = std::string(PyModule_GetName(module)) + '.' + shortName; - - // - insert into the group members - LazyPool.classToGroup.insert(std::make_pair(name, group)); -} - -static void addTypeCreationFunction(PyObject *module, - const char *name, - TypeCreationFunction func, - const char *lazyGroup = nullptr) +void AddTypeCreationFunction(PyObject *module, + const char *name, + TypeCreationFunction func) { static const char *flag = getenv("PYSIDE6_OPTION_LAZY"); static const int value = flag != nullptr ? std::atoi(flag) : 1; @@ -462,10 +311,6 @@ static void addTypeCreationFunction(PyObject *module, else nit->second = pair; - const bool hasLazyGroup = lazyGroup != nullptr; - if (hasLazyGroup) - addToGroup(module, name, lazyGroup); - // PYSIDE-2404: Lazy Loading // // Options: @@ -478,7 +323,6 @@ static void addTypeCreationFunction(PyObject *module, if (value == 0 // completely disabled || canNotLazyLoad(module) // for some reason we cannot lazy load || (value == 1 && !shouldLazyLoad(module)) // not a known module - || (hasLazyGroup && groupMaterialized(lazyGroup)) ) { PyTypeObject *type = func(module); PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(type)); // steals reference @@ -487,21 +331,6 @@ static void addTypeCreationFunction(PyObject *module, void AddTypeCreationFunction(PyObject *module, const char *name, - TypeCreationFunction func) -{ - addTypeCreationFunction(module, name, func); -} - -void AddGroupedTypeCreationFunction(PyObject *module, - const char *name, - TypeCreationFunction func, - const char *lazyGroup) -{ - addTypeCreationFunction(module, name, func, lazyGroup); -} - -void AddTypeCreationFunction(PyObject *module, - const char *name, TypeCreationFunction func, const char *containerName) { diff --git a/sources/shiboken6/libshiboken/sbkmodule.h b/sources/shiboken6/libshiboken/sbkmodule.h index 7acce68dd..1b3de33b7 100644 --- a/sources/shiboken6/libshiboken/sbkmodule.h +++ b/sources/shiboken6/libshiboken/sbkmodule.h @@ -51,11 +51,6 @@ LIBSHIBOKEN_API void AddTypeCreationFunction(PyObject *module, const char *name, TypeCreationFunction func); -LIBSHIBOKEN_API void AddGroupedTypeCreationFunction(PyObject *module, - const char *name, - TypeCreationFunction func, - const char *lazyGroup); - LIBSHIBOKEN_API void AddTypeCreationFunction(PyObject *module, const char *name, TypeCreationFunction func, |