aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-27 17:07:06 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-28 15:07:03 +0100
commit0ed744c1ef955cdb94cbd89c58283663da490d7d (patch)
treee07da64307bb70331ed0a9cbfa78ecd960b57b14 /src/qml/compiler
parent6bbd173a9cb36021ed284522ac628400469eab2f (diff)
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 <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp101
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h42
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp33
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp6
-rw-r--r--src/qml/compiler/qv4compileddata_p.h17
-rw-r--r--src/qml/compiler/qv4compiler.cpp93
-rw-r--r--src/qml/compiler/qv4compiler_p.h35
8 files changed, 183 insertions, 146 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index bd0aedf089..e85703e9aa 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<QString> &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<QQmlJS::AST::UiObjectDefinition*>(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<QQmlJS::AST::ExpressionStatement *>(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<QV4::CompiledData::QmlUnit *>(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<QV4::CompiledData::Import*>(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<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
if (function)
name = function->name.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 a345290672..cd67c52ed7 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 <typename T>
struct PoolList
{
@@ -199,7 +202,7 @@ struct Signal
QV4::CompiledData::Location location;
PoolList<SignalParameter> *parameters;
- QStringList parameterStringList(const QStringList &stringPool) const;
+ QStringList parameterStringList(const QV4::Compiler::StringTableGenerator *stringPool) const;
Signal *next;
};
@@ -285,6 +288,8 @@ public:
FixedPoolArray<int> *runtimeFunctionIndices;
private:
+ friend struct IRLoader;
+
PoolList<Property> *properties;
PoolList<Signal> *qmlSignals;
PoolList<Binding> *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<QV4::CompiledData::Import*> imports;
+ QList<const QV4::CompiledData::Import *> imports;
QList<Pragma*> 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<int, QStringList> 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 <typename _Tp> _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<QString> illegalNames;
- QList<QV4::CompiledData::Import*> _imports;
+ QList<const QV4::CompiledData::Import *> _imports;
QList<Pragma*> _pragmas;
QList<Object*> _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 26f6e0b74f..224bd23898 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<QV4::EvalInstructionSelection> 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<QV4::EvalInstructionSelection> 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<int> &bindings)
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index e21c13c5df..ca84cee1f8 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -99,7 +99,7 @@ public:
QHash<int, QQmlCompiledData::CustomParserData> *customParserData();
QQmlJS::MemoryPool *memoryPool();
QStringRef newStringRef(const QString &string);
- const QStringList &stringPool() const;
+ const QV4::Compiler::StringTableGenerator *stringPool() const;
void setCustomParserBindings(const QVector<int> &bindings);
void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 2220fd5de5..56497ed8a3 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -46,6 +46,7 @@
#include <private/qv4objectproto_p.h>
#include <private/qv4lookup_p.h>
#include <private/qv4regexpobject_p.h>
+#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
#include <algorithm>
@@ -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 474d4c88bc..d6d2419d74 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<const uint*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
+
const Function *functionAt(int idx) const {
- const uint *offsetTable = reinterpret_cast<const uint*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable);
+ const uint *offsetTable = functionOffsetTable();
const uint offset = offsetTable[idx];
return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(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<QV4::Function *> runtimeFunctions;
-// QVector<QV4::Function *> 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 f25b1900ce..0338bf1840 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -45,19 +45,12 @@
#include <qv4engine_p.h>
#include <private/qqmlpropertycache_p.h>
-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<QString, int>::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 6fd597a3b3..756e7cfd52 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<QString, int> 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<QString, int> stringToId;
- QStringList strings;
- uint stringDataSize;
+ StringTableGenerator stringTable;
+private:
+ IR::Module *irModule;
+
QHash<IR::Function *, uint> functionOffsets;
QList<CompiledData::Lookup> lookups;
QVector<CompiledData::RegExp> regexps;