diff options
Diffstat (limited to 'src/qml/jsruntime/qv4executablecompilationunit_p.h')
-rw-r--r-- | src/qml/jsruntime/qv4executablecompilationunit_p.h | 344 |
1 files changed, 147 insertions, 197 deletions
diff --git a/src/qml/jsruntime/qv4executablecompilationunit_p.h b/src/qml/jsruntime/qv4executablecompilationunit_p.h index 6eef3b12c3..930e138732 100644 --- a/src/qml/jsruntime/qv4executablecompilationunit_p.h +++ b/src/qml/jsruntime/qv4executablecompilationunit_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QV4EXECUTABLECOMPILATIONUNIT_P_H #define QV4EXECUTABLECOMPILATIONUNIT_P_H @@ -51,173 +15,138 @@ // We mean it. // -#include <private/qv4compileddata_p.h> -#include <private/qv4identifier_p.h> -#include <private/qqmlrefcount_p.h> #include <private/qintrusivelist_p.h> +#include <private/qqmlmetatype_p.h> +#include <private/qqmlnullablevalue_p.h> #include <private/qqmlpropertycachevector_p.h> +#include <private/qqmlrefcount_p.h> #include <private/qqmltype_p.h> -#include <private/qqmlnullablevalue_p.h> +#include <private/qqmltypenamecache_p.h> +#include <private/qv4compileddata_p.h> +#include <private/qv4identifierhash_p.h> + +#include <memory> QT_BEGIN_NAMESPACE class QQmlScriptData; class QQmlEnginePrivate; -namespace QV4 { -// index is per-object binding index -typedef QVector<QQmlPropertyData*> BindingPropertyData; +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*> + +struct CompilationUnitRuntimeData { - bool addToHash(QCryptographicHash *hash, QQmlEngine *engine) const; + Heap::String **runtimeStrings = nullptr; // Array + + // pointers either to data->constants() or little-endian memory copy. + // We keep this member twice so that the JIT can access it via standard layout. + const StaticValue *constants = nullptr; + + QV4::StaticValue *runtimeRegularExpressions = nullptr; + Heap::InternalClass **runtimeClasses = nullptr; + const StaticValue **imports = nullptr; + + QV4::Lookup *runtimeLookups = nullptr; + QVector<QV4::Function *> runtimeFunctions; + QVector<QV4::Heap::InternalClass *> runtimeBlocks; + mutable QVector<QV4::Heap::Object *> templateObjects; }; -class Q_QML_PRIVATE_EXPORT ExecutableCompilationUnit final: public CompiledData::CompilationUnit, - public QQmlRefCount +static_assert(std::is_standard_layout_v<CompilationUnitRuntimeData>); +static_assert(offsetof(CompilationUnitRuntimeData, runtimeStrings) == 0); +static_assert(offsetof(CompilationUnitRuntimeData, constants) == sizeof(QV4::Heap::String **)); +static_assert(offsetof(CompilationUnitRuntimeData, runtimeRegularExpressions) == offsetof(CompilationUnitRuntimeData, constants) + sizeof(const StaticValue *)); +static_assert(offsetof(CompilationUnitRuntimeData, runtimeClasses) == offsetof(CompilationUnitRuntimeData, runtimeRegularExpressions) + sizeof(const StaticValue *)); +static_assert(offsetof(CompilationUnitRuntimeData, imports) == offsetof(CompilationUnitRuntimeData, runtimeClasses) + sizeof(const StaticValue *)); + +class Q_QML_EXPORT ExecutableCompilationUnit final + : public CompilationUnitRuntimeData, + public QQmlRefCounted<ExecutableCompilationUnit> { Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit) public: + friend class QQmlRefCounted<ExecutableCompilationUnit>; friend class QQmlRefPointer<ExecutableCompilationUnit>; + friend struct ExecutionEngine; - static QQmlRefPointer<ExecutableCompilationUnit> create( - CompiledData::CompilationUnit &&compilationUnit) + ExecutionEngine *engine = nullptr; + + QString finalUrlString() const { return m_compilationUnit->finalUrlString(); } + QString fileName() const { return m_compilationUnit->fileName(); } + + QUrl url() const { return m_compilationUnit->url(); } + QUrl finalUrl() const { return m_compilationUnit->finalUrl(); } + + QQmlRefPointer<QQmlTypeNameCache> typeNameCache() const { - return QQmlRefPointer<ExecutableCompilationUnit>( - new ExecutableCompilationUnit(std::move(compilationUnit)), - QQmlRefPointer<ExecutableCompilationUnit>::Adopt); + return m_compilationUnit->typeNameCache; } - static QQmlRefPointer<ExecutableCompilationUnit> create() + QQmlPropertyCacheVector *propertyCachesPtr() { - return QQmlRefPointer<ExecutableCompilationUnit>( - new ExecutableCompilationUnit, - QQmlRefPointer<ExecutableCompilationUnit>::Adopt); + return &m_compilationUnit->propertyCaches; } - 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 + QQmlPropertyCache::ConstPtr rootPropertyCache() const { - if (m_finalUrl.isNull) - m_finalUrl = QUrl(finalUrlString()); - return m_finalUrl; + return m_compilationUnit->rootPropertyCache(); } - 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 CompiledData::DependentTypesHasher &dependencyHasher) const; + int totalBindingsCount() const { return m_compilationUnit->totalBindingsCount(); } + int totalParserStatusCount() const { return m_compilationUnit->totalParserStatusCount(); } + int totalObjectCount() const { return m_compilationUnit->totalObjectCount(); } - 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 + ResolvedTypeReference *resolvedType(int id) const { - return qmlData->objectAt(index); + return m_compilationUnit->resolvedType(id); } - int importCount() const { return qmlData->nImports; } - const CompiledData::Import *importAt(int index) const + QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const { - return qmlData->importAt(index); + return m_compilationUnit->qmlTypeForComponent(inlineComponentName); } - 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; } - }; + QMetaType metaType() const { return m_compilationUnit->qmlType.typeId(); } - FunctionIterator objectFunctionsBegin(const CompiledObject *object) const + int inlineComponentId(const QString &inlineComponentName) const { - return FunctionIterator(data, object, 0); + return m_compilationUnit->inlineComponentId(inlineComponentName); } - FunctionIterator objectFunctionsEnd(const CompiledObject *object) const - { - return FunctionIterator(data, object, object->nFunctions); - } + // --- interface for QQmlPropertyCacheCreator + using CompiledObject = CompiledData::CompilationUnit::CompiledObject; + using CompiledFunction = CompiledData::CompilationUnit::CompiledFunction; + using CompiledBinding = CompiledData::CompilationUnit::CompiledBinding; + using IdToObjectMap = CompiledData::CompilationUnit::IdToObjectMap; - bool isESModule() const + bool nativeMethodsAcceptThisObjects() const { - return data->flags & CompiledData::Unit::IsESModule; + return m_compilationUnit->nativeMethodsAcceptThisObjects(); } - bool isSharedLibrary() const + bool ignoresFunctionSignature() const { return m_compilationUnit->ignoresFunctionSignature(); } + bool valueTypesAreCopied() const { return m_compilationUnit->valueTypesAreCopied(); } + bool valueTypesAreAddressable() const { return m_compilationUnit->valueTypesAreAddressable(); } + bool valueTypesAreAssertable() const { return m_compilationUnit->valueTypesAreAssertable(); } + bool componentsAreBound() const { return m_compilationUnit->componentsAreBound(); } + bool isESModule() const { return m_compilationUnit->isESModule(); } + + int objectCount() const { return m_compilationUnit->objectCount(); } + const CompiledObject *objectAt(int index) const { - return data->flags & CompiledData::Unit::IsSharedLibrary; + return m_compilationUnit->objectAt(index); } - QStringList moduleRequests() const; - Heap::Module *instantiate(ExecutionEngine *engine); + Heap::Object *templateObjectAt(int index) const; + + Heap::Module *instantiate(); const Value *resolveExport(QV4::String *exportName) { QVector<ResolveSetEntry> resolveSet; @@ -238,33 +167,74 @@ public: void evaluate(); void evaluateModuleRequests(); - QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); - void unlink(); + void mark(MarkStack *markStack) const { markObjects(markStack); } + void markObjects(MarkStack *markStack) const; - void markObjects(MarkStack *markStack); + QString bindingValueAsString(const CompiledData::Binding *binding) const; + double bindingValueAsNumber(const CompiledData::Binding *binding) const + { + return m_compilationUnit->bindingValueAsNumber(binding); + } + QString bindingValueAsScriptString(const CompiledData::Binding *binding) const + { + return m_compilationUnit->bindingValueAsScriptString(binding); + } - bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString); + struct TranslationDataIndex + { + uint index; + bool byId; + }; - static QString localCacheFilePath(const QUrl &url); - bool saveToDisk(const QUrl &unitUrl, QString *errorString); + QString translateFrom(TranslationDataIndex index) const; - QString bindingValueAsString(const CompiledData::Binding *binding) const; - QString bindingValueAsScriptString(const CompiledData::Binding *binding) const; - double bindingValueAsNumber(const CompiledData::Binding *binding) const + Heap::Module *module() const { return m_module; } + void setModule(Heap::Module *module) { m_module = module; } + + const CompiledData::Unit *unitData() const { return m_compilationUnit->data; } + + QString stringAt(uint index) const { return m_compilationUnit->stringAt(index); } + + const QVector<QQmlRefPointer<QQmlScriptData>> *dependentScriptsPtr() const + { + return &m_compilationUnit->dependentScripts; + } + + const CompiledData::BindingPropertyData *bindingPropertyDataPerObjectAt( + qsizetype objectIndex) const + { + return &m_compilationUnit->bindingPropertyDataPerObject.at(objectIndex); + } + + const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &baseCompilationUnit() const + { + return m_compilationUnit; + } + + QV4::Function *rootFunction() { - if (binding->type != CompiledData::Binding::Type_Number) - return 0.0; - return constants[binding->value.constantValueIndex].doubleValue(); + if (!runtimeStrings) + populate(); + + const auto *data = unitData(); + return data->indexOfRootFunction != -1 + ? runtimeFunctions[data->indexOfRootFunction] + : nullptr; } - static bool verifyHeader(const CompiledData::Unit *unit, QDateTime expectedSourceTimeStamp, - QString *errorString); + void populate(); + void clear(); protected: quint32 totalStringCount() const - { return data->stringTableSize; } + { return unitData()->stringTableSize; } private: + friend struct ExecutionEngine; + + QQmlRefPointer<CompiledData::CompilationUnit> m_compilationUnit; + Heap::Module *m_module = nullptr; + struct ResolveSetEntry { ResolveSetEntry() {} @@ -275,9 +245,13 @@ private: }; ExecutableCompilationUnit(); - ExecutableCompilationUnit(CompiledData::CompilationUnit &&compilationUnit); + ExecutableCompilationUnit(QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit); ~ExecutableCompilationUnit(); + static QQmlRefPointer<ExecutableCompilationUnit> create( + QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit, + ExecutionEngine *engine); + const Value *resolveExportRecursively(QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet); @@ -293,36 +267,12 @@ private: 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())) + auto it = namedObjectsPerComponentCache.constFind(componentObjectIndex); + if (Q_UNLIKELY(it == namedObjectsPerComponentCache.cend())) return createNamedObjectsPerComponent(componentObjectIndex); + Q_ASSERT(!it->isEmpty()); return *it; } |