diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-11-30 17:54:03 +0000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-01 18:55:39 +0100 |
commit | 8fd12405b9976ca4c9dec6cf53ccde24bfa76dd7 (patch) | |
tree | 12dd5dfbad6e20a515fc557e2a83a1ef111ca828 | |
parent | 32115087589939225a4516ed15196a4f6632c13b (diff) |
Improve value type read performance
On x86, this gives ~3x improvement in property read time.
Change-Id: I8f75e9bb7450bc56ca42f8258c3a5641bc9c18d3
Reviewed-by: Chris Adams <christopher.adams@nokia.com>
-rw-r--r-- | src/declarative/qml/v8/qv8valuetypewrapper.cpp | 58 | ||||
-rw-r--r-- | src/declarative/qml/v8/qv8valuetypewrapper_p.h | 3 |
2 files changed, 48 insertions, 13 deletions
diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp index 2c46b77823..aca0c85ace 100644 --- a/src/declarative/qml/v8/qv8valuetypewrapper.cpp +++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp @@ -105,8 +105,11 @@ void QV8ValueTypeWrapper::destroy() { qPersistentDispose(m_toString); qPersistentDispose(m_constructor); + qPersistentDispose(m_toStringSymbol); } +static quint32 toStringHash = -1; + void QV8ValueTypeWrapper::init(QV8Engine *engine) { m_engine = engine; @@ -119,6 +122,10 @@ void QV8ValueTypeWrapper::init(QV8Engine *engine) m_toString, v8::DEFAULT, v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); + + m_toStringSymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("toString")); + m_toStringString = QHashedV8String(m_toStringSymbol); + toStringHash = m_toStringString.hash(); } v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(QObject *object, int property, QDeclarativeValueType *type) @@ -231,19 +238,30 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This()); if (!r) return v8::Handle<v8::Value>(); - // XXX This is horribly inefficient. Sadly people seem to have taken a liking to - // value type properties, so we should probably try and optimize it a little. - // We should probably just replace all value properties with dedicated accessors. + QHashedV8String propertystring(property); - QByteArray propName = r->engine->toString(property).toUtf8(); - if (propName == QByteArray("toString")) { - return r->engine->valueTypeWrapper()->m_toString; + { + // Comparing the hash first actually makes a measurable difference here, at least on x86 + quint32 hash = propertystring.hash(); + if (hash == toStringHash && + r->engine->valueTypeWrapper()->m_toStringString == propertystring) { + return r->engine->valueTypeWrapper()->m_toString; + } } - int index = r->type->metaObject()->indexOfProperty(propName.constData()); - if (index == -1) - return v8::Handle<v8::Value>(); + QDeclarativePropertyData local; + QDeclarativePropertyData *result = 0; + { + QDeclarativeData *ddata = QDeclarativeData::get(r->type, false); + if (ddata && ddata->propertyCache) + result = ddata->propertyCache->property(propertystring); + else + result = QDeclarativePropertyCache::property(r->engine->engine(), r->type, + propertystring, local); + } + if (!result) + return v8::Handle<v8::Value>(); if (r->objectType == QV8ValueTypeResource::Reference) { QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r); @@ -251,7 +269,6 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property if (!reference->object) return v8::Handle<v8::Value>(); - r->type->read(reference->object, reference->property); } else { Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy); @@ -261,10 +278,25 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property r->type->setValue(copy->value); } - QMetaProperty prop = r->type->metaObject()->property(index); - QVariant result = prop.read(r->type); +#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \ + if (result->propType == metatype) { \ + cpptype v; \ + void *args[] = { &v, 0 }; \ + r->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); \ + return constructor(v); \ + } - return r->engine->fromVariant(result); + // These four types are the most common used by the value type wrappers + VALUE_TYPE_LOAD(QMetaType::QReal, qreal, v8::Number::New); + VALUE_TYPE_LOAD(QMetaType::Int, int, v8::Integer::New); + VALUE_TYPE_LOAD(QMetaType::QString, QString, r->engine->toString); + VALUE_TYPE_LOAD(QMetaType::Bool, bool, v8::Boolean::New); + + QVariant v(result->propType, (void *)0); + void *args[] = { v.data(), 0 }; + r->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); + return r->engine->fromVariant(v); +#undef VALUE_TYPE_ACCESSOR } v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property, diff --git a/src/declarative/qml/v8/qv8valuetypewrapper_p.h b/src/declarative/qml/v8/qv8valuetypewrapper_p.h index 2582560c0f..ce8944efb5 100644 --- a/src/declarative/qml/v8/qv8valuetypewrapper_p.h +++ b/src/declarative/qml/v8/qv8valuetypewrapper_p.h @@ -56,6 +56,7 @@ #include <QtCore/qglobal.h> #include <QtDeclarative/qdeclarativelist.h> #include <private/qv8_p.h> +#include <private/qhashedstring_p.h> QT_BEGIN_NAMESPACE @@ -92,6 +93,8 @@ private: QV8Engine *m_engine; v8::Persistent<v8::Function> m_constructor; v8::Persistent<v8::Function> m_toString; + v8::Persistent<v8::String> m_toStringSymbol; + QHashedV8String m_toStringString; }; QT_END_NAMESPACE |