diff options
Diffstat (limited to 'src/qml/common/qv4compileddata_p.h')
-rw-r--r-- | src/qml/common/qv4compileddata_p.h | 472 |
1 files changed, 325 insertions, 147 deletions
diff --git a/src/qml/common/qv4compileddata_p.h b/src/qml/common/qv4compileddata_p.h index cd96067769..c21fc19fa9 100644 --- a/src/qml/common/qv4compileddata_p.h +++ b/src/qml/common/qv4compileddata_p.h @@ -16,21 +16,29 @@ #include <functional> +#include <QtCore/qcryptographichash.h> +#include <QtCore/qhash.h> #include <QtCore/qhashfunctions.h> -#include <QtCore/qstring.h> +#include <QtCore/qlocale.h> #include <QtCore/qscopeguard.h> -#include <QtCore/qvector.h> +#include <QtCore/qstring.h> #include <QtCore/qstringlist.h> -#include <QtCore/qhash.h> +#include <QtCore/qurl.h> +#include <QtCore/qvector.h> #include <QtCore/qversionnumber.h> -#include <QtCore/qlocale.h> #if QT_CONFIG(temporaryfile) #include <QtCore/qsavefile.h> #endif #include <private/qendian_p.h> +#include <private/qqmlnullablevalue_p.h> +#include <private/qqmlpropertycachevector_p.h> +#include <private/qqmlrefcount_p.h> +#include <private/qqmltype_p.h> +#include <private/qv4compilationunitmapper_p.h> #include <private/qv4staticvalue_p.h> + #include <functional> #include <limits.h> @@ -43,15 +51,17 @@ QT_BEGIN_NAMESPACE // Also change the comment behind the number to describe the latest change. This has the added // benefit that if another patch changes the version too, it will result in a merge conflict, and // not get removed silently. -#define QV4_DATA_STRUCTURE_VERSION 0x3B // Add isList flag to method parameters and return types +#define QV4_DATA_STRUCTURE_VERSION 0x42 // Change metatype computation of AOT-compiled functions class QIODevice; class QQmlTypeNameCache; class QQmlType; class QQmlEngine; +class QQmlPropertyData; +class QQmlScriptData; namespace QQmlPrivate { -struct TypedFunction; +struct AOTCompiledFunction; } namespace QmlIR { @@ -67,9 +77,19 @@ struct InternalClass; struct Function; class EvalISelFactory; +class ResolvedTypeReference; namespace CompiledData { +// index is per-object binding index +using BindingPropertyData = QVector<const QQmlPropertyData *>; + +// map from name index +struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*> +{ + bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const; +}; + struct String; struct Function; struct Lookup; @@ -141,8 +161,8 @@ struct RegExp RegExp_Global = 0x01, RegExp_IgnoreCase = 0x02, RegExp_Multiline = 0x04, - RegExp_Unicode = 0x08, - RegExp_Sticky = 0x10 + RegExp_Sticky = 0x08, + RegExp_Unicode = 0x10, }; RegExp() : m_data(QSpecialIntegerBitfieldZero) {} @@ -268,31 +288,48 @@ struct Block }; static_assert(sizeof(Block) == 12, "Block structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); -enum class BuiltinType : unsigned int { - Var = 0, Int, Bool, Real, String, Url, - Time, Date, DateTime, Rect, Point, Size, - InvalidBuiltin +enum class NamedBuiltin: unsigned int { + Void, Var, Int, Bool, Real, String, Url, DateTime, RegExp +}; + +enum class CommonType : unsigned int { + // Actual named builtins + Void = uint(NamedBuiltin::Void), + Var = uint(NamedBuiltin::Var), + Int = uint(NamedBuiltin::Int), + Bool = uint(NamedBuiltin::Bool), + Real = uint(NamedBuiltin::Real), + String = uint(NamedBuiltin::String), + Url = uint(NamedBuiltin::Url), + DateTime = uint(NamedBuiltin::DateTime), + RegExp = uint(NamedBuiltin::RegExp), + + // Optimization for very common other types + Time, Date, Rect, Point, Size, + + // No type specified or not recognized + Invalid }; struct ParameterType { enum Flag { NoFlag = 0x0, - Builtin = 0x1, + Common = 0x1, List = 0x2, }; Q_DECLARE_FLAGS(Flags, Flag); - void set(Flags flags, quint32 typeNameIndexOrBuiltinType) + void set(Flags flags, quint32 typeNameIndexOrCommonType) { m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0); - m_data.set<IndexIsBuiltinTypeField>(flags.testFlag(Builtin) ? 1 : 0); - m_data.set<TypeNameIndexOrBuiltinTypeField>(typeNameIndexOrBuiltinType); + m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0); + m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType); } - bool indexIsBuiltinType() const + bool indexIsCommonType() const { - return m_data.get<IndexIsBuiltinTypeField>() != 0; + return m_data.get<IndexIsCommonTypeField>() != 0; } bool isList() const @@ -300,16 +337,16 @@ struct ParameterType return m_data.get<IsListField>() != 0; } - quint32 typeNameIndexOrBuiltinType() const + quint32 typeNameIndexOrCommonType() const { - return m_data.get<TypeNameIndexOrBuiltinTypeField>(); + return m_data.get<TypeNameIndexOrCommonTypeField>(); } private: - using IndexIsBuiltinTypeField = quint32_le_bitfield_member<0, 1>; + using IndexIsCommonTypeField = quint32_le_bitfield_member<0, 1>; using IsListField = quint32_le_bitfield_member<1, 1>; - using TypeNameIndexOrBuiltinTypeField = quint32_le_bitfield_member<2, 30>; - quint32_le_bitfield_union<IndexIsBuiltinTypeField, IsListField, TypeNameIndexOrBuiltinTypeField> m_data; + using TypeNameIndexOrCommonTypeField = quint32_le_bitfield_member<2, 30>; + quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data; }; static_assert(sizeof(ParameterType) == 4, "ParameterType structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); @@ -497,6 +534,7 @@ static_assert(sizeof(ImportEntry) == 16, "ImportEntry structure needs to have th struct TranslationData { + enum { NoContextIndex = std::numeric_limits<quint32>::max() }; quint32_le stringIndex; quint32_le commentIndex; qint32_le number; @@ -669,6 +707,8 @@ struct Binding } bool evaluatesToString() const { return type() == Type_String || isTranslationBinding(); } + bool isNumberBinding() const { return type() == Type_Number; } + bool valueAsBoolean() const { if (type() == Type_Boolean) @@ -748,47 +788,47 @@ static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected struct Property { private: - using BuiltinTypeOrTypeNameIndexField = quint32_le_bitfield_member<0, 28>; + using CommonTypeOrTypeNameIndexField = quint32_le_bitfield_member<0, 28>; using IsRequiredField = quint32_le_bitfield_member<28, 1>; - using IsBuiltinTypeField = quint32_le_bitfield_member<29, 1>; + using IsCommonTypeField = quint32_le_bitfield_member<29, 1>; using IsListField = quint32_le_bitfield_member<30, 1>; using IsReadOnlyField = quint32_le_bitfield_member<31, 1>; public: quint32_le nameIndex; quint32_le_bitfield_union< - BuiltinTypeOrTypeNameIndexField, + CommonTypeOrTypeNameIndexField, IsRequiredField, - IsBuiltinTypeField, + IsCommonTypeField, IsListField, IsReadOnlyField> data; Location location; - void setBuiltinType(BuiltinType t) + void setCommonType(CommonType t) { - data.set<BuiltinTypeOrTypeNameIndexField>(static_cast<quint32>(t)); - data.set<IsBuiltinTypeField>(true); + data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t)); + data.set<IsCommonTypeField>(true); } - BuiltinType builtinType() const { - if (data.get<IsBuiltinTypeField>() != 0) - return BuiltinType(data.get<BuiltinTypeOrTypeNameIndexField>()); - return BuiltinType::InvalidBuiltin; + CommonType commonType() const { + if (data.get<IsCommonTypeField>() != 0) + return CommonType(data.get<CommonTypeOrTypeNameIndexField>()); + return CommonType::Invalid; } - void setCustomType(int nameIndex) + void setTypeNameIndex(int nameIndex) { - data.set<BuiltinTypeOrTypeNameIndexField>(nameIndex); - data.set<IsBuiltinTypeField>(false); + data.set<CommonTypeOrTypeNameIndexField>(nameIndex); + data.set<IsCommonTypeField>(false); } - int customType() const + int typeNameIndex() const { - return data.get<IsBuiltinTypeField>() ? -1 : data.get<BuiltinTypeOrTypeNameIndexField>(); + return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>(); } - bool isBuiltinType() const { return data.get<IsBuiltinTypeField>(); } - uint builtinTypeOrTypeNameIndex() const { return data.get<BuiltinTypeOrTypeNameIndexField>(); } + bool isCommonType() const { return data.get<IsCommonTypeField>(); } + uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); } bool isList() const { return data.get<IsListField>(); } void setIsList(bool isList) { data.set<IsListField>(isList); } @@ -1080,6 +1120,7 @@ public: const Binding *bindingsBegin() const { return bindingTable(); } const Binding *bindingsEnd() const { return bindingTable() + nBindings; } + int bindingCount() const { return nBindings; } const Property *propertiesBegin() const { return propertyTable(); } const Property *propertiesEnd() const { return propertyTable() + nProperties; } @@ -1182,9 +1223,11 @@ struct Unit ListPropertyAssignReplace = ListPropertyAssignReplaceIfDefault | ListPropertyAssignReplaceIfNotDefault, ComponentsBound = 0x200, - FunctionSignaturesEnforced = 0x400, + FunctionSignaturesIgnored = 0x400, NativeMethodsAcceptThisObject = 0x800, ValueTypesCopied = 0x1000, + ValueTypesAddressable = 0x2000, + ValueTypesAssertable = 0x4000, }; quint32_le flags; quint32_le stringTableSize; @@ -1238,8 +1281,8 @@ struct Unit } /* end QML specific fields*/ - QString stringAtInternal(int idx) const { - Q_ASSERT(idx < int(stringTableSize)); + QString stringAtInternal(uint idx) const { + Q_ASSERT(idx < stringTableSize); const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable); const quint32_le offset = offsetTable[idx]; const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset); @@ -1311,12 +1354,28 @@ struct Unit return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable); } + const quint32_le *translationContextIndex() const{ + if ( translationTableSize == 0) + return nullptr; + return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + + offsetToTranslationTable + + translationTableSize * sizeof(CompiledData::TranslationData)); } + + quint32_le *translationContextIndex() { + if ( translationTableSize == 0) + return nullptr; + return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this)) + + offsetToTranslationTable + + translationTableSize * sizeof(CompiledData::TranslationData)); } + const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); } const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); } const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); } const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); } const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); } + + bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const; }; static_assert(sizeof(Unit) == 248, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); @@ -1355,8 +1414,8 @@ struct TypeReferenceMap : QHash<int, TypeReference> auto prop = obj->propertiesBegin(); auto const propEnd = obj->propertiesEnd(); for ( ; prop != propEnd; ++prop) { - if (!prop->isBuiltinType()) { - TypeReference &r = this->add(prop->builtinTypeOrTypeNameIndex(), prop->location); + if (!prop->isCommonType()) { + TypeReference &r = this->add(prop->commonTypeOrTypeNameIndex(), prop->location); r.errorWhenNotFound = true; } } @@ -1385,118 +1444,92 @@ struct TypeReferenceMap : QHash<int, TypeReference> using DependentTypesHasher = std::function<QByteArray()>; -// This is how this hooks into the existing structures: - -struct 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; - } +struct InlineComponentData { + + InlineComponentData() = default; + InlineComponentData( + const QQmlType &qmlType, int objectIndex, int nameIndex, int totalObjectCount, + int totalBindingCount, int totalParserStatusCount) + : qmlType(qmlType) + , objectIndex(objectIndex) + , nameIndex(nameIndex) + , totalObjectCount(totalObjectCount) + , totalBindingCount(totalBindingCount) + , totalParserStatusCount(totalParserStatusCount) + {} - // pointers either to data->constants() or little-endian memory copy. - Heap::String **runtimeStrings = nullptr; // Array - const StaticValue* constants = nullptr; - QV4::StaticValue *runtimeRegularExpressions = nullptr; - Heap::InternalClass **runtimeClasses = nullptr; - const StaticValue** imports = nullptr; + QQmlType qmlType; + int objectIndex = -1; + int nameIndex = -1; + int totalObjectCount = 0; + int totalBindingCount = 0; + int totalParserStatusCount = 0; }; -Q_STATIC_ASSERT(std::is_standard_layout<CompilationUnitBase>::value); -Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeStrings) == 0); -Q_STATIC_ASSERT(offsetof(CompilationUnitBase, constants) == sizeof(QV4::Heap::String **)); -Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offsetof(CompilationUnitBase, constants) + sizeof(const StaticValue *)); -Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeClasses) == offsetof(CompilationUnitBase, runtimeRegularExpressions) + sizeof(const StaticValue *)); -Q_STATIC_ASSERT(offsetof(CompilationUnitBase, imports) == offsetof(CompilationUnitBase, runtimeClasses) + sizeof(const StaticValue *)); - -struct CompilationUnit : public CompilationUnitBase +struct CompilationUnit final : public QQmlRefCounted<CompilationUnit> { - Q_DISABLE_COPY(CompilationUnit) + Q_DISABLE_COPY_MOVE(CompilationUnit) const Unit *data = nullptr; const QmlUnit *qmlData = nullptr; QStringList dynamicStrings; - const QQmlPrivate::TypedFunction *aotCompiledFunctions = nullptr; + const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions = nullptr; + + // pointers either to data->constants() or little-endian memory copy. + const StaticValue *constants = nullptr; + + std::unique_ptr<CompilationUnitMapper> backingFile; + + int m_totalBindingsCount = 0; // Number of bindings used in this type + int m_totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses + int m_totalObjectCount = 0; // Number of objects explicitly instantiated + + std::unique_ptr<QString> icRootName; + QHash<QString, InlineComponentData> inlineComponentData; + + // 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; + + ResolvedTypeReferenceMap resolvedTypes; + QQmlRefPointer<QQmlTypeNameCache> typeNameCache; + + QQmlPropertyCacheVector propertyCaches; + + QQmlType qmlType; + + QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts; + public: - using CompiledObject = CompiledData::Object; + // --- interface for QQmlPropertyCacheCreator + using CompiledObject = const CompiledData::Object; + using CompiledFunction = const CompiledData::Function; + using CompiledBinding = const CompiledData::Binding; - CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), - const QString &finalUrlString = QString()) + // Empty dummy. We don't need to do this when loading from cache. + class IdToObjectMap { - setUnitData(unitData, nullptr, fileName, finalUrlString); - } + public: + void insert(int, int) {} + void clear() {} - explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::TypedFunction *aotCompiledFunctions, + // We have already checked uniqueness of IDs when creating the CU + bool contains(int) { return false; } + }; + + explicit CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions, const QString &fileName = QString(), const QString &finalUrlString = QString()) : CompilationUnit(unitData, fileName, finalUrlString) { this->aotCompiledFunctions = aotCompiledFunctions; } - ~CompilationUnit() - { - if (data) { - if (data->qmlUnit() != qmlData) - free(const_cast<QmlUnit *>(qmlData)); - qmlData = nullptr; - - if (!(data->flags & QV4::CompiledData::Unit::StaticData)) - free(const_cast<Unit *>(data)); - } - data = nullptr; -#if Q_BYTE_ORDER == Q_BIG_ENDIAN - delete [] constants; - constants = nullptr; -#endif - - delete [] imports; - imports = nullptr; - } - - CompilationUnit(CompilationUnit &&other) noexcept - { - *this = std::move(other); - } + Q_QML_EXPORT CompilationUnit( + const Unit *unitData = nullptr, const QString &fileName = QString(), + const QString &finalUrlString = QString()); - CompilationUnit &operator=(CompilationUnit &&other) noexcept - { - if (this != &other) { - data = other.data; - other.data = nullptr; - qmlData = other.qmlData; - other.qmlData = nullptr; - dynamicStrings = std::move(other.dynamicStrings); - aotCompiledFunctions = other.aotCompiledFunctions; - 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; - } + Q_QML_EXPORT ~CompilationUnit(); const Unit *unitData() const { return data; } @@ -1530,19 +1563,19 @@ public: m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex); } - QString stringAt(int index) const + QString stringAt(uint index) const { - if (uint(index) >= data->stringTableSize) - return dynamicStrings.at(index - data->stringTableSize); - return data->stringAtInternal(index); + if (index < data->stringTableSize) + return data->stringAtInternal(index); + + const qsizetype dynamicIndex = index - data->stringTableSize; + Q_ASSERT(dynamicIndex < dynamicStrings.size()); + return dynamicStrings.at(dynamicIndex); } QString fileName() const { return m_fileName; } QString finalUrlString() const { return m_finalUrlString; } - Heap::Module *module() const { return m_module; } - void setModule(Heap::Module *module) { m_module = module; } - QString bindingValueAsString(const CompiledData::Binding *binding) const { using namespace CompiledData; @@ -1581,11 +1614,156 @@ public: return constants[binding->value.constantValueIndex].doubleValue(); } + Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url); + Q_QML_EXPORT bool loadFromDisk( + const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString); + Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString); + + int importCount() const { return qmlData->nImports; } + const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); } + + Q_QML_EXPORT QStringList moduleRequests() const; + + // 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.isValid()) + m_url = QUrl(fileName()); + return m_url; + } + + QUrl finalUrl() const + { + if (!m_finalUrl.isValid()) + m_finalUrl = QUrl(finalUrlString()); + return m_finalUrl; + } + + ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); } + ResolvedTypeReference *resolvedType(QMetaType type) const; + + QQmlPropertyCache::ConstPtr rootPropertyCache() const + { + return propertyCaches.at(/*root object*/0); + } + + int objectCount() const { return qmlData->nObjects; } + const CompiledObject *objectAt(int index) const { return qmlData->objectAt(index); } + + int totalBindingsCount() const; + int totalParserStatusCount() const; + int totalObjectCount() const; + + int inlineComponentId(const QString &inlineComponentName) const + { + for (uint i = 0; i < qmlData->nObjects; ++i) { + auto *object = qmlData->objectAt(i); + for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd(); + it != end; ++it) { + if (stringAt(it->nameIndex) == inlineComponentName) + return it->objectIndex; + } + } + return -1; + } + + void finalizeCompositeType(const QQmlType &type); + + bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const; + + enum class ListPropertyAssignBehavior { Append, Replace, ReplaceIfNotDefault }; + ListPropertyAssignBehavior listPropertyAssignBehavior() const + { + if (unitData()->flags & CompiledData::Unit::ListPropertyAssignReplace) + return ListPropertyAssignBehavior::Replace; + if (unitData()->flags & CompiledData::Unit::ListPropertyAssignReplaceIfNotDefault) + return ListPropertyAssignBehavior::ReplaceIfNotDefault; + return ListPropertyAssignBehavior::Append; + } + + bool ignoresFunctionSignature() const + { + return unitData()->flags & CompiledData::Unit::FunctionSignaturesIgnored; + } + + bool nativeMethodsAcceptThisObjects() const + { + return unitData()->flags & CompiledData::Unit::NativeMethodsAcceptThisObject; + } + + bool valueTypesAreCopied() const + { + return unitData()->flags & CompiledData::Unit::ValueTypesCopied; + } + + bool valueTypesAreAddressable() const + { + return unitData()->flags & CompiledData::Unit::ValueTypesAddressable; + } + + bool valueTypesAreAssertable() const + { + return unitData()->flags & CompiledData::Unit::ValueTypesAssertable; + } + + bool componentsAreBound() const + { + return unitData()->flags & CompiledData::Unit::ComponentsBound; + } + + bool isESModule() const + { + return unitData()->flags & CompiledData::Unit::IsESModule; + } + + bool isSharedLibrary() const + { + return unitData()->flags & CompiledData::Unit::IsSharedLibrary; + } + + 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(unitData(), object, 0); + } + + FunctionIterator objectFunctionsEnd(const CompiledObject *object) const + { + return FunctionIterator(unitData(), object, object->nFunctions); + } + + QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const; + QMetaType metaType() const { return qmlType.typeId(); } + private: QString m_fileName; // initialized from data->sourceFileIndex QString m_finalUrlString; // initialized from data->finalUrlIndex - Heap::Module *m_module = nullptr; + mutable QQmlNullableValue<QUrl> m_url; + mutable QQmlNullableValue<QUrl> m_finalUrl; }; class SaveableUnitPointer |