diff options
author | Olivier Goffart <olivier.goffart@nokia.com> | 2010-05-05 07:44:58 (GMT) |
---|---|---|
committer | Olivier Goffart <olivier.goffart@nokia.com> | 2011-03-31 14:32:44 (GMT) |
commit | bc3491c1b85ca36486c9472ecf7ba82f46699e8a (patch) | |
tree | d08c3752f6e0656974c18eb654811f889276366a /src/tools | |
parent | d7ee1cc6456e35823d2c470feec6219ef516e1f6 (diff) | |
download | Qt-bc3491c1b85ca36486c9472ecf7ba82f46699e8a.zip Qt-bc3491c1b85ca36486c9472ecf7ba82f46699e8a.tar.gz Qt-bc3491c1b85ca36486c9472ecf7ba82f46699e8a.tar.bz2 |
Speedup activation of signals
The virtual QObject::qt_metacall will recurse to the whole object hierarchy
to find from which class a function should be called.
But it is possible to know, at connection time, from which exact
QMetaObject a function belongs, and the relative offset into it.
So we make the slot calls from the qt_static_metacall function.
So activation of signals is faster.
- We must not call a slot from a class that has been destroyed.
To avoid this, there is a check on the methodOffset. If it is
smaller, that means we might be called (indirectly) from
the destructor. We fallback to the virtual call to qt_metacall
that does the right thing.
- The signature of the static method is void (*) (QObject*,MetaCall,int,void**)
It returns void, so the compiler is allowed to do tail recusive
optimization. Having the QObject* as first parameter make it ready
on the stack for the call to the member function.
- The new static method has to be a member function in order to
be able to access the private slots.
Reviewed-by: brad
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/moc/generator.cpp | 157 | ||||
-rw-r--r-- | src/tools/moc/generator.h | 2 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 6 | ||||
-rw-r--r-- | src/tools/moc/moc.h | 3 | ||||
-rw-r--r-- | src/tools/moc/outputrevision.h | 2 |
5 files changed, 103 insertions, 67 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 4df7ae5..ac769d7 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -173,7 +173,7 @@ void Generator::generateCode() int index = 14; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); - fprintf(out, " %4d, // revision\n", 5); + fprintf(out, " %4d, // revision\n", 6); fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; @@ -291,12 +291,11 @@ void Generator::generateCode() } fprintf(out, "\"\n};\n\n"); - // // Generate internal qt_static_metacall() function // - if (isConstructible) - generateStaticMetacall(qualifiedClassNameIdentifier); + if (cdef->hasQObject && !isQt) + generateStaticMetacall(); // // Build extra array @@ -329,17 +328,19 @@ void Generator::generateCode() fprintf(out, " 0\n};\n\n"); } - if (isConstructible || !extraList.isEmpty()) { + bool hasExtraData = (cdef->hasQObject && !isQt) || !extraList.isEmpty(); + if (hasExtraData) { fprintf(out, "static const QMetaObjectExtraData qt_meta_extradata2_%s = {\n ", qualifiedClassNameIdentifier.constData()); if (extraList.isEmpty()) fprintf(out, "0, "); else fprintf(out, "qt_meta_extradata_%s, ", qualifiedClassNameIdentifier.constData()); - if (!isConstructible) - fprintf(out, "0"); + + if (cdef->hasQObject && !isQt) + fprintf(out, " %s::qt_static_metacall", cdef->qualified.constData()); else - fprintf(out, "%s_qt_static_metacall", qualifiedClassNameIdentifier.constData()); + fprintf(out, " 0"); fprintf(out, " \n};\n\n"); } @@ -359,7 +360,7 @@ void Generator::generateCode() fprintf(out, " { 0, "); fprintf(out, "qt_meta_stringdata_%s,\n qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(), qualifiedClassNameIdentifier.constData()); - if (!isConstructible && extraList.isEmpty()) + if (!hasExtraData) fprintf(out, "0 }\n"); else fprintf(out, "&qt_meta_extradata2_%s }\n", qualifiedClassNameIdentifier.constData()); @@ -657,34 +658,11 @@ void Generator::generateMetacall() if (methodList.size()) { needElse = true; - fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n "); - fprintf(out, "switch (_id) {\n"); - for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) { - const FunctionDef &f = methodList.at(methodindex); - fprintf(out, " case %d: ", methodindex); - if (f.normalizedType.size()) - fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData()); - if (f.inPrivateClass.size()) - fprintf(out, "%s->", f.inPrivateClass.constData()); - fprintf(out, "%s(", f.name.constData()); - int offset = 1; - for (int j = 0; j < f.arguments.count(); ++j) { - const ArgumentDef &a = f.arguments.at(j); - if (j) - fprintf(out, ","); - fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++); - } - fprintf(out, ");"); - if (f.normalizedType.size()) - fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ", - noRef(f.normalizedType).constData()); - fprintf(out, " break;\n"); - } - fprintf(out, " default: ;\n"); - fprintf(out, " }\n"); - } - if (methodList.size()) + fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n"); + fprintf(out, " if (_id < %d)\n", methodList.size()); + fprintf(out, " qt_static_metacall(this, _c, _id, _a);\n"); fprintf(out, " _id -= %d;\n }", methodList.size()); + } if (cdef->propertyList.size()) { bool needGet = false; @@ -900,40 +878,95 @@ void Generator::generateMetacall() fprintf(out,"return _id;\n}\n"); } -void Generator::generateStaticMetacall(const QByteArray &prefix) +void Generator::generateStaticMetacall() { - bool isQObject = (cdef->classname == "QObject"); + fprintf(out, "void %s::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)\n{\n", + cdef->qualified.constData()); - fprintf(out, "static int %s_qt_static_metacall(QMetaObject::Call _c, int _id, void **_a)\n{\n", - prefix.constData()); + bool needElse = false; + bool isUsed_a = false; + + if (!cdef->constructorList.isEmpty()) { + fprintf(out, " if (_c == QMetaObject::CreateInstance) {\n"); + fprintf(out, " switch (_id) {\n"); + for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) { + fprintf(out, " case %d: { %s *_r = new %s(", ctorindex, + cdef->classname.constData(), cdef->classname.constData()); + const FunctionDef &f = cdef->constructorList.at(ctorindex); + int offset = 1; + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) + fprintf(out, ","); + fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++); + } + fprintf(out, ");\n"); + fprintf(out, " if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n"); + } + fprintf(out, " }\n"); + fprintf(out, " }"); + needElse = true; + isUsed_a = true; + } - fprintf(out, " if (_c == QMetaObject::CreateInstance) {\n"); - fprintf(out, " switch (_id) {\n"); - for (int ctorindex = 0; ctorindex < cdef->constructorList.count(); ++ctorindex) { - fprintf(out, " case %d: { %s *_r = new %s(", ctorindex, - cdef->qualified.constData(), cdef->qualified.constData()); - const FunctionDef &f = cdef->constructorList.at(ctorindex); - int offset = 1; - for (int j = 0; j < f.arguments.count(); ++j) { - const ArgumentDef &a = f.arguments.at(j); - if (j) - fprintf(out, ","); - fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++); + QList<FunctionDef> methodList; + methodList += cdef->signalList; + methodList += cdef->slotList; + methodList += cdef->methodList; + + if (!methodList.isEmpty()) { + if (needElse) + fprintf(out, " else "); + else + fprintf(out, " "); + fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n"); + fprintf(out, " Q_ASSERT(qobject_cast<%s *>(_o));\n", cdef->classname.constData()); + fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData()); + fprintf(out, " switch (_id) {\n"); + for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) { + const FunctionDef &f = methodList.at(methodindex); + fprintf(out, " case %d: ", methodindex); + if (f.normalizedType.size()) + fprintf(out, "{ %s _r = ", noRef(f.normalizedType).constData()); + fprintf(out, "_t->"); + if (f.inPrivateClass.size()) + fprintf(out, "%s->", f.inPrivateClass.constData()); + fprintf(out, "%s(", f.name.constData()); + int offset = 1; + for (int j = 0; j < f.arguments.count(); ++j) { + const ArgumentDef &a = f.arguments.at(j); + if (j) + fprintf(out, ","); + fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++); + isUsed_a = true; + } + fprintf(out, ");"); + if (f.normalizedType.size()) { + fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ", + noRef(f.normalizedType).constData()); + isUsed_a = true; + } + fprintf(out, " break;\n"); } - fprintf(out, ");\n"); - fprintf(out, " if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n"); + fprintf(out, " default: ;\n"); + fprintf(out, " }\n"); + fprintf(out, " }"); + needElse = true; } - fprintf(out, " }\n"); - fprintf(out, " _id -= %d;\n", cdef->constructorList.count()); - fprintf(out, " return _id;\n"); - fprintf(out, " }\n"); - if (!isQObject) - fprintf(out, " _id = %s::staticMetaObject.superClass()->static_metacall(_c, _id, _a);\n", cdef->qualified.constData()); + if (needElse) + fprintf(out, "\n"); - fprintf(out, " if (_id < 0)\n return _id;\n"); + if (methodList.isEmpty()) { + fprintf(out, " Q_UNUSED(_o);\n"); + if (cdef->constructorList.isEmpty()) { + fprintf(out, " Q_UNUSED(_id);\n"); + fprintf(out, " Q_UNUSED(_c);\n"); + } + } + if (!isUsed_a) + fprintf(out, " Q_UNUSED(_a);\n"); - fprintf(out, " return _id;\n"); fprintf(out, "}\n\n"); } diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index ed0980e..fa5885f 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -62,7 +62,7 @@ private: void generateEnums(int index); void generateProperties(); void generateMetacall(); - void generateStaticMetacall(const QByteArray &prefix); + void generateStaticMetacall(); void generateSignal(FunctionDef *def, int index); // used by binary QMetaObject generator diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 74b1ace..5078b28 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -356,8 +356,9 @@ bool Moc::testFunctionRevision(FunctionDef *def) bool Moc::parseFunction(FunctionDef *def, bool inMacro) { def->isVirtual = false; + def->isStatic = false; //skip modifiers and attributes - while (test(INLINE) || test(STATIC) || + while (test(INLINE) || (test(STATIC) && (def->isStatic = true)) || (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool templateFunction = (lookup() == TEMPLATE); @@ -447,8 +448,9 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) { def->isVirtual = false; + def->isStatic = false; //skip modifiers and attributes - while (test(EXPLICIT) || test(INLINE) || test(STATIC) || + while (test(EXPLICIT) || test(INLINE) || (test(STATIC) && (def->isStatic = true)) || (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool tilde = test(TILDE); diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 38c3917..4049534 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -83,7 +83,7 @@ struct ArgumentDef struct FunctionDef { - FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), + FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), isStatic(false), inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false), isScriptable(false), isSlot(false), isSignal(false), isConstructor(false), isDestructor(false), isAbstract(false), revision(0) {} @@ -99,6 +99,7 @@ struct FunctionDef Access access; bool isConst; bool isVirtual; + bool isStatic; bool inlineCode; bool wasCloned; diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h index 7e2ca8b..104a373 100644 --- a/src/tools/moc/outputrevision.h +++ b/src/tools/moc/outputrevision.h @@ -43,6 +43,6 @@ #define OUTPUTREVISION_H // if the output revision changes, you MUST change it in qobjectdefs.h too -enum { mocOutputRevision = 62 }; // moc format output revision +enum { mocOutputRevision = 63 }; // moc format output revision #endif // OUTPUTREVISION_H |