From 8fd12405b9976ca4c9dec6cf53ccde24bfa76dd7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 30 Nov 2011 17:54:03 +0000 Subject: Improve value type read performance On x86, this gives ~3x improvement in property read time. Change-Id: I8f75e9bb7450bc56ca42f8258c3a5641bc9c18d3 Reviewed-by: Chris Adams --- src/declarative/qml/v8/qv8valuetypewrapper.cpp | 58 ++++++++++++++++++++------ 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(ft->GetFunction()); + + m_toStringSymbol = qPersistentNew(v8::String::NewSymbol("toString")); + m_toStringString = QHashedV8String(m_toStringSymbol); + toStringHash = m_toStringString.hash(); } v8::Local QV8ValueTypeWrapper::newValueType(QObject *object, int property, QDeclarativeValueType *type) @@ -231,19 +238,30 @@ v8::Handle QV8ValueTypeWrapper::Getter(v8::Local property QV8ValueTypeResource *r = v8_resource_cast(info.This()); if (!r) return v8::Handle(); - // 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(); + 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(); if (r->objectType == QV8ValueTypeResource::Reference) { QV8ValueTypeReferenceResource *reference = static_cast(r); @@ -251,7 +269,6 @@ v8::Handle QV8ValueTypeWrapper::Getter(v8::Local property if (!reference->object) return v8::Handle(); - r->type->read(reference->object, reference->property); } else { Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy); @@ -261,10 +278,25 @@ v8::Handle QV8ValueTypeWrapper::Getter(v8::Local 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 QV8ValueTypeWrapper::Setter(v8::Local 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 #include #include +#include QT_BEGIN_NAMESPACE @@ -92,6 +93,8 @@ private: QV8Engine *m_engine; v8::Persistent m_constructor; v8::Persistent m_toString; + v8::Persistent m_toStringSymbol; + QHashedV8String m_toStringString; }; QT_END_NAMESPACE -- cgit v1.2.3