// 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 // // 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 #include #include #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QQmlScriptData; class QQmlEnginePrivate; namespace QV4 { class CompilationUnitMapper; struct CompilationUnitRuntimeData { 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 runtimeFunctions; QVector runtimeBlocks; mutable QVector templateObjects; }; static_assert(std::is_standard_layout_v); 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 { Q_DISABLE_COPY_MOVE(ExecutableCompilationUnit) public: friend class QQmlRefCounted; friend class QQmlRefPointer; friend struct ExecutionEngine; 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 typeNameCache() const { return m_compilationUnit->typeNameCache; } QQmlPropertyCacheVector *propertyCachesPtr() { return &m_compilationUnit->propertyCaches; } QQmlPropertyCache::ConstPtr rootPropertyCache() const { return m_compilationUnit->rootPropertyCache(); } // 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 namedObjectsPerComponentCache; inline IdentifierHash namedObjectsPerComponent(int componentObjectIndex); int totalBindingsCount() const { return m_compilationUnit->totalBindingsCount(); } int totalParserStatusCount() const { return m_compilationUnit->totalParserStatusCount(); } int totalObjectCount() const { return m_compilationUnit->totalObjectCount(); } ResolvedTypeReference *resolvedType(int id) const { return m_compilationUnit->resolvedType(id); } QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const { return m_compilationUnit->qmlTypeForComponent(inlineComponentName); } QMetaType metaType() const { return m_compilationUnit->qmlType.typeId(); } int inlineComponentId(const QString &inlineComponentName) const { return m_compilationUnit->inlineComponentId(inlineComponentName); } // --- interface for QQmlPropertyCacheCreator using CompiledObject = CompiledData::CompilationUnit::CompiledObject; using CompiledFunction = CompiledData::CompilationUnit::CompiledFunction; using CompiledBinding = CompiledData::CompilationUnit::CompiledBinding; using IdToObjectMap = CompiledData::CompilationUnit::IdToObjectMap; bool nativeMethodsAcceptThisObjects() const { return m_compilationUnit->nativeMethodsAcceptThisObjects(); } bool ignoresFunctionSignature() const { return m_compilationUnit->ignoresFunctionSignature(); } bool valueTypesAreCopied() const { return m_compilationUnit->valueTypesAreCopied(); } bool valueTypesAreAddressable() const { return m_compilationUnit->valueTypesAreAddressable(); } 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 m_compilationUnit->objectAt(index); } Heap::Object *templateObjectAt(int index) const; Heap::Module *instantiate(); const Value *resolveExport(QV4::String *exportName) { QVector resolveSet; return resolveExportRecursively(exportName, &resolveSet); } QStringList exportedNames() const { QStringList names; QVector 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(); void mark(MarkStack *markStack) const { markObjects(markStack); } void markObjects(MarkStack *markStack) const; 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); } struct TranslationDataIndex { uint index; bool byId; }; QString translateFrom(TranslationDataIndex index) 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> *dependentScriptsPtr() const { return &m_compilationUnit->dependentScripts; } const CompiledData::BindingPropertyData *bindingPropertyDataPerObjectAt( qsizetype objectIndex) const { return &m_compilationUnit->bindingPropertyDataPerObject.at(objectIndex); } const QQmlRefPointer &baseCompilationUnit() const { return m_compilationUnit; } QV4::Function *rootFunction() { if (!runtimeStrings) populate(); const auto *data = unitData(); return data->indexOfRootFunction != -1 ? runtimeFunctions[data->indexOfRootFunction] : nullptr; } void populate(); void clear(); protected: quint32 totalStringCount() const { return unitData()->stringTableSize; } private: friend struct ExecutionEngine; QQmlRefPointer m_compilationUnit; Heap::Module *m_module = nullptr; struct ResolveSetEntry { ResolveSetEntry() {} ResolveSetEntry(ExecutableCompilationUnit *module, QV4::String *exportName) : module(module), exportName(exportName) {} ExecutableCompilationUnit *module = nullptr; QV4::String *exportName = nullptr; }; ExecutableCompilationUnit(); ExecutableCompilationUnit(QQmlRefPointer &&compilationUnit); ~ExecutableCompilationUnit(); static QQmlRefPointer create( QQmlRefPointer &&compilationUnit, ExecutionEngine *engine); const Value *resolveExportRecursively(QV4::String *exportName, QVector *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 *exportNameSet, bool includeDefaultExport = true) const; }; IdentifierHash ExecutableCompilationUnit::namedObjectsPerComponent(int componentObjectIndex) { auto it = namedObjectsPerComponentCache.constFind(componentObjectIndex); if (Q_UNLIKELY(it == namedObjectsPerComponentCache.cend())) return createNamedObjectsPerComponent(componentObjectIndex); Q_ASSERT(!it->isEmpty()); return *it; } } // namespace QV4 QT_END_NAMESPACE #endif // QV4EXECUTABLECOMPILATIONUNIT_P_H