From e203418096e66f2173d05788e5cb18e79141e772 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 4 Jul 2019 14:43:10 +0200 Subject: Reduce the size of Property fields in type compilation data We can shave off 4 bytes of each property declaration by sharing the bits for the custom type name index or the builtin type enum. Change-Id: I77071cbef66c5a83b3e7e281dba3a435d3c68b39 Reviewed-by: Ulf Hermann --- src/qml/compiler/qqmlirbuilder.cpp | 25 ++++++---------- src/qml/compiler/qv4compileddata_p.h | 31 ++++++++++++++----- src/qml/qml/qqmlpropertycachecreator.cpp | 3 +- src/qml/qml/qqmlpropertycachecreator_p.h | 40 +++++++++++++------------ src/qml/qml/qqmlvmemetaobject.cpp | 51 ++++++++++++++++---------------- 5 files changed, 81 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 8bdbab3b5a..6c61473418 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -872,13 +872,15 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node) } else { const QStringRef &name = node->name; + Property *property = New(); + property->isReadOnly = node->isReadonlyMember; + bool typeFound = false; - QV4::CompiledData::Property::Type type = QV4::CompiledData::Property::Var; for (int ii = 0; !typeFound && ii < propTypeNameToTypesCount; ++ii) { const TypeNameToType *t = propTypeNameToTypes + ii; if (memberType == QLatin1String(t->name, static_cast(t->nameLength))) { - type = t->type; + property->setBuiltinType(t->type); typeFound = true; } } @@ -886,11 +888,10 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node) if (!typeFound && memberType.at(0).isUpper()) { const QStringRef &typeModifier = node->typeModifier; - if (typeModifier.isEmpty()) { - type = QV4::CompiledData::Property::Custom; - } else if (typeModifier == QLatin1String("list")) { - type = QV4::CompiledData::Property::CustomList; - } else { + property->setCustomType(registerString(memberType)); + if (typeModifier == QLatin1String("list")) { + property->isList = true; + } else if (!typeModifier.isEmpty()) { recordError(node->typeModifierToken, QCoreApplication::translate("QQmlParser","Invalid property type modifier")); return false; } @@ -905,14 +906,6 @@ bool IRBuilder::visit(QQmlJS::AST::UiPublicMember *node) return false; } - Property *property = New(); - property->isReadOnly = node->isReadonlyMember; - property->type = type; - if (type >= QV4::CompiledData::Property::Custom) - property->customTypeNameIndex = registerString(memberType); - else - property->customTypeNameIndex = emptyStringIndex; - const QString propName = name.toString(); property->nameIndex = registerString(propName); @@ -1530,7 +1523,7 @@ bool IRBuilder::isStatementNodeScript(QQmlJS::AST::Statement *statement) bool IRBuilder::isRedundantNullInitializerForPropertyDeclaration(Property *property, QQmlJS::AST::Statement *statement) { - if (property->type != QV4::CompiledData::Property::Custom) + if (property->isBuiltinType || property->isList) return false; QQmlJS::AST::ExpressionStatement *exprStmt = QQmlJS::AST::cast(statement); if (!exprStmt) diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 9123f9f0ec..639595509a 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -642,18 +642,35 @@ struct Property { enum Type : unsigned int { Var = 0, Variant, Int, Bool, Real, String, Url, Color, Font, Time, Date, DateTime, Rect, Point, Size, - Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion, - Custom, CustomList }; + Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion, InvalidBuiltin }; quint32_le nameIndex; union { - quint32_le_bitfield<0, 31> type; + quint32_le_bitfield<0, 29> builtinTypeOrTypeNameIndex; + quint32_le_bitfield<29, 1> isBuiltinType; + quint32_le_bitfield<30, 1> isList; quint32_le_bitfield<31, 1> isReadOnly; }; - quint32_le customTypeNameIndex; // If type >= Custom + Location location; + + void setBuiltinType(Type t) + { + builtinTypeOrTypeNameIndex = t; + isBuiltinType = true; + } + Type builtinType() const { + if (isBuiltinType) + return static_cast(quint32(builtinTypeOrTypeNameIndex)); + return InvalidBuiltin; + } + void setCustomType(int nameIndex) + { + builtinTypeOrTypeNameIndex = nameIndex; + isBuiltinType = false; + } }; -static_assert(sizeof(Property) == 16, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Property) == 12, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Alias { enum Flags : unsigned int { @@ -1044,8 +1061,8 @@ struct TypeReferenceMap : QHash auto prop = obj->propertiesBegin(); auto propEnd = obj->propertiesEnd(); for ( ; prop != propEnd; ++prop) { - if (prop->type >= QV4::CompiledData::Property::Custom) { - TypeReference &r = this->add(prop->customTypeNameIndex, prop->location); + if (!prop->isBuiltinType) { + TypeReference &r = this->add(prop->builtinTypeOrTypeNameIndex, prop->location); r.errorWhenNotFound = true; } } diff --git a/src/qml/qml/qqmlpropertycachecreator.cpp b/src/qml/qml/qqmlpropertycachecreator.cpp index 822241d58c..6e492f7a80 100644 --- a/src/qml/qml/qqmlpropertycachecreator.cpp +++ b/src/qml/qml/qqmlpropertycachecreator.cpp @@ -69,8 +69,7 @@ int QQmlPropertyCacheCreatorBase::metaTypeForPropertyType(QV4::CompiledData::Pro case QV4::CompiledData::Property::Vector4D: return QMetaType::QVector4D; case QV4::CompiledData::Property::Matrix4x4: return QMetaType::QMatrix4x4; case QV4::CompiledData::Property::Quaternion: return QMetaType::QQuaternion; - case QV4::CompiledData::Property::Custom: break; - case QV4::CompiledData::Property::CustomList: break; + case QV4::CompiledData::Property::InvalidBuiltin: break; }; return QMetaType::UnknownType; } diff --git a/src/qml/qml/qqmlpropertycachecreator_p.h b/src/qml/qml/qqmlpropertycachecreator_p.h index e227301175..5421e2c61b 100644 --- a/src/qml/qml/qqmlpropertycachecreator_p.h +++ b/src/qml/qml/qqmlpropertycachecreator_p.h @@ -304,7 +304,7 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator::crea auto p = obj->propertiesBegin(); auto pend = obj->propertiesEnd(); for ( ; p != pend; ++p) { - if (p->type == QV4::CompiledData::Property::Var) + if (p->builtinType() == QV4::CompiledData::Property::Var) varPropCount++; bool notInRevision = false; @@ -477,20 +477,22 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator::crea int propertTypeMinorVersion = 0; QQmlPropertyData::Flags propertyFlags; - if (p->type == QV4::CompiledData::Property::Var) { - propertyType = QMetaType::QVariant; + const QV4::CompiledData::Property::Type type = p->builtinType(); + + if (type == QV4::CompiledData::Property::Var) propertyFlags.type = QQmlPropertyData::Flags::VarPropertyType; - } else if (p->type < QV4::CompiledData::Property::Custom) { - propertyType = metaTypeForPropertyType(static_cast(quint32(p->type))); - if (p->type == QV4::CompiledData::Property::Variant) + + if (type != QV4::CompiledData::Property::InvalidBuiltin) { + propertyType = metaTypeForPropertyType(type); + + if (type == QV4::CompiledData::Property::Variant) propertyFlags.type = QQmlPropertyData::Flags::QVariantType; } else { - Q_ASSERT(p->type == QV4::CompiledData::Property::CustomList || - p->type == QV4::CompiledData::Property::Custom); + Q_ASSERT(!p->isBuiltinType); QQmlType qmltype; - if (!imports->resolveType(stringAt(p->customTypeNameIndex), &qmltype, nullptr, nullptr, nullptr)) { + if (!imports->resolveType(stringAt(p->builtinTypeOrTypeNameIndex), &qmltype, nullptr, nullptr, nullptr)) { return qQmlCompileError(p->location, QQmlPropertyCacheCreatorBase::tr("Invalid property type")); } @@ -502,27 +504,27 @@ inline QQmlJS::DiagnosticMessage QQmlPropertyCacheCreator::crea auto compilationUnit = tdata->compilationUnit(); - if (p->type == QV4::CompiledData::Property::Custom) { - propertyType = compilationUnit->metaTypeId; - } else { + if (p->isList) { propertyType = compilationUnit->listMetaTypeId; + } else { + propertyType = compilationUnit->metaTypeId; } } else { - if (p->type == QV4::CompiledData::Property::Custom) { + if (p->isList) { + propertyType = qmltype.qListTypeId(); + } else { propertyType = qmltype.typeId(); propertTypeMinorVersion = qmltype.minorVersion(); - } else { - propertyType = qmltype.qListTypeId(); } } - if (p->type == QV4::CompiledData::Property::Custom) - propertyFlags.type = QQmlPropertyData::Flags::QObjectDerivedType; - else + if (p->isList) propertyFlags.type = QQmlPropertyData::Flags::QListType; + else + propertyFlags.type = QQmlPropertyData::Flags::QObjectDerivedType; } - if (!p->isReadOnly && p->type != QV4::CompiledData::Property::CustomList) + if (!p->isReadOnly && !p->isList) propertyFlags.isWritable = true; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index e26dc4d9aa..d210b049df 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -639,7 +639,8 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * id -= propOffset(); if (id < propertyCount) { - const QV4::CompiledData::Property::Type t = static_cast(qint32(compiledObject->propertyTable()[id].type)); + const QV4::CompiledData::Property &property = compiledObject->propertyTable()[id]; + const QV4::CompiledData::Property::Type t = property.builtinType(); // the context can be null if accessing var properties from cpp after re-parenting an item. QQmlEnginePrivate *ep = (ctxt == nullptr || ctxt->engine == nullptr) ? nullptr : QQmlEnginePrivate::get(ctxt->engine); @@ -678,22 +679,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * case QV4::CompiledData::Property::Point: *reinterpret_cast(a[0]) = readPropertyAsPointF(id); break; - case QV4::CompiledData::Property::Custom: - *reinterpret_cast(a[0]) = readPropertyAsQObject(id); - break; case QV4::CompiledData::Property::Variant: *reinterpret_cast(a[0]) = readPropertyAsVariant(id); break; - case QV4::CompiledData::Property::CustomList: { - QList *list = readPropertyAsList(id); - QQmlListProperty *p = static_cast *>(a[0]); - *p = QQmlListProperty(object, list, - list_append, list_count, list_at, - list_clear); - p->dummy1 = this; - p->dummy2 = reinterpret_cast(quintptr(methodOffset() + id)); - break; - } case QV4::CompiledData::Property::Font: case QV4::CompiledData::Property::Time: case QV4::CompiledData::Property::Color: @@ -718,6 +706,18 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * *reinterpret_cast(a[0]) = QVariant(); } break; + case QV4::CompiledData::Property::InvalidBuiltin: + if (property.isList) { + QList *list = readPropertyAsList(id); + QQmlListProperty *p = static_cast *>(a[0]); + *p = QQmlListProperty(object, list, + list_append, list_count, list_at, + list_clear); + p->dummy1 = this; + p->dummy2 = reinterpret_cast(quintptr(methodOffset() + id)); + } else { + *reinterpret_cast(a[0]) = readPropertyAsQObject(id); + } } } else if (c == QMetaObject::WriteProperty) { @@ -763,17 +763,9 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * needActivate = *reinterpret_cast(a[0]) != readPropertyAsPointF(id); writeProperty(id, *reinterpret_cast(a[0])); break; - case QV4::CompiledData::Property::Custom: - needActivate = *reinterpret_cast(a[0]) != readPropertyAsQObject(id); - writeProperty(id, *reinterpret_cast(a[0])); - break; case QV4::CompiledData::Property::Variant: writeProperty(id, *reinterpret_cast(a[0])); break; - 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: @@ -798,6 +790,15 @@ int QQmlVMEMetaObject::metaCall(QObject *o, QMetaObject::Call c, int _id, void * if (ep) writeProperty(id, *reinterpret_cast(a[0])); break; + case QV4::CompiledData::Property::InvalidBuiltin: + if (property.isList) { + // Writing such a property is not supported. Content is added through the list property + // methods. + } else { + needActivate = *reinterpret_cast(a[0]) != readPropertyAsQObject(id); + writeProperty(id, *reinterpret_cast(a[0])); + } + } if (needActivate) @@ -965,7 +966,7 @@ QV4::ReturnedValue QQmlVMEMetaObject::method(int index) const QV4::ReturnedValue QQmlVMEMetaObject::readVarProperty(int id) const { - Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var); + Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].builtinType() == QV4::CompiledData::Property::Var); QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (md) @@ -990,7 +991,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id) const void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) { - Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var); + Q_ASSERT(compiledObject && compiledObject->propertyTable()[id].builtinType() == QV4::CompiledData::Property::Var); QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) @@ -1030,7 +1031,7 @@ void QQmlVMEMetaObject::writeVarProperty(int id, const QV4::Value &value) void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) { - if (compiledObject && compiledObject->propertyTable()[id].type == QV4::CompiledData::Property::Var) { + if (compiledObject && compiledObject->propertyTable()[id].builtinType() == QV4::CompiledData::Property::Var) { QV4::MemberData *md = propertyAndMethodStorageAsMemberData(); if (!md) return; -- cgit v1.2.3