diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2016-05-20 15:22:31 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2016-05-23 08:59:34 +0000 |
commit | 7f7e2b0c9cc8e6d4f4eb18be8e5cc4053a0d4b11 (patch) | |
tree | 6b246d2ec9d0259a6e3fddfc4ec0db40a65d9d83 | |
parent | b0377f4581a7f62cccd375a1f9400ca57225e4ac (diff) |
Simplify VME meta object meta-data
For each type of VME meta object we store an array of integers holding the
meta-type ids of the QML declared properties. We can replace that array with
access to the QV4::CompiledData::Property entry for each property, where the
type is also accessible.
This is a fairly straight-forward change, except for the bit in
QV4::CompilationUnit where we delay the release of the CompiledData::Unit and
friends until the destructor instead of releasing it at unlink time. That
should be a safe change and is necessary as there are a few tests around where
the VME meta object still needs access to this meta-data at a very late stage
in the life-cycle right before the deferred deletion is run.
Change-Id: I431de15d12766df837c0e0251192df16a5a76868
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 11 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 168 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject_p.h | 21 | ||||
-rw-r--r-- | src/quick/designer/qqmldesignermetaobject.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 1 |
7 files changed, 121 insertions, 90 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index fed0ec1f37..594a0d9152 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -662,7 +662,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob typedef QQmlVMEMetaData VMD; QByteArray &dynamicData = vmeMetaObjects[objectIndex] = QByteArray(sizeof(QQmlVMEMetaData) - + obj->propertyCount() * sizeof(VMD::PropertyData) + obj->aliasCount() * sizeof(VMD::AliasData), 0); VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); @@ -808,16 +807,13 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob int propertyIdx = 0; for (const QmlIR::Property *p = obj->firstProperty(); p; p = p->next, ++propertyIdx) { int propertyType = 0; - int vmePropertyType = 0; quint32 propertyFlags = 0; if (p->type == QV4::CompiledData::Property::Var) { propertyType = QMetaType::QVariant; - vmePropertyType = QQmlVMEMetaData::VarPropertyType; propertyFlags = QQmlPropertyData::IsVarProperty; } else if (p->type < builtinTypeCount) { propertyType = builtinTypes[p->type].metaType; - vmePropertyType = propertyType; if (p->type == QV4::CompiledData::Property::Variant) propertyFlags |= QQmlPropertyData::IsQVariant; @@ -840,20 +836,16 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob if (p->type == QV4::CompiledData::Property::Custom) { propertyType = data->metaTypeId; - vmePropertyType = QMetaType::QObjectStar; } else { propertyType = data->listMetaTypeId; - vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >(); } tdata->release(); } else { if (p->type == QV4::CompiledData::Property::Custom) { propertyType = qmltype->typeId(); - vmePropertyType = QMetaType::QObjectStar; } else { propertyType = qmltype->qListTypeId(); - vmePropertyType = qMetaTypeId<QQmlListProperty<QObject> >(); } } @@ -874,9 +866,6 @@ bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Ob propertyType, effectiveSignalIndex); effectiveSignalIndex++; - - VMD *vmd = (QQmlVMEMetaData *)dynamicData.data(); - (vmd->propertyData() + propertyIdx)->propertyType = vmePropertyType; } return true; diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index a63f35152a..ded2c1a9f8 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -72,6 +72,9 @@ CompilationUnit::CompilationUnit() CompilationUnit::~CompilationUnit() { unlink(); + if (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) + free(data); + data = 0; } QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) @@ -163,9 +166,6 @@ void CompilationUnit::unlink() if (engine) engine->compilationUnits.erase(engine->compilationUnits.find(this)); engine = 0; - if (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) - free(data); - data = 0; free(runtimeStrings); runtimeStrings = 0; delete [] runtimeLookups; diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index b8c12f70d1..8d3c5962bd 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -1289,7 +1289,7 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * if (!data.isEmpty()) { Q_ASSERT(!cache.isNull()); // install on _object - vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData())); + vmeMetaObject = new QQmlVMEMetaObject(_qobject, cache, reinterpret_cast<const QQmlVMEMetaData*>(data.constData()), compiledData->compilationUnit, _compiledObjectIndex); if (_ddata->propertyCache) _ddata->propertyCache->release(); _ddata->propertyCache = cache; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 8211a834ec..14d2e39ccb 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -304,23 +304,25 @@ QAbstractDynamicMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObje QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, - const QQmlVMEMetaData *meta) + const QQmlVMEMetaData *meta, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId) : QQmlInterceptorMetaObject(obj, cache), ctxt(QQmlData::get(obj, true)->outerContext), metaData(meta), - aliasEndpoints(0) + aliasEndpoints(0), compilationUnit(qmlCompilationUnit), compiledObject(0) { cache->addref(); QQmlData::get(obj)->hasVMEMetaObject = true; if (metaData->propertyCount || metaData->methodCount) { + Q_ASSERT(compilationUnit); + Q_ASSERT(qmlObjectId >= 0); + compiledObject = compilationUnit->data->objectAt(qmlObjectId); Q_ASSERT(cache && cache->engine); QV4::ExecutionEngine *v4 = cache->engine; QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount + metaData->methodCount); propertyAndMethodStorage.set(v4, data); std::fill(data->data, data->data + data->size, QV4::Encode::undefined()); - // Need JS wrapper to ensure properties/methods are marked. ensureQObjectWrapper(); } @@ -615,11 +617,11 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (id >= propOffset()) { id -= propOffset(); - if (id < metaData->propertyCount) { - int t = (metaData->propertyData() + id)->propertyType; + if (id < metaData->propertyCount && compiledObject) { + const QV4::CompiledData::Property::Type t = static_cast<QV4::CompiledData::Property::Type>(compiledObject->propertyTable()[id].type); bool needActivate = false; - if (t == QQmlVMEMetaData::VarPropertyType) { + if (t == QV4::CompiledData::Property::Var) { // the context can be null if accessing var properties from cpp after re-parenting an item. QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine); QV8Engine *v8e = (ep == 0) ? 0 : ep->v8engine(); @@ -635,131 +637,179 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * } } else { + int fallbackMetaType = QMetaType::UnknownType; + switch (t) { + case QV4::CompiledData::Property::Font: + fallbackMetaType = QMetaType::QFont; + break; + case QV4::CompiledData::Property::Time: + fallbackMetaType = QMetaType::QTime; + break; + case QV4::CompiledData::Property::Color: + fallbackMetaType = QMetaType::QColor; + break; + case QV4::CompiledData::Property::Vector2D: + fallbackMetaType = QMetaType::QVector2D; + break; + case QV4::CompiledData::Property::Vector3D: + fallbackMetaType = QMetaType::QVector3D; + break; + case QV4::CompiledData::Property::Vector4D: + fallbackMetaType = QMetaType::QVector4D; + break; + case QV4::CompiledData::Property::Matrix4x4: + fallbackMetaType = QMetaType::QMatrix4x4; + break; + case QV4::CompiledData::Property::Quaternion: + fallbackMetaType = QMetaType::QQuaternion; + break; + default: break; + } + if (c == QMetaObject::ReadProperty) { - switch(t) { - case QVariant::Int: + switch (t) { + case QV4::CompiledData::Property::Int: *reinterpret_cast<int *>(a[0]) = readPropertyAsInt(id); break; - case QVariant::Bool: + case QV4::CompiledData::Property::Bool: *reinterpret_cast<bool *>(a[0]) = readPropertyAsBool(id); break; - case QVariant::Double: + case QV4::CompiledData::Property::Real: *reinterpret_cast<double *>(a[0]) = readPropertyAsDouble(id); break; - case QVariant::String: + case QV4::CompiledData::Property::String: *reinterpret_cast<QString *>(a[0]) = readPropertyAsString(id); break; - case QVariant::Url: + case QV4::CompiledData::Property::Url: *reinterpret_cast<QUrl *>(a[0]) = readPropertyAsUrl(id); break; - case QVariant::Date: + case QV4::CompiledData::Property::Date: *reinterpret_cast<QDate *>(a[0]) = readPropertyAsDate(id); break; - case QVariant::DateTime: + case QV4::CompiledData::Property::DateTime: *reinterpret_cast<QDateTime *>(a[0]) = readPropertyAsDateTime(id); break; - case QVariant::RectF: + case QV4::CompiledData::Property::Rect: *reinterpret_cast<QRectF *>(a[0]) = readPropertyAsRectF(id); break; - case QVariant::SizeF: + case QV4::CompiledData::Property::Size: *reinterpret_cast<QSizeF *>(a[0]) = readPropertyAsSizeF(id); break; - case QVariant::PointF: + case QV4::CompiledData::Property::Point: *reinterpret_cast<QPointF *>(a[0]) = readPropertyAsPointF(id); break; - case QMetaType::QObjectStar: + case QV4::CompiledData::Property::Custom: *reinterpret_cast<QObject **>(a[0]) = readPropertyAsQObject(id); break; - case QMetaType::QVariant: + case QV4::CompiledData::Property::Variant: *reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id); break; - default: - { - if (t == qMetaTypeId<QQmlListProperty<QObject> >()) { - QList<QObject *> *list = readPropertyAsList(id); - QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]); - *p = QQmlListProperty<QObject>(object, list, - list_append, list_count, list_at, - list_clear); - p->dummy1 = this; - p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id)); - } else { - QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); - if (md) { - QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); - if (v) - QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t); - } - } + case QV4::CompiledData::Property::CustomList: { + QList<QObject *> *list = readPropertyAsList(id); + QQmlListProperty<QObject> *p = static_cast<QQmlListProperty<QObject> *>(a[0]); + *p = QQmlListProperty<QObject>(object, list, + list_append, list_count, list_at, + list_clear); + p->dummy1 = this; + p->dummy2 = reinterpret_cast<void *>(quintptr(methodOffset() + id)); break; } + case QV4::CompiledData::Property::Font: + case QV4::CompiledData::Property::Time: + case QV4::CompiledData::Property::Color: + case QV4::CompiledData::Property::Vector2D: + case QV4::CompiledData::Property::Vector3D: + case QV4::CompiledData::Property::Vector4D: + case QV4::CompiledData::Property::Matrix4x4: + case QV4::CompiledData::Property::Quaternion: + Q_ASSERT(fallbackMetaType != QMetaType::UnknownType); + if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { + QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); + if (v) + QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], fallbackMetaType); + } + break; + case QV4::CompiledData::Property::Var: + Q_UNREACHABLE(); } } else if (c == QMetaObject::WriteProperty) { switch(t) { - case QVariant::Int: + case QV4::CompiledData::Property::Int: needActivate = *reinterpret_cast<int *>(a[0]) != readPropertyAsInt(id); writeProperty(id, *reinterpret_cast<int *>(a[0])); break; - case QVariant::Bool: + case QV4::CompiledData::Property::Bool: needActivate = *reinterpret_cast<bool *>(a[0]) != readPropertyAsBool(id); writeProperty(id, *reinterpret_cast<bool *>(a[0])); break; - case QVariant::Double: + case QV4::CompiledData::Property::Real: needActivate = *reinterpret_cast<double *>(a[0]) != readPropertyAsDouble(id); writeProperty(id, *reinterpret_cast<double *>(a[0])); break; - case QVariant::String: + case QV4::CompiledData::Property::String: needActivate = *reinterpret_cast<QString *>(a[0]) != readPropertyAsString(id); writeProperty(id, *reinterpret_cast<QString *>(a[0])); break; - case QVariant::Url: + case QV4::CompiledData::Property::Url: needActivate = *reinterpret_cast<QUrl *>(a[0]) != readPropertyAsUrl(id); writeProperty(id, *reinterpret_cast<QUrl *>(a[0])); break; - case QVariant::Date: + case QV4::CompiledData::Property::Date: needActivate = *reinterpret_cast<QDate *>(a[0]) != readPropertyAsDate(id); writeProperty(id, *reinterpret_cast<QDate *>(a[0])); break; - case QVariant::DateTime: + case QV4::CompiledData::Property::DateTime: needActivate = *reinterpret_cast<QDateTime *>(a[0]) != readPropertyAsDateTime(id); writeProperty(id, *reinterpret_cast<QDateTime *>(a[0])); break; - case QVariant::RectF: + case QV4::CompiledData::Property::Rect: needActivate = *reinterpret_cast<QRectF *>(a[0]) != readPropertyAsRectF(id); writeProperty(id, *reinterpret_cast<QRectF *>(a[0])); break; - case QVariant::SizeF: + case QV4::CompiledData::Property::Size: needActivate = *reinterpret_cast<QSizeF *>(a[0]) != readPropertyAsSizeF(id); writeProperty(id, *reinterpret_cast<QSizeF *>(a[0])); break; - case QVariant::PointF: + case QV4::CompiledData::Property::Point: needActivate = *reinterpret_cast<QPointF *>(a[0]) != readPropertyAsPointF(id); writeProperty(id, *reinterpret_cast<QPointF *>(a[0])); break; - case QMetaType::QObjectStar: + case QV4::CompiledData::Property::Custom: needActivate = *reinterpret_cast<QObject **>(a[0]) != readPropertyAsQObject(id); writeProperty(id, *reinterpret_cast<QObject **>(a[0])); break; - case QMetaType::QVariant: + case QV4::CompiledData::Property::Variant: writeProperty(id, *reinterpret_cast<QVariant *>(a[0])); break; - default: { - QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); - if (md) { + case QV4::CompiledData::Property::CustomList: + // Writing such a property is not supported. Content is added through the list property + // methods. + break; + case QV4::CompiledData::Property::Font: + case QV4::CompiledData::Property::Time: + case QV4::CompiledData::Property::Color: + case QV4::CompiledData::Property::Vector2D: + case QV4::CompiledData::Property::Vector3D: + case QV4::CompiledData::Property::Vector4D: + case QV4::CompiledData::Property::Matrix4x4: + case QV4::CompiledData::Property::Quaternion: + Q_ASSERT(fallbackMetaType != QMetaType::UnknownType); + if (QV4::MemberData *md = propertyAndMethodStorageAsMemberData()) { QV4::VariantObject *v = (md->data() + id)->as<QV4::VariantObject>(); if (!v) { *(md->data() + id) = cache->engine->newVariantObject(QVariant()); v = (md->data() + id)->as<QV4::VariantObject>(); - QQml_valueTypeProvider()->initValueType(t, v->d()->data); + QQml_valueTypeProvider()->initValueType(fallbackMetaType, v->d()->data); } - needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data); - QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data); + needActivate = !QQml_valueTypeProvider()->equalValueType(fallbackMetaType, a[0], v->d()->data); + QQml_valueTypeProvider()->writeValueType(fallbackMetaType, a[0], v->d()->data); } break; - } + case QV4::CompiledData::Property::Var: + Q_UNREACHABLE(); } } @@ -914,7 +964,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id) { - Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType); + Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var); QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) @@ -939,7 +989,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) { - Q_ASSERT((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType); + Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var); QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) @@ -979,7 +1029,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) { - if ((metaData->propertyData() + id)->propertyType == QQmlVMEMetaData::VarPropertyType) { + if (compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index cbb79f2d0c..2b1956ecfd 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -113,20 +113,8 @@ struct QQmlVMEMetaData } }; - enum { - VarPropertyType = -1 - }; - - struct PropertyData { - int propertyType; - }; - - PropertyData *propertyData() const { - return (PropertyData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData)); - } - AliasData *aliasData() const { - return (AliasData *)(propertyData() + propertyCount); + return (AliasData *)(((char *)const_cast<QQmlVMEMetaData *>(this)) + sizeof(QQmlVMEMetaData)); } }; @@ -189,7 +177,7 @@ class QQmlVMEMetaObjectEndpoint; class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject { public: - QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data); + QQmlVMEMetaObject(QObject *obj, QQmlPropertyCache *cache, const QQmlVMEMetaData *data, QV4::CompiledData::CompilationUnit *qmlCompilationUnit, int qmlObjectId); ~QQmlVMEMetaObject(); bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const; @@ -267,6 +255,11 @@ public: QList<QQmlVMEVariantQObjectPtr *> varObjectGuards; QQmlVMEVariantQObjectPtr *getQObjectGuardForProperty(int) const; + + // keep a reference to the compilation unit in order to still + // do property access when the context has been invalidated. + QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit; + const QV4::CompiledData::Object *compiledObject; }; QQmlVMEMetaObject *QQmlVMEMetaObject::get(QObject *obj) diff --git a/src/quick/designer/qqmldesignermetaobject.cpp b/src/quick/designer/qqmldesignermetaobject.cpp index 0bfa72e9d4..05794e262b 100644 --- a/src/quick/designer/qqmldesignermetaobject.cpp +++ b/src/quick/designer/qqmldesignermetaobject.cpp @@ -157,7 +157,7 @@ void QQmlDesignerMetaObject::init(QObject *object, QQmlEngine *engine) } QQmlDesignerMetaObject::QQmlDesignerMetaObject(QObject *object, QQmlEngine *engine) - : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object)), + : QQmlVMEMetaObject(object, cacheForObject(object, engine), vMEMetaDataForObject(object), /*qml compilation unit*/nullptr, /*qmlObjectId*/-1), m_context(engine->contextForObject(object)), m_data(new MetaPropertyData), m_cache(0) diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp index 974b2b0b9d..98a97ebd66 100644 --- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp +++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp @@ -4135,7 +4135,6 @@ void tst_qqmllanguage::dataAlignment() { QVERIFY(sizeof(QQmlVMEMetaData) % sizeof(int) == 0); QVERIFY(sizeof(QQmlVMEMetaData::AliasData) % sizeof(int) == 0); - QVERIFY(sizeof(QQmlVMEMetaData::PropertyData) % sizeof(int) == 0); } void tst_qqmllanguage::deleteSingletons() |