Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4compileddata_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4#ifndef QV4COMPILEDDATA_P_H
5#define QV4COMPILEDDATA_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <functional>
19
20#include <QtCore/qcryptographichash.h>
21#include <QtCore/qhash.h>
22#include <QtCore/qhashfunctions.h>
23#include <QtCore/qlocale.h>
24#include <QtCore/qscopeguard.h>
25#include <QtCore/qstring.h>
26#include <QtCore/qstringlist.h>
27#include <QtCore/qurl.h>
28#include <QtCore/qvector.h>
29#include <QtCore/qtyperevision.h>
30
31#if QT_CONFIG(temporaryfile)
32#include <QtCore/qsavefile.h>
33#endif
34
35#include <private/qendian_p.h>
36#include <private/qqmlnullablevalue_p.h>
37#include <private/qqmlpropertycachevector_p.h>
38#include <private/qqmlrefcount_p.h>
39#include <private/qqmltype_p.h>
40#include <private/qv4compilationunitmapper_p.h>
41#include <private/qv4staticvalue_p.h>
42
43#include <functional>
44#include <limits.h>
45
46QT_BEGIN_NAMESPACE
47
48// Bump this whenever the compiler data structures change in an incompatible way.
49//
50// IMPORTANT:
51//
52// Also change the comment behind the number to describe the latest change. This has the added
53// benefit that if another patch changes the version too, it will result in a merge conflict, and
54// not get removed silently.
55// Also update the comparison functions in qqmlpreviewdiff.cpp when you change the data structures.
56#define QV4_DATA_STRUCTURE_VERSION 0x4d // Added AOT lookup validation
57
58class QIODevice;
59class QQmlTypeNameCache;
60class QQmlType;
61class QQmlEngine;
63class QQmlScriptData;
64
65namespace QQmlPrivate {
67}
68
69namespace QmlIR {
70struct Document;
71}
72
73namespace QV4 {
74namespace Heap {
75struct Module;
76struct String;
77struct InternalClass;
78};
79
80struct Function;
81class EvalISelFactory;
83
84namespace CompiledData {
85
86// index is per-object binding index
88
89// map from name index
91{
92 bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
93};
94
95struct String;
96struct Function;
97struct Lookup;
98struct RegExp;
99struct Unit;
100
101template <typename ItemType, typename Container, const ItemType *(Container::*IndexedGetter)(int index) const>
103{
104 TableIterator(const Container *container, int index) : container(container), index(index) {}
105 const Container *container;
106 int index;
107
108 const ItemType *operator->() const { return (container->*IndexedGetter)(index); }
109 ItemType operator*() const {return *operator->();}
110
112 {
113 ++index;
114 return *this;
115 }
116
118 {
120 ++index;
121 return result;
122 }
123
124 TableIterator operator+(int offset) const { return TableIterator(container, index + offset); }
125 TableIterator operator-(int offset) const { return TableIterator(container, index - offset); }
126 int operator-(TableIterator other) const { return index - other.index; }
127
128 bool operator==(const TableIterator &rhs) const { return index == rhs.index; }
129 bool operator!=(const TableIterator &rhs) const { return index != rhs.index; }
130};
131
133{
135 Location(quint32 l, quint32 c) : Location()
136 {
137 m_data.set<LineField>(l);
138 m_data.set<ColumnField>(c);
139 Q_ASSERT(m_data.get<LineField>() == l);
140 Q_ASSERT(m_data.get<ColumnField>() == c);
141 }
142
143 inline bool operator<(const Location &other) const {
144 return m_data.get<LineField>() < other.m_data.get<LineField>()
145 || (m_data.get<LineField>() == other.m_data.get<LineField>()
146 && m_data.get<ColumnField>() < other.m_data.get<ColumnField>());
147 }
148
149 friend size_t qHash(const Location &location, size_t seed = 0)
150 {
151 return QT_PREPEND_NAMESPACE(qHash)(location.m_data.data(), seed);
152 }
153
154 friend bool comparesEqual(const Location &a, const Location &b) noexcept
155 {
156 return a.m_data.data()== b.m_data.data();
157 }
159
165
166 quint32 line() const { return m_data.get<LineField>(); }
167 quint32 column() const { return m_data.get<ColumnField>(); }
168
169private:
172
173 quint32_le_bitfield_union<LineField, ColumnField> m_data;
174};
175static_assert(sizeof(Location) == 4, "Location structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
176
177struct RegExp
178{
187
189
191 RegExp(quint32 flags, quint32 stringIndex) : RegExp()
192 {
193 m_data.set<FlagsField>(flags);
194 m_data.set<StringIndexField>(stringIndex);
195 }
196
197 quint32 flags() const { return m_data.get<FlagsField>(); }
198 quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
199
200private:
203 quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
204};
205static_assert(sizeof(RegExp) == 4, "RegExp structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
206
207struct Lookup
208{
215
216 enum Mode : unsigned int {
219 };
220
221 quint32 type() const { return m_data.get<TypeField>(); }
222 quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
223 quint32 mode() const { return m_data.get<ModeField>(); }
224
226 Lookup(Type type, Mode mode, quint32 nameIndex) : Lookup()
227 {
228 m_data.set<TypeField>(type);
229 m_data.set<ModeField>(mode);
230 m_data.set<NameIndexField>(nameIndex);
231 }
232
233private:
236 // 1 bit left
238 quint32_le_bitfield_union<TypeField, ModeField, NameIndexField> m_data;
239};
240static_assert(sizeof(Lookup) == 4, "Lookup structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
241
243{
245
246 void set(quint32 nameOffset, bool isAccessor)
247 {
248 m_data.set<NameOffsetField>(nameOffset);
249 m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
250 }
251
252 quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
253 bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
254
255private:
258 quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
259};
260static_assert(sizeof(JSClassMember) == 4, "JSClassMember structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
261
263{
265 // JSClassMember[nMembers]
266
267 static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
268};
269static_assert(sizeof(JSClass) == 4, "JSClass structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
270
271struct String
272{
274
275 static int calculateSize(const QString &str) {
276 // we cannot enconuter strings larger than INT_MAX anyway, as such a string
277 // would already break in other parts of the compilation process
278 return (sizeof(String) + (int(str.size()) + 1) * sizeof(quint16) + 7) & ~0x7;
279 }
280};
281
282static_assert (sizeof (String) == 4, "String structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
283
286 qint32_le line; // signed because debug instructions get negative line numbers
288};
289static_assert(sizeof(CodeOffsetToLineAndStatement) == 12, "CodeOffsetToLineAndStatement structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
290
291struct Block
292{
297
298 const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
299
300 static int calculateSize(int nLocals) {
301 int trailingData = nLocals*sizeof (quint32);
302 size_t size = align(align(sizeof(Block)) + size_t(trailingData));
303 Q_ASSERT(size < INT_MAX);
304 return int(size);
305 }
306
307 static size_t align(size_t a) {
308 return (a + 7) & ~size_t(7);
309 }
310};
311static_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");
312
313enum class NamedBuiltin: unsigned int {
315};
316
317enum class CommonType : unsigned int {
318 // Actual named builtins
328
329 // Optimization for very common other types
331
332 // No type specified or not recognized
334};
335
337{
338 enum Flag {
339 NoFlag = 0x0,
340 Common = 0x1,
341 List = 0x2,
342 };
344
345 void set(Flags flags, quint32 typeNameIndexOrCommonType)
346 {
347 m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0);
348 m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0);
349 m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType);
350 }
351
352 bool indexIsCommonType() const
353 {
354 return m_data.get<IndexIsCommonTypeField>() != 0;
355 }
356
357 bool isList() const
358 {
359 return m_data.get<IsListField>() != 0;
360 }
361
363 {
364 return m_data.get<TypeNameIndexOrCommonTypeField>();
365 }
366
367private:
371 quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data;
372};
373static_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");
374
380static_assert(sizeof(Parameter) == 8, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
381
382// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
383// for unaligned access. The ordering of the fields is also from largest to smallest.
385{
386 enum Flags : unsigned int {
387 IsStrict = 0x1,
391 };
392
393 // Absolute offset into file where the code for this function is located.
396
400 quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
405 size_t lineAndStatementNumberOffset() const { return localsOffset + nLocals * sizeof(quint32); }
406 quint32_le nestedFunctionIndex; // for functions that only return a single closure, used in signal handlers
407
411
415
417 {
418 return lineAndStatementNumberOffset() + nLineAndStatementNumbers * sizeof(CodeOffsetToLineAndStatement);
419 }
420
421 // Keep all unaligned data at the end
424
425 // quint32 formalsIndex[nFormals]
426 // quint32 localsIndex[nLocals]
427
428 const Parameter *formalsTable() const
429 {
430 return reinterpret_cast<const Parameter *>(
431 reinterpret_cast<const char *>(this) + formalsOffset);
432 }
433 const quint32_le *localsTable() const
434 {
435 return reinterpret_cast<const quint32_le *>(
436 reinterpret_cast<const char *>(this) + localsOffset);
437 }
439 {
440 return reinterpret_cast<const CodeOffsetToLineAndStatement *>(
441 reinterpret_cast<const char *>(this) + lineAndStatementNumberOffset());
442 }
443
444 // --- QQmlPropertyCacheCreator interface
445 const Parameter *formalsBegin() const { return formalsTable(); }
446 const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
447 // ---
448
449 const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
450
451 const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
452
453 static int calculateSize(
454 int nFormals, int nLocals, int nLinesAndStatements, int labelInfoSize, int codeSize)
455 {
456 const size_t trailingData = nFormals * sizeof(Parameter)
457 + (nLocals + labelInfoSize) * sizeof (quint32)
458 + nLinesAndStatements * sizeof(CodeOffsetToLineAndStatement);
459 size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize);
460 Q_ASSERT(size < INT_MAX);
461 return int(size);
462 }
463
464 static size_t align(size_t a) {
465 return (a + 7) & ~size_t(7);
466 }
467};
468static_assert(sizeof(Function) == 56, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
469
481static_assert(sizeof(Method) == 12, "Method structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
482
483struct Class
484{
491
492 const Method *methodTable() const { return reinterpret_cast<const Method *>(reinterpret_cast<const char *>(this) + methodTableOffset); }
493
494 static int calculateSize(int nStaticMethods, int nMethods) {
495 int trailingData = (nStaticMethods + nMethods) * sizeof(Method);
496 size_t size = align(sizeof(Class) + trailingData);
497 Q_ASSERT(size < INT_MAX);
498 return int(size);
499 }
500
501 static size_t align(size_t a) {
502 return (a + 7) & ~size_t(7);
503 }
504};
505static_assert(sizeof(Class) == 24, "Class structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
506
508{
510
511 static int calculateSize(int size) {
512 int trailingData = 2 * size * sizeof(quint32_le);
513 size_t s = align(sizeof(TemplateObject) + trailingData);
514 Q_ASSERT(s < INT_MAX);
515 return int(s);
516 }
517
518 static size_t align(size_t a) {
519 return (a + 7) & ~size_t(7);
520 }
521
522 const quint32_le *stringTable() const {
523 return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this + 1));
524 }
525
526 uint stringIndexAt(uint i) const {
527 return stringTable()[i];
528 }
529 uint rawStringIndexAt(uint i) const {
530 return stringTable()[size + i];
531 }
532};
533static_assert(sizeof(TemplateObject) == 4, "Template object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
534
543static_assert(sizeof(ExportEntry) == 20, "ExportEntry structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
544
552static_assert(sizeof(ImportEntry) == 16, "ImportEntry structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
553
554// Qml data structures
555
564static_assert(sizeof(TranslationData) == 16, "TranslationData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
565
567{
569
583
598
602
603 void clearFlags() { flagsAndType.set<FlagsField>(0); }
604 void setFlag(Flag flag) { flagsAndType.set<FlagsField>(flagsAndType.get<FlagsField>() | flag); }
605 bool hasFlag(Flag flag) const { return Flags(flagsAndType.get<FlagsField>()) & flag; }
606 Flags flags() const { return Flags(flagsAndType.get<FlagsField>()); }
607
608 void setType(Type type) { flagsAndType.set<TypeField>(type); }
609 Type type() const { return Type(flagsAndType.get<TypeField>()); }
610
611 union {
612 bool b;
614 quint32_le compiledScriptIndex; // used when Type_Script
616 quint32_le translationDataIndex; // used when Type_Translation
618 } value;
619 quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
620
623
625 {
626 const Flags bindingFlags = flags();
627 return bindingFlags & IsSignalHandlerExpression
628 || bindingFlags & IsSignalHandlerObject
629 || bindingFlags & IsPropertyObserver;
630 }
631
632 bool isValueBinding() const
633 {
634 switch (type()) {
637 return false;
638 default:
640 }
641 }
642
645
646 bool isSignalHandler() const
647 {
649 Q_ASSERT(!isValueBinding());
650 Q_ASSERT(!isAttachedProperty());
651 Q_ASSERT(!isGroupProperty());
652 return true;
653 }
654 return false;
655 }
656
658 {
660 Q_ASSERT(!isValueBinding());
661 Q_ASSERT(!isSignalHandler());
662 Q_ASSERT(!isGroupProperty());
663 return true;
664 }
665 return false;
666 }
667
668 bool isGroupProperty() const
669 {
670 if (type() == Type_GroupProperty) {
671 Q_ASSERT(!isValueBinding());
672 Q_ASSERT(!isSignalHandler());
673 Q_ASSERT(!isAttachedProperty());
674 return true;
675 }
676 return false;
677 }
678
680
681 //reverse of Lexer::singleEscape()
682 static QString escapedString(const QString &string)
683 {
684 QString tmp = QLatin1String("\"");
685 for (int i = 0; i < string.size(); ++i) {
686 const QChar &c = string.at(i);
687 switch (c.unicode()) {
688 case 0x08:
689 tmp += QLatin1String("\\b");
690 break;
691 case 0x09:
692 tmp += QLatin1String("\\t");
693 break;
694 case 0x0A:
695 tmp += QLatin1String("\\n");
696 break;
697 case 0x0B:
698 tmp += QLatin1String("\\v");
699 break;
700 case 0x0C:
701 tmp += QLatin1String("\\f");
702 break;
703 case 0x0D:
704 tmp += QLatin1String("\\r");
705 break;
706 case 0x22:
707 tmp += QLatin1String("\\\"");
708 break;
709 case 0x27:
710 tmp += QLatin1String("\\\'");
711 break;
712 case 0x5C:
713 tmp += QLatin1String("\\\\");
714 break;
715 default:
716 tmp += c;
717 break;
718 }
719 }
720 tmp += QLatin1Char('\"');
721 return tmp;
722 }
723
725 {
726 const Binding::Type bindingType = type();
727 return bindingType == Type_Translation || bindingType == Type_TranslationById;
728 }
730
731 bool isNumberBinding() const { return type() == Type_Number; }
732
733 bool valueAsBoolean() const
734 {
735 if (type() == Type_Boolean)
736 return value.b;
737 return false;
738 }
739};
740
741static_assert(sizeof(Binding) == 24, "Binding structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
742
749
750static_assert(sizeof(InlineComponent) == 12, "InlineComponent structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
751
757static_assert(sizeof(EnumValue) == 8, "EnumValue structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
758
759struct Enum
760{
764
765 const EnumValue *enumValueAt(int idx) const {
766 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
767 }
768
769 static int calculateSize(int nEnumValues) {
770 return (sizeof(Enum)
771 + nEnumValues * sizeof(EnumValue)
772 + 7) & ~0x7;
773 }
774
775 // --- QQmlPropertyCacheCreatorInterface
776 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
777 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
778 int enumValueCount() const { return nEnumValues; }
779 // ---
780};
781static_assert(sizeof(Enum) == 12, "Enum structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
782
783struct Signal
784{
788 // Parameter parameters[1];
789
790 const Parameter *parameterAt(int idx) const {
791 return reinterpret_cast<const Parameter*>(this + 1) + idx;
792 }
793
794 static int calculateSize(int nParameters) {
795 return (sizeof(Signal)
796 + nParameters * sizeof(Parameter)
797 + 7) & ~0x7;
798 }
799
800 // --- QQmlPropertyCacheCceatorInterface
801 const Parameter *parametersBegin() const { return parameterAt(0); }
802 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
803 int parameterCount() const { return nParameters; }
804 // ---
805};
806static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
807
808/*
809 * We aim to minimize the size of a struct as much as possible, while preserving at least 28 bits
810 * for each index.
811 *
812 * Note that Name and Type indices are provided by StringTableGenerator, containing a hashmap
813 * (and a list) of unique strings within one Compilation Unit. It sounds rather unrealistic to have
814 * 2^28 (260+ million) unique strings within 1 CU (even if it's some form of global registry), not
815 * to mention the amount of memory needed to maintain such a StringTableGenerator.
816 * Therefore, after some preliminary analysis, it seems that even 20 bits
817 * should be a rather conservative cap.
818 *
819 * However it doesn't seem to easily provide many benefits atm other than better (logically) grouped
820 * unions like, let's say nameIndexAndAttributes.
821 *
822 * Atm 32-bit member nameIndexAndVirtSpecifiers looks smth like this:
823 *
824 * NameIndexField IsVirtualField IsOverrideField IsFinalField
825 * |10100000101000111000001110000| 0 | 1 | 0 |
826 *
827 */
829{
830private:
835
841
842public:
852
853 quint32 nameIndex() const { return nameIndexAndVirtSpecifiers.get<NameIndexField>(); }
854 void setNameIndex(int nameIndex) { nameIndexAndVirtSpecifiers.set<NameIndexField>(nameIndex); }
855
856 bool isVirtual() const { return nameIndexAndVirtSpecifiers.get<IsVirtualField>(); }
857 void setIsVirtual(bool isVirtual)
858 {
859 nameIndexAndVirtSpecifiers.set<IsVirtualField>(isVirtual ? 1 : 0);
860 }
861
862 bool isOverride() const { return nameIndexAndVirtSpecifiers.get<IsOverrideField>(); }
863 void setIsOverride(bool isOverride)
864 {
865 nameIndexAndVirtSpecifiers.set<IsOverrideField>(isOverride ? 1 : 0);
866 }
867
868 bool isFinal() const { return nameIndexAndVirtSpecifiers.get<IsFinalField>(); }
869 void setIsFinal(bool isFinal) { nameIndexAndVirtSpecifiers.set<IsFinalField>(isFinal ? 1 : 0); }
870
872 {
873 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
874 data.set<IsCommonTypeField>(true);
875 }
876
878 if (isCommonType())
879 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
880 return CommonType::Invalid;
881 }
882
883 void setTypeNameIndex(int nameIndex)
884 {
885 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
886 data.set<IsCommonTypeField>(false);
887 }
888
889 int typeNameIndex() const
890 {
891 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
892 }
893
894 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
895 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
896
897 bool isList() const { return data.get<IsListField>(); }
898 void setIsList(bool isList) { data.set<IsListField>(isList); }
899
900 bool isRequired() const { return data.get<IsRequiredField>(); }
901 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
902
903 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
904 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
905};
906static_assert(sizeof(Property) == 12, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
907
911
912static_assert (sizeof(RequiredPropertyExtraData) == 4, "RequiredPropertyExtraData structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
913
914struct Alias
915{
916 bool isReadOnly() const { return m_nameIndexAndFlags.get<IsReadOnlyField>(); }
917 void setIsReadOnly(bool isReadOnly) { m_nameIndexAndFlags.set<IsReadOnlyField>(isReadOnly); }
918
919 quint32 nameIndex() const { return m_nameIndexAndFlags.get<NameIndexField>(); }
920 void setNameIndex(quint32 nameIndex)
921 {
922 m_nameIndexAndFlags.set<NameIndexField>(nameIndex);
923 }
924
925 quint32 idIndex() const { return m_idIndexField; }
926 void setIdIndex(quint32 idIndex) { m_idIndexField = idIndex; }
927
928 quint32 propertyNameIndex() const { return m_propertyNameIndex; }
929 void setPropertyNameIndex(quint32 propertyNameIndex)
930 {
931 m_propertyNameIndex = propertyNameIndex;
932 }
933
934 Location location() const { return m_location; }
935 void setLocation(Location location) { m_location = location; }
936
937 Location referenceLocation() const { return m_referenceLocation; }
938 void setReferenceLocation(Location referenceLocation)
939 {
940 m_referenceLocation = referenceLocation;
941 }
942
943private:
946
947 quint32_le_bitfield_union<NameIndexField, IsReadOnlyField> m_nameIndexAndFlags;
948 quint32_le m_idIndexField;
949 quint32_le m_propertyNameIndex; // string index
950 Location m_location;
951 Location m_referenceLocation;
952};
953static_assert(sizeof(Alias) == 20, "Alias structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
954
955struct Object
956{
957private:
961public:
962 enum Flag : unsigned int {
963 NoFlag = 0x0,
964 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
965 HasDeferredBindings = 0x2, // any of the bindings are deferred
969 };
971
972 // Depending on the use, this may be the type name to instantiate before instantiating this
973 // object. For grouped properties the type name will be empty and for attached properties
974 // it will be the name of the attached type.
979 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
987 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
988 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
1000// Function[]
1001// Property[]
1002// Signal[]
1003// Binding[]
1004// InlineComponent[]
1005// RequiredPropertyExtraData[]
1006
1007 Flags flags() const
1008 {
1009 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
1010 }
1011
1012 bool hasFlag(Flag flag) const
1013 {
1014 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
1015 }
1016
1017 void setFlag(Flag flag)
1018 {
1019 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(
1020 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1021 }
1022
1023 void setFlags(Flags flags)
1024 {
1025 flagsAndDefaultPropertyIsAliasAndId.set<FlagsField>(flags);
1026 }
1027
1029 {
1030 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1031 }
1032
1033 void setHasAliasAsDefaultProperty(bool defaultAlias)
1034 {
1035 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1036 }
1037
1039 {
1040 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1041 }
1042
1043 void setObjectId(qint32 id)
1044 {
1045 flagsAndDefaultPropertyIsAliasAndId.set<IdField>(id);
1046 }
1047
1048
1049 static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
1050 {
1051 return ( sizeof(Object)
1052 + nFunctions * sizeof(quint32)
1053 + nProperties * sizeof(Property)
1054 + nAliases * sizeof(Alias)
1055 + nEnums * sizeof(quint32)
1056 + nSignals * sizeof(quint32)
1057 + nBindings * sizeof(Binding)
1058 + nNamedObjectsInComponent * sizeof(int)
1059 + nInlineComponents * sizeof(InlineComponent)
1060 + nRequiredPropertyExtraData * sizeof(RequiredPropertyExtraData)
1061 + 0x7
1062 ) & ~0x7;
1063 }
1064
1066 {
1067 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1068 }
1069
1071 {
1072 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1073 }
1074
1075 const Alias *aliasTable() const
1076 {
1077 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1078 }
1079
1080 const Binding *bindingTable() const
1081 {
1082 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1083 }
1084
1085 const Enum *enumAt(int idx) const
1086 {
1087 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1088 const quint32_le offset = offsetTable[idx];
1089 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1090 }
1091
1092 const Signal *signalAt(int idx) const
1093 {
1094 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1095 const quint32_le offset = offsetTable[idx];
1096 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1097 }
1098
1100 {
1101 return inlineComponentTable() + idx;
1102 }
1103
1105 {
1106 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1107 }
1108
1110 {
1111 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1112 }
1113
1118
1120 {
1121 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1122 }
1123
1124 // --- QQmlPropertyCacheCreator interface
1125 int propertyCount() const { return nProperties; }
1126 int aliasCount() const { return nAliases; }
1127 int enumCount() const { return nEnums; }
1128 int signalCount() const { return nSignals; }
1129 int functionCount() const { return nFunctions; }
1130 int inlineComponentCount() const { return nInlineComponents; }
1131
1132 const Binding *bindingsBegin() const { return bindingTable(); }
1133 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1134 int bindingCount() const { return nBindings; }
1135
1136 const Property *propertiesBegin() const { return propertyTable(); }
1137 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1138
1139 const Alias *aliasesBegin() const { return aliasTable(); }
1140 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1141
1143 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1144 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1145
1147 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1148 SignalIterator signalsEnd() const { return SignalIterator(this, nSignals); }
1149
1151 InlineComponentIterator inlineComponentsBegin() const {return InlineComponentIterator(this, 0);}
1152 InlineComponentIterator inlineComponentsEnd() const {return InlineComponentIterator(this, nInlineComponents);}
1153
1155 RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const {return RequiredPropertyExtraDataIterator(this, 0); }
1156 RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const {return RequiredPropertyExtraDataIterator(this, nRequiredPropertyExtraData); }
1157
1158 int namedObjectsInComponentCount() const { return nNamedObjectsInComponent; }
1159 // ---
1160};
1161static_assert(sizeof(Object) == 84, "Object structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1162
1164{
1165 enum ImportType : unsigned int {
1170 };
1172
1175
1179
1181 {
1182 type = 0; uriIndex = 0; qualifierIndex = 0; version = QTypeRevision::zero(); reserved = 0;
1183 }
1184};
1185static_assert(sizeof(Import) == 20, "Import structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1186
1188{
1193
1194 const Import *importAt(int idx) const {
1195 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1196 }
1197
1198 const Object *objectAt(int idx) const {
1199 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1200 const quint32_le offset = offsetTable[idx];
1201 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1202 }
1203};
1204static_assert(sizeof(QmlUnit) == 16, "QmlUnit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1205
1206static const char magic_str[] = "qv4cdata";
1207
1208struct Unit
1209{
1210 // DO NOT CHANGE THESE FIELDS EVER
1211 char magic[8];
1213 // END DO NOT CHANGE THESE FIELDS EVER
1214
1215 quint32_le reserved; // For predictable alignment and size. Used to be Qt version.
1217 quint32_le unitSize; // Size of the Unit and any depending data.
1218
1219 char md5Checksum[16]; // checksum of all bytes following this field.
1221
1222 enum : unsigned int {
1224 StaticData = 0x2, // Unit data persistent in memory?
1226 IsSharedLibrary = 0x8, // .pragma shared?
1228 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1229 IsStrict = 0x40,
1240 };
1275
1277
1278 /* QML specific fields */
1279
1280 const QmlUnit *qmlUnit() const {
1281 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1282 }
1283
1285 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1286 }
1287
1288 bool isSingleton() const {
1289 return flags & Unit::IsSingleton;
1290 }
1291 /* end QML specific fields*/
1292
1293 QString stringAtInternal(uint idx) const {
1294 Q_ASSERT(idx < stringTableSize);
1295 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1296 const quint32_le offset = offsetTable[idx];
1297 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1298 Q_ASSERT(str->size >= 0);
1299#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1300 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1301 if (flags & StaticData)
1302 return QString::fromRawData(characters, str->size);
1303 return QString(characters, str->size);
1304#else
1305 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1306 QString qstr(str->size, Qt::Uninitialized);
1307 QChar *ch = qstr.data();
1308 for (int i = 0; i < str->size; ++i)
1309 ch[i] = QChar(quint16(characters[i]));
1310 return qstr;
1311#endif
1312 }
1313
1314 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1315 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1316 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1317 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1318
1319 const Function *functionAt(int idx) const {
1320 const quint32_le *offsetTable = functionOffsetTable();
1321 const quint32_le offset = offsetTable[idx];
1322 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1323 }
1324
1325 const Class *classAt(int idx) const {
1326 const quint32_le *offsetTable = classOffsetTable();
1327 const quint32_le offset = offsetTable[idx];
1328 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1329 }
1330
1331 const TemplateObject *templateObjectAt(int idx) const {
1332 const quint32_le *offsetTable = templateObjectOffsetTable();
1333 const quint32_le offset = offsetTable[idx];
1334 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1335 }
1336
1337 const Block *blockAt(int idx) const {
1338 const quint32_le *offsetTable = blockOffsetTable();
1339 const quint32_le offset = offsetTable[idx];
1340 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1341 }
1342
1343 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1344 const RegExp *regexpAt(int index) const {
1345 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1346 }
1347 const quint64_le *constants() const {
1348 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1349 }
1350
1351 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1352 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1353 const quint32_le offset = offsetTable[idx];
1354 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1355 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1356 *nMembers = klass->nMembers;
1357 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1358 }
1359
1361 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1362 }
1363
1365 if ( translationTableSize == 0)
1366 return nullptr;
1367 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1368 + offsetToTranslationTable
1369 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1370
1372 if ( translationTableSize == 0)
1373 return nullptr;
1374 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1375 + offsetToTranslationTable
1376 + translationTableSize * sizeof(CompiledData::TranslationData)); }
1377
1378 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1379 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1380 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1381 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1382
1383 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1384
1385 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1386};
1387
1388static_assert(sizeof(Unit) == 200, "Unit structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
1389
1391{
1393 : location(loc)
1394 , needsCreation(false)
1395 , errorWhenNotFound(false)
1396 {}
1397 Location location; // first use
1398 bool needsCreation : 1; // whether the type needs to be creatable or not
1400};
1401
1402// Map from name index to location of first use.
1404{
1405 TypeReference &add(int nameIndex, const Location &loc) {
1406 Iterator it = find(nameIndex);
1407 if (it != end())
1408 return *it;
1409 return *insert(nameIndex, loc);
1410 }
1411
1412 template <typename CompiledObject>
1413 void collectFromObject(const CompiledObject *obj)
1414 {
1415 if (obj->inheritedTypeNameIndex != 0) {
1416 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1417 r.needsCreation = true;
1418 r.errorWhenNotFound = true;
1419 }
1420
1421 auto binding = obj->bindingsBegin();
1422 auto const bindingEnd = obj->bindingsEnd();
1423 for ( ; binding != bindingEnd; ++binding) {
1425 this->add(binding->propertyNameIndex, binding->location);
1426 }
1427
1428 auto ic = obj->inlineComponentsBegin();
1429 auto const icEnd = obj->inlineComponentsEnd();
1430 for (; ic != icEnd; ++ic) {
1431 this->add(ic->nameIndex, ic->location);
1432 }
1433 }
1434
1435 template <typename Iterator>
1436 void collectFromObjects(Iterator it, Iterator end)
1437 {
1438 for (; it != end; ++it)
1439 collectFromObject(*it);
1440 }
1441};
1442
1444
1446
1448 InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
1449 : qmlType(qmlType)
1450 , objectIndex(objectIndex)
1451 , nameIndex(nameIndex)
1452 {}
1453
1454 QQmlType qmlType;
1455 int objectIndex = -1;
1456 int nameIndex = -1;
1457};
1458
1460{
1462
1463 const Unit *data = nullptr;
1464 const QmlUnit *qmlData = nullptr;
1468
1469 // pointers either to data->constants() or little-endian memory copy.
1470 const StaticValue *constants = nullptr;
1471
1473
1475
1476 // index is object index. This allows fast access to the
1477 // property data when initializing bindings, avoiding expensive
1478 // lookups by string (property name).
1480
1483
1485
1486 QQmlType qmlType;
1487
1489
1490public:
1491 // --- interface for QQmlPropertyCacheCreator
1495
1496 // Empty dummy. We don't need to do this when loading from cache.
1498 {
1499 public:
1500 void insert(int, int) {}
1501 void clear() {}
1502
1503 // We have already checked uniqueness of IDs when creating the CU
1504 bool contains(int) { return false; }
1505 };
1506
1507 explicit CompilationUnit(const Unit *unitData,
1508 const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions,
1509 LookupValidationFn validateLookupSignatures,
1510 const QString &fileName = QString(),
1511 const QString &finalUrlString = QString())
1512 : CompilationUnit(unitData, fileName, finalUrlString)
1513 {
1514 this->aotCompiledFunctions = aotCompiledFunctions;
1515 this->validateLookupSignatures = validateLookupSignatures;
1516 }
1517
1519 const Unit *unitData = nullptr, const QString &fileName = QString(),
1520 const QString &finalUrlString = QString());
1521
1523
1524 const Unit *unitData() const { return data; }
1525
1526 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1527 const QString &fileName = QString(), const QString &finalUrlString = QString())
1528 {
1529 data = unitData;
1530 qmlData = nullptr;
1531#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1532 delete [] constants;
1533#endif
1534 constants = nullptr;
1535 m_fileName.clear();
1536 m_finalUrlString.clear();
1537 if (!data)
1538 return;
1539
1540 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1541
1542#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1543 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1544 const quint64_le *littleEndianConstants = data->constants();
1545 for (uint i = 0; i < data->constantTableSize; ++i)
1546 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1547 constants = bigEndianConstants;
1548#else
1549 constants = reinterpret_cast<const StaticValue*>(data->constants());
1550#endif
1551
1552 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1553 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1554 }
1555
1556 QString stringAt(uint index) const
1557 {
1558 if (index < data->stringTableSize)
1559 return data->stringAtInternal(index);
1560
1561 const qsizetype dynamicIndex = index - data->stringTableSize;
1562 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1563 return dynamicStrings.at(dynamicIndex);
1564 }
1565
1566 QString fileName() const { return m_fileName; }
1567 QString finalUrlString() const { return m_finalUrlString; }
1568
1570 {
1571 using namespace CompiledData;
1572 switch (binding->type()) {
1573 case Binding::Type_Script:
1574 case Binding::Type_String:
1575 return stringAt(binding->stringIndex);
1576 case Binding::Type_Null:
1577 return QStringLiteral("null");
1579 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1580 case Binding::Type_Number:
1581 return QString::number(bindingValueAsNumber(binding), 'g', QLocale::FloatingPointShortest);
1583 return QString();
1584 case Binding::Type_TranslationById:
1585 case Binding::Type_Translation:
1586 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1587 default:
1588 break;
1589 }
1590 return QString();
1591 }
1592
1594 {
1595 return (binding->type() == CompiledData::Binding::Type_String)
1596 ? CompiledData::Binding::escapedString(stringAt(binding->stringIndex))
1597 : bindingValueAsString(binding);
1598 }
1599
1600 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1601 {
1603 return 0.0;
1604 return constants[binding->value.constantValueIndex].doubleValue();
1605 }
1606
1607 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1609 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1610 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const;
1611
1612 int importCount() const { return qmlData->nImports; }
1613 const CompiledData::Import *importAt(int index) const { return qmlData->importAt(index); }
1614
1615 Q_QML_EXPORT QStringList moduleRequests() const;
1616
1617 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1618 // warnings about that code. They include any potential URL interceptions and thus represent the
1619 // "physical" location of the code.
1620 //
1621 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1622 // They are _not_ intercepted and thus represent the "logical" name for the code.
1623
1624 QUrl url() const
1625 {
1626 if (!m_url.isValid())
1627 m_url = QUrl(fileName());
1628 return m_url;
1629 }
1630
1632 {
1633 if (!m_finalUrl.isValid())
1634 m_finalUrl = QUrl(finalUrlString());
1635 return m_finalUrl;
1636 }
1637
1638 ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
1639 ResolvedTypeReference *resolvedType(QMetaType type) const;
1640
1642 {
1643 return propertyCaches.isEmpty()
1644 ? QQmlPropertyCache::ConstPtr()
1645 : propertyCaches.at(/*root object*/0);
1646 }
1647
1648 int objectCount() const { return qmlData->nObjects; }
1649
1650 // Resolves implicit component wrapper indices (>= objectCount()) to the
1651 // wrapped child object index. Returns the index unchanged for real objects.
1652 int resolvedIndex(int index) const
1653 {
1654 if (index < objectCount())
1655 return index;
1656 const QQmlPropertyData *p = propertyCaches.at(index)->defaultProperty();
1657 Q_ASSERT(p && p->isComponentWrapper());
1658 return p->wrappedObjectIndex();
1659 }
1660
1661 const CompiledObject *objectAt(int index) const
1662 {
1664 }
1665
1666 // Returns the index of the implicit component wrapper, or -1.
1667 // Scans property caches at indices >= objectCount().
1668 int implicitComponentForObject(int index) const
1669 {
1670 for (int i = objectCount(), end = propertyCaches.count(); i < end; ++i) {
1671 const QQmlPropertyData *p = propertyCaches.at(i)->defaultProperty();
1672 Q_ASSERT(p && p->isComponentWrapper());
1673 if (p->wrappedObjectIndex() == index)
1674 return i;
1675 }
1676 return -1;
1677 }
1678
1679 int inlineComponentId(const QString &inlineComponentName) const
1680 {
1681 for (uint i = 0; i < qmlData->nObjects; ++i) {
1682 auto *object = qmlData->objectAt(i);
1683 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1684 it != end; ++it) {
1685 if (stringAt(it->nameIndex) == inlineComponentName)
1686 return it->objectIndex;
1687 }
1688 }
1689 return -1;
1690 }
1691
1692 void finalizeCompositeType(const QQmlType &type);
1693
1694 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1695
1705
1710
1715
1717 {
1719 }
1720
1725
1727 {
1729 }
1730
1732 {
1734 }
1735
1736 bool isESModule() const
1737 {
1739 }
1740
1741 bool isSharedLibrary() const
1742 {
1744 }
1745
1747 {
1748 FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
1749 : unit(unit), object(object), index(index) {}
1753
1755 {
1756 return unit->functionAt(object->functionOffsetTable()[index]);
1757 }
1758
1759 void operator++() { ++index; }
1760 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1761 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1762 };
1763
1765 {
1766 return FunctionIterator(unitData(), object, 0);
1767 }
1768
1770 {
1771 return FunctionIterator(unitData(), object, object->nFunctions);
1772 }
1773
1774 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1775 QMetaType metaType() const { return qmlType.typeId(); }
1776
1777private:
1778 QString m_fileName; // initialized from data->sourceFileIndex
1779 QString m_finalUrlString; // initialized from data->finalUrlIndex
1780
1781 mutable QQmlNullableValue<QUrl> m_url;
1782 mutable QQmlNullableValue<QUrl> m_finalUrl;
1783};
1784
1786{
1788public:
1794
1796
1797 template<typename Char>
1798 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1799 {
1800 const quint32_le oldFlags = mutableFlags();
1801 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1802 mutableFlags() |= temporaryFlags;
1803 return writer(data<Char>(), size());
1804 }
1805
1806 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1807 QString *errorString)
1808 {
1809#if QT_CONFIG(temporaryfile)
1810 QSaveFile cacheFile(outputFileName);
1811 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1812 || cacheFile.write(data, size) != size
1813 || !cacheFile.commit()) {
1814 *errorString = cacheFile.errorString();
1815 return false;
1816 }
1817
1818 errorString->clear();
1819 return true;
1820#else
1821 Q_UNUSED(outputFileName);
1822 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1823 return false;
1824#endif
1825 }
1826
1827private:
1828 const Unit *unit;
1829 quint32 temporaryFlags;
1830
1831 quint32_le &mutableFlags() const
1832 {
1833 return const_cast<Unit *>(unit)->flags;
1834 }
1835
1836 template<typename Char>
1837 const Char *data() const
1838 {
1839 Q_STATIC_ASSERT(sizeof(Char) == 1);
1840 const Char *dataPtr;
1841 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1842 return dataPtr;
1843 }
1844
1845 quint32 size() const
1846 {
1847 return unit->unitSize;
1848 }
1849};
1850
1851
1852} // CompiledData namespace
1853} // QV4 namespace
1854
1857
1858QT_END_NAMESPACE
1859
1860#endif
static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size, QString *errorString)
bool saveToDisk(const std::function< bool(const Char *, quint32)> &writer) const
Combined button and popup list for selecting options.
static const char magic_str[]
Definition qjsvalue.h:24
Q_DECLARE_TYPEINFO(QV4::CompiledData::JSClassMember, Q_PRIMITIVE_TYPE)
#define QV4_DATA_STRUCTURE_VERSION
Q_DECLARE_OPERATORS_FOR_FLAGS(QV4::CompiledData::ParameterType::Flags)
void setPropertyNameIndex(quint32 propertyNameIndex)
quint32 propertyNameIndex() const
void setIsReadOnly(bool isReadOnly)
void setReferenceLocation(Location referenceLocation)
void setNameIndex(quint32 nameIndex)
Location referenceLocation() const
void setIdIndex(quint32 idIndex)
void setLocation(Location location)
quint32_le_bitfield_union< FlagsField, TypeField > flagsAndType
bool hasFlag(Flag flag) const
static QString escapedString(const QString &string)
const quint32_le * localsTable() const
static size_t align(size_t a)
static int calculateSize(int nLocals)
static int calculateSize(int nStaticMethods, int nMethods)
static size_t align(size_t a)
const Method * methodTable() const
bool operator!=(const FunctionIterator &rhs) const
bool operator==(const FunctionIterator &rhs) const
FunctionIterator(const CompiledData::Unit *unit, const CompiledObject *object, int index)
std::unique_ptr< CompilationUnitMapper > backingFile
Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString) const
QString bindingValueAsScriptString(const CompiledData::Binding *binding) const
QHash< QString, InlineComponentData > inlineComponentData
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit=nullptr, const QString &fileName=QString(), const QString &finalUrlString=QString())
int inlineComponentId(const QString &inlineComponentName) const
double bindingValueAsNumber(const CompiledData::Binding *binding) const
void finalizeCompositeType(const QQmlType &type)
ResolvedTypeReference * resolvedType(int id) const
const CompiledData::Function CompiledFunction
const QQmlPrivate::AOTCompiledFunction * aotCompiledFunctions
int implicitComponentForObject(int index) const
ResolvedTypeReferenceMap resolvedTypes
QList< BindingPropertyData > bindingPropertyDataPerObject
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
QQmlType qmlTypeForComponent(const QString &inlineComponentName=QString()) const
FunctionIterator objectFunctionsBegin(const CompiledObject *object) const
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
FunctionIterator objectFunctionsEnd(const CompiledObject *object) const
ListPropertyAssignBehavior listPropertyAssignBehavior() const
const CompiledObject * objectAt(int index) const
const CompiledData::Object CompiledObject
const CompiledData::Binding CompiledBinding
const CompiledData::Import * importAt(int index) const
CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions, LookupValidationFn validateLookupSignatures, const QString &fileName=QString(), const QString &finalUrlString=QString())
QList< QQmlRefPointer< QQmlScriptData > > dependentScripts
Q_QML_EXPORT bool loadFromDisk(const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString)
QString bindingValueAsString(const CompiledData::Binding *binding) const
QQmlPropertyCache::ConstPtr rootPropertyCache() const
const EnumValue * enumValueAt(int idx) const
const EnumValue * enumValuesEnd() const
const EnumValue * enumValuesBegin() const
static int calculateSize(int nEnumValues)
const quint32_le * localsTable() const
static size_t align(size_t a)
const CodeOffsetToLineAndStatement * lineAndStatementNumberTable() const
size_t lineAndStatementNumberOffset() const
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int labelInfoSize, int codeSize)
const Parameter * formalsTable() const
const Parameter * formalsEnd() const
const Parameter * formalsBegin() const
const quint32_le * labelInfoTable() const
InlineComponentData(const QQmlType &qmlType, int objectIndex, int nameIndex)
void set(quint32 nameOffset, bool isAccessor)
static int calculateSize(int nMembers)
Location(quint32 l, quint32 c)
friend size_t qHash(const Location &location, size_t seed=0)
bool operator<(const Location &other) const
friend bool comparesEqual(const Location &a, const Location &b) noexcept
Lookup(Type type, Mode mode, quint32 nameIndex)
TableIterator< Enum, Object, &Object::enumAt > EnumIterator
EnumIterator enumsBegin() const
Q_DECLARE_FLAGS(Flags, Flag)
const RequiredPropertyExtraData * requiredPropertyExtraDataAt(int idx) const
EnumIterator enumsEnd() const
const Enum * enumAt(int idx) const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataEnd() const
const RequiredPropertyExtraData * requiredPropertyExtraDataTable() const
TableIterator< Signal, Object, &Object::signalAt > SignalIterator
const Binding * bindingsEnd() const
bool hasFlag(Flag flag) const
const Property * propertyTable() const
SignalIterator signalsBegin() const
quint32_le_bitfield_union< FlagsField, DefaultPropertyIsAliasField, IdField > flagsAndDefaultPropertyIsAliasAndId
InlineComponentIterator inlineComponentsEnd() const
const Alias * aliasTable() const
const InlineComponent * inlineComponentAt(int idx) const
const Property * propertiesEnd() const
const Binding * bindingTable() const
const Signal * signalAt(int idx) const
const Property * propertiesBegin() const
const quint32_le * functionOffsetTable() const
static int calculateSizeExcludingSignalsAndEnums(int nFunctions, int nProperties, int nAliases, int nEnums, int nSignals, int nBindings, int nNamedObjectsInComponent, int nInlineComponents, int nRequiredPropertyExtraData)
TableIterator< InlineComponent, Object, &Object::inlineComponentAt > InlineComponentIterator
const InlineComponent * inlineComponentTable() const
InlineComponentIterator inlineComponentsBegin() const
TableIterator< RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt > RequiredPropertyExtraDataIterator
SignalIterator signalsEnd() const
const Alias * aliasesEnd() const
const Binding * bindingsBegin() const
RequiredPropertyExtraDataIterator requiredPropertyExtraDataBegin() const
void setHasAliasAsDefaultProperty(bool defaultAlias)
const Alias * aliasesBegin() const
const quint32_le * namedObjectsInComponentTable() const
void set(Flags flags, quint32 typeNameIndexOrCommonType)
void setNameIndex(int nameIndex)
void setIsReadOnly(bool isReadOnly)
void setTypeNameIndex(int nameIndex)
void setIsVirtual(bool isVirtual)
quint32_le_bitfield_union< CommonTypeOrTypeNameIndexField, IsRequiredField, IsCommonTypeField, IsListField, IsReadOnlyField > data
quint32_le_bitfield_union< NameIndexField, IsVirtualField, IsOverrideField, IsFinalField > nameIndexAndVirtSpecifiers
void setIsOverride(bool isOverride)
void setIsRequired(bool isRequired)
const Object * objectAt(int idx) const
const Import * importAt(int idx) const
RegExp(quint32 flags, quint32 stringIndex)
Q_DECLARE_FLAGS(Flags, Flag)
bool addToHash(QCryptographicHash *hash, QHash< quintptr, QByteArray > *checksums) const
const Parameter * parametersBegin() const
static int calculateSize(int nParameters)
const Parameter * parametersEnd() const
const Parameter * parameterAt(int idx) const
static int calculateSize(const QString &str)
bool operator==(const TableIterator &rhs) const
bool operator!=(const TableIterator &rhs) const
TableIterator(const Container *container, int index)
TableIterator operator+(int offset) const
const ItemType * operator->() const
int operator-(TableIterator other) const
TableIterator operator-(int offset) const
const quint32_le * stringTable() const
void collectFromObject(const CompiledObject *obj)
TypeReference & add(int nameIndex, const Location &loc)
void collectFromObjects(Iterator it, Iterator end)
quint32_le offsetToIndirectExportEntryTable
quint32_le * translationContextIndex()
const TranslationData * translations() const
const ExportEntry * indirectExportEntryTable() const
const quint64_le * constants() const
QString stringAtInternal(uint idx) const
const quint32_le * functionOffsetTable() const
bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const
const Function * functionAt(int idx) const
const TemplateObject * templateObjectAt(int idx) const
const ExportEntry * starExportEntryTable() const
const Lookup * lookupTable() const
const RegExp * regexpAt(int index) const
const Block * blockAt(int idx) const
const ExportEntry * localExportEntryTable() const
const quint32_le * translationContextIndex() const
const quint32_le * classOffsetTable() const
const quint32_le * moduleRequestTable() const
const Class * classAt(int idx) const
const ImportEntry * importEntryTable() const
const QmlUnit * qmlUnit() const
const quint32_le * blockOffsetTable() const
const JSClassMember * jsClassAt(int idx, int *nMembers) const
const quint32_le * templateObjectOffsetTable() const