diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2018-07-20 15:41:29 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-07-31 07:28:47 +0000 |
commit | 2ee5331d8ae73c0abde129eb26df4ca000470007 (patch) | |
tree | 748ef5bdf37fce8c5d8acdc448ddb7ac430f11dd /src/qml/compiler | |
parent | fcf9b7efa5b2a0d8f49e59b2a977b8122632aff6 (diff) |
Shrink CompiledData::Binding by 8 bytes
Move the translation data out into a separately indexed table, which
allows to shrunk the value union down to 4 bytes, together with the
previous commit.
Saves ~4k with examples/quickcontrols/extras/flat/Content.qml and ~37K
RAM with the gallery.
Task-number: QTBUG-69588
Change-Id: Ia5016b072320ebb6b8fcfbb4dad128d53c901c74
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 8 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 16 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 23 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 15 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler_p.h | 3 |
5 files changed, 46 insertions, 19 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 1f6a702e4a..d5d7d6d6b0 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1120,6 +1120,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg } else { return; // first argument is not a string, stop } + translationData.stringIndex = jsGenerator->registerString(translation.toString()); args = args->next; @@ -1144,8 +1145,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg return; // too many arguments, stop binding->type = QV4::CompiledData::Binding::Type_Translation; - binding->stringIndex = jsGenerator->registerString(translation.toString()); - binding->value.translationData = translationData; + binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData); } else if (base == QLatin1String("qsTrId")) { QV4::CompiledData::TranslationData translationData; translationData.number = -1; @@ -1160,6 +1160,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg } else { return; // first argument is not a string, stop } + translationData.stringIndex = jsGenerator->registerString(id.toString()); args = args->next; @@ -1176,8 +1177,7 @@ void IRBuilder::tryGeneratingTranslationBinding(const QStringRef &base, AST::Arg return; // too many arguments, stop binding->type = QV4::CompiledData::Binding::Type_TranslationById; - binding->stringIndex = jsGenerator->registerString(id.toString()); - binding->value.translationData = translationData; + binding->value.translationDataIndex = jsGenerator->registerTranslation(translationData); } else if (base == QLatin1String("QT_TR_NOOP") || base == QLatin1String("QT_TRID_NOOP")) { if (!args || !args->expression) return; // no arguments, stop diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 3e3859d9fb..357c6fc04a 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -604,23 +604,25 @@ QString Binding::valueAsString(const CompilationUnit *unit) const #if !QT_CONFIG(translation) case Type_TranslationById: case Type_Translation: - return unit->stringAt(stringIndex); + return unit->stringAt(unit->unitData->translations()[value.translationDataIndex].stringIndex); #else case Type_TranslationById: { - QByteArray id = unit->stringAt(stringIndex).toUtf8(); - return qtTrId(id.constData(), value.translationData.number); + const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex]; + QByteArray id = unit->stringAt(translation.stringIndex).toUtf8(); + return qtTrId(id.constData(), translation.number); } case Type_Translation: { + const TranslationData &translation = unit->unitData()->translations()[value.translationDataIndex]; // This code must match that in the qsTr() implementation - const QString &path = unit->stringAt(unit->data->sourceFileIndex); + const QString &path = unit->stringAt(unit->unitData()->sourceFileIndex); int lastSlash = path.lastIndexOf(QLatin1Char('/')); QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5) : QStringRef(); QByteArray contextUtf8 = context.toUtf8(); - QByteArray comment = unit->stringAt(value.translationData.commentIndex).toUtf8(); - QByteArray text = unit->stringAt(stringIndex).toUtf8(); + QByteArray comment = unit->stringAt(translation.commentIndex).toUtf8(); + QByteArray text = unit->stringAt(translation.stringIndex).toUtf8(); return QCoreApplication::translate(contextUtf8.constData(), text.constData(), - comment.constData(), value.translationData.number); + comment.constData(), translation.number); } #endif default: diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 7bbc4d2835..20e8db528e 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -362,11 +362,14 @@ static_assert(sizeof(Class) == 24, "Class structure needs to have the expected s // Qml data structures -struct Q_QML_EXPORT TranslationData { +struct Q_QML_EXPORT TranslationData +{ + quint32_le stringIndex; quint32_le commentIndex; qint32_le number; + quint32_le padding; }; -static_assert(sizeof(TranslationData) == 8, "TranslationData 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(TranslationData) == 16, "TranslationData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Q_QML_PRIVATE_EXPORT Binding { @@ -407,15 +410,13 @@ struct Q_QML_PRIVATE_EXPORT Binding quint32_le constantValueIndex; quint32_le compiledScriptIndex; // used when Type_Script quint32_le objectIndex; - TranslationData translationData; // used when Type_Translation + quint32_le translationDataIndex; // used when Type_Translation } value; - quint32_le stringIndex; // Set for Type_String, Type_Translation and Type_Script (the latter because of script strings) + quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings) Location location; Location valueLocation; - quint32_le padding; - bool isValueBinding() const { if (type == Type_AttachedProperty @@ -490,7 +491,7 @@ struct Q_QML_PRIVATE_EXPORT Binding }; -static_assert(sizeof(Binding) == 32, "Binding 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(Binding) == 24, "Binding structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct EnumValue { @@ -799,6 +800,8 @@ struct Unit quint32_le offsetToConstantTable; quint32_le jsClassTableSize; quint32_le offsetToJSClassTable; + quint32_le translationTableSize; + quint32_le offsetToTranslationTable; qint32_le indexOfRootFunction; quint32_le sourceFileIndex; quint32_le finalUrlIndex; @@ -889,9 +892,13 @@ struct Unit *nMembers = klass->nMembers; return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass)); } + + const TranslationData *translations() const { + return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable); + } }; -static_assert(sizeof(Unit) == 208, "Unit 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(Unit) == 216, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct TypeReference { diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index a2afc7fefe..252056b2b6 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -208,6 +208,12 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(const QStringList &members) return jsClassOffsets.size() - 1; } +int QV4::Compiler::JSUnitGenerator::registerTranslation(const QV4::CompiledData::TranslationData &translation) +{ + translations.append(translation); + return translations.size() - 1; +} + QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorOption option) { registerString(module->fileName); @@ -286,6 +292,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO jsClassOffsetTable[i] = jsClassDataOffset + jsClassOffsets.at(i); } + memcpy(dataPtr + unit->offsetToTranslationTable, translations.constData(), translations.count() * sizeof(CompiledData::TranslationData)); + // write strings and string table if (option == GenerateWithStringTable) stringTable.serialize(unit); @@ -521,6 +529,12 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp nextOffset = (nextOffset + 7) & ~quint32(0x7); + unit.translationTableSize = translations.count(); + unit.offsetToTranslationTable = nextOffset; + nextOffset += unit.translationTableSize * sizeof(CompiledData::TranslationData); + + nextOffset = (nextOffset + 7) & ~quint32(0x7); + quint32 functionSize = 0; for (int i = 0; i < module->functions.size(); ++i) { @@ -575,6 +589,7 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp if (showStats) { qDebug() << "Generated JS unit that is" << unit.unitSize << "bytes contains:"; qDebug() << " " << functionSize << "bytes for non-code function data for" << unit.functionTableSize << "functions"; + qDebug() << " " << translations.count() * sizeof(CompiledData::TranslationData) << "bytes for" << translations.count() << "translations"; } return unit; diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index 944c44b1ff..381b6fad21 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -120,6 +120,8 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator { int registerJSClass(const QStringList &members); + int registerTranslation(const CompiledData::TranslationData &translation); + enum GeneratorOption { GenerateWithStringTable, GenerateWithoutStringTable @@ -142,6 +144,7 @@ private: QVector<ReturnedValue> constants; QByteArray jsClassData; QVector<int> jsClassOffsets; + QVector<CompiledData::TranslationData> translations; }; } |