diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2012-05-21 09:27:43 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-08-24 00:55:55 +0200 |
commit | 0853343c33e394f35c31c161b019b2aed17f9256 (patch) | |
tree | 3f792f58979ae75f8e75a0c0ef6e7f89265b1c16 /src/qml/qml/qqmlpropertycache.cpp | |
parent | 9ee6bb0e14d968647350683eafbe80eed7a27058 (diff) |
Avoid dynamic lookup of signal handler arguments
Rewrite signal handlers to include the parameters
in the rewrite. Also check whether parameters are
actually used when possible, and if not don't
provide them to the expression.
Change-Id: I7d65c05f4639979dd61035cf7478119ef7647c25
Reviewed-by: Matthew Vogt <matthew.vogt@nokia.com>
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'src/qml/qml/qqmlpropertycache.cpp')
-rw-r--r-- | src/qml/qml/qqmlpropertycache.cpp | 142 |
1 files changed, 128 insertions, 14 deletions
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp index 89febc24cb..3519d46017 100644 --- a/src/qml/qml/qqmlpropertycache.cpp +++ b/src/qml/qml/qqmlpropertycache.cpp @@ -48,6 +48,7 @@ #include <private/qmetaobject_p.h> #include <private/qqmlaccessors_p.h> #include <private/qmetaobjectbuilder_p.h> +#include <private/qqmlrewrite_p.h> #include <QtCore/qdebug.h> @@ -70,6 +71,12 @@ class QQmlPropertyCacheMethodArguments public: QQmlPropertyCacheMethodArguments *next; + //for signal handler rewrites + QString *signalParameterStringForJS; + int signalParameterCountForJS:30; + int parameterError:1; + int argumentsValid:1; + QList<QByteArray> *names; int arguments[0]; }; @@ -261,6 +268,7 @@ QQmlPropertyCache::~QQmlPropertyCache() QQmlPropertyCacheMethodArguments *args = argumentsCache; while (args) { QQmlPropertyCacheMethodArguments *next = args->next; + if (args->signalParameterStringForJS) delete args->signalParameterStringForJS; if (args->names) delete args->names; free(args); args = next; @@ -392,6 +400,10 @@ void QQmlPropertyCache::appendSignal(const QString &name, quint32 flags, int cor typedef QQmlPropertyCacheMethodArguments A; A *args = static_cast<A *>(malloc(sizeof(A) + (argumentCount + 1) * sizeof(int))); ::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int)); + args->argumentsValid = true; + args->signalParameterStringForJS = 0; + args->signalParameterCountForJS = 0; + args->parameterError = false; args->names = new QList<QByteArray>(names); args->next = argumentsCache; argumentsCache = args; @@ -432,6 +444,10 @@ void QQmlPropertyCache::appendSignal(const QHashedCStringRef &name, quint32 flag typedef QQmlPropertyCacheMethodArguments A; A *args = static_cast<A *>(malloc(sizeof(A) + (argumentCount + 1) * sizeof(int))); ::memcpy(args->arguments, types, (argumentCount + 1) * sizeof(int)); + args->argumentsValid = true; + args->signalParameterStringForJS = 0; + args->signalParameterCountForJS = 0; + args->parameterError = false; args->names = new QList<QByteArray>(names); args->next = argumentsCache; argumentsCache = args; @@ -468,6 +484,10 @@ void QQmlPropertyCache::appendMethod(const QString &name, quint32 flags, int cor args->arguments[0] = argumentCount; for (int ii = 0; ii < argumentCount; ++ii) args->arguments[ii + 1] = QMetaType::QVariant; + args->argumentsValid = true; + args->signalParameterStringForJS = 0; + args->signalParameterCountForJS = 0; + args->parameterError = false; args->names = 0; if (argumentCount) args->names = new QList<QByteArray>(names); @@ -503,6 +523,10 @@ void QQmlPropertyCache::appendMethod(const QHashedCStringRef &name, quint32 flag args->arguments[0] = argumentCount; for (int ii = 0; ii < argumentCount; ++ii) args->arguments[ii + 1] = QMetaType::QVariant; + args->argumentsValid = true; + args->signalParameterStringForJS = 0; + args->signalParameterCountForJS = 0; + args->parameterError = false; args->names = 0; if (argumentCount) args->names = new QList<QByteArray>(names); @@ -1001,16 +1025,60 @@ static int EnumType(const QMetaObject *metaobj, const QByteArray &str, int type) \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()). This is different from QMetaMethod::methodIndex(). */ -QList<QByteArray> QQmlPropertyCache::signalParameterNames(QObject *object, int index) +QString QQmlPropertyCache::signalParameterStringForJS(int index, int *count, QString *errorString) { - QQmlData *data = QQmlData::get(object, false); - if (data->propertyCache) { - QQmlPropertyData *p = data->propertyCache->signal(index); - if (!p->hasArguments()) - return QList<QByteArray>(); + QQmlPropertyData *signalData = signal(index); + if (!signalData) + return QString(); + + typedef QQmlPropertyCacheMethodArguments A; + + if (signalData->arguments) { + A *arguments = static_cast<A *>(signalData->arguments); + if (arguments->signalParameterStringForJS) { + if (count) + *count = arguments->signalParameterCountForJS; + if (arguments->parameterError) { + if (errorString) + *errorString = *arguments->signalParameterStringForJS; + return QString(); + } + return *arguments->signalParameterStringForJS; + } } - return QMetaObjectPrivate::signal(object->metaObject(), index).parameterNames(); + QList<QByteArray> parameterNameList = signalParameterNames(index); + + if (!signalData->arguments) { + int argc = parameterNameList.count(); + A *args = static_cast<A *>(malloc(sizeof(A) + (argc + 1) * sizeof(int))); + args->arguments[0] = argc; + args->argumentsValid = false; + args->signalParameterStringForJS = 0; + args->signalParameterCountForJS = 0; + args->parameterError = false; + args->names = new QList<QByteArray>(parameterNameList); + signalData->arguments = args; + } + + QQmlRewrite::RewriteSignalHandler rewriter; + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); + const QString ¶meters = rewriter.createParameterString(parameterNameList, + ep->v8engine()->illegalNames()); + + bool error = rewriter.hasParameterError(); + A *arguments = static_cast<A *>(signalData->arguments); + arguments->signalParameterStringForJS = new QString(error ? rewriter.parameterError() : parameters); + arguments->signalParameterCountForJS = rewriter.parameterCountForJS(); + if (count) + *count = arguments->signalParameterCountForJS; + if (error) { + arguments->parameterError = true; + if (errorString) + *errorString = *arguments->signalParameterStringForJS; + return QString(); + } + return *arguments->signalParameterStringForJS; } // Returns an array of the arguments for method \a index. The first entry in the array @@ -1034,7 +1102,7 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart)); - if (rv->arguments) + if (rv->arguments && static_cast<A *>(rv->arguments)->argumentsValid) return static_cast<A *>(rv->arguments)->arguments; const QMetaObject *metaObject = c->createMetaObject(); @@ -1042,9 +1110,18 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, QMetaMethod m = metaObject->method(index); int argc = m.parameterCount(); - A *args = static_cast<A *>(malloc(sizeof(A) + (argc + 1) * sizeof(int))); - args->arguments[0] = argc; - args->names = 0; + if (!rv->arguments) { + A *args = static_cast<A *>(malloc(sizeof(A) + (argc + 1) * sizeof(int))); + args->arguments[0] = argc; + args->argumentsValid = false; + args->signalParameterStringForJS = 0; + args->signalParameterCountForJS = 0; + args->parameterError = false; + args->names = 0; + rv->arguments = args; + } + A *args = static_cast<A *>(rv->arguments); + QList<QByteArray> argTypeNames; // Only loaded if needed for (int ii = 0; ii < argc; ++ii) { @@ -1062,13 +1139,12 @@ int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index, } if (type == QMetaType::UnknownType) { if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii); - free(args); return 0; } args->arguments[ii + 1] = type; } + args->argumentsValid = true; - rv->arguments = args; args->next = c->argumentsCache; c->argumentsCache = args; return static_cast<A *>(rv->arguments)->arguments; @@ -1154,6 +1230,27 @@ int QQmlPropertyCache::methodReturnType(QObject *object, const QQmlPropertyData return type; } +int QQmlPropertyCache::originalClone(int index) +{ + while (signal(index)->isCloned()) + --index; + return index; +} + +int QQmlPropertyCache::originalClone(QObject *object, int index) +{ + QQmlData *data = QQmlData::get(object, false); + if (data && data->propertyCache) { + QQmlPropertyCache *cache = data->propertyCache; + while (cache->signal(index)->isCloned()) + --index; + } else { + while (QMetaObjectPrivate::signal(object->metaObject(), index).attributes() & QMetaMethod::Cloned) + --index; + } + return index; +} + QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QString &property) { Q_ASSERT(metaObject); @@ -1355,7 +1452,7 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder) QQmlPropertyCacheMethodArguments *arguments = 0; if (data->hasArguments()) { arguments = (QQmlPropertyCacheMethodArguments *)data->arguments; - + Q_ASSERT(arguments->argumentsValid); for (int ii = 0; ii < arguments->arguments[0]; ++ii) { if (ii != 0) signature.append(","); signature.append(QMetaType::typeName(arguments->arguments[1 + ii])); @@ -1388,6 +1485,23 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder) } } +/*! \internal + \a index MUST be in the signal index range (see QObjectPrivate::signalIndex()). + This is different from QMetaMethod::methodIndex(). +*/ +QList<QByteArray> QQmlPropertyCache::signalParameterNames(int index) const +{ + QQmlPropertyData *signalData = signal(index); + if (signalData && signalData->hasArguments()) { + QQmlPropertyCacheMethodArguments *args = (QQmlPropertyCacheMethodArguments *)signalData->arguments; + if (args && args->names) + return *args->names; + const QMetaMethod &method = QMetaObjectPrivate::signal(firstCppMetaObject(), index); + return method.parameterNames(); + } + return QList<QByteArray>(); +} + // Returns true if \a from is assignable to a property of type \a to bool QQmlMetaObject::canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to) { |