From: Simon Hausmann Date: Thu, 27 Mar 2014 16:07:06 +0000 (+0100) Subject: Various cleanups X-Git-Tag: upstream/5.2.95+rc1^2~81 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0ed744c1ef955cdb94cbd89c58283663da490d7d;p=platform%2Fupstream%2Fqtdeclarative.git Various cleanups * Encapsulate the string pooling for the V4 data generation into a StringGenerator class. * Move type reference collection into the IR::Document, where it belongs (as it writes into the typeReferences there) * const fixes * Remove unused methods and members * Store unit and qml unit sizes right in the generated data structure. That makes copying easier (like we do when generating the QML data based on the JS fields) Change-Id: I053146ab0b00cc90ac7f72f867415962d1be121b Reviewed-by: Lars Knoll --- diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index bd0aedf08..e85703e9a 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -188,12 +188,12 @@ void Object::insertSorted(Binding *b) bindings->insertAfter(insertionPoint, b); } -QStringList Signal::parameterStringList(const QStringList &stringPool) const +QStringList Signal::parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const { QStringList result; result.reserve(parameters->count); for (SignalParameter *param = parameters->first; param; param = param->next) - result << stringPool.at(param->nameIndex); + result << stringPool->stringForIndex(param->nameIndex); return result; } @@ -259,6 +259,32 @@ static inline bool isUriToken(int token) return false; } +void Document::collectTypeReferences() +{ + foreach (Object *obj, objects) { + if (obj->inheritedTypeNameIndex != emptyStringIndex) { + QV4::CompiledData::TypeReference &r = typeReferences.add(obj->inheritedTypeNameIndex, obj->location); + r.needsCreation = true; + r.errorWhenNotFound = true; + } + + for (const Property *prop = obj->firstProperty(); prop; prop = prop->next) { + if (prop->type >= QV4::CompiledData::Property::Custom) { + // ### FIXME: We could report the more accurate location here by using prop->location, but the old + // compiler can't and the tests expect it to be the object location right now. + QV4::CompiledData::TypeReference &r = typeReferences.add(prop->customTypeNameIndex, obj->location); + r.needsCreation = true; + r.errorWhenNotFound = true; + } + } + + for (const Binding *binding = obj->firstBinding(); binding; binding = binding->next) { + if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) + typeReferences.add(binding->propertyNameIndex, binding->location); + } + } +} + void Document::extractScriptMetaData(QString &script, QQmlError *error) { Q_ASSERT(error); @@ -504,6 +530,15 @@ void Document::removeScriptPragmas(QString &script) } } +Document::Document(bool debugMode) + : jsModule(debugMode) + , program(0) + , jsGenerator(&jsModule, sizeof(QV4::CompiledData::QmlUnit)) + , unitFlags(0) + , javaScriptCompilationUnit(0) +{ +} + IRBuilder::IRBuilder(const QSet &illegalNames) : illegalNames(illegalNames) , _object(0) @@ -546,7 +581,6 @@ bool IRBuilder::generateFromQml(const QString &code, const QUrl &url, const QStr qSwap(_imports, output->imports); qSwap(_pragmas, output->pragmas); qSwap(_objects, output->objects); - qSwap(_typeReferences, output->typeReferences); this->pool = output->jsParserEngine.pool(); this->jsGenerator = &output->jsGenerator; @@ -565,13 +599,11 @@ bool IRBuilder::generateFromQml(const QString &code, const QUrl &url, const QStr QQmlJS::AST::UiObjectDefinition *rootObject = QQmlJS::AST::cast(program->members->member); Q_ASSERT(rootObject); - if (defineQMLObject(&output->indexOfRootObject, rootObject)) - collectTypeReferences(); + defineQMLObject(&output->indexOfRootObject, rootObject); qSwap(_imports, output->imports); qSwap(_pragmas, output->pragmas); qSwap(_objects, output->objects); - qSwap(_typeReferences, output->typeReferences); return errors.isEmpty(); } @@ -789,10 +821,10 @@ bool IRBuilder::visit(QQmlJS::AST::UiImport *node) // Check for script qualifier clashes bool isScript = import->type == QV4::CompiledData::Import::ImportScript; for (int ii = 0; ii < _imports.count(); ++ii) { - QV4::CompiledData::Import *other = _imports.at(ii); + const QV4::CompiledData::Import *other = _imports.at(ii); bool otherIsScript = other->type == QV4::CompiledData::Import::ImportScript; - if ((isScript || otherIsScript) && qualifier == jsGenerator->strings.at(other->qualifierIndex)) { + if ((isScript || otherIsScript) && qualifier == jsGenerator->stringForIndex(other->qualifierIndex)) { recordError(node->importIdToken, QCoreApplication::translate("QQmlParser","Script import qualifiers must be unique.")); return false; } @@ -1372,7 +1404,7 @@ bool IRBuilder::resolveQualifiedId(QQmlJS::AST::UiQualifiedId **nameToResolve, O // If it's a namespace, prepend the qualifier and we'll resolve it later to the correct type. QString currentName = qualifiedIdElement->name.toString(); if (qualifiedIdElement->next) { - foreach (QV4::CompiledData::Import* import, _imports) + foreach (const QV4::CompiledData::Import* import, _imports) if (import->qualifierIndex != emptyStringIndex && stringAt(import->qualifierIndex) == currentName) { qualifiedIdElement = qualifiedIdElement->next; @@ -1451,32 +1483,6 @@ void IRBuilder::recordError(const QQmlJS::AST::SourceLocation &location, const Q errors << error; } -void IRBuilder::collectTypeReferences() -{ - foreach (Object *obj, _objects) { - if (obj->inheritedTypeNameIndex != emptyStringIndex) { - QV4::CompiledData::TypeReference &r = _typeReferences.add(obj->inheritedTypeNameIndex, obj->location); - r.needsCreation = true; - r.errorWhenNotFound = true; - } - - for (const Property *prop = obj->firstProperty(); prop; prop = prop->next) { - if (prop->type >= QV4::CompiledData::Property::Custom) { - // ### FIXME: We could report the more accurate location here by using prop->location, but the old - // compiler can't and the tests expect it to be the object location right now. - QV4::CompiledData::TypeReference &r = _typeReferences.add(prop->customTypeNameIndex, obj->location); - r.needsCreation = true; - r.errorWhenNotFound = true; - } - } - - for (const Binding *binding = obj->firstBinding(); binding; binding = binding->next) { - if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) - _typeReferences.add(binding->propertyNameIndex, binding->location); - } - } -} - bool IRBuilder::isStatementNodeScript(QQmlJS::AST::Statement *statement) { if (QQmlJS::AST::ExpressionStatement *stmt = QQmlJS::AST::cast(statement)) { @@ -1502,11 +1508,11 @@ bool IRBuilder::isStatementNodeScript(QQmlJS::AST::Statement *statement) return true; } -QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(Document &output, int *totalUnitSizeInBytes) +QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(Document &output) { - jsUnitGenerator = &output.jsGenerator; - int unitSize = 0; - QV4::CompiledData::Unit *jsUnit = jsUnitGenerator->generateUnit(&unitSize); + QV4::CompiledData::CompilationUnit *compilationUnit = output.javaScriptCompilationUnit; + QV4::CompiledData::Unit *jsUnit = compilationUnit->createUnitData(&output); + const uint unitSize = jsUnit->unitSize; const int importSize = sizeof(QV4::CompiledData::Import) * output.imports.count(); const int objectOffsetTableSize = output.objects.count() * sizeof(quint32); @@ -1526,14 +1532,14 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(Document &output, int *to } const int totalSize = unitSize + importSize + objectOffsetTableSize + objectsSize; - if (totalUnitSizeInBytes) - *totalUnitSizeInBytes = totalSize; char *data = (char*)malloc(totalSize); memcpy(data, jsUnit, unitSize); - free(jsUnit); + if (jsUnit != compilationUnit->data) + free(jsUnit); jsUnit = 0; QV4::CompiledData::QmlUnit *qmlUnit = reinterpret_cast(data); + qmlUnit->qmlUnitSize = totalSize; qmlUnit->header.flags |= output.unitFlags; qmlUnit->header.flags |= QV4::CompiledData::Unit::IsQml; qmlUnit->offsetToImports = unitSize; @@ -1544,7 +1550,7 @@ QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(Document &output, int *to // write imports char *importPtr = data + qmlUnit->offsetToImports; - foreach (QV4::CompiledData::Import *imp, output.imports) { + foreach (const QV4::CompiledData::Import *imp, output.imports) { QV4::CompiledData::Import *importToWrite = reinterpret_cast(importPtr); *importToWrite = *imp; importPtr += sizeof(QV4::CompiledData::Import); @@ -1649,13 +1655,8 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter return bindingPtr; } -int QmlUnitGenerator::getStringId(const QString &str) const -{ - return jsUnitGenerator->getStringId(str); -} - JSCodeGen::JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, - QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, const QStringList &stringPool) + QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool) : QQmlJS::Codegen(/*strict mode*/false) , sourceCode(sourceCode) , jsEngine(jsEngine) @@ -1723,7 +1724,7 @@ QVector JSCodeGen::generateJSCodeForFunctionsAndBindings(const QListname.toString(); else if (qmlFunction.nameIndex != 0) - name = stringPool.value(qmlFunction.nameIndex); + name = stringPool->stringForIndex(qmlFunction.nameIndex); else name = QStringLiteral("%qml-expression-entry"); diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index a34529067..cd67c52ed 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -60,6 +60,9 @@ class QQmlTypeNameCache; namespace QmlIR { +struct Document; +struct IRLoader; + template struct PoolList { @@ -199,7 +202,7 @@ struct Signal QV4::CompiledData::Location location; PoolList *parameters; - QStringList parameterStringList(const QStringList &stringPool) const; + QStringList parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const; Signal *next; }; @@ -285,6 +288,8 @@ public: FixedPoolArray *runtimeFunctionIndices; private: + friend struct IRLoader; + PoolList *properties; PoolList *qmlSignals; PoolList *bindings; @@ -303,15 +308,11 @@ struct Q_QML_EXPORT Pragma struct Q_QML_EXPORT Document { - Document(bool debugMode) - : jsModule(debugMode) - , jsGenerator(&jsModule, sizeof(QV4::CompiledData::QmlUnit)) - , unitFlags(0) - {} + Document(bool debugMode); QString code; QQmlJS::Engine jsParserEngine; QV4::IR::Module jsModule; - QList imports; + QList imports; QList pragmas; QQmlJS::AST::UiProgram *program; int indexOfRootObject; @@ -319,10 +320,14 @@ struct Q_QML_EXPORT Document QV4::Compiler::JSUnitGenerator jsGenerator; quint32 unitFlags; + QV4::CompiledData::CompilationUnit *javaScriptCompilationUnit; + QHash extraSignalParameters; + QV4::CompiledData::TypeReferenceMap typeReferences; + void collectTypeReferences(); int registerString(const QString &str) { return jsGenerator.registerString(str); } - QString stringAt(int index) const { return jsGenerator.strings.value(index); } + QString stringAt(int index) const { return jsGenerator.stringForIndex(index); } void extractScriptMetaData(QString &script, QQmlError *error); static void removeScriptPragmas(QString &script); @@ -388,12 +393,10 @@ public: void recordError(const QQmlJS::AST::SourceLocation &location, const QString &description); - void collectTypeReferences(); - quint32 registerString(const QString &str) const { return jsGenerator->registerString(str); } template _Tp *New() { return pool->New<_Tp>(); } - QString stringAt(int index) const { return jsGenerator->strings.at(index); } + QString stringAt(int index) const { return jsGenerator->stringForIndex(index); } static bool isStatementNodeScript(QQmlJS::AST::Statement *statement); @@ -401,7 +404,7 @@ public: QSet illegalNames; - QList _imports; + QList _imports; QList _pragmas; QList _objects; @@ -418,20 +421,11 @@ public: struct Q_QML_EXPORT QmlUnitGenerator { - QmlUnitGenerator() - : jsUnitGenerator(0) - { - } - - QV4::CompiledData::QmlUnit *generate(Document &output, int *totalUnitSizeInBytes = 0); + QV4::CompiledData::QmlUnit *generate(Document &output); private: typedef bool (Binding::*BindingFilter)() const; char *writeBindings(char *bindingPtr, Object *o, BindingFilter filter) const; - - int getStringId(const QString &str) const; - - QV4::Compiler::JSUnitGenerator *jsUnitGenerator; }; struct Q_QML_EXPORT PropertyResolver @@ -457,7 +451,7 @@ struct Q_QML_EXPORT JSCodeGen : public QQmlJS::Codegen { JSCodeGen(const QString &fileName, const QString &sourceCode, QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, - const QStringList &stringPool); + const QV4::Compiler::StringTableGenerator *stringPool); struct IdMapping { @@ -484,7 +478,7 @@ private: QQmlJS::Engine *jsEngine; // needed for memory pool QQmlJS::AST::UiProgram *qmlRoot; QQmlTypeNameCache *imports; - const QStringList &stringPool; + const QV4::Compiler::StringTableGenerator *stringPool; bool _disableAcceleratedLookups; ObjectIdMapping _idObjects; diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 26f6e0b74..224bd2389 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -202,37 +202,32 @@ bool QQmlTypeCompiler::compile() } // Compile JS binding expressions and signal handlers - { - QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, compiledData->importCache, document->jsGenerator.strings); + if (!document->javaScriptCompilationUnit) { + QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, compiledData->importCache, &document->jsGenerator.stringTable); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return false; - } - { QQmlJavaScriptBindingExpressionSimplificationPass pass(this); pass.reduceTranslationBindings(); - } - QV4::ExecutionEngine *v4 = engine->v4engine(); - - QScopedPointer isel(v4->iselFactory->create(engine, v4->executableAllocator, &document->jsModule, &document->jsGenerator)); - isel->setUseFastLookups(false); - QV4::CompiledData::CompilationUnit *jsUnit = isel->compile(/*generated unit data*/false); + QV4::ExecutionEngine *v4 = engine->v4engine(); + QScopedPointer isel(v4->iselFactory->create(engine, v4->executableAllocator, &document->jsModule, &document->jsGenerator)); + isel->setUseFastLookups(false); + document->javaScriptCompilationUnit = isel->compile(/*generated unit data*/false); + } // Generate QML compiled type data structures QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(*document); - if (jsUnit) { - Q_ASSERT(!jsUnit->data); - Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header); - // The js unit owns the data and will free the qml unit. - jsUnit->data = &qmlUnit->header; - } + Q_ASSERT(document->javaScriptCompilationUnit); + Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header); + // The js unit owns the data and will free the qml unit. + document->javaScriptCompilationUnit->data = &qmlUnit->header; - compiledData->compilationUnit = jsUnit; + compiledData->compilationUnit = document->javaScriptCompilationUnit; if (compiledData->compilationUnit) compiledData->compilationUnit->ref(); compiledData->qmlUnit = qmlUnit; // ownership transferred to m_compiledData @@ -383,9 +378,9 @@ QStringRef QQmlTypeCompiler::newStringRef(const QString &string) return document->jsParserEngine.newStringRef(string); } -const QStringList &QQmlTypeCompiler::stringPool() const +const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const { - return document->jsGenerator.strings; + return &document->jsGenerator.stringTable; } void QQmlTypeCompiler::setCustomParserBindings(const QVector &bindings) diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h index e21c13c5d..ca84cee1f 100644 --- a/src/qml/compiler/qqmltypecompiler_p.h +++ b/src/qml/compiler/qqmltypecompiler_p.h @@ -99,7 +99,7 @@ public: QHash *customParserData(); QQmlJS::MemoryPool *memoryPool(); QStringRef newStringRef(const QString &string); - const QStringList &stringPool() const; + const QV4::Compiler::StringTableGenerator *stringPool() const; void setCustomParserBindings(const QVector &bindings); void setDeferredBindingsPerObject(const QHash &deferredBindingsPerObject); diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 2220fd5de..56497ed8a 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -180,6 +181,11 @@ void CompilationUnit::markObjects(QV4::ExecutionEngine *e) } } +Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) +{ + return irDocument->jsGenerator.generateUnit(); +} + QString Binding::valueAsString(const Unit *unit) const { switch (type) { diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 474d4c88b..d6d2419d7 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -50,6 +50,10 @@ QT_BEGIN_NAMESPACE +namespace QmlIR { +struct Document; +} + namespace QV4 { namespace IR { struct Function; @@ -163,6 +167,7 @@ struct Unit char magic[8]; qint16 architecture; qint16 version; + quint32 unitSize; // Size of the Unit and any depending data. Does _not_ include size of data needed by QmlUnit. enum { IsJavascript = 0x1, @@ -198,8 +203,10 @@ struct Unit return QString(qstr.constData(), qstr.length()); } + const uint *functionOffsetTable() const { return reinterpret_cast((reinterpret_cast(this)) + offsetToFunctionTable); } + const Function *functionAt(int idx) const { - const uint *offsetTable = reinterpret_cast((reinterpret_cast(this)) + offsetToFunctionTable); + const uint *offsetTable = functionOffsetTable(); const uint offset = offsetTable[idx]; return reinterpret_cast(reinterpret_cast(this) + offset); } @@ -524,6 +531,7 @@ struct Import struct QmlUnit { Unit header; + quint32 qmlUnitSize; // size including header and all surrounding data. quint32 nImports; quint32 offsetToImports; quint32 nObjects; @@ -578,16 +586,15 @@ struct Q_QML_EXPORT CompilationUnit QV4::Value *runtimeRegularExpressions; QV4::InternalClass **runtimeClasses; QVector runtimeFunctions; -// QVector runtimeFunctionsSortedByAddress; + + // Called only when building QML, when we build the header for JS first and append QML data + virtual QV4::CompiledData::Unit *createUnitData(QmlIR::Document *irDocument); QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); void unlink(); virtual QV4::ExecutableAllocator::ChunkOfPages *chunkForFunction(int /*functionIndex*/) { return 0; } - // ### runtime data - // pointer to qml data for QML unit - void markObjects(QV4::ExecutionEngine *e); protected: diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index f25b1900c..0338bf184 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -45,19 +45,12 @@ #include #include -QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QV4::IR::Module *module, int headerSize) - : irModule(module) - , stringDataSize(0) - , jsClassDataSize(0) +QV4::Compiler::StringTableGenerator::StringTableGenerator() { - if (headerSize == -1) - headerSize = sizeof(QV4::CompiledData::Unit); - this->headerSize = headerSize; - // Make sure the empty string always gets index 0 - registerString(QString()); + clear(); } -int QV4::Compiler::JSUnitGenerator::registerString(const QString &str) +int QV4::Compiler::StringTableGenerator::registerString(const QString &str) { QHash::ConstIterator it = stringToId.find(str); if (it != stringToId.end()) @@ -68,12 +61,50 @@ int QV4::Compiler::JSUnitGenerator::registerString(const QString &str) return strings.size() - 1; } -int QV4::Compiler::JSUnitGenerator::getStringId(const QString &string) const +int QV4::Compiler::StringTableGenerator::getStringId(const QString &string) const { Q_ASSERT(stringToId.contains(string)); return stringToId.value(string); } +void QV4::Compiler::StringTableGenerator::clear() +{ + strings.clear(); + stringToId.clear(); + stringDataSize = 0; +} + +void QV4::Compiler::StringTableGenerator::serialize(uint *stringTable, char *dataStart, char *stringData) +{ + for (int i = 0; i < strings.size(); ++i) { + stringTable[i] = stringData - dataStart; + const QString &qstr = strings.at(i); + + QV4::CompiledData::String *s = (QV4::CompiledData::String*)(stringData); + s->hash = QV4::String::createHashValue(qstr.constData(), qstr.length()); + s->flags = 0; // ### + s->str.ref.atomic.store(-1); + s->str.size = qstr.length(); + s->str.alloc = 0; + s->str.capacityReserved = false; + s->str.offset = sizeof(QArrayData); + memcpy(s + 1, qstr.constData(), (qstr.length() + 1)*sizeof(ushort)); + + stringData += QV4::CompiledData::String::calculateSize(qstr); + } +} + +QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QV4::IR::Module *module, int headerSize) + : irModule(module) + , jsClassDataSize(0) +{ + if (headerSize == -1) + headerSize = sizeof(QV4::CompiledData::Unit); + this->headerSize = headerSize; + // Make sure the empty string always gets index 0 + registerString(QString()); +} + uint QV4::Compiler::JSUnitGenerator::registerIndexedGetterLookup() { CompiledData::Lookup l; @@ -175,7 +206,7 @@ int QV4::Compiler::JSUnitGenerator::registerJSClass(int count, IR::ExprList *arg return jsClasses.size() - 1; } -QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *totalUnitSize) +QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit() { registerString(irModule->fileName); foreach (QV4::IR::Function *f, irModule->functions) { @@ -186,22 +217,20 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total registerString(*f->locals.at(i)); } - int unitSize = QV4::CompiledData::Unit::calculateSize(headerSize, strings.size(), irModule->functions.size(), regexps.size(), + int unitSize = QV4::CompiledData::Unit::calculateSize(headerSize, stringTable.stringCount(), irModule->functions.size(), regexps.size(), constants.size(), lookups.size(), jsClasses.count()); uint functionDataSize = 0; for (int i = 0; i < irModule->functions.size(); ++i) { QV4::IR::Function *f = irModule->functions.at(i); - functionOffsets.insert(f, functionDataSize + unitSize + stringDataSize); + functionOffsets.insert(f, functionDataSize + unitSize + stringTable.dataSize()); const int qmlIdDepsCount = f->idObjectDependencies.count(); const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count(); functionDataSize += QV4::CompiledData::Function::calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size(), qmlIdDepsCount, qmlPropertyDepsCount); } - const int totalSize = unitSize + functionDataSize + stringDataSize + jsClassDataSize; - if (totalUnitSize) - *totalUnitSize = totalSize; + const int totalSize = unitSize + functionDataSize + stringTable.dataSize() + jsClassDataSize; char *data = (char *)malloc(totalSize); memset(data, 0, totalSize); QV4::CompiledData::Unit *unit = (QV4::CompiledData::Unit*)data; @@ -210,7 +239,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total unit->architecture = 0; // ### unit->flags = QV4::CompiledData::Unit::IsJavascript; unit->version = 1; - unit->stringTableSize = strings.size(); + unit->unitSize = totalSize; + unit->stringTableSize = stringTable.stringCount(); unit->offsetToStringTable = headerSize; unit->functionTableSize = irModule->functions.size(); unit->offsetToFunctionTable = unit->offsetToStringTable + unit->stringTableSize * sizeof(uint); @@ -226,30 +256,17 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total unit->sourceFileIndex = getStringId(irModule->fileName); // write strings and string table - uint *stringTable = (uint *)(data + unit->offsetToStringTable); - char *string = data + unitSize; - for (int i = 0; i < strings.size(); ++i) { - stringTable[i] = string - data; - const QString &qstr = strings.at(i); - - QV4::CompiledData::String *s = (QV4::CompiledData::String*)(string); - s->hash = QV4::String::createHashValue(qstr.constData(), qstr.length()); - s->flags = 0; // ### - s->str.ref.atomic.store(-1); - s->str.size = qstr.length(); - s->str.alloc = 0; - s->str.capacityReserved = false; - s->str.offset = sizeof(QArrayData); - memcpy(s + 1, qstr.constData(), (qstr.length() + 1)*sizeof(ushort)); - - string += QV4::CompiledData::String::calculateSize(qstr); + { + uint *stringTablePtr = (uint *)(data + unit->offsetToStringTable); + char *string = data + unitSize; + stringTable.serialize(stringTablePtr, data, string); } uint *functionTable = (uint *)(data + unit->offsetToFunctionTable); for (int i = 0; i < irModule->functions.size(); ++i) functionTable[i] = functionOffsets.value(irModule->functions.at(i)); - char *f = data + unitSize + stringDataSize; + char *f = data + unitSize + stringTable.dataSize(); for (int i = 0; i < irModule->functions.size(); ++i) { QV4::IR::Function *function = irModule->functions.at(i); if (function == irModule->rootFunction) @@ -271,7 +288,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(int *total // write js classes and js class lookup table uint *jsClassTable = (uint*)(data + unit->offsetToJSClassTable); - char *jsClass = data + unitSize + stringDataSize + functionDataSize; + char *jsClass = data + unitSize + stringTable.dataSize() + functionDataSize; for (int i = 0; i < jsClasses.count(); ++i) { jsClassTable[i] = jsClass - data; @@ -383,5 +400,3 @@ int QV4::Compiler::JSUnitGenerator::writeFunction(char *f, int index, QV4::IR::F return CompiledData::Function::calculateSize(function->nFormals, function->nLocals, function->nInnerFunctions, function->nDependingIdObjects, function->nDependingContextProperties + function->nDependingScopeProperties); } - - diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index 6fd597a3b..756e7cfd5 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -59,13 +59,31 @@ struct JSClassMember; namespace Compiler { -struct Q_QML_EXPORT JSUnitGenerator { - JSUnitGenerator(IR::Module *module, int headerSize = -1); - - IR::Module *irModule; +struct Q_QML_EXPORT StringTableGenerator { + StringTableGenerator(); int registerString(const QString &str); int getStringId(const QString &string) const; + QString stringForIndex(int index) const { return strings.at(index); } + uint stringCount() const { return strings.size(); } + uint dataSize() const { return stringDataSize; } + + void clear(); + + void serialize(uint *stringTable, char *dataStart, char *stringData); + +private: + QHash stringToId; + QStringList strings; + uint stringDataSize; +}; + +struct Q_QML_EXPORT JSUnitGenerator { + JSUnitGenerator(IR::Module *module, int headerSize = -1); + + int registerString(const QString &str) { return stringTable.registerString(str); } + int getStringId(const QString &string) const { return stringTable.getStringId(string); } + QString stringForIndex(int index) const { return stringTable.stringForIndex(index); } uint registerGetterLookup(const QString &name); uint registerSetterLookup(const QString &name); @@ -79,13 +97,14 @@ struct Q_QML_EXPORT JSUnitGenerator { int registerJSClass(int count, IR::ExprList *args); - QV4::CompiledData::Unit *generateUnit(int *totalUnitSize = 0); + QV4::CompiledData::Unit *generateUnit(); // Returns bytes written int writeFunction(char *f, int index, IR::Function *irFunction); - QHash stringToId; - QStringList strings; - uint stringDataSize; + StringTableGenerator stringTable; +private: + IR::Module *irModule; + QHash functionOffsets; QList lookups; QVector regexps; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index a90551955..7f7ea1e5c 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -1172,7 +1172,7 @@ void QQmlDataLoader::shutdownThread() } QQmlTypeLoader::Blob::Blob(const QUrl &url, QQmlDataBlob::Type type, QQmlTypeLoader *loader) - : QQmlDataBlob(url, type), m_typeLoader(loader), m_importCache(loader), m_stringPool(0), m_isSingleton(false) + : QQmlDataBlob(url, type), m_typeLoader(loader), m_importCache(loader), m_isSingleton(false) { } @@ -2046,7 +2046,7 @@ void QQmlTypeData::done() const TypeReference &type = *it; Q_ASSERT(!type.typeData || type.typeData->isCompleteOrError()); if (type.typeData && type.typeData->isError()) { - QString typeName = m_document->jsGenerator.strings.at(it.key()); + QString typeName = m_document->stringAt(it.key()); QList errors = type.typeData->errors(); QQmlError error; @@ -2142,7 +2142,7 @@ void QQmlTypeData::dataReceived(const Data &data) return; } - m_stringPool = &m_document->jsGenerator.strings; + m_document->collectTypeReferences(); m_importCache.setBaseUrl(finalUrl(), finalUrlString()); @@ -2172,7 +2172,7 @@ void QQmlTypeData::dataReceived(const Data &data) QList errors; - foreach (QV4::CompiledData::Import *import, m_document->imports) { + foreach (const QV4::CompiledData::Import *import, m_document->imports) { if (!addImport(import, &errors)) { Q_ASSERT(errors.size()); QQmlError error(errors.takeFirst()); @@ -2232,6 +2232,11 @@ void QQmlTypeData::downloadProgressChanged(qreal p) } } +QString QQmlTypeData::stringAt(int index) const +{ + return m_document->jsGenerator.stringTable.stringForIndex(index); +} + void QQmlTypeData::compile() { Q_ASSERT(m_compiledData == 0); @@ -2299,15 +2304,7 @@ void QQmlTypeData::resolveTypes() } } - QV4::CompiledData::TypeReferenceMap typeReferences; - QStringList names; - if (m_document) { - typeReferences = m_document->typeReferences; - names = m_document->jsGenerator.strings; - } else { - // ### collect from available QV4::CompiledData::QmlUnit - } - for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = typeReferences.constBegin(), end = typeReferences.constEnd(); + for (QV4::CompiledData::TypeReferenceMap::ConstIterator unresolvedRef = m_document->typeReferences.constBegin(), end = m_document->typeReferences.constEnd(); unresolvedRef != end; ++unresolvedRef) { TypeReference ref; // resolved reference @@ -2319,7 +2316,7 @@ void QQmlTypeData::resolveTypes() QQmlImportNamespace *typeNamespace = 0; QList errors; - const QString name = names.at(unresolvedRef.key()); + const QString name = stringAt(unresolvedRef.key()); bool typeFound = m_importCache.resolveType(name, &ref.type, &majorVersion, &minorVersion, &typeNamespace, &errors); if (!typeNamespace && !typeFound && !m_implicitImportLoaded) { @@ -2606,8 +2603,6 @@ void QQmlScriptBlob::dataReceived(const Data &data) return; } - m_stringPool = &m_irUnit.jsGenerator.strings; - QList errors; QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine()); m_scriptData->m_precompiledScript = QV4::Script::precompile(&m_irUnit.jsModule, &m_irUnit.jsGenerator, v4, m_scriptData->url, source, &errors); @@ -2619,6 +2614,7 @@ void QQmlScriptBlob::dataReceived(const Data &data) return; } + m_irUnit.javaScriptCompilationUnit = m_scriptData->m_precompiledScript; QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(m_irUnit); if (m_scriptData->m_precompiledScript) { @@ -2687,6 +2683,11 @@ void QQmlScriptBlob::done() m_importCache.populateCache(m_scriptData->importCache); } +QString QQmlScriptBlob::stringAt(int index) const +{ + return m_scriptData->m_precompiledScript->data->stringAt(index); +} + void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace) { ScriptReference ref; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 8335ffa7d..43828c572 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -293,11 +293,10 @@ public: virtual void dependencyComplete(QQmlDataBlob *); protected: - const QString &stringAt(int index) const { Q_ASSERT(m_stringPool); return m_stringPool->at(index); } + virtual QString stringAt(int) const { return QString(); } QQmlTypeLoader *m_typeLoader; QQmlImports m_importCache; - QStringList *m_stringPool; // used to resolve string indices in imports bool m_isSingleton; QHash m_unresolvedImports; QList m_qmldirs; @@ -451,6 +450,8 @@ protected: virtual void allDependenciesDone(); virtual void downloadProgressChanged(qreal); + virtual QString stringAt(int index) const; + private: void resolveTypes(); void compile(); @@ -542,6 +543,8 @@ protected: virtual void dataReceived(const Data &); virtual void done(); + virtual QString stringAt(int index) const; + private: virtual void scriptImported(QQmlScriptBlob *blob, const QV4::CompiledData::Location &location, const QString &qualifier, const QString &nameSpace);