aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2019-04-26 09:31:48 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2019-04-30 11:51:32 +0000
commite83e07dd9fba3a2c69afe07cbee70346a1ee6ec8 (patch)
tree7c8287ba6a5270d08538180a70f5b24511cbc0d6 /sources/shiboken2
parentf332f2e8e66a5fa67b302893a13f0be3687ccc38 (diff)
shiboken/Generators: Cache class information lists per class
The function ShibokenGenerator::getFunctionGroups(class) is called many times for each function during code generation and causes a slowdown for the OpenGL version function classes, which have 1000 member functions. Split away getGlobalFunctionGroups() for the case scope=0 and introduce a global-static cache for class information that is more involved to determine for use by the various generators. Speeds up the generation of the QtGui module including the OpenGL version functions from 420s to 90s. Task-number: PYSIDE-955 Change-Id: I6b6aa35ef2197aa9cddbf339db9eb0220932f361 Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'sources/shiboken2')
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp13
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp96
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h10
3 files changed, 89 insertions, 30 deletions
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index 29220c739..67f8f1a7b 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -453,8 +453,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
s << endl << "// Target ---------------------------------------------------------" << endl << endl;
s << "extern \"C\" {" << endl;
- const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass);
- for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
+ const auto &functionGroups = getFunctionGroups(metaClass);
+ for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
QSet<QString> seenSignatures;
bool staticEncountered = false;
@@ -5404,8 +5404,8 @@ bool CppGenerator::finishGeneration()
Indentation indent(INDENT);
- const FunctionGroupMap &functionGroups = getFunctionGroups();
- for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
+ const auto functionGroups = getGlobalFunctionGroups();
+ for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
for (AbstractMetaFunction *func : it.value()) {
if (!func->isModifiedRemoved()) {
@@ -5824,7 +5824,10 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta
const int numArgs = func->arguments().count();
bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy;
- bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this));
+ const auto &groups = func->implementingClass()
+ ? getFunctionGroups(func->implementingClass())
+ : getGlobalFunctionGroups();
+ bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(groups[func->name()], this));
ArgumentOwner argOwner = getArgumentOwner(func, argIndex);
ArgumentOwner::Action action = argOwner.action;
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
index 002ab8cfb..12efb68c3 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -118,6 +118,16 @@ static QString resolveScopePrefix(const AbstractMetaEnum *metaEnum,
return resolveScopePrefix(parts, value);
}
+struct GeneratorClassInfoCacheEntry
+{
+ ShibokenGenerator::FunctionGroups functionGroups;
+ bool needsGetattroFunction = false;
+};
+
+using GeneratorClassInfoCache = QHash<const AbstractMetaClass *, GeneratorClassInfoCacheEntry>;
+
+Q_GLOBAL_STATIC(GeneratorClassInfoCache, generatorClassInfoCache)
+
ShibokenGenerator::ShibokenGenerator()
{
if (m_pythonPrimitiveTypeName.isEmpty())
@@ -1739,7 +1749,10 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s,
argsRemoved++;
}
- OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this);
+ const auto &groups = func->implementingClass()
+ ? getFunctionGroups(func->implementingClass())
+ : getGlobalFunctionGroups();
+ OverloadData od(groups[func->name()], this);
bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od);
// Replace %PYARG_# variables.
@@ -2174,17 +2187,19 @@ bool ShibokenGenerator::hasMultipleInheritanceInAncestry(const AbstractMetaClass
return hasMultipleInheritanceInAncestry(metaClass->baseClass());
}
-typedef QMap<QString, AbstractMetaFunctionList> FunctionGroupMap;
-typedef FunctionGroupMap::const_iterator FunctionGroupMapIt;
-
bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* metaClass)
{
+ return getGeneratorClassInfo(metaClass).needsGetattroFunction;
+}
+
+bool ShibokenGenerator::classNeedsGetattroFunctionImpl(const AbstractMetaClass* metaClass)
+{
if (!metaClass)
return false;
if (metaClass->typeEntry()->isSmartPointer())
return true;
- const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass);
- for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) {
+ const auto &functionGroup = getFunctionGroups(metaClass);
+ for (auto it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
for (AbstractMetaFunction *func : qAsConst(it.value())) {
if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved()
@@ -2212,8 +2227,8 @@ AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStatic
{
AbstractMetaFunctionList methods;
if (metaClass) {
- const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass);
- for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
+ const auto &functionGroups = getFunctionGroups(metaClass);
+ for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
for (AbstractMetaFunction *func : qAsConst(it.value())) {
if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved()
@@ -2358,23 +2373,56 @@ static bool isGroupable(const AbstractMetaFunction* func)
return true;
}
-QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(const AbstractMetaClass* scope)
+ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const
{
- AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions();
+ const AbstractMetaFunctionList &lst = globalFunctions();
+ FunctionGroups results;
+ for (AbstractMetaFunction *func : lst) {
+ if (isGroupable(func))
+ results[func->name()].append(func);
+ }
+ return results;
+}
- QMap<QString, AbstractMetaFunctionList> results;
- for (AbstractMetaFunction *func : qAsConst(lst)) {
+const GeneratorClassInfoCacheEntry &ShibokenGenerator::getGeneratorClassInfo(const AbstractMetaClass *scope)
+{
+ auto cache = generatorClassInfoCache();
+ auto it = cache->find(scope);
+ if (it == cache->end()) {
+ it = cache->insert(scope, {});
+ it.value().functionGroups = getFunctionGroupsImpl(scope);
+ it.value().needsGetattroFunction = classNeedsGetattroFunctionImpl(scope);
+ }
+ return it.value();
+}
+
+ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const AbstractMetaClass *scope)
+{
+ Q_ASSERT(scope);
+ return getGeneratorClassInfo(scope).functionGroups;
+}
+
+ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope)
+{
+ const AbstractMetaFunctionList &lst = scope->functions();
+
+ FunctionGroups results;
+ for (AbstractMetaFunction *func : lst) {
if (isGroupable(func)) {
- AbstractMetaFunctionList &list = results[func->name()];
- // If there are virtuals methods in the mix (PYSIDE-570,
- // QFileSystemModel::index(QString,int) and
- // QFileSystemModel::index(int,int,QModelIndex)) override, make sure
- // the overriding method of the most-derived class is seen first
- // and inserted into the "seenSignatures" set.
- if (func->isVirtual())
- list.prepend(func);
- else
- list.append(func);
+ auto it = results.find(func->name());
+ if (it == results.end()) {
+ results.insert(func->name(), AbstractMetaFunctionList(1, func));
+ } else {
+ // If there are virtuals methods in the mix (PYSIDE-570,
+ // QFileSystemModel::index(QString,int) and
+ // QFileSystemModel::index(int,int,QModelIndex)) override, make sure
+ // the overriding method of the most-derived class is seen first
+ // and inserted into the "seenSignatures" set.
+ if (func->isVirtual())
+ it.value().prepend(func);
+ else
+ it.value().append(func);
+ }
}
}
return results;
@@ -2503,8 +2551,8 @@ bool ShibokenGenerator::doSetup()
Q_ASSERT(moduleEntry);
getCode(snips, moduleEntry);
- const FunctionGroupMap &functionGroups = getFunctionGroups();
- for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
+ const auto &functionGroups = getGlobalFunctionGroups();
+ for (auto it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
for (AbstractMetaFunction *func : it.value())
getCode(snips, func->injectedCodeSnips());
}
diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
index 80b172778..ebfc059de 100644
--- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
@@ -54,6 +54,7 @@ extern const char *END_ALLOW_THREADS;
class DocParser;
class CodeSnip;
class OverloadData;
+struct GeneratorClassInfoCacheEntry;
QT_FORWARD_DECLARE_CLASS(QTextStream)
@@ -63,6 +64,8 @@ QT_FORWARD_DECLARE_CLASS(QTextStream)
class ShibokenGenerator : public Generator
{
public:
+ using FunctionGroups = QMap<QString, AbstractMetaFunctionList>; // Sorted
+
ShibokenGenerator();
~ShibokenGenerator() override;
@@ -99,7 +102,8 @@ protected:
* Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"}
* \param scope Where to search for functions, null means all global functions.
*/
- QMap<QString, AbstractMetaFunctionList> getFunctionGroups(const AbstractMetaClass* scope = 0);
+ FunctionGroups getGlobalFunctionGroups() const;
+ static FunctionGroups getFunctionGroups(const AbstractMetaClass *scope);
/**
* Returns all different inherited overloads of func, and includes func as well.
@@ -440,6 +444,10 @@ protected:
static QStringList m_knownPythonTypes;
private:
+ static const GeneratorClassInfoCacheEntry &getGeneratorClassInfo(const AbstractMetaClass *scope);
+ static FunctionGroups getFunctionGroupsImpl(const AbstractMetaClass *scope);
+ static bool classNeedsGetattroFunctionImpl(const AbstractMetaClass *metaClass);
+
QString translateTypeForWrapperMethod(const AbstractMetaType* cType,
const AbstractMetaClass* context,
Options opt = NoOption) const;