aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/compiler.pri12
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp283
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h47
-rw-r--r--src/qml/compiler/qqmlirloader.cpp205
-rw-r--r--src/qml/compiler/qqmlirloader_p.h81
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator.cpp4
-rw-r--r--src/qml/compiler/qqmlpropertycachecreator_p.h3
-rw-r--r--src/qml/compiler/qqmlpropertyresolver.cpp92
-rw-r--r--src/qml/compiler/qqmlpropertyresolver_p.h87
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator.cpp43
-rw-r--r--src/qml/compiler/qqmlpropertyvalidator_p.h6
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp41
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h15
-rw-r--r--src/qml/compiler/qv4codegen.cpp74
-rw-r--r--src/qml/compiler/qv4codegen_p.h13
-rw-r--r--src/qml/compiler/qv4compileddata.cpp772
-rw-r--r--src/qml/compiler/qv4compileddata_p.h300
-rw-r--r--src/qml/compiler/qv4compiler.cpp1
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp1
-rw-r--r--src/qml/compiler/qv4executablecompilationunit.cpp809
-rw-r--r--src/qml/compiler/qv4executablecompilationunit_p.h324
-rw-r--r--src/qml/compiler/qv4instr_moth.cpp35
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h2
23 files changed, 1855 insertions, 1395 deletions
diff --git a/src/qml/compiler/compiler.pri b/src/qml/compiler/compiler.pri
index da3c173545..3291d6e1f5 100644
--- a/src/qml/compiler/compiler.pri
+++ b/src/qml/compiler/compiler.pri
@@ -10,7 +10,6 @@ HEADERS += \
$$PWD/qv4compilerscanfunctions_p.h \
$$PWD/qv4codegen_p.h \
$$PWD/qqmlirbuilder_p.h \
- $$PWD/qqmltypecompiler_p.h \
$$PWD/qv4instr_moth_p.h \
$$PWD/qv4bytecodehandler_p.h
@@ -28,17 +27,22 @@ SOURCES += \
!qmldevtools_build {
HEADERS += \
+ $$PWD/qqmlirloader_p.h \
+ $$PWD/qqmlpropertyresolver_p.h \
$$PWD/qqmltypecompiler_p.h \
$$PWD/qqmlpropertycachecreator_p.h \
$$PWD/qqmlpropertyvalidator_p.h \
- $$PWD/qv4compilationunitmapper_p.h
-
+ $$PWD/qv4compilationunitmapper_p.h \
+ $$PWD/qv4executablecompilationunit_p.h
SOURCES += \
+ $$PWD/qqmlirloader.cpp \
+ $$PWD/qqmlpropertyresolver.cpp \
$$PWD/qqmltypecompiler.cpp \
$$PWD/qqmlpropertycachecreator.cpp \
$$PWD/qqmlpropertyvalidator.cpp \
- $$PWD/qv4compilationunitmapper.cpp
+ $$PWD/qv4compilationunitmapper.cpp \
+ $$PWD/qv4executablecompilationunit.cpp
unix: SOURCES += $$PWD/qv4compilationunitmapper_unix.cpp
else: SOURCES += $$PWD/qv4compilationunitmapper_win.cpp
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 6e077ec44c..6f46648572 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -48,12 +48,6 @@
#include <QCryptographicHash>
#include <cmath>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmlglobal_p.h>
-#include <private/qqmltypeloader_p.h>
-#include <private/qqmlengine_p.h>
-#endif
-
#ifdef CONST
#undef CONST
#endif
@@ -61,11 +55,6 @@
QT_USE_NAMESPACE
static const quint32 emptyStringIndex = 0;
-
-#if 0 //ndef V4_BOOTSTRAP
-DEFINE_BOOL_CONFIG_OPTION(lookupHints, QML_LOOKUP_HINTS);
-#endif // V4_BOOTSTRAP
-
using namespace QmlIR;
#define COMPILE_EXCEPTION(location, desc) \
@@ -1559,20 +1548,12 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
output.jsGenerator.stringTable.registerString(output.jsModule.fileName);
output.jsGenerator.stringTable.registerString(output.jsModule.finalUrl);
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = output.javaScriptCompilationUnit;
-
- const QV4::CompiledData::Unit *jsUnit = nullptr;
- std::function<QV4::CompiledData::QmlUnit *(QV4::CompiledData::QmlUnit *, uint)> unitFinalizer
- = [](QV4::CompiledData::QmlUnit *unit, uint) {
- return unit;
- };
+ QV4::CompiledData::Unit *jsUnit = nullptr;
// We may already have unit data if we're loading an ahead-of-time generated cache file.
- if (compilationUnit->data) {
- jsUnit = compilationUnit->data;
-#ifndef V4_BOOTSTRAP
- output.javaScriptCompilationUnit->dynamicStrings = output.jsGenerator.stringTable.allStrings();
-#endif
+ if (output.javaScriptCompilationUnit.data) {
+ jsUnit = const_cast<QV4::CompiledData::Unit *>(output.javaScriptCompilationUnit.data);
+ output.javaScriptCompilationUnit.dynamicStrings = output.jsGenerator.stringTable.allStrings();
} else {
QV4::CompiledData::Unit *createdUnit;
jsUnit = createdUnit = output.jsGenerator.generateUnit();
@@ -1584,38 +1565,17 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
break;
}
}
- // This unit's memory was allocated with malloc on the heap, so it's
- // definitely not suitable for StaticData access.
- createdUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
-#ifndef V4_BOOTSTRAP
if (dependencyHasher) {
- QCryptographicHash hash(QCryptographicHash::Md5);
- if (dependencyHasher(&hash)) {
- QByteArray checksum = hash.result();
- Q_ASSERT(checksum.size() == sizeof(createdUnit->dependencyMD5Checksum));
- memcpy(createdUnit->dependencyMD5Checksum, checksum.constData(), sizeof(createdUnit->dependencyMD5Checksum));
+ const QByteArray checksum = dependencyHasher();
+ if (checksum.size() == sizeof(createdUnit->dependencyMD5Checksum)) {
+ memcpy(createdUnit->dependencyMD5Checksum, checksum.constData(),
+ sizeof(createdUnit->dependencyMD5Checksum));
}
}
-#else
- Q_UNUSED(dependencyHasher);
-#endif
+
createdUnit->sourceFileIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.fileName);
createdUnit->finalUrlIndex = output.jsGenerator.stringTable.getStringId(output.jsModule.finalUrl);
-
- // Combine the qml data into the general unit data.
- unitFinalizer = [&jsUnit](QV4::CompiledData::QmlUnit *qmlUnit, uint qmlDataSize) {
- void *ptr = const_cast<QV4::CompiledData::Unit*>(jsUnit);
- QV4::CompiledData::Unit *newUnit = (QV4::CompiledData::Unit *)realloc(ptr, jsUnit->unitSize + qmlDataSize);
- jsUnit = newUnit;
- newUnit->offsetToQmlUnit = newUnit->unitSize;
- newUnit->unitSize += qmlDataSize;
- memcpy(const_cast<QV4::CompiledData::QmlUnit *>(newUnit->qmlUnit()), qmlUnit, qmlDataSize);
- free(const_cast<QV4::CompiledData::QmlUnit*>(qmlUnit));
- qmlUnit = nullptr;
- newUnit->generateChecksum();
- return const_cast<QV4::CompiledData::QmlUnit*>(newUnit->qmlUnit());
- };
}
// No more new strings after this point, we're calculating offsets.
@@ -1782,7 +1742,16 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
}
}
- qmlUnit = unitFinalizer(qmlUnit, totalSize);
+ if (!output.javaScriptCompilationUnit.data) {
+ // Combine the qml data into the general unit data.
+ jsUnit = static_cast<QV4::CompiledData::Unit *>(realloc(jsUnit, jsUnit->unitSize + totalSize));
+ jsUnit->offsetToQmlUnit = jsUnit->unitSize;
+ jsUnit->unitSize += totalSize;
+ memcpy(jsUnit->qmlUnit(), qmlUnit, totalSize);
+ free(qmlUnit);
+ jsUnit->generateChecksum();
+ qmlUnit = jsUnit->qmlUnit();
+ }
static const bool showStats = qEnvironmentVariableIsSet("QML_SHOW_UNIT_STATS");
if (showStats) {
@@ -1806,7 +1775,8 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
qDebug() << " " << totalStringSize << "bytes total strings";
}
- compilationUnit->setUnitData(jsUnit, qmlUnit, output.jsModule.fileName, output.jsModule.finalUrl);
+ output.javaScriptCompilationUnit.setUnitData(jsUnit, qmlUnit, output.jsModule.fileName,
+ output.jsModule.finalUrl);
}
char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const
@@ -1911,214 +1881,3 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil
return runtimeFunctionIndices;
}
-
-#ifndef V4_BOOTSTRAP
-
-QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) const
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
-
- // Find the first property
- while (d && d->isFunction())
- d = cache->overrideData(d);
-
- if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return nullptr;
- } else {
- return d;
- }
-}
-
-
-QQmlPropertyData *PropertyResolver::signal(const QString &name, bool *notInRevision) const
-{
- if (notInRevision) *notInRevision = false;
-
- QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
- if (notInRevision) *notInRevision = false;
-
- while (d && !(d->isFunction()))
- d = cache->overrideData(d);
-
- if (d && !cache->isAllowedInRevision(d)) {
- if (notInRevision) *notInRevision = true;
- return nullptr;
- } else if (d && d->isSignal()) {
- return d;
- }
-
- if (name.endsWith(QLatin1String("Changed"))) {
- QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
-
- d = property(propName, notInRevision);
- if (d)
- return cache->signal(d->notifyIndex());
- }
-
- return nullptr;
-}
-
-IRLoader::IRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
- : unit(qmlData)
- , output(output)
-{
- pool = output->jsParserEngine.pool();
-}
-
-void IRLoader::load()
-{
- output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
-
- const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
-
- for (quint32 i = 0; i < qmlUnit->nImports; ++i)
- output->imports << qmlUnit->importAt(i);
-
- if (unit->flags & QV4::CompiledData::Unit::IsSingleton) {
- QmlIR::Pragma *p = New<QmlIR::Pragma>();
- p->location = QV4::CompiledData::Location();
- p->type = QmlIR::Pragma::PragmaSingleton;
- output->pragmas << p;
- }
-
- for (uint i = 0; i < qmlUnit->nObjects; ++i) {
- const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(i);
- QmlIR::Object *object = loadObject(serializedObject);
- output->objects.append(object);
- }
-}
-
-struct FakeExpression : public QQmlJS::AST::NullExpression
-{
- FakeExpression(int start, int length)
- : location(start, length)
- {}
-
- virtual QQmlJS::AST::SourceLocation firstSourceLocation() const
- { return location; }
-
- virtual QQmlJS::AST::SourceLocation lastSourceLocation() const
- { return location; }
-
-private:
- QQmlJS::AST::SourceLocation location;
-};
-
-QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
-{
- QmlIR::Object *object = pool->New<QmlIR::Object>();
- object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
-
- object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
- object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
- object->flags = serializedObject->flags;
- object->id = serializedObject->id;
- object->location = serializedObject->location;
- object->locationOfIdProperty = serializedObject->locationOfIdProperty;
-
- QVector<int> functionIndices;
- functionIndices.reserve(serializedObject->nFunctions + serializedObject->nBindings / 2);
-
- for (uint i = 0; i < serializedObject->nBindings; ++i) {
- QmlIR::Binding *b = pool->New<QmlIR::Binding>();
- *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
- object->bindings->append(b);
- if (b->type == QV4::CompiledData::Binding::Type_Script) {
- functionIndices.append(b->value.compiledScriptIndex);
- b->value.compiledScriptIndex = functionIndices.count() - 1;
-
- QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
- foe->nameIndex = 0;
-
- QQmlJS::AST::ExpressionNode *expr;
-
- if (b->stringIndex != quint32(0)) {
- const int start = output->code.length();
- const QString script = output->stringAt(b->stringIndex);
- const int length = script.length();
- output->code.append(script);
- expr = new (pool) FakeExpression(start, length);
- } else
- expr = new (pool) QQmlJS::AST::NullExpression();
- foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
- object->functionsAndExpressions->append(foe);
- }
- }
-
- Q_ASSERT(object->functionsAndExpressions->count == functionIndices.count());
-
- for (uint i = 0; i < serializedObject->nSignals; ++i) {
- const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(i);
- QmlIR::Signal *s = pool->New<QmlIR::Signal>();
- s->nameIndex = serializedSignal->nameIndex;
- s->location = serializedSignal->location;
- s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
-
- for (uint i = 0; i < serializedSignal->nParameters; ++i) {
- QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
- *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
- s->parameters->append(p);
- }
-
- object->qmlSignals->append(s);
- }
-
- for (uint i = 0; i < serializedObject->nEnums; ++i) {
- const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
- QmlIR::Enum *e = pool->New<QmlIR::Enum>();
- e->nameIndex = serializedEnum->nameIndex;
- e->location = serializedEnum->location;
- e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
-
- for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
- QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
- *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
- e->enumValues->append(v);
- }
-
- object->qmlEnums->append(e);
- }
-
- const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
- for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
- QmlIR::Property *p = pool->New<QmlIR::Property>();
- *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
- object->properties->append(p);
- }
-
- {
- const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
- for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
- QmlIR::Alias *a = pool->New<QmlIR::Alias>();
- *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
- object->aliases->append(a);
- }
- }
-
- const quint32_le *functionIdx = serializedObject->functionOffsetTable();
- for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
- QmlIR::Function *f = pool->New<QmlIR::Function>();
- const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
-
- functionIndices.append(*functionIdx);
- f->index = functionIndices.count() - 1;
- f->location = compiledFunction->location;
- f->nameIndex = compiledFunction->nameIndex;
-
- f->formals.allocate(pool, int(compiledFunction->nFormals));
- const quint32_le *formalNameIdx = compiledFunction->formalsTable();
- for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
- f->formals[i] = *formalNameIdx;
-
- object->functions->append(f);
- }
-
- object->runtimeFunctionIndices.allocate(pool, functionIndices);
-
- return object;
-}
-
-#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 298fe7dd92..b49eaee420 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -65,11 +65,11 @@ QT_BEGIN_NAMESPACE
class QQmlPropertyCache;
class QQmlContextData;
class QQmlTypeNameCache;
+struct QQmlIRLoader;
namespace QmlIR {
struct Document;
-struct IRLoader;
template <typename T>
struct PoolList
@@ -347,7 +347,7 @@ public:
const quint32 *namedObjectsInComponentTable() const { return namedObjectsInComponent.begin(); }
private:
- friend struct IRLoader;
+ friend struct ::QQmlIRLoader;
PoolList<Property> *properties;
PoolList<Alias> *aliases;
@@ -379,7 +379,7 @@ struct Q_QML_PRIVATE_EXPORT Document
QVector<Object*> objects;
QV4::Compiler::JSUnitGenerator jsGenerator;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> javaScriptCompilationUnit;
+ QV4::CompiledData::CompilationUnit javaScriptCompilationUnit;
int registerString(const QString &str) { return jsGenerator.registerString(str); }
QString stringAt(int index) const { return jsGenerator.stringForIndex(index); }
@@ -508,32 +508,6 @@ private:
char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const;
};
-#ifndef V4_BOOTSTRAP
-struct Q_QML_EXPORT PropertyResolver
-{
- PropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
- : cache(cache)
- {}
-
- QQmlPropertyData *property(int index) const
- {
- return cache->property(index);
- }
-
- enum RevisionCheck {
- CheckRevision,
- IgnoreRevision
- };
-
- QQmlPropertyData *property(const QString &name, bool *notInRevision = nullptr, RevisionCheck check = CheckRevision) const;
-
- // This code must match the semantics of QQmlPropertyPrivate::findSignalByName
- QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
-
- QQmlRefPointer<QQmlPropertyCache> cache;
-};
-#endif
-
struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
{
JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator, QV4::Compiler::Module *jsModule,
@@ -550,21 +524,6 @@ private:
const QV4::Compiler::StringTableGenerator *stringPool;
};
-struct Q_QML_PRIVATE_EXPORT IRLoader {
- IRLoader(const QV4::CompiledData::Unit *unit, QmlIR::Document *output);
-
- void load();
-
-private:
- QmlIR::Object *loadObject(const QV4::CompiledData::Object *serializedObject);
-
- template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
-
- const QV4::CompiledData::Unit *unit;
- QmlIR::Document *output;
- QQmlJS::MemoryPool *pool;
-};
-
} // namespace QmlIR
struct QQmlCompileError
diff --git a/src/qml/compiler/qqmlirloader.cpp b/src/qml/compiler/qqmlirloader.cpp
new file mode 100644
index 0000000000..c2eb6da2fa
--- /dev/null
+++ b/src/qml/compiler/qqmlirloader.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlirloader_p.h"
+#include <private/qqmlirbuilder_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QQmlIRLoader::QQmlIRLoader(const QV4::CompiledData::Unit *qmlData, QmlIR::Document *output)
+ : unit(qmlData)
+ , output(output)
+{
+ pool = output->jsParserEngine.pool();
+}
+
+void QQmlIRLoader::load()
+{
+ output->jsGenerator.stringTable.initializeFromBackingUnit(unit);
+
+ const QV4::CompiledData::QmlUnit *qmlUnit = unit->qmlUnit();
+
+ for (quint32 i = 0; i < qmlUnit->nImports; ++i)
+ output->imports << qmlUnit->importAt(i);
+
+ if (unit->flags & QV4::CompiledData::Unit::IsSingleton) {
+ QmlIR::Pragma *p = New<QmlIR::Pragma>();
+ p->location = QV4::CompiledData::Location();
+ p->type = QmlIR::Pragma::PragmaSingleton;
+ output->pragmas << p;
+ }
+
+ for (uint i = 0; i < qmlUnit->nObjects; ++i) {
+ const QV4::CompiledData::Object *serializedObject = qmlUnit->objectAt(i);
+ QmlIR::Object *object = loadObject(serializedObject);
+ output->objects.append(object);
+ }
+}
+
+struct FakeExpression : public QQmlJS::AST::NullExpression
+{
+ FakeExpression(int start, int length)
+ : location(start, length)
+ {}
+
+ virtual QQmlJS::AST::SourceLocation firstSourceLocation() const
+ { return location; }
+
+ virtual QQmlJS::AST::SourceLocation lastSourceLocation() const
+ { return location; }
+
+private:
+ QQmlJS::AST::SourceLocation location;
+};
+
+QmlIR::Object *QQmlIRLoader::loadObject(const QV4::CompiledData::Object *serializedObject)
+{
+ QmlIR::Object *object = pool->New<QmlIR::Object>();
+ object->init(pool, serializedObject->inheritedTypeNameIndex, serializedObject->idNameIndex);
+
+ object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
+ object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
+ object->flags = serializedObject->flags;
+ object->id = serializedObject->id;
+ object->location = serializedObject->location;
+ object->locationOfIdProperty = serializedObject->locationOfIdProperty;
+
+ QVector<int> functionIndices;
+ functionIndices.reserve(serializedObject->nFunctions + serializedObject->nBindings / 2);
+
+ for (uint i = 0; i < serializedObject->nBindings; ++i) {
+ QmlIR::Binding *b = pool->New<QmlIR::Binding>();
+ *static_cast<QV4::CompiledData::Binding*>(b) = serializedObject->bindingTable()[i];
+ object->bindings->append(b);
+ if (b->type == QV4::CompiledData::Binding::Type_Script) {
+ functionIndices.append(b->value.compiledScriptIndex);
+ b->value.compiledScriptIndex = functionIndices.count() - 1;
+
+ QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>();
+ foe->nameIndex = 0;
+
+ QQmlJS::AST::ExpressionNode *expr;
+
+ if (b->stringIndex != quint32(0)) {
+ const int start = output->code.length();
+ const QString script = output->stringAt(b->stringIndex);
+ const int length = script.length();
+ output->code.append(script);
+ expr = new (pool) FakeExpression(start, length);
+ } else
+ expr = new (pool) QQmlJS::AST::NullExpression();
+ foe->node = new (pool) QQmlJS::AST::ExpressionStatement(expr); // dummy
+ object->functionsAndExpressions->append(foe);
+ }
+ }
+
+ Q_ASSERT(object->functionsAndExpressions->count == functionIndices.count());
+
+ for (uint i = 0; i < serializedObject->nSignals; ++i) {
+ const QV4::CompiledData::Signal *serializedSignal = serializedObject->signalAt(i);
+ QmlIR::Signal *s = pool->New<QmlIR::Signal>();
+ s->nameIndex = serializedSignal->nameIndex;
+ s->location = serializedSignal->location;
+ s->parameters = pool->New<QmlIR::PoolList<QmlIR::SignalParameter> >();
+
+ for (uint i = 0; i < serializedSignal->nParameters; ++i) {
+ QmlIR::SignalParameter *p = pool->New<QmlIR::SignalParameter>();
+ *static_cast<QV4::CompiledData::Parameter*>(p) = *serializedSignal->parameterAt(i);
+ s->parameters->append(p);
+ }
+
+ object->qmlSignals->append(s);
+ }
+
+ for (uint i = 0; i < serializedObject->nEnums; ++i) {
+ const QV4::CompiledData::Enum *serializedEnum = serializedObject->enumAt(i);
+ QmlIR::Enum *e = pool->New<QmlIR::Enum>();
+ e->nameIndex = serializedEnum->nameIndex;
+ e->location = serializedEnum->location;
+ e->enumValues = pool->New<QmlIR::PoolList<QmlIR::EnumValue> >();
+
+ for (uint i = 0; i < serializedEnum->nEnumValues; ++i) {
+ QmlIR::EnumValue *v = pool->New<QmlIR::EnumValue>();
+ *static_cast<QV4::CompiledData::EnumValue*>(v) = *serializedEnum->enumValueAt(i);
+ e->enumValues->append(v);
+ }
+
+ object->qmlEnums->append(e);
+ }
+
+ const QV4::CompiledData::Property *serializedProperty = serializedObject->propertyTable();
+ for (uint i = 0; i < serializedObject->nProperties; ++i, ++serializedProperty) {
+ QmlIR::Property *p = pool->New<QmlIR::Property>();
+ *static_cast<QV4::CompiledData::Property*>(p) = *serializedProperty;
+ object->properties->append(p);
+ }
+
+ {
+ const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
+ for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
+ QmlIR::Alias *a = pool->New<QmlIR::Alias>();
+ *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
+ object->aliases->append(a);
+ }
+ }
+
+ const quint32_le *functionIdx = serializedObject->functionOffsetTable();
+ for (uint i = 0; i < serializedObject->nFunctions; ++i, ++functionIdx) {
+ QmlIR::Function *f = pool->New<QmlIR::Function>();
+ const QV4::CompiledData::Function *compiledFunction = unit->functionAt(*functionIdx);
+
+ functionIndices.append(*functionIdx);
+ f->index = functionIndices.count() - 1;
+ f->location = compiledFunction->location;
+ f->nameIndex = compiledFunction->nameIndex;
+
+ f->formals.allocate(pool, int(compiledFunction->nFormals));
+ const quint32_le *formalNameIdx = compiledFunction->formalsTable();
+ for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
+ f->formals[i] = *formalNameIdx;
+
+ object->functions->append(f);
+ }
+
+ object->runtimeFunctionIndices.allocate(pool, functionIndices);
+
+ return object;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlirloader_p.h b/src/qml/compiler/qqmlirloader_p.h
new file mode 100644
index 0000000000..aa303c923f
--- /dev/null
+++ b/src/qml/compiler/qqmlirloader_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLIRLOADER_P_H
+#define QQMLIRLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4compileddata_p.h>
+#include <private/qqmljsmemorypool_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QmlIR {
+struct Document;
+struct Object;
+}
+
+struct Q_QML_PRIVATE_EXPORT QQmlIRLoader {
+ QQmlIRLoader(const QV4::CompiledData::Unit *unit, QmlIR::Document *output);
+
+ void load();
+
+private:
+ QmlIR::Object *loadObject(const QV4::CompiledData::Object *serializedObject);
+
+ template <typename _Tp> _Tp *New() { return pool->New<_Tp>(); }
+
+ const QV4::CompiledData::Unit *unit;
+ QmlIR::Document *output;
+ QQmlJS::MemoryPool *pool;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLIRLOADER_P_H
diff --git a/src/qml/compiler/qqmlpropertycachecreator.cpp b/src/qml/compiler/qqmlpropertycachecreator.cpp
index fb54da5b73..bd4f2a0612 100644
--- a/src/qml/compiler/qqmlpropertycachecreator.cpp
+++ b/src/qml/compiler/qqmlpropertycachecreator.cpp
@@ -64,7 +64,9 @@ bool QQmlBindingInstantiationContext::resolveInstantiatingProperty()
Q_ASSERT(instantiatingBinding->propertyNameIndex != 0);
bool notInRevision = false;
- instantiatingProperty = QmlIR::PropertyResolver(referencingObjectPropertyCache).property(instantiatingPropertyName, &notInRevision, QmlIR::PropertyResolver::IgnoreRevision);
+ instantiatingProperty = QQmlPropertyResolver(referencingObjectPropertyCache)
+ .property(instantiatingPropertyName, &notInRevision,
+ QQmlPropertyResolver::IgnoreRevision);
return instantiatingProperty != nullptr;
}
diff --git a/src/qml/compiler/qqmlpropertycachecreator_p.h b/src/qml/compiler/qqmlpropertycachecreator_p.h
index 346cfb5803..28eea27675 100644
--- a/src/qml/compiler/qqmlpropertycachecreator_p.h
+++ b/src/qml/compiler/qqmlpropertycachecreator_p.h
@@ -53,6 +53,7 @@
#include <private/qqmlvaluetype_p.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlmetaobject_p.h>
+#include <private/qqmlpropertyresolver_p.h>
QT_BEGIN_NAMESPACE
@@ -323,7 +324,7 @@ inline QQmlCompileError QQmlPropertyCacheCreator<ObjectContainer>::createMetaObj
int varPropCount = 0;
- QmlIR::PropertyResolver resolver(baseTypeCache);
+ QQmlPropertyResolver resolver(baseTypeCache);
auto p = obj->propertiesBegin();
auto pend = obj->propertiesEnd();
diff --git a/src/qml/compiler/qqmlpropertyresolver.cpp b/src/qml/compiler/qqmlpropertyresolver.cpp
new file mode 100644
index 0000000000..90eaca0b90
--- /dev/null
+++ b/src/qml/compiler/qqmlpropertyresolver.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qqmlpropertyresolver_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlPropertyData *QQmlPropertyResolver::property(const QString &name, bool *notInRevision,
+ RevisionCheck check) const
+{
+ if (notInRevision) *notInRevision = false;
+
+ QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
+
+ // Find the first property
+ while (d && d->isFunction())
+ d = cache->overrideData(d);
+
+ if (check != IgnoreRevision && d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return nullptr;
+ } else {
+ return d;
+ }
+}
+
+
+QQmlPropertyData *QQmlPropertyResolver::signal(const QString &name, bool *notInRevision) const
+{
+ if (notInRevision) *notInRevision = false;
+
+ QQmlPropertyData *d = cache->property(name, nullptr, nullptr);
+ if (notInRevision) *notInRevision = false;
+
+ while (d && !(d->isFunction()))
+ d = cache->overrideData(d);
+
+ if (d && !cache->isAllowedInRevision(d)) {
+ if (notInRevision) *notInRevision = true;
+ return nullptr;
+ } else if (d && d->isSignal()) {
+ return d;
+ }
+
+ if (name.endsWith(QLatin1String("Changed"))) {
+ QString propName = name.mid(0, name.length() - static_cast<int>(strlen("Changed")));
+
+ d = property(propName, notInRevision);
+ if (d)
+ return cache->signal(d->notifyIndex());
+ }
+
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qqmlpropertyresolver_p.h b/src/qml/compiler/qqmlpropertyresolver_p.h
new file mode 100644
index 0000000000..df857f242e
--- /dev/null
+++ b/src/qml/compiler/qqmlpropertyresolver_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLPROPERTYRESOLVER_P_H
+#define QQMLPROPERTYRESOLVER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qtqmlglobal_p.h>
+#include <private/qqmlpropertycache_p.h>
+#include <private/qqmlrefcount_p.h>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_QML_EXPORT QQmlPropertyResolver
+{
+ QQmlPropertyResolver(const QQmlRefPointer<QQmlPropertyCache> &cache)
+ : cache(cache)
+ {}
+
+ QQmlPropertyData *property(int index) const
+ {
+ return cache->property(index);
+ }
+
+ enum RevisionCheck {
+ CheckRevision,
+ IgnoreRevision
+ };
+
+ QQmlPropertyData *property(const QString &name, bool *notInRevision = nullptr,
+ RevisionCheck check = CheckRevision) const;
+
+ // This code must match the semantics of QQmlPropertyPrivate::findSignalByName
+ QQmlPropertyData *signal(const QString &name, bool *notInRevision) const;
+
+ QQmlRefPointer<QQmlPropertyCache> cache;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQMLPROPERTYRESOLVER_P_H
diff --git a/src/qml/compiler/qqmlpropertyvalidator.cpp b/src/qml/compiler/qqmlpropertyvalidator.cpp
index 8c06760d42..71d5318652 100644
--- a/src/qml/compiler/qqmlpropertyvalidator.cpp
+++ b/src/qml/compiler/qqmlpropertyvalidator.cpp
@@ -41,11 +41,12 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlstringconverters_p.h>
+#include <private/qqmlpropertyresolver_p.h>
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE
-QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
+QQmlPropertyValidator::QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit)
: enginePrivate(enginePrivate)
, compilationUnit(compilationUnit)
, imports(imports)
@@ -121,7 +122,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
groupProperties.insert(pos, binding);
}
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QString defaultPropertyName;
QQmlPropertyData *defaultProperty = nullptr;
@@ -164,7 +165,7 @@ QVector<QQmlCompileError> QQmlPropertyValidator::validateObject(int objectIndex,
pd = propertyResolver.signal(name, &notInRevision);
} else {
pd = propertyResolver.property(name, &notInRevision,
- QmlIR::PropertyResolver::CheckRevision);
+ QQmlPropertyResolver::CheckRevision);
}
if (notInRevision) {
@@ -338,7 +339,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
if (binding->flags & QV4::CompiledData::Binding::IsResolvedEnum)
return noError;
- QString value = binding->valueAsString(compilationUnit.data());
+ QString value = compilationUnit->bindingValueAsString(binding);
QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex());
bool ok;
if (p.isFlagType()) {
@@ -396,7 +397,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::UInt: {
if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber(compilationUnit->constants);
+ double d = compilationUnit->bindingValueAsNumber(binding);
if (double(uint(d)) == d)
return noError;
}
@@ -405,7 +406,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Int: {
if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- double d = binding->valueAsNumber(compilationUnit->constants);
+ double d = compilationUnit->bindingValueAsNumber(binding);
if (double(int(d)) == d)
return noError;
}
@@ -426,7 +427,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Color: {
bool ok = false;
- QQmlStringConverters::rgbaFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: color expected"));
}
@@ -435,7 +436,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
#if QT_CONFIG(datestring)
case QVariant::Date: {
bool ok = false;
- QQmlStringConverters::dateFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: date expected"));
}
@@ -443,7 +444,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Time: {
bool ok = false;
- QQmlStringConverters::timeFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: time expected"));
}
@@ -451,7 +452,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::DateTime: {
bool ok = false;
- QQmlStringConverters::dateTimeFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: datetime expected"));
}
@@ -460,7 +461,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
#endif // datestring
case QVariant::Point: {
bool ok = false;
- QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: point expected"));
}
@@ -468,7 +469,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::PointF: {
bool ok = false;
- QQmlStringConverters::pointFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: point expected"));
}
@@ -476,7 +477,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Size: {
bool ok = false;
- QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: size expected"));
}
@@ -484,7 +485,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::SizeF: {
bool ok = false;
- QQmlStringConverters::sizeFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: size expected"));
}
@@ -492,7 +493,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::Rect: {
bool ok = false;
- QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: rect expected"));
}
@@ -500,7 +501,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
break;
case QVariant::RectF: {
bool ok = false;
- QQmlStringConverters::rectFFromString(binding->valueAsString(compilationUnit.data()), &ok);
+ QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
if (!ok) {
return warnOrError(tr("Invalid property assignment: point expected"));
}
@@ -517,7 +518,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float xp;
float yp;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector2D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: 2D vector expected"));
}
}
@@ -528,7 +529,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float yp;
float zy;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector3D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: 3D vector expected"));
}
}
@@ -540,7 +541,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float zy;
float wp;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QVector4D, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: 4D vector expected"));
}
}
@@ -552,7 +553,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
float yp;
float zp;
} vec;
- if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, binding->valueAsString(compilationUnit.data()), &vec, sizeof(vec))) {
+ if (!QQmlStringConverters::createFromString(QMetaType::QQuaternion, compilationUnit->bindingValueAsString(binding), &vec, sizeof(vec))) {
return warnOrError(tr("Invalid property assignment: quaternion expected"));
}
}
@@ -570,7 +571,7 @@ QQmlCompileError QQmlPropertyValidator::validateLiteralBinding(QQmlPropertyCache
} else if (property->propType() == qMetaTypeId<QList<int> >()) {
bool ok = (binding->type == QV4::CompiledData::Binding::Type_Number);
if (ok) {
- double n = binding->valueAsNumber(compilationUnit->constants);
+ double n = compilationUnit->bindingValueAsNumber(binding);
if (double(int(n)) != n)
ok = false;
}
diff --git a/src/qml/compiler/qqmlpropertyvalidator_p.h b/src/qml/compiler/qqmlpropertyvalidator_p.h
index e9ae844ccb..8244b2df21 100644
--- a/src/qml/compiler/qqmlpropertyvalidator_p.h
+++ b/src/qml/compiler/qqmlpropertyvalidator_p.h
@@ -58,7 +58,7 @@ class QQmlPropertyValidator
{
Q_DECLARE_TR_FUNCTIONS(QQmlPropertyValidator)
public:
- QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit);
+ QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports &imports, const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit);
QVector<QQmlCompileError> validate();
@@ -72,13 +72,13 @@ private:
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QV4::CompiledData::Location &location, const QString &description) const;
Q_REQUIRED_RESULT QVector<QQmlCompileError> recordError(const QQmlCompileError &error) const;
QString stringAt(int index) const { return compilationUnit->stringAt(index); }
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{
return compilationUnit->resolvedType(id);
}
QQmlEnginePrivate *enginePrivate;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
const QQmlImports &imports;
const QV4::CompiledData::Unit *qmlUnit;
const QQmlPropertyCacheVector &propertyCaches;
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 239f04a58f..66320b8db9 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -44,6 +44,7 @@
#include <private/qqmlcustomparser_p.h>
#include <private/qqmlvmemetaobject_p.h>
#include <private/qqmlcomponent_p.h>
+#include <private/qqmlpropertyresolver_p.h>
#define COMPILE_EXCEPTION(token, desc) \
{ \
@@ -55,7 +56,7 @@ QT_BEGIN_NAMESPACE
QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData,
QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
: resolvedTypes(resolvedTypeCache)
, engine(engine)
, typeData(typeData)
@@ -65,7 +66,7 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *type
{
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
+QQmlRefPointer<QV4::ExecutableCompilationUnit> QQmlTypeCompiler::compile()
{
// Build property caches and VME meta object data
@@ -133,7 +134,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
return nullptr;
}
- if (!document->javaScriptCompilationUnit) {
+ if (!document->javaScriptCompilationUnit.unitData()) {
// Compile JS binding expressions and signal handlers if necessary
{
// We can compile script strings ahead of time, but they must be compiled
@@ -145,7 +146,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
document->jsModule.fileName = typeData->urlString();
document->jsModule.finalUrl = typeData->finalUrlString();
QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine,
- document->program, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
+ document->program, &document->jsGenerator.stringTable, engine->v4engine()->illegalNames());
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return nullptr;
@@ -158,7 +159,9 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile()
QmlIR::QmlUnitGenerator qmlGenerator;
qmlGenerator.generate(*document, dependencyHasher);
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = document->javaScriptCompilationUnit;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit
+ = QV4::ExecutableCompilationUnit::create(std::move(
+ document->javaScriptCompilationUnit));
compilationUnit->typeNameCache = typeNameCache;
compilationUnit->resolvedTypes = *resolvedTypes;
compilationUnit->propertyCaches = std::move(m_propertyCaches);
@@ -208,7 +211,7 @@ int QQmlTypeCompiler::registerConstant(QV4::ReturnedValue v)
const QV4::CompiledData::Unit *QQmlTypeCompiler::qmlUnit() const
{
- return document->javaScriptCompilationUnit->unitData();
+ return document->javaScriptCompilationUnit.unitData();
}
const QQmlImports *QQmlTypeCompiler::imports() const
@@ -252,11 +255,6 @@ const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const
return &document->jsGenerator.stringTable;
}
-void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
-{
- document->javaScriptCompilationUnit->bindingPropertyDataPerObject = propertyData;
-}
-
QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
{
return object->bindingAsString(document, scriptIndex);
@@ -297,7 +295,7 @@ SignalHandlerConverter::SignalHandlerConverter(QQmlTypeCompiler *typeCompiler)
, qmlObjects(*typeCompiler->qmlObjects())
, imports(typeCompiler->imports())
, customParsers(typeCompiler->customParserCache())
- , illegalNames(typeCompiler->enginePrivate()->v8engine()->illegalNames())
+ , illegalNames(typeCompiler->enginePrivate()->v4engine()->illegalNames())
, propertyCaches(typeCompiler->propertyCaches())
{
}
@@ -357,7 +355,7 @@ bool SignalHandlerConverter::convertSignalHandlerExpressionsToFunctionDeclaratio
if (!QmlIR::IRBuilder::isSignalPropertyName(propertyName))
continue;
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
Q_ASSERT(propertyName.startsWith(QLatin1String("on")));
propertyName.remove(0, 2);
@@ -513,7 +511,7 @@ bool QQmlEnumTypeResolver::resolveEnumBindings()
continue;
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
@@ -722,7 +720,7 @@ void QQmlAliasAnnotator::annotateBindingsToAliases()
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -754,7 +752,7 @@ void QQmlScriptStringScanner::scan()
const QmlIR::Object *obj = qmlObjects.at(i);
- QmlIR::PropertyResolver resolver(propertyCache);
+ QQmlPropertyResolver resolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
@@ -799,7 +797,7 @@ static bool isUsableComponent(const QMetaObject *metaObject)
void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlIR::Object *obj, QQmlPropertyCache *propertyCache)
{
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
@@ -856,7 +854,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
if (!containsResolvedType(syntheticComponent->inheritedTypeNameIndex)) {
- auto typeRef = new QV4::CompiledData::ResolvedTypeReference;
+ auto typeRef = new QV4::ResolvedTypeReference;
typeRef->type = componentType;
typeRef->majorVersion = componentType.majorVersion();
typeRef->minorVersion = componentType.minorVersion();
@@ -1110,7 +1108,7 @@ QQmlComponentAndAliasResolver::AliasResolutionResult QQmlComponentAndAliasResolv
break;
}
- QmlIR::PropertyResolver resolver(targetCache);
+ QQmlPropertyResolver resolver(targetCache);
QQmlPropertyData *targetProperty = resolver.property(property.toString());
@@ -1224,7 +1222,7 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex);
- QmlIR::PropertyResolver propertyResolver(propertyCache);
+ QQmlPropertyResolver propertyResolver(propertyCache);
QStringList deferredPropertyNames;
{
@@ -1263,7 +1261,8 @@ bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
continue;
bool notInRevision = false;
- pd = propertyResolver.property(name, &notInRevision, QmlIR::PropertyResolver::CheckRevision);
+ pd = propertyResolver.property(name, &notInRevision,
+ QQmlPropertyResolver::CheckRevision);
}
bool seenSubObjectWithId = false;
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index a49b97453f..f588909c42 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -81,7 +81,7 @@ struct QQmlTypeCompiler
public:
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document,
const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
+ QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
// --- interface used by QQmlPropertyCacheCreator
@@ -91,10 +91,10 @@ public:
QString stringAt(int idx) const;
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
- QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
+ QV4::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
// ---
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compile();
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compile();
QList<QQmlError> compilationErrors() const { return errors; }
void recordError(QQmlError error);
@@ -118,7 +118,6 @@ public:
QQmlJS::MemoryPool *memoryPool();
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
- void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -126,7 +125,7 @@ public:
void addImport(const QString &module, const QString &qualifier, int majorVersion, int minorVersion);
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{
return resolvedTypes->value(id);
}
@@ -157,12 +156,12 @@ protected:
void recordError(const QQmlCompileError &error)
{ compiler->recordError(error); }
- QV4::CompiledData::ResolvedTypeReference *resolvedType(int id) const
+ QV4::ResolvedTypeReference *resolvedType(int id) const
{ return compiler->resolvedType(id); }
bool containsResolvedType(int id) const
{ return compiler->resolvedTypes->contains(id); }
- QV4::CompiledData::ResolvedTypeReferenceMap::iterator insertResolvedType(
- int id, QV4::CompiledData::ResolvedTypeReference *value)
+ QV4::ResolvedTypeReferenceMap::iterator insertResolvedType(
+ int id, QV4::ResolvedTypeReference *value)
{ return compiler->resolvedTypes->insert(id, value); }
QQmlTypeCompiler *compiler;
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 1bf0e7147d..b145ceb51e 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -45,16 +45,15 @@
#include <QtCore/QStack>
#include <QScopeGuard>
#include <private/qqmljsast_p.h>
-#include <private/qv4string_p.h>
+#include <private/qqmljslexer_p.h>
+#include <private/qqmljsparser_p.h>
+#include <private/qv4stringtoarrayindex_p.h>
#include <private/qv4value_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4compilercontrolflow_p.h>
#include <private/qv4bytecodegenerator_p.h>
#include <private/qv4compilerscanfunctions_p.h>
-
-#ifndef V4_BOOTSTRAP
-# include <qqmlerror.h>
-#endif
+#include <qqmlerror.h>
#include <cmath>
#include <iostream>
@@ -1243,7 +1242,7 @@ bool Codegen::visit(ArrayMemberExpression *ast)
return false;
if (AST::StringLiteral *str = AST::cast<AST::StringLiteral *>(ast->expression)) {
QString s = str->value.toString();
- uint arrayIndex = QV4::String::toArrayIndex(s);
+ uint arrayIndex = stringToArrayIndex(s);
if (arrayIndex == UINT_MAX) {
setExprResult(Reference::fromMember(base, str->value.toString()));
return false;
@@ -2513,7 +2512,7 @@ bool Codegen::visit(ObjectPattern *ast)
if (cname || p->type != PatternProperty::Literal)
break;
QString name = p->name->asString();
- uint arrayIndex = QV4::String::toArrayIndex(name);
+ uint arrayIndex = stringToArrayIndex(name);
if (arrayIndex != UINT_MAX)
break;
if (members.contains(name))
@@ -3781,23 +3780,54 @@ QList<QQmlJS::DiagnosticMessage> Codegen::errors() const
return _errors;
}
-QQmlRefPointer<CompiledData::CompilationUnit> Codegen::generateCompilationUnit(bool generateUnitData)
+QV4::CompiledData::CompilationUnit Codegen::generateCompilationUnit(
+ bool generateUnitData)
{
- CompiledData::Unit *unitData = nullptr;
- if (generateUnitData)
- unitData = jsUnitGenerator->generateUnit();
- CompiledData::CompilationUnit *compilationUnit = new CompiledData::CompilationUnit(unitData);
-
- QQmlRefPointer<CompiledData::CompilationUnit> unit;
- unit.adopt(compilationUnit);
- return unit;
+ return QV4::CompiledData::CompilationUnit(
+ generateUnitData ? jsUnitGenerator->generateUnit() : nullptr);
}
-QQmlRefPointer<CompiledData::CompilationUnit> Codegen::createUnitForLoading()
+CompiledData::CompilationUnit Codegen::compileModule(
+ bool debugMode, const QString &url, const QString &sourceCode,
+ const QDateTime &sourceTimeStamp, QList<QQmlJS::DiagnosticMessage> *diagnostics)
{
- QQmlRefPointer<CompiledData::CompilationUnit> result;
- result.adopt(new CompiledData::CompilationUnit);
- return result;
+ QQmlJS::Engine ee;
+ QQmlJS::Lexer lexer(&ee);
+ lexer.setCode(sourceCode, /*line*/1, /*qml mode*/false);
+ QQmlJS::Parser parser(&ee);
+
+ const bool parsed = parser.parseModule();
+
+ if (diagnostics)
+ *diagnostics = parser.diagnosticMessages();
+
+ if (!parsed)
+ return CompiledData::CompilationUnit();
+
+ QQmlJS::AST::ESModule *moduleNode = QQmlJS::AST::cast<QQmlJS::AST::ESModule*>(parser.rootNode());
+ if (!moduleNode) {
+ // if parsing was successful, and we have no module, then
+ // the file was empty.
+ if (diagnostics)
+ diagnostics->clear();
+ return nullptr;
+ }
+
+ using namespace QV4::Compiler;
+ Compiler::Module compilerModule(debugMode);
+ compilerModule.unitFlags |= CompiledData::Unit::IsESModule;
+ compilerModule.sourceTimeStamp = sourceTimeStamp;
+ JSUnitGenerator jsGenerator(&compilerModule);
+ Codegen cg(&jsGenerator, /*strictMode*/true);
+ cg.generateFromModule(url, url, sourceCode, moduleNode, &compilerModule);
+ auto errors = cg.errors();
+ if (diagnostics)
+ *diagnostics << errors;
+
+ if (!errors.isEmpty())
+ return CompiledData::CompilationUnit();
+
+ return cg.generateCompilationUnit();
}
class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor
@@ -3914,8 +3944,6 @@ Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node
}
-#ifndef V4_BOOTSTRAP
-
QList<QQmlError> Codegen::qmlErrors() const
{
QList<QQmlError> qmlErrors;
@@ -3939,8 +3967,6 @@ QList<QQmlError> Codegen::qmlErrors() const
return qmlErrors;
}
-#endif // V4_BOOTSTRAP
-
bool Codegen::RValue::operator==(const RValue &other) const
{
switch (type) {
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index ad86483132..e519da0142 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -52,12 +52,15 @@
#include "private/qv4global_p.h"
#include <private/qqmljsastvisitor_p.h>
+#include <private/qqmljsengine_p.h>
#include <private/qqmljsast_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4util_p.h>
#include <private/qv4bytecodegenerator_p.h>
-#include <private/qv4stackframe_p.h>
+#include <private/qv4calldata_p.h>
+
+#include <QtQml/qqmlerror.h>
QT_BEGIN_NAMESPACE
@@ -659,9 +662,7 @@ protected:
public:
QList<DiagnosticMessage> errors() const;
-#ifndef V4_BOOTSTRAP
QList<QQmlError> qmlErrors() const;
-#endif
Reference binopHelper(QSOperator::Op oper, Reference &left, Reference &right);
Reference jumpBinop(QSOperator::Op oper, Reference &left, Reference &right);
@@ -681,8 +682,10 @@ public:
Reference referenceForName(const QString &name, bool lhs, const QQmlJS::AST::SourceLocation &accessLocation = QQmlJS::AST::SourceLocation());
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> generateCompilationUnit(bool generateUnitData = true);
- static QQmlRefPointer<QV4::CompiledData::CompilationUnit> createUnitForLoading();
+ QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData = true);
+ static QV4::CompiledData::CompilationUnit compileModule(
+ bool debugMode, const QString &url, const QString &sourceCode,
+ const QDateTime &sourceTimeStamp, QList<DiagnosticMessage> *diagnostics);
Context *currentContext() const { return _context; }
BytecodeGenerator *generator() const { return bytecodeGenerator; }
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index a78094f17c..0fed0a03b2 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -39,34 +39,12 @@
#include "qv4compileddata_p.h"
#include <private/qv4value_p.h>
-#ifndef V4_BOOTSTRAP
-#include <private/qv4engine_p.h>
-#include <private/qv4function_p.h>
-#include <private/qv4objectproto_p.h>
-#include <private/qv4lookup_p.h>
-#include <private/qv4regexpobject_p.h>
-#include <private/qv4regexp_p.h>
-#include <private/qqmltypeloader_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qv4vme_moth_p.h>
-#include <private/qv4module_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <private/qqmlvaluetypewrapper_p.h>
-#include "qv4compilationunitmapper_p.h"
-#include <QQmlPropertyMap>
-#include <QDateTime>
-#include <QFile>
-#include <QFileInfo>
-#include <QScopedValueRollback>
-#include <QStandardPaths>
-#include <QDir>
-#include <private/qv4identifiertable_p.h>
-#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QSaveFile>
#include <QScopeGuard>
+#include <QFileInfo>
// generated by qmake:
#include "qml_compile_hash_p.h"
@@ -99,23 +77,13 @@ CompilationUnit::CompilationUnit(const Unit *unitData, const QString &fileName,
CompilationUnit::~CompilationUnit()
{
-#ifndef V4_BOOTSTRAP
- unlink();
-#endif
-
if (data) {
if (data->qmlUnit() != qmlData)
free(const_cast<QmlUnit *>(qmlData));
qmlData = nullptr;
-#ifndef V4_BOOTSTRAP
if (!(data->flags & QV4::CompiledData::Unit::StaticData))
free(const_cast<Unit *>(data));
-#else
- // Unconditionally free the memory. In the dev tools we create units that have
- // the flag set and will be saved to disk, so intended to persist later.
- free(const_cast<Unit *>(data));
-#endif
}
data = nullptr;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -126,585 +94,11 @@ CompilationUnit::~CompilationUnit()
delete [] imports;
imports = nullptr;
}
-#ifndef V4_BOOTSTRAP
-
-QString CompilationUnit::localCacheFilePath(const QUrl &url)
-{
- const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix();
- QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
- fileNameHash.addData(localSourcePath.toUtf8());
- QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
- QDir::root().mkpath(directory);
- return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix;
-}
-
-QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
-{
- this->engine = engine;
- engine->compilationUnits.insert(this);
-
- Q_ASSERT(!runtimeStrings);
- Q_ASSERT(data);
- const quint32 stringCount = totalStringCount();
- runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*));
- // memset the strings to 0 in case a GC run happens while we're within the loop below
- memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*));
- for (uint i = 0; i < stringCount; ++i)
- runtimeStrings[i] = engine->newString(stringAt(i));
-
- runtimeRegularExpressions = new QV4::Value[data->regexpTableSize];
- // memset the regexps to 0 in case a GC run happens while we're within the loop below
- memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value));
- for (uint i = 0; i < data->regexpTableSize; ++i) {
- const CompiledData::RegExp *re = data->regexpAt(i);
- uint f = re->flags;
- const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
- runtimeRegularExpressions[i] = QV4::RegExp::create(engine, stringAt(re->stringIndex), flags);
- }
-
- if (data->lookupTableSize) {
- runtimeLookups = new QV4::Lookup[data->lookupTableSize];
- memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup));
- const CompiledData::Lookup *compiledLookups = data->lookupTable();
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup *l = runtimeLookups + i;
-
- Lookup::Type type = Lookup::Type(uint(compiledLookups[i].type_and_flags));
- if (type == CompiledData::Lookup::Type_Getter)
- l->getter = QV4::Lookup::getterGeneric;
- else if (type == CompiledData::Lookup::Type_Setter)
- l->setter = QV4::Lookup::setterGeneric;
- else if (type == CompiledData::Lookup::Type_GlobalGetter)
- l->globalGetter = QV4::Lookup::globalGetterGeneric;
- else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
- l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
- l->nameIndex = compiledLookups[i].nameIndex;
- }
- }
-
- if (data->jsClassTableSize) {
- runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
- // memset the regexps to 0 in case a GC run happens while we're within the loop below
- memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
- for (uint i = 0; i < data->jsClassTableSize; ++i) {
- int memberCount = 0;
- const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
- runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
- for (int j = 0; j < memberCount; ++j, ++member)
- runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
- }
- }
-
- runtimeFunctions.resize(data->functionTableSize);
- for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
- const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
- runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction);
- }
-
- Scope scope(engine);
- Scoped<InternalClass> ic(scope);
-
- runtimeBlocks.resize(data->blockTableSize);
- for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
- const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
- ic = engine->internalClasses(EngineBase::Class_CallContext);
-
- // first locals
- const quint32_le *localsIndices = compiledBlock->localsTable();
- for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
- ic = ic->addMember(engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]), Attr_NotConfigurable);
- runtimeBlocks[i] = ic->d();
- }
-
- static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
- if (showCode) {
- qDebug() << "=== Constant table";
- Moth::dumpConstantTable(constants, data->constantTableSize);
- qDebug() << "=== String table";
- for (uint i = 0, end = totalStringCount(); i < end; ++i)
- qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
- qDebug() << "=== Closure table";
- for (uint i = 0; i < data->functionTableSize; ++i)
- qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
- qDebug() << "root function at index " << (data->indexOfRootFunction != -1 ? data->indexOfRootFunction : 0);
- }
-
- if (data->indexOfRootFunction != -1)
- return runtimeFunctions[data->indexOfRootFunction];
- else
- return nullptr;
-}
-
-Heap::Object *CompilationUnit::templateObjectAt(int index) const
-{
- Q_ASSERT(index < int(data->templateObjectTableSize));
- if (!templateObjects.size())
- templateObjects.resize(data->templateObjectTableSize);
- Heap::Object *o = templateObjects.at(index);
- if (o)
- return o;
-
- // create the template object
- Scope scope(engine);
- const CompiledData::TemplateObject *t = data->templateObjectAt(index);
- Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size));
- Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size));
- ScopedValue s(scope);
- for (uint i = 0; i < t->size; ++i) {
- s = runtimeStrings[t->stringIndexAt(i)];
- a->arraySet(i, s);
- s = runtimeStrings[t->rawStringIndexAt(i)];
- raw->arraySet(i, s);
- }
-
- ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1);
- a->defineReadonlyProperty(QStringLiteral("raw"), raw);
- ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1);
-
- templateObjects[index] = a->objectValue()->d();
- return templateObjects.at(index);
-}
-
-void CompilationUnit::unlink()
-{
- if (engine)
- nextCompilationUnit.remove();
-
- if (isRegisteredWithEngine) {
- Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0));
- if (qmlEngine)
- qmlEngine->unregisterInternalCompositeType(this);
- QQmlMetaType::unregisterInternalCompositeType(this);
- isRegisteredWithEngine = false;
- }
-
- propertyCaches.clear();
-
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i) {
- QV4::Lookup &l = runtimeLookups[i];
- if (l.getter == QV4::QObjectWrapper::lookupGetter) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) {
- if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
- pc->release();
- }
-
- if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) {
- if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
- pc->release();
- }
- }
- }
-
- dependentScripts.clear();
-
- typeNameCache = nullptr;
-
- qDeleteAll(resolvedTypes);
- resolvedTypes.clear();
-
- engine = nullptr;
- qmlEngine = nullptr;
- free(runtimeStrings);
- runtimeStrings = nullptr;
- delete [] runtimeLookups;
- runtimeLookups = nullptr;
- delete [] runtimeRegularExpressions;
- runtimeRegularExpressions = nullptr;
- free(runtimeClasses);
- runtimeClasses = nullptr;
- for (QV4::Function *f : qAsConst(runtimeFunctions))
- f->destroy();
- runtimeFunctions.clear();
-}
-void CompilationUnit::markObjects(QV4::MarkStack *markStack)
-{
- if (runtimeStrings) {
- for (uint i = 0, end = totalStringCount(); i < end; ++i)
- if (runtimeStrings[i])
- runtimeStrings[i]->mark(markStack);
- }
- if (runtimeRegularExpressions) {
- for (uint i = 0; i < data->regexpTableSize; ++i)
- runtimeRegularExpressions[i].mark(markStack);
- }
- if (runtimeClasses) {
- for (uint i = 0; i < data->jsClassTableSize; ++i)
- if (runtimeClasses[i])
- runtimeClasses[i]->mark(markStack);
- }
- for (QV4::Function *f : qAsConst(runtimeFunctions))
- if (f && f->internalClass)
- f->internalClass->mark(markStack);
- for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks))
- if (c)
- c->mark(markStack);
-
- for (QV4::Heap::Object *o : qAsConst(templateObjects))
- if (o)
- o->mark(markStack);
-
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i)
- runtimeLookups[i].markObjects(markStack);
- }
-
- if (m_module)
- m_module->mark(markStack);
-}
-
-IdentifierHash CompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
-{
- IdentifierHash namedObjectCache(engine);
- const CompiledData::Object *component = objectAt(componentObjectIndex);
- const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
- for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
- const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
- namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
- }
- return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
-}
-
-void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
-{
- this->qmlEngine = qmlEngine;
-
- // Add to type registry of composites
- if (propertyCaches.needsVMEMetaObject(/*root object*/0)) {
- QQmlMetaType::registerInternalCompositeType(this);
- qmlEngine->registerInternalCompositeType(this);
- } else {
- const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
- auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
- Q_ASSERT(typeRef);
- if (typeRef->compilationUnit) {
- metaTypeId = typeRef->compilationUnit->metaTypeId;
- listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
- } else {
- metaTypeId = typeRef->type.typeId();
- listMetaTypeId = typeRef->type.qListTypeId();
- }
- }
-
- // Collect some data for instantiation later.
- int bindingCount = 0;
- int parserStatusCount = 0;
- int objectCount = 0;
- for (quint32 i = 0, count = this->objectCount(); i < count; ++i) {
- const QV4::CompiledData::Object *obj = objectAt(i);
- bindingCount += obj->nBindings;
- if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
- if (typeRef->type.isValid()) {
- if (typeRef->type.parserStatusCast() != -1)
- ++parserStatusCount;
- }
- ++objectCount;
- if (typeRef->compilationUnit) {
- bindingCount += typeRef->compilationUnit->totalBindingsCount;
- parserStatusCount += typeRef->compilationUnit->totalParserStatusCount;
- objectCount += typeRef->compilationUnit->totalObjectCount;
- }
- }
- }
-
- totalBindingsCount = bindingCount;
- totalParserStatusCount = parserStatusCount;
- totalObjectCount = objectCount;
-}
-
-bool CompilationUnit::verifyChecksum(const DependentTypesHasher &dependencyHasher) const
-{
- if (!dependencyHasher) {
- for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) {
- if (data->dependencyMD5Checksum[i] != 0)
- return false;
- }
- return true;
- }
- QCryptographicHash hash(QCryptographicHash::Md5);
- if (!dependencyHasher(&hash))
- return false;
- QByteArray checksum = hash.result();
- Q_ASSERT(checksum.size() == sizeof(data->dependencyMD5Checksum));
- return memcmp(data->dependencyMD5Checksum, checksum.constData(),
- sizeof(data->dependencyMD5Checksum)) == 0;
-}
-
-QStringList CompilationUnit::moduleRequests() const
-{
- QStringList requests;
- requests.reserve(data->moduleRequestTableSize);
- for (uint i = 0; i < data->moduleRequestTableSize; ++i)
- requests << stringAt(data->moduleRequestTable()[i]);
- return requests;
-}
-
-Heap::Module *CompilationUnit::instantiate(ExecutionEngine *engine)
-{
- if (isESModule() && m_module)
- return m_module;
-
- if (data->indexOfRootFunction < 0)
- return nullptr;
-
- if (!this->engine)
- linkToEngine(engine);
-
- Scope scope(engine);
- Scoped<Module> module(scope, engine->memoryManager->allocate<Module>(engine, this));
-
- if (isESModule())
- m_module = module->d();
-
- for (const QString &request: moduleRequests()) {
- auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
- if (engine->hasException)
- return nullptr;
- dependentModuleUnit->instantiate(engine);
- }
-
- ScopedString importName(scope);
-
- const uint importCount = data->importEntryTableSize;
- if (importCount > 0) {
- imports = new const Value *[importCount];
- memset(imports, 0, importCount * sizeof(Value *));
- }
- for (uint i = 0; i < importCount; ++i) {
- const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- importName = runtimeStrings[entry.importName];
- const Value *valuePtr = dependentModuleUnit->resolveExport(importName);
- if (!valuePtr) {
- QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
- referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
- return nullptr;
- }
- imports[i] = valuePtr;
- }
-
- for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- if (!dependentModuleUnit)
- return nullptr;
-
- ScopedString importName(scope, runtimeStrings[entry.importName]);
- if (!dependentModuleUnit->resolveExport(importName)) {
- QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
- referenceErrorMessage += importName->toQString();
- engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
- return nullptr;
- }
- }
-
- return module->d();
-}
-
-const Value *CompilationUnit::resolveExport(QV4::String *exportName)
-{
- QVector<ResolveSetEntry> resolveSet;
- return resolveExportRecursively(exportName, &resolveSet);
-}
-
-QStringList CompilationUnit::exportedNames() const
-{
- QStringList names;
- QVector<const CompiledData::CompilationUnit*> exportNameSet;
- getExportedNamesRecursively(&names, &exportNameSet);
- names.sort();
- auto last = std::unique(names.begin(), names.end());
- names.erase(last, names.end());
- return names;
-}
-
-const Value *CompilationUnit::resolveExportRecursively(QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
-{
- if (!m_module)
- return nullptr;
-
- for (const auto &entry: *resolveSet)
- if (entry.module == this && entry.exportName->isEqualTo(exportName))
- return nullptr;
-
- (*resolveSet) << ResolveSetEntry(this, exportName);
-
- if (exportName->toQString() == QLatin1String("*"))
- return &m_module->self;
-
- Scope scope(engine);
-
- if (auto localExport = lookupNameInExportTable(data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
- ScopedString localName(scope, runtimeStrings[localExport->localName]);
- uint index = m_module->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
- if (index == UINT_MAX)
- return nullptr;
- if (index >= m_module->scope->locals.size)
- return imports[index - m_module->scope->locals.size];
- return &m_module->scope->locals[index];
- }
-
- if (auto indirectExport = lookupNameInExportTable(data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) {
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(indirectExport->moduleRequest)), this);
- if (!dependentModuleUnit)
- return nullptr;
- ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
- return dependentModuleUnit->resolveExportRecursively(importName, resolveSet);
- }
-
-
- if (exportName->toQString() == QLatin1String("default"))
- return nullptr;
-
- const Value *starResolution = nullptr;
-
- for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- if (!dependentModuleUnit)
- return nullptr;
-
- const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet);
- // ### handle ambiguous
- if (resolution) {
- if (!starResolution) {
- starResolution = resolution;
- continue;
- }
- if (resolution != starResolution)
- return nullptr;
- }
- }
-
- return starResolution;
-}
-
-const ExportEntry *CompilationUnit::lookupNameInExportTable(const ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const
-{
- const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
- auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) {
- return stringAt(lhs.exportName) < name->toQString();
- });
- if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString())
- return nullptr;
- return matchingExport;
-}
-
-void CompilationUnit::getExportedNamesRecursively(QStringList *names, QVector<const CompilationUnit*> *exportNameSet, bool includeDefaultExport) const
-{
- if (exportNameSet->contains(this))
- return;
- exportNameSet->append(this);
-
- const auto append = [names, includeDefaultExport](const QString &name) {
- if (!includeDefaultExport && name == QLatin1String("default"))
- return;
- names->append(name);
- };
-
- for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i];
- append(stringAt(entry.exportName));
- }
-
- for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
- append(stringAt(entry.exportName));
- }
-
- for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
- const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
- auto dependentModuleUnit = engine->loadModule(QUrl(stringAt(entry.moduleRequest)), this);
- if (!dependentModuleUnit)
- return;
- dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false);
- }
-}
-
-void CompilationUnit::evaluate()
-{
- QV4::Scope scope(engine);
- QV4::Scoped<Module> module(scope, m_module);
- module->evaluate();
-}
-
-void CompilationUnit::evaluateModuleRequests()
-{
- for (const QString &request: moduleRequests()) {
- auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
- if (engine->hasException)
- return;
- dependentModuleUnit->evaluate();
- if (engine->hasException)
- return;
- }
-}
-
-bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
-{
- if (!QQmlFile::isLocalFile(url)) {
- *errorString = QStringLiteral("File has to be a local file.");
- return false;
- }
-
- const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
- QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
-
- const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) };
- for (const QString &cachePath : cachePaths) {
- CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
- if (!mappedUnit)
- continue;
-
- const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
- const Unit *oldData = data;
- auto dataPtrRevert = qScopeGuard([this, oldData](){
- setUnitData(oldData);
- });
- setUnitData(mappedUnit);
-
- if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
- *errorString = QStringLiteral("QML source file has moved to a different location.");
- continue;
- }
-
- dataPtrRevert.dismiss();
- free(const_cast<Unit*>(oldDataPtr));
- backingFile.reset(cacheFile.take());
- return true;
- }
-
- return false;
-}
-
-#endif // V4_BOOTSTRAP
-
-#if defined(V4_BOOTSTRAP)
-bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString)
-#else
-bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
-#endif
+bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString) const
{
errorString->clear();
-#if !defined(V4_BOOTSTRAP)
- if (data->sourceTimeStamp == 0) {
- *errorString = QStringLiteral("Missing time stamp for source file");
- return false;
- }
-
- if (!QQmlFile::isLocalFile(unitUrl)) {
- *errorString = QStringLiteral("File has to be a local file.");
- return false;
- }
- const QString outputFileName = localCacheFilePath(unitUrl);
-#endif
-
#if QT_CONFIG(temporaryfile)
// Foo.qml -> Foo.qmlc
QSaveFile cacheFile(outputFileName);
@@ -713,16 +107,9 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
return false;
}
- QByteArray modifiedUnit;
- modifiedUnit.resize(data->unitSize);
- memcpy(modifiedUnit.data(), data, data->unitSize);
- const char *dataPtr = modifiedUnit.data();
- Unit *unitPtr;
- memcpy(&unitPtr, &dataPtr, sizeof(unitPtr));
- unitPtr->flags |= Unit::StaticData;
-
- qint64 headerWritten = cacheFile.write(modifiedUnit);
- if (headerWritten != modifiedUnit.size()) {
+ SaveableUnitPointer saveable(this);
+ qint64 headerWritten = cacheFile.write(saveable.data<char>(), saveable.size());
+ if (headerWritten != saveable.size()) {
*errorString = cacheFile.errorString();
return false;
}
@@ -770,51 +157,6 @@ void CompilationUnit::setUnitData(const Unit *unitData, const QmlUnit *qmlUnit,
m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
}
-#ifndef V4_BOOTSTRAP
-QString Binding::valueAsString(const CompilationUnit *unit) const
-{
- switch (type) {
- case Type_Script:
- case Type_String:
- return unit->stringAt(stringIndex);
- case Type_Null:
- return QStringLiteral("null");
- case Type_Boolean:
- return value.b ? QStringLiteral("true") : QStringLiteral("false");
- case Type_Number:
- return QString::number(valueAsNumber(unit->constants));
- case Type_Invalid:
- return QString();
-#if !QT_CONFIG(translation)
- case Type_TranslationById:
- case Type_Translation:
- return unit->stringAt(unit->unitData()->translations()[value.translationDataIndex].stringIndex);
-#else
- case Type_TranslationById: {
- 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->fileName();
- 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(translation.commentIndex).toUtf8();
- QByteArray text = unit->stringAt(translation.stringIndex).toUtf8();
- return QCoreApplication::translate(contextUtf8.constData(), text.constData(),
- comment.constData(), translation.number);
- }
-#endif
- default:
- break;
- }
- return QString();
-}
-
//reverse of Lexer::singleEscape()
QString Binding::escapedString(const QString &string)
{
@@ -858,101 +200,19 @@ QString Binding::escapedString(const QString &string)
return tmp;
}
-QString Binding::valueAsScriptString(const CompilationUnit *unit) const
-{
- if (type == Type_String)
- return escapedString(unit->stringAt(stringIndex));
- else
- return valueAsString(unit);
-}
-
-/*!
-Returns the property cache, if one alread exists. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
-{
- if (type.isValid())
- return typePropertyCache;
- else
- return compilationUnit->rootPropertyCache();
-}
-
-/*!
-Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
-*/
-QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
-{
- if (typePropertyCache) {
- return typePropertyCache;
- } else if (type.isValid()) {
- typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
- return typePropertyCache;
- } else {
- return compilationUnit->rootPropertyCache();
- }
-}
-
-bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
-{
- if (type.isValid()) {
- bool ok = false;
- hash->addData(createPropertyCache(engine)->checksum(&ok));
- return ok;
- }
- if (!compilationUnit)
- return false;
- hash->addData(compilationUnit->unitData()->md5Checksum, sizeof(compilationUnit->unitData()->md5Checksum));
- return true;
-}
-
-template <typename T>
-bool qtTypeInherits(const QMetaObject *mo) {
- while (mo) {
- if (mo == &T::staticMetaObject)
- return true;
- mo = mo->superClass();
- }
- return false;
-}
-
-void ResolvedTypeReference::doDynamicTypeCheck()
-{
- const QMetaObject *mo = nullptr;
- if (typePropertyCache)
- mo = typePropertyCache->firstCppMetaObject();
- else if (type.isValid())
- mo = type.metaObject();
- else if (compilationUnit)
- mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
- isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
-}
-
-bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
-{
- for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
- if (!it.value()->addToHash(hash, engine))
- return false;
- }
-
- return true;
-}
-
-#endif
-
-void CompilationUnit::destroy()
+void CompilationUnit::unlink()
{
-#if !defined(V4_BOOTSTRAP)
- if (qmlEngine)
- QQmlEnginePrivate::deleteInEngineThread(qmlEngine, this);
- else
-#endif
- delete this;
+ free(runtimeStrings);
+ runtimeStrings = nullptr;
+ delete [] runtimeRegularExpressions;
+ runtimeRegularExpressions = nullptr;
+ free(runtimeClasses);
+ runtimeClasses = nullptr;
}
-
void Unit::generateChecksum()
{
-#ifndef V4_BOOTSTRAP
+#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
QCryptographicHash hash(QCryptographicHash::Md5);
const int checksummableDataOffset = offsetof(QV4::CompiledData::Unit, md5Checksum) + sizeof(md5Checksum);
@@ -970,7 +230,6 @@ void Unit::generateChecksum()
bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const
{
-#ifndef V4_BOOTSTRAP
if (strncmp(magic, CompiledData::magic_str, sizeof(magic))) {
*errorString = QStringLiteral("Magic bytes in the header do not match");
return false;
@@ -1008,11 +267,6 @@ bool Unit::verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString)
#endif
return true;
-#else
- Q_UNUSED(expectedSourceTimeStamp)
- Q_UNUSED(errorString)
- return false;
-#endif
}
Location &Location::operator=(const QQmlJS::AST::SourceLocation &astLocation)
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index dd7ba471c3..94b64694ae 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -51,12 +51,12 @@
//
#include <QtCore/qstring.h>
+#include <QtCore/qcryptographichash.h>
#include <QVector>
#include <QStringList>
#include <QHash>
#include <QUrl>
-#include <private/qv4value_p.h>
#include <private/qv4executableallocator_p.h>
#include <private/qqmlrefcount_p.h>
#include <private/qqmlnullablevalue_p.h>
@@ -64,11 +64,6 @@
#include <private/qflagpointer_p.h>
#include <private/qendian_p.h>
#include <private/qqmljsastfwd_p.h>
-#ifndef V4_BOOTSTRAP
-#include <private/qqmltypenamecache_p.h>
-#include <private/qqmlpropertycachevector_p.h>
-#include "private/qintrusivelist_p.h"
-#endif
QT_BEGIN_NAMESPACE
@@ -100,7 +95,6 @@ struct Module;
struct Function;
class EvalISelFactory;
-class CompilationUnitMapper;
namespace CompiledData {
@@ -527,17 +521,6 @@ struct Q_QML_PRIVATE_EXPORT Binding
bool isTranslationBinding() const { return type == Type_Translation || type == Type_TranslationById; }
bool evaluatesToString() const { return type == Type_String || isTranslationBinding(); }
-#ifndef V4_BOOTSTRAP
- QString valueAsString(const CompilationUnit *unit) const;
- QString valueAsScriptString(const CompilationUnit *unit) const;
-#endif
- double valueAsNumber(const Value *constantTable) const
- {
- if (type != Type_Number)
- return 0.0;
- return constantTable[value.constantValueIndex].doubleValue();
- }
-
bool valueAsBoolean() const
{
if (type == Type_Boolean)
@@ -903,6 +886,10 @@ struct Unit
return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
}
+ QmlUnit *qmlUnit() {
+ return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
+ }
+
bool isSingleton() const {
return flags & Unit::IsSingleton;
}
@@ -1048,20 +1035,7 @@ struct TypeReferenceMap : QHash<int, TypeReference>
}
};
-#ifndef V4_BOOTSTRAP
-struct ResolvedTypeReference;
-// map from name index
-// While this could be a hash, a map is chosen here to provide a stable
-// order, which is used to calculating a check-sum on dependent meta-objects.
-struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
-{
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
-};
-
-using DependentTypesHasher = std::function<bool(QCryptographicHash *)>;
-#else
-struct DependentTypesHasher {};
-#endif
+using DependentTypesHasher = std::function<QByteArray()>;
// index is per-object binding index
typedef QVector<QQmlPropertyData*> BindingPropertyData;
@@ -1070,6 +1044,30 @@ typedef QVector<QQmlPropertyData*> BindingPropertyData;
struct Q_QML_PRIVATE_EXPORT CompilationUnitBase
{
+ Q_DISABLE_COPY(CompilationUnitBase)
+
+ CompilationUnitBase() = default;
+ ~CompilationUnitBase() = default;
+
+ CompilationUnitBase(CompilationUnitBase &&other) noexcept { *this = std::move(other); }
+
+ CompilationUnitBase &operator=(CompilationUnitBase &&other) noexcept
+ {
+ if (this != &other) {
+ runtimeStrings = other.runtimeStrings;
+ other.runtimeStrings = nullptr;
+ constants = other.constants;
+ other.constants = nullptr;
+ runtimeRegularExpressions = other.runtimeRegularExpressions;
+ other.runtimeRegularExpressions = nullptr;
+ runtimeClasses = other.runtimeClasses;
+ other.runtimeClasses = nullptr;
+ imports = other.imports;
+ other.imports = nullptr;
+ }
+ return *this;
+ }
+
// pointers either to data->constants() or little-endian memory copy.
QV4::Heap::String **runtimeStrings = nullptr; // Array
const Value* constants = nullptr;
@@ -1085,105 +1083,48 @@ Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offs
Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeClasses) == offsetof(CompilationUnitBase, runtimeRegularExpressions) + sizeof(const Value *));
Q_STATIC_ASSERT(offsetof(CompilationUnitBase, imports) == offsetof(CompilationUnitBase, runtimeClasses) + sizeof(const Value *));
-struct Q_QML_PRIVATE_EXPORT CompilationUnit final : public CompilationUnitBase
+struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase
{
+ Q_DISABLE_COPY(CompilationUnit)
+
const Unit *data = nullptr;
const QmlUnit *qmlData = nullptr;
+ QStringList dynamicStrings;
public:
+ using CompiledObject = CompiledData::Object;
+
CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString());
~CompilationUnit();
- void addref()
+ CompilationUnit(CompilationUnit &&other) noexcept
{
- Q_ASSERT(refCount.load() > 0);
- refCount.ref();
+ *this = std::move(other);
}
- void release()
+ CompilationUnit &operator=(CompilationUnit &&other) noexcept
{
- Q_ASSERT(refCount.load() > 0);
- if (!refCount.deref())
- destroy();
- }
- int count() const
- {
- return refCount.load();
+ if (this != &other) {
+ data = other.data;
+ other.data = nullptr;
+ qmlData = other.qmlData;
+ other.qmlData = nullptr;
+ dynamicStrings = std::move(other.dynamicStrings);
+ other.dynamicStrings.clear();
+ m_fileName = std::move(other.m_fileName);
+ other.m_fileName.clear();
+ m_finalUrlString = std::move(other.m_finalUrlString);
+ other.m_finalUrlString.clear();
+ m_module = other.m_module;
+ other.m_module = nullptr;
+ CompilationUnitBase::operator=(std::move(other));
+ }
+ return *this;
}
const Unit *unitData() const { return data; }
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
const QString &fileName = QString(), const QString &finalUrlString = QString());
-#ifndef V4_BOOTSTRAP
- QIntrusiveListNode nextCompilationUnit;
- ExecutionEngine *engine = nullptr;
- QQmlEnginePrivate *qmlEngine = nullptr; // only used in QML environment for composite types, not in plain QJSEngine case.
-
- // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
- // warnings about that code. They include any potential URL interceptions and thus represent the
- // "physical" location of the code.
- //
- // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
- // They are _not_ intercepted and thus represent the "logical" name for the code.
-
- QString fileName() const { return m_fileName; }
- QString finalUrlString() const { return m_finalUrlString; }
- QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
- QUrl finalUrl() const
- {
- if (m_finalUrl.isNull)
- m_finalUrl = QUrl(finalUrlString());
- return m_finalUrl;
- }
-
- QV4::Lookup *runtimeLookups = nullptr;
- QVector<QV4::Function *> runtimeFunctions;
- QVector<QV4::Heap::InternalClass *> runtimeBlocks;
- mutable QVector<QV4::Heap::Object *> templateObjects;
- mutable QQmlNullableValue<QUrl> m_url;
- mutable QQmlNullableValue<QUrl> m_finalUrl;
-
- // QML specific fields
- QQmlPropertyCacheVector propertyCaches;
- QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
-
- QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
-
- // index is object index. This allows fast access to the
- // property data when initializing bindings, avoiding expensive
- // lookups by string (property name).
- QVector<BindingPropertyData> bindingPropertyDataPerObject;
-
- // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
- // this is initialized on-demand by QQmlContextData
- QHash<int, IdentifierHash> namedObjectsPerComponentCache;
- inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
-
- void finalizeCompositeType(QQmlEnginePrivate *qmlEngine);
-
- int totalBindingsCount = 0; // Number of bindings used in this type
- int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses
- int totalObjectCount = 0; // Number of objects explicitly instantiated
-
- QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
- ResolvedTypeReferenceMap resolvedTypes;
- ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
-
- bool verifyChecksum(const DependentTypesHasher &dependencyHasher) const;
-
- int metaTypeId = -1;
- int listMetaTypeId = -1;
- bool isRegisteredWithEngine = false;
-
- QScopedPointer<CompilationUnitMapper> backingFile;
- QStringList dynamicStrings;
-
- // --- interface for QQmlPropertyCacheCreator
- typedef Object CompiledObject;
- int objectCount() const { return qmlData->nObjects; }
- const Object *objectAt(int index) const { return qmlData->objectAt(index); }
- int importCount() const { return qmlData->nImports; }
- const Import *importAt(int index) const { return qmlData->importAt(index); }
QString stringAt(int index) const
{
if (uint(index) >= data->stringTableSize)
@@ -1191,117 +1132,66 @@ public:
return data->stringAtInternal(index);
}
- Heap::Object *templateObjectAt(int index) const;
-
- struct FunctionIterator
- {
- FunctionIterator(const Unit *unit, const Object *object, int index) : unit(unit), object(object), index(index) {}
- const Unit *unit;
- const Object *object;
- int index;
-
- const Function *operator->() const { return unit->functionAt(object->functionOffsetTable()[index]); }
- void operator++() { ++index; }
- bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
- bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
- };
- FunctionIterator objectFunctionsBegin(const Object *object) const { return FunctionIterator(data, object, 0); }
- FunctionIterator objectFunctionsEnd(const Object *object) const { return FunctionIterator(data, object, object->nFunctions); }
- // ---
+ QString fileName() const { return m_fileName; }
+ QString finalUrlString() const { return m_finalUrlString; }
- bool isESModule() const { return data->flags & Unit::IsESModule; }
- bool isSharedLibrary() const { return data->flags & Unit::IsSharedLibrary; }
- QStringList moduleRequests() const;
- Heap::Module *instantiate(ExecutionEngine *engine);
- const Value *resolveExport(QV4::String *exportName);
- QStringList exportedNames() const;
- void evaluate();
- void evaluateModuleRequests();
+ Heap::Module *module() const { return m_module; }
+ void setModule(Heap::Module *module) { m_module = module; }
- QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
- void markObjects(MarkStack *markStack);
-
- bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
-
- static QString localCacheFilePath(const QUrl &url);
-
-protected:
- quint32 totalStringCount() const
- { return data->stringTableSize; }
-
-#else // V4_BOOTSTRAP
- QString stringAt(int index) const { return data->stringAtInternal(index); }
-#endif // V4_BOOTSTRAP
-
private:
- void destroy();
-
- struct ResolveSetEntry
- {
- ResolveSetEntry() {}
- ResolveSetEntry(CompilationUnit *module, QV4::String *exportName)
- : module(module), exportName(exportName) {}
- CompilationUnit *module = nullptr;
- QV4::String *exportName = nullptr;
- };
-
- const Value *resolveExportRecursively(QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet);
- const ExportEntry *lookupNameInExportTable(const ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const;
- void getExportedNamesRecursively(QStringList *names, QVector<const CompilationUnit *> *exportNameSet, bool includeDefaultExport = true) const;
-
QString m_fileName; // initialized from data->sourceFileIndex
QString m_finalUrlString; // initialized from data->finalUrlIndex
- QAtomicInt refCount = 1;
-
- Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex);
-
Heap::Module *m_module = nullptr;
public:
-#if defined(V4_BOOTSTRAP)
- bool saveToDisk(const QString &outputFileName, QString *errorString);
-#else
- bool saveToDisk(const QUrl &unitUrl, QString *errorString);
-#endif
+ bool saveToDisk(const QString &outputFileName, QString *errorString) const;
};
-#ifndef V4_BOOTSTRAP
-struct ResolvedTypeReference
+class SaveableUnitPointer
{
- ResolvedTypeReference()
- : majorVersion(0)
- , minorVersion(0)
- , isFullyDynamicType(false)
- {}
+ Q_DISABLE_COPY_MOVE(SaveableUnitPointer)
+public:
+ SaveableUnitPointer(const CompilationUnit *unit, quint32 temporaryFlags = Unit::StaticData) :
+ unit(unit)
+ {
+ quint32_le &unitFlags = mutableFlags();
+ quint32 origFlags = unitFlags;
+ unitFlags |= temporaryFlags;
+ changedFlags = origFlags ^ unitFlags;
+ }
- QQmlType type;
- QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
+ ~SaveableUnitPointer()
+ {
+ mutableFlags() ^= changedFlags;
+ }
- int majorVersion;
- int minorVersion;
- // Types such as QQmlPropertyMap can add properties dynamically at run-time and
- // therefore cannot have a property cache installed when instantiated.
- bool isFullyDynamicType;
+ const CompilationUnit *operator->() const { return unit; }
+ const CompilationUnit &operator*() const { return *unit; }
+ operator const CompilationUnit *() { return unit; }
- QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
- QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
- bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+ template<typename Char>
+ const Char *data() const
+ {
+ Q_STATIC_ASSERT(sizeof(Char) == 1);
+ const Char *dataPtr;
+ memcpy(&dataPtr, &unit->data, sizeof(dataPtr));
+ return dataPtr;
+ }
- void doDynamicTypeCheck();
+ quint32 size() const
+ {
+ return unit->data->unitSize;
+ }
+
+private:
+ quint32_le &mutableFlags() { return const_cast<Unit *>(unit->unitData())->flags; };
+ const CompilationUnit *unit;
+ quint32 changedFlags;
};
-IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
-{
- auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
- if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end()))
- return createNamedObjectsPerComponent(componentObjectIndex);
- return *it;
-}
-#endif // V4_BOOTSTRAP
} // CompiledData namespace
} // QV4 namespace
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 123d77f788..4a54e5a44b 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -40,7 +40,6 @@
#include <qv4compiler_p.h>
#include <qv4compileddata_p.h>
#include <qv4codegen_p.h>
-#include <private/qv4string_p.h>
#include <private/qv4value_p.h>
#include <private/qv4alloca_p.h>
#include <private/qqmljslexer_p.h>
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 8984b6931e..ef67a11a70 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -49,7 +49,6 @@
#include <private/qqmljsast_p.h>
#include <private/qv4compilercontext_p.h>
#include <private/qv4codegen_p.h>
-#include <private/qv4string_p.h>
QT_USE_NAMESPACE
using namespace QV4;
diff --git a/src/qml/compiler/qv4executablecompilationunit.cpp b/src/qml/compiler/qv4executablecompilationunit.cpp
new file mode 100644
index 0000000000..97c828d4d8
--- /dev/null
+++ b/src/qml/compiler/qv4executablecompilationunit.cpp
@@ -0,0 +1,809 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4executablecompilationunit_p.h"
+
+#include <private/qv4engine_p.h>
+#include <private/qv4regexp_p.h>
+#include <private/qv4lookup_p.h>
+#include <private/qv4qmlcontext_p.h>
+#include <private/qv4identifiertable_p.h>
+#include <private/qv4instr_moth_p.h>
+#include <private/qv4objectproto_p.h>
+#include <private/qqmlengine_p.h>
+#include <private/qv4qobjectwrapper_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
+#include <private/qv4module_p.h>
+#include <private/qv4compilationunitmapper_p.h>
+
+#include <QtQml/qqmlfile.h>
+#include <QtQml/qqmlpropertymap.h>
+
+#include <QtCore/qdir.h>
+#include <QtCore/qstandardpaths.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qscopeguard.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+ExecutableCompilationUnit::ExecutableCompilationUnit() = default;
+
+ExecutableCompilationUnit::ExecutableCompilationUnit(
+ CompiledData::CompilationUnit &&compilationUnit)
+ : CompiledData::CompilationUnit(std::move(compilationUnit))
+{}
+
+ExecutableCompilationUnit::~ExecutableCompilationUnit()
+{
+ unlink();
+}
+
+QString ExecutableCompilationUnit::localCacheFilePath(const QUrl &url)
+{
+ const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
+ const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix();
+ QCryptographicHash fileNameHash(QCryptographicHash::Sha1);
+ fileNameHash.addData(localSourcePath.toUtf8());
+ QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/");
+ QDir::root().mkpath(directory);
+ return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix;
+}
+
+static QString toString(QV4::ReturnedValue v)
+{
+ Value val = Value::fromReturnedValue(v);
+ QString result;
+ if (val.isInt32())
+ result = QLatin1String("int ");
+ else if (val.isDouble())
+ result = QLatin1String("double ");
+ if (val.isEmpty())
+ result += QLatin1String("empty");
+ else
+ result += val.toQStringNoThrow();
+ return result;
+}
+
+static void dumpConstantTable(const Value *constants, uint count)
+{
+ QDebug d = qDebug();
+ d.nospace() << right;
+ for (uint i = 0; i < count; ++i) {
+ d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
+ << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
+ }
+}
+
+QV4::Function *ExecutableCompilationUnit::linkToEngine(ExecutionEngine *engine)
+{
+ this->engine = engine;
+ engine->compilationUnits.insert(this);
+
+ Q_ASSERT(!runtimeStrings);
+ Q_ASSERT(data);
+ const quint32 stringCount = totalStringCount();
+ runtimeStrings = (QV4::Heap::String **)malloc(stringCount * sizeof(QV4::Heap::String*));
+ // memset the strings to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeStrings, 0, stringCount * sizeof(QV4::Heap::String*));
+ for (uint i = 0; i < stringCount; ++i)
+ runtimeStrings[i] = engine->newString(stringAt(i));
+
+ runtimeRegularExpressions
+ = new QV4::Value[data->regexpTableSize];
+ // memset the regexps to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeRegularExpressions, 0,
+ data->regexpTableSize * sizeof(QV4::Value));
+ for (uint i = 0; i < data->regexpTableSize; ++i) {
+ const CompiledData::RegExp *re = data->regexpAt(i);
+ uint f = re->flags;
+ const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
+ runtimeRegularExpressions[i] = QV4::RegExp::create(
+ engine, stringAt(re->stringIndex), flags);
+ }
+
+ if (data->lookupTableSize) {
+ runtimeLookups = new QV4::Lookup[data->lookupTableSize];
+ memset(runtimeLookups, 0, data->lookupTableSize * sizeof(QV4::Lookup));
+ const CompiledData::Lookup *compiledLookups = data->lookupTable();
+ for (uint i = 0; i < data->lookupTableSize; ++i) {
+ QV4::Lookup *l = runtimeLookups + i;
+
+ CompiledData::Lookup::Type type
+ = CompiledData::Lookup::Type(uint(compiledLookups[i].type_and_flags));
+ if (type == CompiledData::Lookup::Type_Getter)
+ l->getter = QV4::Lookup::getterGeneric;
+ else if (type == CompiledData::Lookup::Type_Setter)
+ l->setter = QV4::Lookup::setterGeneric;
+ else if (type == CompiledData::Lookup::Type_GlobalGetter)
+ l->globalGetter = QV4::Lookup::globalGetterGeneric;
+ else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
+ l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
+ l->nameIndex = compiledLookups[i].nameIndex;
+ }
+ }
+
+ if (data->jsClassTableSize) {
+ runtimeClasses
+ = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize
+ * sizeof(QV4::Heap::InternalClass *));
+ // memset the regexps to 0 in case a GC run happens while we're within the loop below
+ memset(runtimeClasses, 0,
+ data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *));
+ for (uint i = 0; i < data->jsClassTableSize; ++i) {
+ int memberCount = 0;
+ const CompiledData::JSClassMember *member
+ = data->jsClassAt(i, &memberCount);
+ runtimeClasses[i]
+ = engine->internalClasses(QV4::ExecutionEngine::Class_Object);
+ for (int j = 0; j < memberCount; ++j, ++member)
+ runtimeClasses[i]
+ = runtimeClasses[i]->addMember(
+ engine->identifierTable->asPropertyKey(
+ runtimeStrings[member->nameOffset]),
+ member->isAccessor
+ ? QV4::Attr_Accessor
+ : QV4::Attr_Data);
+ }
+ }
+
+ runtimeFunctions.resize(data->functionTableSize);
+ for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
+ const QV4::CompiledData::Function *compiledFunction = data->functionAt(i);
+ runtimeFunctions[i] = QV4::Function::create(engine, this, compiledFunction);
+ }
+
+ Scope scope(engine);
+ Scoped<InternalClass> ic(scope);
+
+ runtimeBlocks.resize(data->blockTableSize);
+ for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
+ const QV4::CompiledData::Block *compiledBlock = data->blockAt(i);
+ ic = engine->internalClasses(EngineBase::Class_CallContext);
+
+ // first locals
+ const quint32_le *localsIndices = compiledBlock->localsTable();
+ for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
+ ic = ic->addMember(
+ engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[j]]),
+ Attr_NotConfigurable);
+ runtimeBlocks[i] = ic->d();
+ }
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
+ if (showCode) {
+ qDebug() << "=== Constant table";
+ dumpConstantTable(constants, data->constantTableSize);
+ qDebug() << "=== String table";
+ for (uint i = 0, end = totalStringCount(); i < end; ++i)
+ qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
+ qDebug() << "=== Closure table";
+ for (uint i = 0; i < data->functionTableSize; ++i)
+ qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
+ qDebug() << "root function at index "
+ << (data->indexOfRootFunction != -1
+ ? data->indexOfRootFunction : 0);
+ }
+
+ if (data->indexOfRootFunction != -1)
+ return runtimeFunctions[data->indexOfRootFunction];
+ else
+ return nullptr;
+}
+
+Heap::Object *ExecutableCompilationUnit::templateObjectAt(int index) const
+{
+ Q_ASSERT(index < int(data->templateObjectTableSize));
+ if (!templateObjects.size())
+ templateObjects.resize(data->templateObjectTableSize);
+ Heap::Object *o = templateObjects.at(index);
+ if (o)
+ return o;
+
+ // create the template object
+ Scope scope(engine);
+ const CompiledData::TemplateObject *t = data->templateObjectAt(index);
+ Scoped<ArrayObject> a(scope, engine->newArrayObject(t->size));
+ Scoped<ArrayObject> raw(scope, engine->newArrayObject(t->size));
+ ScopedValue s(scope);
+ for (uint i = 0; i < t->size; ++i) {
+ s = runtimeStrings[t->stringIndexAt(i)];
+ a->arraySet(i, s);
+ s = runtimeStrings[t->rawStringIndexAt(i)];
+ raw->arraySet(i, s);
+ }
+
+ ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, raw, 1);
+ a->defineReadonlyProperty(QStringLiteral("raw"), raw);
+ ObjectPrototype::method_freeze(engine->functionCtor(), nullptr, a, 1);
+
+ templateObjects[index] = a->objectValue()->d();
+ return templateObjects.at(index);
+}
+
+void ExecutableCompilationUnit::unlink()
+{
+ if (engine)
+ nextCompilationUnit.remove();
+
+ if (isRegisteredWithEngine) {
+ Q_ASSERT(data && propertyCaches.count() > 0 && propertyCaches.at(/*root object*/0));
+ if (qmlEngine)
+ qmlEngine->unregisterInternalCompositeType(this);
+ QQmlMetaType::unregisterInternalCompositeType(this);
+ isRegisteredWithEngine = false;
+ }
+
+ propertyCaches.clear();
+
+ if (runtimeLookups) {
+ for (uint i = 0; i < data->lookupTableSize; ++i) {
+ QV4::Lookup &l = runtimeLookups[i];
+ if (l.getter == QV4::QObjectWrapper::lookupGetter) {
+ if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
+ pc->release();
+ } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) {
+ if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache)
+ pc->release();
+ }
+
+ if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) {
+ if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache)
+ pc->release();
+ }
+ }
+ }
+
+ dependentScripts.clear();
+
+ typeNameCache = nullptr;
+
+ qDeleteAll(resolvedTypes);
+ resolvedTypes.clear();
+
+ engine = nullptr;
+ qmlEngine = nullptr;
+
+ delete [] runtimeLookups;
+ runtimeLookups = nullptr;
+
+ for (QV4::Function *f : qAsConst(runtimeFunctions))
+ f->destroy();
+ runtimeFunctions.clear();
+
+ CompiledData::CompilationUnit::unlink();
+}
+
+void ExecutableCompilationUnit::markObjects(QV4::MarkStack *markStack)
+{
+ if (runtimeStrings) {
+ for (uint i = 0, end = totalStringCount(); i < end; ++i)
+ if (runtimeStrings[i])
+ runtimeStrings[i]->mark(markStack);
+ }
+ if (runtimeRegularExpressions) {
+ for (uint i = 0; i < data->regexpTableSize; ++i)
+ runtimeRegularExpressions[i].mark(markStack);
+ }
+ if (runtimeClasses) {
+ for (uint i = 0; i < data->jsClassTableSize; ++i)
+ if (runtimeClasses[i])
+ runtimeClasses[i]->mark(markStack);
+ }
+ for (QV4::Function *f : qAsConst(runtimeFunctions))
+ if (f && f->internalClass)
+ f->internalClass->mark(markStack);
+ for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks))
+ if (c)
+ c->mark(markStack);
+
+ for (QV4::Heap::Object *o : qAsConst(templateObjects))
+ if (o)
+ o->mark(markStack);
+
+ if (runtimeLookups) {
+ for (uint i = 0; i < data->lookupTableSize; ++i)
+ runtimeLookups[i].markObjects(markStack);
+ }
+
+ if (auto mod = module())
+ mod->mark(markStack);
+}
+
+IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(int componentObjectIndex)
+{
+ IdentifierHash namedObjectCache(engine);
+ const CompiledData::Object *component = objectAt(componentObjectIndex);
+ const quint32_le *namedObjectIndexPtr = component->namedObjectsInComponentTable();
+ for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
+ const CompiledData::Object *namedObject = objectAt(*namedObjectIndexPtr);
+ namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
+ }
+ return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
+}
+
+void ExecutableCompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine)
+{
+ this->qmlEngine = qmlEngine;
+
+ // Add to type registry of composites
+ if (propertyCaches.needsVMEMetaObject(/*root object*/0)) {
+ QQmlMetaType::registerInternalCompositeType(this);
+ qmlEngine->registerInternalCompositeType(this);
+ } else {
+ const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
+ auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ Q_ASSERT(typeRef);
+ if (typeRef->compilationUnit) {
+ metaTypeId = typeRef->compilationUnit->metaTypeId;
+ listMetaTypeId = typeRef->compilationUnit->listMetaTypeId;
+ } else {
+ metaTypeId = typeRef->type.typeId();
+ listMetaTypeId = typeRef->type.qListTypeId();
+ }
+ }
+
+ // Collect some data for instantiation later.
+ int bindingCount = 0;
+ int parserStatusCount = 0;
+ int objectCount = 0;
+ for (quint32 i = 0, count = this->objectCount(); i < count; ++i) {
+ const QV4::CompiledData::Object *obj = objectAt(i);
+ bindingCount += obj->nBindings;
+ if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
+ if (typeRef->type.isValid()) {
+ if (typeRef->type.parserStatusCast() != -1)
+ ++parserStatusCount;
+ }
+ ++objectCount;
+ if (typeRef->compilationUnit) {
+ bindingCount += typeRef->compilationUnit->totalBindingsCount;
+ parserStatusCount += typeRef->compilationUnit->totalParserStatusCount;
+ objectCount += typeRef->compilationUnit->totalObjectCount;
+ }
+ }
+ }
+
+ totalBindingsCount = bindingCount;
+ totalParserStatusCount = parserStatusCount;
+ totalObjectCount = objectCount;
+}
+
+bool ExecutableCompilationUnit::verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
+{
+ if (!dependencyHasher) {
+ for (size_t i = 0; i < sizeof(data->dependencyMD5Checksum); ++i) {
+ if (data->dependencyMD5Checksum[i] != 0)
+ return false;
+ }
+ return true;
+ }
+ const QByteArray checksum = dependencyHasher();
+ return checksum.size() == sizeof(data->dependencyMD5Checksum)
+ && memcmp(data->dependencyMD5Checksum, checksum.constData(),
+ sizeof(data->dependencyMD5Checksum)) == 0;
+}
+
+QStringList ExecutableCompilationUnit::moduleRequests() const
+{
+ QStringList requests;
+ requests.reserve(data->moduleRequestTableSize);
+ for (uint i = 0; i < data->moduleRequestTableSize; ++i)
+ requests << stringAt(data->moduleRequestTable()[i]);
+ return requests;
+}
+
+Heap::Module *ExecutableCompilationUnit::instantiate(ExecutionEngine *engine)
+{
+ if (isESModule() && module())
+ return module();
+
+ if (data->indexOfRootFunction < 0)
+ return nullptr;
+
+ if (!this->engine)
+ linkToEngine(engine);
+
+ Scope scope(engine);
+ Scoped<Module> module(scope, engine->memoryManager->allocate<Module>(engine, this));
+
+ if (isESModule())
+ setModule(module->d());
+
+ for (const QString &request: moduleRequests()) {
+ auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
+ if (engine->hasException)
+ return nullptr;
+ dependentModuleUnit->instantiate(engine);
+ }
+
+ ScopedString importName(scope);
+
+ const uint importCount = data->importEntryTableSize;
+ if (importCount > 0) {
+ imports = new const Value *[importCount];
+ memset(imports, 0, importCount * sizeof(Value *));
+ }
+ for (uint i = 0; i < importCount; ++i) {
+ const CompiledData::ImportEntry &entry = data->importEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ importName = runtimeStrings[entry.importName];
+ const Value *valuePtr = dependentModuleUnit->resolveExport(importName);
+ if (!valuePtr) {
+ QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
+ referenceErrorMessage += importName->toQString();
+ engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
+ return nullptr;
+ }
+ imports[i] = valuePtr;
+ }
+
+ for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ if (!dependentModuleUnit)
+ return nullptr;
+
+ ScopedString importName(scope, runtimeStrings[entry.importName]);
+ if (!dependentModuleUnit->resolveExport(importName)) {
+ QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
+ referenceErrorMessage += importName->toQString();
+ engine->throwReferenceError(referenceErrorMessage, fileName(), entry.location.line, entry.location.column);
+ return nullptr;
+ }
+ }
+
+ return module->d();
+}
+
+const Value *ExecutableCompilationUnit::resolveExportRecursively(
+ QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
+{
+ if (!module())
+ return nullptr;
+
+ for (const auto &entry: *resolveSet)
+ if (entry.module == this && entry.exportName->isEqualTo(exportName))
+ return nullptr;
+
+ (*resolveSet) << ResolveSetEntry(this, exportName);
+
+ if (exportName->toQString() == QLatin1String("*"))
+ return &module()->self;
+
+ Scope scope(engine);
+
+ if (auto localExport = lookupNameInExportTable(
+ data->localExportEntryTable(), data->localExportEntryTableSize, exportName)) {
+ ScopedString localName(scope, runtimeStrings[localExport->localName]);
+ uint index = module()->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
+ if (index == UINT_MAX)
+ return nullptr;
+ if (index >= module()->scope->locals.size)
+ return imports[index - module()->scope->locals.size];
+ return &module()->scope->locals[index];
+ }
+
+ if (auto indirectExport = lookupNameInExportTable(
+ data->indirectExportEntryTable(), data->indirectExportEntryTableSize, exportName)) {
+ auto dependentModuleUnit = engine->loadModule(urlAt(indirectExport->moduleRequest), this);
+ if (!dependentModuleUnit)
+ return nullptr;
+ ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
+ return dependentModuleUnit->resolveExportRecursively(importName, resolveSet);
+ }
+
+
+ if (exportName->toQString() == QLatin1String("default"))
+ return nullptr;
+
+ const Value *starResolution = nullptr;
+
+ for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ if (!dependentModuleUnit)
+ return nullptr;
+
+ const Value *resolution = dependentModuleUnit->resolveExportRecursively(exportName, resolveSet);
+ // ### handle ambiguous
+ if (resolution) {
+ if (!starResolution) {
+ starResolution = resolution;
+ continue;
+ }
+ if (resolution != starResolution)
+ return nullptr;
+ }
+ }
+
+ return starResolution;
+}
+
+const CompiledData::ExportEntry *ExecutableCompilationUnit::lookupNameInExportTable(
+ const CompiledData::ExportEntry *firstExportEntry, int tableSize, QV4::String *name) const
+{
+ const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
+ auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry, name, [this](const CompiledData::ExportEntry &lhs, QV4::String *name) {
+ return stringAt(lhs.exportName) < name->toQString();
+ });
+ if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) != name->toQString())
+ return nullptr;
+ return matchingExport;
+}
+
+void ExecutableCompilationUnit::getExportedNamesRecursively(
+ QStringList *names, QVector<const ExecutableCompilationUnit*> *exportNameSet,
+ bool includeDefaultExport) const
+{
+ if (exportNameSet->contains(this))
+ return;
+ exportNameSet->append(this);
+
+ const auto append = [names, includeDefaultExport](const QString &name) {
+ if (!includeDefaultExport && name == QLatin1String("default"))
+ return;
+ names->append(name);
+ };
+
+ for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->localExportEntryTable()[i];
+ append(stringAt(entry.exportName));
+ }
+
+ for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->indirectExportEntryTable()[i];
+ append(stringAt(entry.exportName));
+ }
+
+ for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
+ const CompiledData::ExportEntry &entry = data->starExportEntryTable()[i];
+ auto dependentModuleUnit = engine->loadModule(urlAt(entry.moduleRequest), this);
+ if (!dependentModuleUnit)
+ return;
+ dependentModuleUnit->getExportedNamesRecursively(names, exportNameSet, /*includeDefaultExport*/false);
+ }
+}
+
+void ExecutableCompilationUnit::evaluate()
+{
+ QV4::Scope scope(engine);
+ QV4::Scoped<Module> mod(scope, module());
+ mod->evaluate();
+}
+
+void ExecutableCompilationUnit::evaluateModuleRequests()
+{
+ for (const QString &request: moduleRequests()) {
+ auto dependentModuleUnit = engine->loadModule(QUrl(request), this);
+ if (engine->hasException)
+ return;
+ dependentModuleUnit->evaluate();
+ if (engine->hasException)
+ return;
+ }
+}
+
+bool ExecutableCompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
+{
+ if (!QQmlFile::isLocalFile(url)) {
+ *errorString = QStringLiteral("File has to be a local file.");
+ return false;
+ }
+
+ const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url);
+ QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper());
+
+ const QStringList cachePaths = { sourcePath + QLatin1Char('c'), localCacheFilePath(url) };
+ for (const QString &cachePath : cachePaths) {
+ CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString);
+ if (!mappedUnit)
+ continue;
+
+ const CompiledData::Unit * const oldDataPtr
+ = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data
+ : nullptr;
+ const CompiledData::Unit *oldData = data;
+ auto dataPtrRevert = qScopeGuard([this, oldData](){
+ setUnitData(oldData);
+ });
+ setUnitData(mappedUnit);
+
+ if (data->sourceFileIndex != 0
+ && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
+ *errorString = QStringLiteral("QML source file has moved to a different location.");
+ continue;
+ }
+
+ dataPtrRevert.dismiss();
+ free(const_cast<CompiledData::Unit*>(oldDataPtr));
+ backingFile.reset(cacheFile.take());
+ return true;
+ }
+
+ return false;
+}
+
+bool ExecutableCompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
+{
+ if (data->sourceTimeStamp == 0) {
+ *errorString = QStringLiteral("Missing time stamp for source file");
+ return false;
+ }
+
+ if (!QQmlFile::isLocalFile(unitUrl)) {
+ *errorString = QStringLiteral("File has to be a local file.");
+ return false;
+ }
+
+ return CompilationUnit::saveToDisk(localCacheFilePath(unitUrl), errorString);
+}
+
+/*!
+Returns the property cache, if one alread exists. The cache is not referenced.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const
+{
+ if (type.isValid())
+ return typePropertyCache;
+ else
+ return compilationUnit->rootPropertyCache();
+}
+
+/*!
+Returns the property cache, creating one if it doesn't already exist. The cache is not referenced.
+*/
+QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine)
+{
+ if (typePropertyCache) {
+ return typePropertyCache;
+ } else if (type.isValid()) {
+ typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type.metaObject(), minorVersion);
+ return typePropertyCache;
+ } else {
+ return compilationUnit->rootPropertyCache();
+ }
+}
+
+bool ResolvedTypeReference::addToHash(QCryptographicHash *hash, QQmlEngine *engine)
+{
+ if (type.isValid()) {
+ bool ok = false;
+ hash->addData(createPropertyCache(engine)->checksum(&ok));
+ return ok;
+ }
+ if (!compilationUnit)
+ return false;
+ hash->addData(compilationUnit->data->md5Checksum,
+ sizeof(compilationUnit->data->md5Checksum));
+ return true;
+}
+
+template <typename T>
+bool qtTypeInherits(const QMetaObject *mo) {
+ while (mo) {
+ if (mo == &T::staticMetaObject)
+ return true;
+ mo = mo->superClass();
+ }
+ return false;
+}
+
+void ResolvedTypeReference::doDynamicTypeCheck()
+{
+ const QMetaObject *mo = nullptr;
+ if (typePropertyCache)
+ mo = typePropertyCache->firstCppMetaObject();
+ else if (type.isValid())
+ mo = type.metaObject();
+ else if (compilationUnit)
+ mo = compilationUnit->rootPropertyCache()->firstCppMetaObject();
+ isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
+}
+
+bool ResolvedTypeReferenceMap::addToHash(QCryptographicHash *hash, QQmlEngine *engine) const
+{
+ for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
+ if (!it.value()->addToHash(hash, engine))
+ return false;
+ }
+
+ return true;
+}
+
+QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const
+{
+ using namespace CompiledData;
+ switch (binding->type) {
+ case Binding::Type_Script:
+ case Binding::Type_String:
+ return stringAt(binding->stringIndex);
+ case Binding::Type_Null:
+ return QStringLiteral("null");
+ case Binding::Type_Boolean:
+ return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
+ case Binding::Type_Number:
+ return QString::number(bindingValueAsNumber(binding));
+ case Binding::Type_Invalid:
+ return QString();
+#if !QT_CONFIG(translation)
+ case Binding::Type_TranslationById:
+ case Binding::Type_Translation:
+ return unit->stringAt(
+ unit->data->translations()[binding->value.translationDataIndex].stringIndex);
+#else
+ case Binding::Type_TranslationById: {
+ const TranslationData &translation
+ = data->translations()[binding->value.translationDataIndex];
+ QByteArray id = stringAt(translation.stringIndex).toUtf8();
+ return qtTrId(id.constData(), translation.number);
+ }
+ case Binding::Type_Translation: {
+ const TranslationData &translation
+ = data->translations()[binding->value.translationDataIndex];
+ // This code must match that in the qsTr() implementation
+ const QString &path = fileName();
+ int lastSlash = path.lastIndexOf(QLatin1Char('/'));
+ QStringRef context = (lastSlash > -1) ? path.midRef(lastSlash + 1, path.length() - lastSlash - 5)
+ : QStringRef();
+ QByteArray contextUtf8 = context.toUtf8();
+ QByteArray comment = stringAt(translation.commentIndex).toUtf8();
+ QByteArray text = stringAt(translation.stringIndex).toUtf8();
+ return QCoreApplication::translate(contextUtf8.constData(), text.constData(),
+ comment.constData(), translation.number);
+ }
+#endif
+ default:
+ break;
+ }
+ return QString();
+}
+
+QString ExecutableCompilationUnit::bindingValueAsScriptString(
+ const CompiledData::Binding *binding) const
+{
+ return (binding->type == CompiledData::Binding::Type_String)
+ ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
+ : bindingValueAsString(binding);
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4executablecompilationunit_p.h b/src/qml/compiler/qv4executablecompilationunit_p.h
new file mode 100644
index 0000000000..4e3aadf28a
--- /dev/null
+++ b/src/qml/compiler/qv4executablecompilationunit_p.h
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV4EXECUTABLECOMPILATIONUNIT_P_H
+#define QV4EXECUTABLECOMPILATIONUNIT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qv4compileddata_p.h>
+#include <private/qqmlrefcount_p.h>
+#include <private/qintrusivelist_p.h>
+#include <private/qqmlpropertycachevector_p.h>
+#include <private/qqmltype_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlEnginePrivate;
+namespace QV4 {
+
+class CompilationUnitMapper;
+struct ResolvedTypeReference;
+// map from name index
+// While this could be a hash, a map is chosen here to provide a stable
+// order, which is used to calculating a check-sum on dependent meta-objects.
+struct ResolvedTypeReferenceMap: public QMap<int, ResolvedTypeReference*>
+{
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const;
+};
+
+class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit,
+ public QQmlRefCount
+{
+ Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit)
+public:
+ friend class QQmlRefPointer<ExecutableCompilationUnit>;
+
+ static QQmlRefPointer<ExecutableCompilationUnit> create(
+ CompiledData::CompilationUnit &&compilationUnit)
+ {
+ return QQmlRefPointer<ExecutableCompilationUnit>(
+ new ExecutableCompilationUnit(std::move(compilationUnit)),
+ QQmlRefPointer<ExecutableCompilationUnit>::Adopt);
+ }
+
+ static QQmlRefPointer<ExecutableCompilationUnit> create()
+ {
+ return QQmlRefPointer<ExecutableCompilationUnit>(
+ new ExecutableCompilationUnit,
+ QQmlRefPointer<ExecutableCompilationUnit>::Adopt);
+ }
+
+ QIntrusiveListNode nextCompilationUnit;
+ ExecutionEngine *engine = nullptr;
+ QQmlEnginePrivate *qmlEngine = nullptr; // only used in QML environment for composite types, not in plain QJSEngine case.
+
+ // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
+ // warnings about that code. They include any potential URL interceptions and thus represent the
+ // "physical" location of the code.
+ //
+ // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
+ // They are _not_ intercepted and thus represent the "logical" name for the code.
+
+ QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
+ QUrl finalUrl() const
+ {
+ if (m_finalUrl.isNull)
+ m_finalUrl = QUrl(finalUrlString());
+ return m_finalUrl;
+ }
+
+ QV4::Lookup *runtimeLookups = nullptr;
+ QVector<QV4::Function *> runtimeFunctions;
+ QVector<QV4::Heap::InternalClass *> runtimeBlocks;
+ mutable QVector<QV4::Heap::Object *> templateObjects;
+ mutable QQmlNullableValue<QUrl> m_url;
+ mutable QQmlNullableValue<QUrl> m_finalUrl;
+
+ // QML specific fields
+ QQmlPropertyCacheVector propertyCaches;
+ QQmlRefPointer<QQmlPropertyCache> rootPropertyCache() const { return propertyCaches.at(/*root object*/0); }
+
+ QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
+
+ // index is object index. This allows fast access to the
+ // property data when initializing bindings, avoiding expensive
+ // lookups by string (property name).
+ QVector<CompiledData::BindingPropertyData> bindingPropertyDataPerObject;
+
+ // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
+ // this is initialized on-demand by QQmlContextData
+ QHash<int, IdentifierHash> namedObjectsPerComponentCache;
+ inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex);
+
+ void finalizeCompositeType(QQmlEnginePrivate *qmlEngine);
+
+ int totalBindingsCount = 0; // Number of bindings used in this type
+ int totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses
+ int totalObjectCount = 0; // Number of objects explicitly instantiated
+
+ QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
+ ResolvedTypeReferenceMap resolvedTypes;
+ ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
+
+ bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
+
+ int metaTypeId = -1;
+ int listMetaTypeId = -1;
+ bool isRegisteredWithEngine = false;
+
+ QScopedPointer<CompilationUnitMapper> backingFile;
+
+ // --- interface for QQmlPropertyCacheCreator
+ using CompiledObject = CompiledData::Object;
+ using CompiledFunction = CompiledData::Function;
+
+ int objectCount() const { return qmlData->nObjects; }
+ const CompiledObject *objectAt(int index) const
+ {
+ return qmlData->objectAt(index);
+ }
+
+ int importCount() const { return qmlData->nImports; }
+ const CompiledData::Import *importAt(int index) const
+ {
+ return qmlData->importAt(index);
+ }
+
+ Heap::Object *templateObjectAt(int index) const;
+
+ struct FunctionIterator
+ {
+ FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
+ : unit(unit), object(object), index(index) {}
+ const CompiledData::Unit *unit;
+ const CompiledObject *object;
+ int index;
+
+ const CompiledFunction *operator->() const
+ {
+ return unit->functionAt(object->functionOffsetTable()[index]);
+ }
+
+ void operator++() { ++index; }
+ bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
+ bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
+ };
+
+ FunctionIterator objectFunctionsBegin(const CompiledObject *object) const
+ {
+ return FunctionIterator(data, object, 0);
+ }
+
+ FunctionIterator objectFunctionsEnd(const CompiledObject *object) const
+ {
+ return FunctionIterator(data, object, object->nFunctions);
+ }
+
+ bool isESModule() const
+ {
+ return data->flags & CompiledData::Unit::IsESModule;
+ }
+
+ bool isSharedLibrary() const
+ {
+ return data->flags & CompiledData::Unit::IsSharedLibrary;
+ }
+
+ QStringList moduleRequests() const;
+ Heap::Module *instantiate(ExecutionEngine *engine);
+ const Value *resolveExport(QV4::String *exportName)
+ {
+ QVector<ResolveSetEntry> resolveSet;
+ return resolveExportRecursively(exportName, &resolveSet);
+ }
+
+ QStringList exportedNames() const
+ {
+ QStringList names;
+ QVector<const ExecutableCompilationUnit*> exportNameSet;
+ getExportedNamesRecursively(&names, &exportNameSet);
+ names.sort();
+ auto last = std::unique(names.begin(), names.end());
+ names.erase(last, names.end());
+ return names;
+ }
+
+ void evaluate();
+ void evaluateModuleRequests();
+
+ QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
+ void unlink();
+
+ void markObjects(MarkStack *markStack);
+
+ bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
+
+ static QString localCacheFilePath(const QUrl &url);
+ bool saveToDisk(const QUrl &unitUrl, QString *errorString);
+
+ QString bindingValueAsString(const CompiledData::Binding *binding) const;
+ QString bindingValueAsScriptString(const CompiledData::Binding *binding) const;
+ double bindingValueAsNumber(const CompiledData::Binding *binding) const
+ {
+ if (binding->type != CompiledData::Binding::Type_Number)
+ return 0.0;
+ return constants[binding->value.constantValueIndex].doubleValue();
+ }
+
+protected:
+ quint32 totalStringCount() const
+ { return data->stringTableSize; }
+
+private:
+ struct ResolveSetEntry
+ {
+ ResolveSetEntry() {}
+ ResolveSetEntry(ExecutableCompilationUnit *module, QV4::String *exportName)
+ : module(module), exportName(exportName) {}
+ ExecutableCompilationUnit *module = nullptr;
+ QV4::String *exportName = nullptr;
+ };
+
+ ExecutableCompilationUnit();
+ ExecutableCompilationUnit(CompiledData::CompilationUnit &&compilationUnit);
+ ~ExecutableCompilationUnit();
+
+ const Value *resolveExportRecursively(QV4::String *exportName,
+ QVector<ResolveSetEntry> *resolveSet);
+
+ QUrl urlAt(int index) const { return QUrl(stringAt(index)); }
+
+ Q_NEVER_INLINE IdentifierHash createNamedObjectsPerComponent(int componentObjectIndex);
+ const CompiledData::ExportEntry *lookupNameInExportTable(
+ const CompiledData::ExportEntry *firstExportEntry, int tableSize,
+ QV4::String *name) const;
+
+ void getExportedNamesRecursively(
+ QStringList *names, QVector<const ExecutableCompilationUnit *> *exportNameSet,
+ bool includeDefaultExport = true) const;
+};
+
+struct ResolvedTypeReference
+{
+ ResolvedTypeReference()
+ : majorVersion(0)
+ , minorVersion(0)
+ , isFullyDynamicType(false)
+ {}
+
+ QQmlType type;
+ QQmlRefPointer<QQmlPropertyCache> typePropertyCache;
+ QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit;
+
+ int majorVersion;
+ int minorVersion;
+ // Types such as QQmlPropertyMap can add properties dynamically at run-time and
+ // therefore cannot have a property cache installed when instantiated.
+ bool isFullyDynamicType;
+
+ QQmlRefPointer<QQmlPropertyCache> propertyCache() const;
+ QQmlRefPointer<QQmlPropertyCache> createPropertyCache(QQmlEngine *);
+ bool addToHash(QCryptographicHash *hash, QQmlEngine *engine);
+
+ void doDynamicTypeCheck();
+};
+
+IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
+{
+ auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
+ if (Q_UNLIKELY(it == namedObjectsPerComponentCache.end()))
+ return createNamedObjectsPerComponent(componentObjectIndex);
+ return *it;
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif // QV4EXECUTABLECOMPILATIONUNIT_P_H
diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp
index 5148154a6a..8a9bd66103 100644
--- a/src/qml/compiler/qv4instr_moth.cpp
+++ b/src/qml/compiler/qv4instr_moth.cpp
@@ -39,7 +39,7 @@
#include "qv4instr_moth_p.h"
#include <private/qv4compileddata_p.h>
-#include <private/qv4stackframe_p.h>
+#include <private/qv4calldata_p.h>
using namespace QV4;
using namespace QV4::Moth;
@@ -56,9 +56,7 @@ int InstrInfo::size(Instr::Type type)
static QByteArray alignedNumber(int n) {
QByteArray number = QByteArray::number(n);
- while (number.size() < 8)
- number.prepend(' ');
- return number;
+ return number.prepend(8 - number.size(), ' ');
}
static QByteArray alignedLineNumber(int line) {
@@ -83,25 +81,6 @@ static QByteArray rawBytes(const char *data, int n)
return ba;
}
-static QString toString(QV4::ReturnedValue v)
-{
-#ifdef V4_BOOTSTRAP
- return QStringLiteral("string-const(%1)").arg(v);
-#else // !V4_BOOTSTRAP
- Value val = Value::fromReturnedValue(v);
- QString result;
- if (val.isInt32())
- result = QLatin1String("int ");
- else if (val.isDouble())
- result = QLatin1String("double ");
- if (val.isEmpty())
- result += QLatin1String("empty");
- else
- result += val.toQStringNoThrow();
- return result;
-#endif // V4_BOOTSTRAP
-}
-
#define ABSOLUTE_OFFSET() \
(code - start + offset)
@@ -128,16 +107,6 @@ const int InstrInfo::argumentCount[] = {
FOR_EACH_MOTH_INSTR_ALL(MOTH_COLLECT_NARGS)
};
-
-void dumpConstantTable(const Value *constants, uint count)
-{
- QDebug d = qDebug();
- d.nospace();
- for (uint i = 0; i < count; ++i)
- d << alignedNumber(int(i)).constData() << ": "
- << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
-}
-
QString dumpRegister(int reg, int nFormals)
{
Q_STATIC_ASSERT(offsetof(CallData, function) == 0);
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 35a5fdfba5..5338583164 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -51,7 +51,6 @@
// We mean it.
//
#include <private/qv4global_p.h>
-#include <private/qv4value_p.h>
#include <private/qv4runtime_p.h>
#include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper
#include <qendian.h>
@@ -534,7 +533,6 @@ inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackS
// When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h
-void dumpConstantTable(const Value *constants, uint count);
void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1,
const QVector<CompiledData::CodeOffsetToLine> &lineNumberMapping = QVector<CompiledData::CodeOffsetToLine>());
inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1,