Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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#ifndef QV4COMPILEDDATA_P_H
4#define QV4COMPILEDDATA_P_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include <functional>
18
19#include <QtCore/qcryptographichash.h>
20#include <QtCore/qhash.h>
21#include <QtCore/qhashfunctions.h>
22#include <QtCore/qlocale.h>
23#include <QtCore/qscopeguard.h>
24#include <QtCore/qstring.h>
25#include <QtCore/qstringlist.h>
26#include <QtCore/qurl.h>
27#include <QtCore/qvector.h>
28#include <QtCore/qversionnumber.h>
29
30#if QT_CONFIG(temporaryfile)
31#include <QtCore/qsavefile.h>
32#endif
33
34#include <private/qendian_p.h>
35#include <private/qqmlnullablevalue_p.h>
36#include <private/qqmlpropertycachevector_p.h>
37#include <private/qqmlrefcount_p.h>
38#include <private/qqmltype_p.h>
39#include <private/qv4compilationunitmapper_p.h>
40#include <private/qv4staticvalue_p.h>
41
42#include <functional>
43#include <limits.h>
44
46
47// Bump this whenever the compiler data structures change in an incompatible way.
48//
49// IMPORTANT:
50//
51// Also change the comment behind the number to describe the latest change. This has the added
52// benefit that if another patch changes the version too, it will result in a merge conflict, and
53// not get removed silently.
54#define QV4_DATA_STRUCTURE_VERSION 0x42 // Change metatype computation of AOT-compiled functions
55
56class QIODevice;
58class QQmlType;
59class QQmlEngine;
61class QQmlScriptData;
62
63namespace QQmlPrivate {
65}
66
67namespace QmlIR {
68struct Document;
69}
70
71namespace QV4 {
72namespace Heap {
73struct Module;
74struct String;
75struct InternalClass;
76};
77
78struct Function;
79class EvalISelFactory;
81
82namespace CompiledData {
83
84// index is per-object binding index
85using BindingPropertyData = QVector<const QQmlPropertyData *>;
86
87// map from name index
88struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*>
89{
90 bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
91};
92
93struct String;
94struct Function;
95struct Lookup;
96struct RegExp;
97struct Unit;
98
99template <typename ItemType, typename Container, const ItemType *(Container::*IndexedGetter)(int index) const>
101{
103 const Container *container;
104 int index;
105
106 const ItemType *operator->() { return (container->*IndexedGetter)(index); }
107 ItemType operator*() {return *operator->();}
108 void operator++() { ++index; }
109 bool operator==(const TableIterator &rhs) const { return index == rhs.index; }
110 bool operator!=(const TableIterator &rhs) const { return index != rhs.index; }
111};
112
114{
117 {
118 m_data.set<LineField>(l);
119 m_data.set<ColumnField>(c);
120 Q_ASSERT(m_data.get<LineField>() == l);
121 Q_ASSERT(m_data.get<ColumnField>() == c);
122 }
123
124 inline bool operator<(const Location &other) const {
125 return m_data.get<LineField>() < other.m_data.get<LineField>()
126 || (m_data.get<LineField>() == other.m_data.get<LineField>()
127 && m_data.get<ColumnField>() < other.m_data.get<ColumnField>());
128 }
129
130 friend size_t qHash(const Location &location, size_t seed = 0)
131 {
132 return QT_PREPEND_NAMESPACE(qHash)(location.m_data.data(), seed);
133 }
134
135 friend bool operator==(const Location &a, const Location &b)
136 {
137 return a.m_data.data()== b.m_data.data();
138 }
139
141 {
142 m_data.set<LineField>(line);
143 m_data.set<ColumnField>(column);
144 }
145
146 quint32 line() const { return m_data.get<LineField>(); }
147 quint32 column() const { return m_data.get<ColumnField>(); }
148
149private:
150 using LineField = quint32_le_bitfield_member<0, 20>;
151 using ColumnField = quint32_le_bitfield_member<20, 12>;
152
153 quint32_le_bitfield_union<LineField, ColumnField> m_data;
154};
155static_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");
156
157struct RegExp
158{
159 enum Flags : unsigned int {
166 };
167
170 {
171 m_data.set<FlagsField>(flags);
172 m_data.set<StringIndexField>(stringIndex);
173 }
174
175 quint32 flags() const { return m_data.get<FlagsField>(); }
176 quint32 stringIndex() const { return m_data.get<StringIndexField>(); }
177
178private:
179 using FlagsField = quint32_le_bitfield_member<0, 5>;
180 using StringIndexField = quint32_le_bitfield_member<5, 27>;
181 quint32_le_bitfield_union<FlagsField, StringIndexField> m_data;
182};
183static_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");
184
185struct Lookup
186{
193
194 enum Mode : unsigned int {
196 Mode_ForCall = 1
197 };
198
199 quint32 type() const { return m_data.get<TypeField>(); }
200 quint32 nameIndex() const { return m_data.get<NameIndexField>(); }
201 quint32 mode() const { return m_data.get<ModeField>(); }
202
205 {
206 m_data.set<TypeField>(type);
207 m_data.set<ModeField>(mode);
208 m_data.set<NameIndexField>(nameIndex);
209 }
210
211private:
212 using TypeField = quint32_le_bitfield_member<0, 2>;
213 using ModeField = quint32_le_bitfield_member<2, 1>;
214 // 1 bit left
215 using NameIndexField = quint32_le_bitfield_member<4, 28>;
216 quint32_le_bitfield_union<TypeField, ModeField, NameIndexField> m_data;
217};
218static_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");
219
221{
223
225 {
226 m_data.set<NameOffsetField>(nameOffset);
227 m_data.set<IsAccessorField>(isAccessor ? 1 : 0);
228 }
229
230 quint32 nameOffset() const { return m_data.get<NameOffsetField>(); }
231 bool isAccessor() const { return m_data.get<IsAccessorField>() != 0; }
232
233private:
234 using NameOffsetField = quint32_le_bitfield_member<0, 31>;
235 using IsAccessorField = quint32_le_bitfield_member<31, 1>;
236 quint32_le_bitfield_union<NameOffsetField, IsAccessorField> m_data;
237};
238static_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");
239
241{
243 // JSClassMember[nMembers]
244
245 static int calculateSize(int nMembers) { return (sizeof(JSClass) + nMembers * sizeof(JSClassMember) + 7) & ~7; }
246};
247static_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");
248
249struct String
250{
252
253 static int calculateSize(const QString &str) {
254 // we cannot enconuter strings larger than INT_MAX anyway, as such a string
255 // would already break in other parts of the compilation process
256 return (sizeof(String) + (int(str.size()) + 1) * sizeof(quint16) + 7) & ~0x7;
257 }
258};
259
260static_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");
261
264 qint32_le line; // signed because debug instructions get negative line numbers
266};
267static_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");
268
269struct Block
270{
275
276 const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); }
277
278 static int calculateSize(int nLocals) {
279 int trailingData = nLocals*sizeof (quint32);
280 size_t size = align(align(sizeof(Block)) + size_t(trailingData));
281 Q_ASSERT(size < INT_MAX);
282 return int(size);
283 }
284
285 static size_t align(size_t a) {
286 return (a + 7) & ~size_t(7);
287 }
288};
289static_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");
290
291enum class NamedBuiltin: unsigned int {
293};
294
295enum class CommonType : unsigned int {
296 // Actual named builtins
306
307 // Optimization for very common other types
308 Time, Date, Rect, Point, Size,
309
310 // No type specified or not recognized
311 Invalid
312};
313
315{
316 enum Flag {
317 NoFlag = 0x0,
318 Common = 0x1,
319 List = 0x2,
320 };
322
324 {
325 m_data.set<IsListField>(flags.testFlag(List) ? 1 : 0);
326 m_data.set<IndexIsCommonTypeField>(flags.testFlag(Common) ? 1 : 0);
327 m_data.set<TypeNameIndexOrCommonTypeField>(typeNameIndexOrCommonType);
328 }
329
330 bool indexIsCommonType() const
331 {
332 return m_data.get<IndexIsCommonTypeField>() != 0;
333 }
334
335 bool isList() const
336 {
337 return m_data.get<IsListField>() != 0;
338 }
339
341 {
342 return m_data.get<TypeNameIndexOrCommonTypeField>();
343 }
344
345private:
346 using IndexIsCommonTypeField = quint32_le_bitfield_member<0, 1>;
347 using IsListField = quint32_le_bitfield_member<1, 1>;
348 using TypeNameIndexOrCommonTypeField = quint32_le_bitfield_member<2, 30>;
349 quint32_le_bitfield_union<IndexIsCommonTypeField, IsListField, TypeNameIndexOrCommonTypeField> m_data;
350};
351static_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");
352
358static_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");
359
360// Function is aligned on an 8-byte boundary to make sure there are no bus errors or penalties
361// for unaligned access. The ordering of the fields is also from largest to smallest.
363{
364 enum Flags : unsigned int {
365 IsStrict = 0x1,
369 };
370
371 // Absolute offset into file where the code for this function is located.
374
378 quint32_le formalsOffset; // Can't turn this into a calculated offset because of the mutation in CompilationUnit::createUnitData.
383 size_t lineAndStatementNumberOffset() const { return localsOffset + nLocals * sizeof(quint32); }
384 quint32_le nestedFunctionIndex; // for functions that only return a single closure, used in signal handlers
385
389
393
398
399 // Keep all unaligned data at the end
402
403 // quint32 formalsIndex[nFormals]
404 // quint32 localsIndex[nLocals]
405
406 const Parameter *formalsTable() const
407 {
408 return reinterpret_cast<const Parameter *>(
409 reinterpret_cast<const char *>(this) + formalsOffset);
410 }
411 const quint32_le *localsTable() const
412 {
413 return reinterpret_cast<const quint32_le *>(
414 reinterpret_cast<const char *>(this) + localsOffset);
415 }
417 {
418 return reinterpret_cast<const CodeOffsetToLineAndStatement *>(
419 reinterpret_cast<const char *>(this) + lineAndStatementNumberOffset());
420 }
421
422 // --- QQmlPropertyCacheCreator interface
423 const Parameter *formalsBegin() const { return formalsTable(); }
424 const Parameter *formalsEnd() const { return formalsTable() + nFormals; }
425 // ---
426
427 const quint32_le *labelInfoTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + labelInfosOffset()); }
428
429 const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; }
430
431 static int calculateSize(
432 int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions,
433 int labelInfoSize, int codeSize)
434 {
435 int trailingData = nFormals * sizeof(Parameter)
436 + (nLocals + nInnerfunctions + labelInfoSize) * sizeof (quint32)
437 + nLinesAndStatements * sizeof(CodeOffsetToLineAndStatement);
438 size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize);
439 Q_ASSERT(size < INT_MAX);
440 return int(size);
441 }
442
443 static size_t align(size_t a) {
444 return (a + 7) & ~size_t(7);
445 }
446};
447static_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");
448
460static_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");
461
462struct Class
463{
470
471 const Method *methodTable() const { return reinterpret_cast<const Method *>(reinterpret_cast<const char *>(this) + methodTableOffset); }
472
473 static int calculateSize(int nStaticMethods, int nMethods) {
474 int trailingData = (nStaticMethods + nMethods) * sizeof(Method);
475 size_t size = align(sizeof(Class) + trailingData);
476 Q_ASSERT(size < INT_MAX);
477 return int(size);
478 }
479
480 static size_t align(size_t a) {
481 return (a + 7) & ~size_t(7);
482 }
483};
484static_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");
485
487{
489
490 static int calculateSize(int size) {
491 int trailingData = 2 * size * sizeof(quint32_le);
492 size_t s = align(sizeof(TemplateObject) + trailingData);
493 Q_ASSERT(s < INT_MAX);
494 return int(s);
495 }
496
497 static size_t align(size_t a) {
498 return (a + 7) & ~size_t(7);
499 }
500
501 const quint32_le *stringTable() const {
502 return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this + 1));
503 }
504
506 return stringTable()[i];
507 }
509 return stringTable()[size + i];
510 }
511};
512static_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");
513
522static_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");
523
531static_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");
532
533// Qml data structures
534
543static_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");
544
546{
548
562
577
578 using FlagsField = quint32_le_bitfield_member<0, 16>;
579 using TypeField = quint32_le_bitfield_member<16, 16>;
580 quint32_le_bitfield_union<FlagsField, TypeField> flagsAndType;
581
583 void setFlag(Flag flag) { flagsAndType.set<FlagsField>(flagsAndType.get<FlagsField>() | flag); }
584 bool hasFlag(Flag flag) const { return Flags(flagsAndType.get<FlagsField>()) & flag; }
585 Flags flags() const { return Flags(flagsAndType.get<FlagsField>()); }
586
588 Type type() const { return Type(flagsAndType.get<TypeField>()); }
589
590 union {
591 bool b;
593 quint32_le compiledScriptIndex; // used when Type_Script
595 quint32_le translationDataIndex; // used when Type_Translation
598 quint32_le stringIndex; // Set for Type_String and Type_Script (the latter because of script strings)
599
602
604 {
605 const Flags bindingFlags = flags();
606 return bindingFlags & IsSignalHandlerExpression
607 || bindingFlags & IsSignalHandlerObject
608 || bindingFlags & IsPropertyObserver;
609 }
610
611 bool isValueBinding() const
612 {
613 switch (type()) {
616 return false;
617 default:
619 }
620 }
621
624
625 bool isSignalHandler() const
626 {
631 return true;
632 }
633 return false;
634 }
635
637 {
638 if (type() == Type_AttachedProperty) {
642 return true;
643 }
644 return false;
645 }
646
647 bool isGroupProperty() const
648 {
649 if (type() == Type_GroupProperty) {
653 return true;
654 }
655 return false;
656 }
657
659
660 //reverse of Lexer::singleEscape()
661 static QString escapedString(const QString &string)
662 {
663 QString tmp = QLatin1String("\"");
664 for (int i = 0; i < string.size(); ++i) {
665 const QChar &c = string.at(i);
666 switch (c.unicode()) {
667 case 0x08:
668 tmp += QLatin1String("\\b");
669 break;
670 case 0x09:
671 tmp += QLatin1String("\\t");
672 break;
673 case 0x0A:
674 tmp += QLatin1String("\\n");
675 break;
676 case 0x0B:
677 tmp += QLatin1String("\\v");
678 break;
679 case 0x0C:
680 tmp += QLatin1String("\\f");
681 break;
682 case 0x0D:
683 tmp += QLatin1String("\\r");
684 break;
685 case 0x22:
686 tmp += QLatin1String("\\\"");
687 break;
688 case 0x27:
689 tmp += QLatin1String("\\\'");
690 break;
691 case 0x5C:
692 tmp += QLatin1String("\\\\");
693 break;
694 default:
695 tmp += c;
696 break;
697 }
698 }
699 tmp += QLatin1Char('\"');
700 return tmp;
701 }
702
704 {
705 const Binding::Type bindingType = type();
706 return bindingType == Type_Translation || bindingType == Type_TranslationById;
707 }
708 bool evaluatesToString() const { return type() == Type_String || isTranslationBinding(); }
709
710 bool isNumberBinding() const { return type() == Type_Number; }
711
712 bool valueAsBoolean() const
713 {
714 if (type() == Type_Boolean)
715 return value.b;
716 return false;
717 }
718};
719
720static_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");
721
728
729static_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");
730
737static_assert(sizeof(EnumValue) == 12, "EnumValue structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
738
739struct Enum
740{
744
745 const EnumValue *enumValueAt(int idx) const {
746 return reinterpret_cast<const EnumValue*>(this + 1) + idx;
747 }
748
749 static int calculateSize(int nEnumValues) {
750 return (sizeof(Enum)
751 + nEnumValues * sizeof(EnumValue)
752 + 7) & ~0x7;
753 }
754
755 // --- QQmlPropertyCacheCreatorInterface
756 const EnumValue *enumValuesBegin() const { return enumValueAt(0); }
757 const EnumValue *enumValuesEnd() const { return enumValueAt(nEnumValues); }
758 int enumValueCount() const { return nEnumValues; }
759 // ---
760};
761static_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");
762
763struct Signal
764{
768 // Parameter parameters[1];
769
770 const Parameter *parameterAt(int idx) const {
771 return reinterpret_cast<const Parameter*>(this + 1) + idx;
772 }
773
774 static int calculateSize(int nParameters) {
775 return (sizeof(Signal)
776 + nParameters * sizeof(Parameter)
777 + 7) & ~0x7;
778 }
779
780 // --- QQmlPropertyCacheCceatorInterface
781 const Parameter *parametersBegin() const { return parameterAt(0); }
782 const Parameter *parametersEnd() const { return parameterAt(nParameters); }
783 int parameterCount() const { return nParameters; }
784 // ---
785};
786static_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");
787
789{
790private:
791 using CommonTypeOrTypeNameIndexField = quint32_le_bitfield_member<0, 28>;
792 using IsRequiredField = quint32_le_bitfield_member<28, 1>;
793 using IsCommonTypeField = quint32_le_bitfield_member<29, 1>;
794 using IsListField = quint32_le_bitfield_member<30, 1>;
795 using IsReadOnlyField = quint32_le_bitfield_member<31, 1>;
796
797public:
800 CommonTypeOrTypeNameIndexField,
801 IsRequiredField,
802 IsCommonTypeField,
803 IsListField,
804 IsReadOnlyField> data;
806
808 {
809 data.set<CommonTypeOrTypeNameIndexField>(static_cast<quint32>(t));
810 data.set<IsCommonTypeField>(true);
811 }
812
814 if (data.get<IsCommonTypeField>() != 0)
815 return CommonType(data.get<CommonTypeOrTypeNameIndexField>());
816 return CommonType::Invalid;
817 }
818
820 {
821 data.set<CommonTypeOrTypeNameIndexField>(nameIndex);
822 data.set<IsCommonTypeField>(false);
823 }
824
825 int typeNameIndex() const
826 {
827 return data.get<IsCommonTypeField>() ? -1 : data.get<CommonTypeOrTypeNameIndexField>();
828 }
829
830 bool isCommonType() const { return data.get<IsCommonTypeField>(); }
831 uint commonTypeOrTypeNameIndex() const { return data.get<CommonTypeOrTypeNameIndexField>(); }
832
833 bool isList() const { return data.get<IsListField>(); }
834 void setIsList(bool isList) { data.set<IsListField>(isList); }
835
836 bool isRequired() const { return data.get<IsRequiredField>(); }
837 void setIsRequired(bool isRequired) { data.set<IsRequiredField>(isRequired); }
838
839 bool isReadOnly() const { return data.get<IsReadOnlyField>(); }
840 void setIsReadOnly(bool isReadOnly) { data.set<IsReadOnlyField>(isReadOnly); }
841};
842static_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");
843
847
848static_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");
849
850struct Alias {
851private:
852 using NameIndexField = quint32_le_bitfield_member<0, 29>;
853 using FlagsField = quint32_le_bitfield_member<29, 3>;
854
855 // object id index (in QQmlContextData::idValues)
856 using TargetObjectIdField = quint32_le_bitfield_member<0, 31>;
857 using AliasToLocalAliasField = quint32_le_bitfield_member<31, 1>;
858 using IdIndexField = quint32_le_bitfield_member<0, 32>;
859
860public:
861
862 enum Flag : unsigned int {
864 Resolved = 0x2,
866 };
868
869 quint32_le_bitfield_union<NameIndexField, FlagsField> nameIndexAndFlags;
870 quint32_le_bitfield_union<IdIndexField, TargetObjectIdField, AliasToLocalAliasField>
872
873 union {
876 quint32_le localAliasIndex; // index in list of aliases local to the object (if targetObjectId == objectId)
877 };
880
881 bool hasFlag(Flag flag) const
882 {
883 return nameIndexAndFlags.get<FlagsField>() & flag;
884 }
885
886 void setFlag(Flag flag)
887 {
888 nameIndexAndFlags.set<FlagsField>(nameIndexAndFlags.get<FlagsField>() | flag);
889 }
890
892 {
893 nameIndexAndFlags.set<FlagsField>(0);
894 }
895
897 {
898 return nameIndexAndFlags.get<NameIndexField>();
899 }
900
902 {
903 nameIndexAndFlags.set<NameIndexField>(nameIndex);
904 }
905
906 bool isObjectAlias() const
907 {
909 return encodedMetaPropertyIndex == -1;
910 }
911
913 {
914 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<IdIndexField>();
915 }
916
921
922
924 {
925 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<AliasToLocalAliasField>();
926 }
927
932
934 {
935 return idIndexAndTargetObjectIdAndAliasToLocalAlias.get<TargetObjectIdField>();
936 }
937
942};
943static_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");
944
945struct Object
946{
947private:
948 using FlagsField = quint32_le_bitfield_member<0, 15>;
949 using DefaultPropertyIsAliasField = quint32_le_bitfield_member<15, 1>;
950 using IdField = quint32_le_bitfield_member<16, 16, qint32>;
951public:
952 enum Flag : unsigned int {
953 NoFlag = 0x0,
954 IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
955 HasDeferredBindings = 0x2, // any of the bindings are deferred
959 };
961
962 // Depending on the use, this may be the type name to instantiate before instantiating this
963 // object. For grouped properties the type name will be empty and for attached properties
964 // it will be the name of the attached type.
967 quint32_le_bitfield_union<FlagsField, DefaultPropertyIsAliasField, IdField>
969 qint32_le indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
977 quint32_le offsetToEnums; // which in turn will be a table with offsets to variable-sized Enum objects
978 quint32_le offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
990// Function[]
991// Property[]
992// Signal[]
993// Binding[]
994// InlineComponent[]
995// RequiredPropertyExtraData[]
996
997 Flags flags() const
998 {
999 return Flags(flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>());
1000 }
1001
1002 bool hasFlag(Flag flag) const
1003 {
1004 return flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() & flag;
1005 }
1006
1007 void setFlag(Flag flag)
1008 {
1010 flagsAndDefaultPropertyIsAliasAndId.get<FlagsField>() | flag);
1011 }
1012
1014 {
1016 }
1017
1019 {
1020 return flagsAndDefaultPropertyIsAliasAndId.get<DefaultPropertyIsAliasField>();
1021 }
1022
1023 void setHasAliasAsDefaultProperty(bool defaultAlias)
1024 {
1025 flagsAndDefaultPropertyIsAliasAndId.set<DefaultPropertyIsAliasField>(defaultAlias);
1026 }
1027
1029 {
1030 return flagsAndDefaultPropertyIsAliasAndId.get<IdField>();
1031 }
1032
1034 {
1036 }
1037
1038
1040 {
1041 return ( sizeof(Object)
1042 + nFunctions * sizeof(quint32)
1043 + nProperties * sizeof(Property)
1044 + nAliases * sizeof(Alias)
1045 + nEnums * sizeof(quint32)
1046 + nSignals * sizeof(quint32)
1047 + nBindings * sizeof(Binding)
1048 + nNamedObjectsInComponent * sizeof(int)
1051 + 0x7
1052 ) & ~0x7;
1053 }
1054
1056 {
1057 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToFunctions);
1058 }
1059
1061 {
1062 return reinterpret_cast<const Property*>(reinterpret_cast<const char *>(this) + offsetToProperties);
1063 }
1064
1065 const Alias *aliasTable() const
1066 {
1067 return reinterpret_cast<const Alias*>(reinterpret_cast<const char *>(this) + offsetToAliases);
1068 }
1069
1070 const Binding *bindingTable() const
1071 {
1072 return reinterpret_cast<const Binding*>(reinterpret_cast<const char *>(this) + offsetToBindings);
1073 }
1074
1075 const Enum *enumAt(int idx) const
1076 {
1077 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToEnums);
1078 const quint32_le offset = offsetTable[idx];
1079 return reinterpret_cast<const Enum*>(reinterpret_cast<const char*>(this) + offset);
1080 }
1081
1082 const Signal *signalAt(int idx) const
1083 {
1084 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToSignals);
1085 const quint32_le offset = offsetTable[idx];
1086 return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
1087 }
1088
1090 {
1091 return inlineComponentTable() + idx;
1092 }
1093
1095 {
1096 return reinterpret_cast<const quint32_le*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
1097 }
1098
1100 {
1101 return reinterpret_cast<const InlineComponent*>(reinterpret_cast<const char *>(this) + offsetToInlineComponents);
1102 }
1103
1105 {
1106 return requiredPropertyExtraDataTable() + idx;
1107 }
1108
1110 {
1111 return reinterpret_cast<const RequiredPropertyExtraData*>(reinterpret_cast<const char *>(this) + offsetToRequiredPropertyExtraData);
1112 }
1113
1114 // --- QQmlPropertyCacheCreator interface
1115 int propertyCount() const { return nProperties; }
1116 int aliasCount() const { return nAliases; }
1117 int enumCount() const { return nEnums; }
1118 int signalCount() const { return nSignals; }
1119 int functionCount() const { return nFunctions; }
1120
1121 const Binding *bindingsBegin() const { return bindingTable(); }
1122 const Binding *bindingsEnd() const { return bindingTable() + nBindings; }
1123 int bindingCount() const { return nBindings; }
1124
1125 const Property *propertiesBegin() const { return propertyTable(); }
1126 const Property *propertiesEnd() const { return propertyTable() + nProperties; }
1127
1128 const Alias *aliasesBegin() const { return aliasTable(); }
1129 const Alias *aliasesEnd() const { return aliasTable() + nAliases; }
1130
1131 typedef TableIterator<Enum, Object, &Object::enumAt> EnumIterator;
1132 EnumIterator enumsBegin() const { return EnumIterator(this, 0); }
1133 EnumIterator enumsEnd() const { return EnumIterator(this, nEnums); }
1134
1135 typedef TableIterator<Signal, Object, &Object::signalAt> SignalIterator;
1136 SignalIterator signalsBegin() const { return SignalIterator(this, 0); }
1138
1139 typedef TableIterator<InlineComponent, Object, &Object::inlineComponentAt> InlineComponentIterator;
1142
1143 typedef TableIterator<RequiredPropertyExtraData, Object, &Object::requiredPropertyExtraDataAt> RequiredPropertyExtraDataIterator;
1146
1148 // ---
1149};
1150static_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");
1151
1174static_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");
1175
1177{
1182
1183 const Import *importAt(int idx) const {
1184 return reinterpret_cast<const Import*>((reinterpret_cast<const char *>(this)) + offsetToImports + idx * sizeof(Import));
1185 }
1186
1187 const Object *objectAt(int idx) const {
1188 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToObjects);
1189 const quint32_le offset = offsetTable[idx];
1190 return reinterpret_cast<const Object*>(reinterpret_cast<const char*>(this) + offset);
1191 }
1192};
1193static_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");
1194
1196static const char magic_str[] = "qv4cdata";
1197
1198struct Unit
1199{
1200 // DO NOT CHANGE THESE FIELDS EVER
1201 char magic[8];
1205 quint32_le unitSize; // Size of the Unit and any depending data.
1206 // END DO NOT CHANGE THESE FIELDS EVER
1207
1209
1210 char md5Checksum[16]; // checksum of all bytes following this field.
1212
1213 enum : unsigned int {
1215 StaticData = 0x2, // Unit data persistent in memory?
1217 IsSharedLibrary = 0x8, // .pragma shared?
1219 PendingTypeCompilation = 0x20, // the QML data structures present are incomplete and require type compilation
1220 IsStrict = 0x40,
1230 };
1265
1267
1268 /* QML specific fields */
1269
1270 const QmlUnit *qmlUnit() const {
1271 return reinterpret_cast<const QmlUnit *>(reinterpret_cast<const char *>(this) + offsetToQmlUnit);
1272 }
1273
1275 return reinterpret_cast<QmlUnit *>(reinterpret_cast<char *>(this) + offsetToQmlUnit);
1276 }
1277
1278 bool isSingleton() const {
1279 return flags & Unit::IsSingleton;
1280 }
1281 /* end QML specific fields*/
1282
1285 const quint32_le *offsetTable = reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
1286 const quint32_le offset = offsetTable[idx];
1287 const String *str = reinterpret_cast<const String*>(reinterpret_cast<const char *>(this) + offset);
1288 Q_ASSERT(str->size >= 0);
1289 if (str->size == 0)
1290 return QString();
1291#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
1292 const QChar *characters = reinterpret_cast<const QChar *>(str + 1);
1293 if (flags & StaticData)
1295 return QString(characters, str->size);
1296#else
1297 const quint16_le *characters = reinterpret_cast<const quint16_le *>(str + 1);
1299 QChar *ch = qstr.data();
1300 for (int i = 0; i < str->size; ++i)
1301 ch[i] = QChar(characters[i]);
1302 return qstr;
1303#endif
1304 }
1305
1306 const quint32_le *functionOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToFunctionTable); }
1307 const quint32_le *classOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToClassTable); }
1308 const quint32_le *templateObjectOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToTemplateObjectTable); }
1309 const quint32_le *blockOffsetTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToBlockTable); }
1310
1311 const Function *functionAt(int idx) const {
1312 const quint32_le *offsetTable = functionOffsetTable();
1313 const quint32_le offset = offsetTable[idx];
1314 return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
1315 }
1316
1317 const Class *classAt(int idx) const {
1318 const quint32_le *offsetTable = classOffsetTable();
1319 const quint32_le offset = offsetTable[idx];
1320 return reinterpret_cast<const Class *>(reinterpret_cast<const char *>(this) + offset);
1321 }
1322
1323 const TemplateObject *templateObjectAt(int idx) const {
1324 const quint32_le *offsetTable = templateObjectOffsetTable();
1325 const quint32_le offset = offsetTable[idx];
1326 return reinterpret_cast<const TemplateObject *>(reinterpret_cast<const char *>(this) + offset);
1327 }
1328
1329 const Block *blockAt(int idx) const {
1330 const quint32_le *offsetTable = blockOffsetTable();
1331 const quint32_le offset = offsetTable[idx];
1332 return reinterpret_cast<const Block *>(reinterpret_cast<const char *>(this) + offset);
1333 }
1334
1335 const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
1336 const RegExp *regexpAt(int index) const {
1337 return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
1338 }
1339 const quint64_le *constants() const {
1340 return reinterpret_cast<const quint64_le*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
1341 }
1342
1343 const JSClassMember *jsClassAt(int idx, int *nMembers) const {
1344 const quint32_le *offsetTable = reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + offsetToJSClassTable);
1345 const quint32_le offset = offsetTable[idx];
1346 const char *ptr = reinterpret_cast<const char *>(this) + offset;
1347 const JSClass *klass = reinterpret_cast<const JSClass *>(ptr);
1348 *nMembers = klass->nMembers;
1349 return reinterpret_cast<const JSClassMember*>(ptr + sizeof(JSClass));
1350 }
1351
1353 return reinterpret_cast<const TranslationData *>(reinterpret_cast<const char *>(this) + offsetToTranslationTable);
1354 }
1355
1357 if ( translationTableSize == 0)
1358 return nullptr;
1359 return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this))
1362
1364 if ( translationTableSize == 0)
1365 return nullptr;
1366 return reinterpret_cast<quint32_le*>((reinterpret_cast<char *>(this))
1369
1370 const ImportEntry *importEntryTable() const { return reinterpret_cast<const ImportEntry *>(reinterpret_cast<const char *>(this) + offsetToImportEntryTable); }
1371 const ExportEntry *localExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToLocalExportEntryTable); }
1372 const ExportEntry *indirectExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToIndirectExportEntryTable); }
1373 const ExportEntry *starExportEntryTable() const { return reinterpret_cast<const ExportEntry *>(reinterpret_cast<const char *>(this) + offsetToStarExportEntryTable); }
1374
1375 const quint32_le *moduleRequestTable() const { return reinterpret_cast<const quint32_le*>((reinterpret_cast<const char *>(this)) + offsetToModuleRequestTable); }
1376
1377 bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
1378};
1379
1380static_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");
1381
1383{
1385 : location(loc)
1388 {}
1389 Location location; // first use
1390 bool needsCreation : 1; // whether the type needs to be creatable or not
1392};
1393
1394// Map from name index to location of first use.
1395struct TypeReferenceMap : QHash<int, TypeReference>
1396{
1397 TypeReference &add(int nameIndex, const Location &loc) {
1398 Iterator it = find(nameIndex);
1399 if (it != end())
1400 return *it;
1401 return *insert(nameIndex, loc);
1402 }
1403
1404 template <typename CompiledObject>
1405 void collectFromObject(const CompiledObject *obj)
1406 {
1407 if (obj->inheritedTypeNameIndex != 0) {
1408 TypeReference &r = this->add(obj->inheritedTypeNameIndex, obj->location);
1409 r.needsCreation = true;
1410 r.errorWhenNotFound = true;
1411 }
1412
1413 auto prop = obj->propertiesBegin();
1414 auto const propEnd = obj->propertiesEnd();
1415 for ( ; prop != propEnd; ++prop) {
1416 if (!prop->isCommonType()) {
1417 TypeReference &r = this->add(prop->commonTypeOrTypeNameIndex(), prop->location);
1418 r.errorWhenNotFound = true;
1419 }
1420 }
1421
1422 auto binding = obj->bindingsBegin();
1423 auto const bindingEnd = obj->bindingsEnd();
1424 for ( ; binding != bindingEnd; ++binding) {
1426 this->add(binding->propertyNameIndex, binding->location);
1427 }
1428
1429 auto ic = obj->inlineComponentsBegin();
1430 auto const icEnd = obj->inlineComponentsEnd();
1431 for (; ic != icEnd; ++ic) {
1432 this->add(ic->nameIndex, ic->location);
1433 }
1434 }
1435
1436 template <typename Iterator>
1438 {
1439 for (; it != end; ++it)
1441 }
1442};
1443
1444using DependentTypesHasher = std::function<QByteArray()>;
1445
1467
1468struct CompilationUnit final : public QQmlRefCounted<CompilationUnit>
1469{
1470 Q_DISABLE_COPY_MOVE(CompilationUnit)
1471
1472 const Unit *data = nullptr;
1473 const QmlUnit *qmlData = nullptr;
1475 const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions = nullptr;
1476
1477 // pointers either to data->constants() or little-endian memory copy.
1478 const StaticValue *constants = nullptr;
1479
1481
1482 int m_totalBindingsCount = 0; // Number of bindings used in this type
1483 int m_totalParserStatusCount = 0; // Number of instantiated types that are QQmlParserStatus subclasses
1484 int m_totalObjectCount = 0; // Number of objects explicitly instantiated
1485
1486 std::unique_ptr<QString> icRootName;
1488
1489 // index is object index. This allows fast access to the
1490 // property data when initializing bindings, avoiding expensive
1491 // lookups by string (property name).
1493
1496
1498
1500
1502
1503public:
1504 // --- interface for QQmlPropertyCacheCreator
1505 using CompiledObject = const CompiledData::Object;
1506 using CompiledFunction = const CompiledData::Function;
1507 using CompiledBinding = const CompiledData::Binding;
1508
1509 // Empty dummy. We don't need to do this when loading from cache.
1511 {
1512 public:
1513 void insert(int, int) {}
1514 void clear() {}
1515
1516 // We have already checked uniqueness of IDs when creating the CU
1517 bool contains(int) { return false; }
1518 };
1519
1526
1527 Q_QML_EXPORT CompilationUnit(
1528 const Unit *unitData = nullptr, const QString &fileName = QString(),
1529 const QString &finalUrlString = QString());
1530
1531 Q_QML_EXPORT ~CompilationUnit();
1532
1533 const Unit *unitData() const { return data; }
1534
1535 void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
1536 const QString &fileName = QString(), const QString &finalUrlString = QString())
1537 {
1538 data = unitData;
1539 qmlData = nullptr;
1540#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1541 delete [] constants;
1542#endif
1543 constants = nullptr;
1544 m_fileName.clear();
1545 m_finalUrlString.clear();
1546 if (!data)
1547 return;
1548
1549 qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
1550
1551#if Q_BYTE_ORDER == Q_BIG_ENDIAN
1552 StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
1553 const quint64_le *littleEndianConstants = data->constants();
1554 for (uint i = 0; i < data->constantTableSize; ++i)
1555 bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
1556 constants = bigEndianConstants;
1557#else
1558 constants = reinterpret_cast<const StaticValue*>(data->constants());
1559#endif
1560
1561 m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
1562 m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
1563 }
1564
1566 {
1567 if (index < data->stringTableSize)
1568 return data->stringAtInternal(index);
1569
1570 const qsizetype dynamicIndex = index - data->stringTableSize;
1571 Q_ASSERT(dynamicIndex < dynamicStrings.size());
1572 return dynamicStrings.at(dynamicIndex);
1573 }
1574
1575 QString fileName() const { return m_fileName; }
1576 QString finalUrlString() const { return m_finalUrlString; }
1577
1579 {
1580 using namespace CompiledData;
1581 switch (binding->type()) {
1584 return stringAt(binding->stringIndex);
1585 case Binding::Type_Null:
1586 return QStringLiteral("null");
1588 return binding->value.b ? QStringLiteral("true") : QStringLiteral("false");
1592 return QString();
1595 return stringAt(data->translations()[binding->value.translationDataIndex].stringIndex);
1596 default:
1597 break;
1598 }
1599 return QString();
1600 }
1601
1608
1609 double bindingValueAsNumber(const CompiledData::Binding *binding) const
1610 {
1611 if (binding->type() != CompiledData::Binding::Type_Number)
1612 return 0.0;
1613 return constants[binding->value.constantValueIndex].doubleValue();
1614 }
1615
1616 Q_QML_EXPORT static QString localCacheFilePath(const QUrl &url);
1617 Q_QML_EXPORT bool loadFromDisk(
1618 const QUrl &url, const QDateTime &sourceTimeStamp, QString *errorString);
1619 Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString);
1620
1621 int importCount() const { return qmlData->nImports; }
1623
1624 Q_QML_EXPORT QStringList moduleRequests() const;
1625
1626 // url() and fileName() shall be used to load the actual QML/JS code or to show errors or
1627 // warnings about that code. They include any potential URL interceptions and thus represent the
1628 // "physical" location of the code.
1629 //
1630 // finalUrl() and finalUrlString() shall be used to resolve further URLs referred to in the code
1631 // They are _not_ intercepted and thus represent the "logical" name for the code.
1632
1633 QUrl url() const
1634 {
1635 if (!m_url.isValid())
1636 m_url = QUrl(fileName());
1637 return m_url;
1638 }
1639
1641 {
1642 if (!m_finalUrl.isValid())
1643 m_finalUrl = QUrl(finalUrlString());
1644 return m_finalUrl;
1645 }
1646
1649
1651 {
1652 return propertyCaches.at(/*root object*/0);
1653 }
1654
1655 int objectCount() const { return qmlData->nObjects; }
1656 const CompiledObject *objectAt(int index) const { return qmlData->objectAt(index); }
1657
1658 int totalBindingsCount() const;
1659 int totalParserStatusCount() const;
1660 int totalObjectCount() const;
1661
1662 int inlineComponentId(const QString &inlineComponentName) const
1663 {
1664 for (uint i = 0; i < qmlData->nObjects; ++i) {
1665 auto *object = qmlData->objectAt(i);
1666 for (auto it = object->inlineComponentsBegin(), end = object->inlineComponentsEnd();
1667 it != end; ++it) {
1668 if (stringAt(it->nameIndex) == inlineComponentName)
1669 return it->objectIndex;
1670 }
1671 }
1672 return -1;
1673 }
1674
1675 void finalizeCompositeType(const QQmlType &type);
1676
1677 bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;
1678
1688
1693
1698
1700 {
1702 }
1703
1708
1710 {
1712 }
1713
1714 bool isESModule() const
1715 {
1717 }
1718
1719 bool isSharedLibrary() const
1720 {
1722 }
1723
1725 {
1731
1733 {
1734 return unit->functionAt(object->functionOffsetTable()[index]);
1735 }
1736
1737 void operator++() { ++index; }
1738 bool operator==(const FunctionIterator &rhs) const { return index == rhs.index; }
1739 bool operator!=(const FunctionIterator &rhs) const { return index != rhs.index; }
1740 };
1741
1743 {
1744 return FunctionIterator(unitData(), object, 0);
1745 }
1746
1748 {
1749 return FunctionIterator(unitData(), object, object->nFunctions);
1750 }
1751
1752 QQmlType qmlTypeForComponent(const QString &inlineComponentName = QString()) const;
1753 QMetaType metaType() const { return qmlType.typeId(); }
1754
1755private:
1756 QString m_fileName; // initialized from data->sourceFileIndex
1757 QString m_finalUrlString; // initialized from data->finalUrlIndex
1758
1759 mutable QQmlNullableValue<QUrl> m_url;
1760 mutable QQmlNullableValue<QUrl> m_finalUrl;
1761};
1762
1764{
1765 Q_DISABLE_COPY_MOVE(SaveableUnitPointer)
1766public:
1767 SaveableUnitPointer(const Unit *unit, quint32 temporaryFlags = Unit::StaticData) :
1768 unit(unit),
1769 temporaryFlags(temporaryFlags)
1770 {
1771 }
1772
1774
1775 template<typename Char>
1776 bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
1777 {
1778 const quint32_le oldFlags = mutableFlags();
1779 auto cleanup = qScopeGuard([this, oldFlags]() { mutableFlags() = oldFlags; });
1780 mutableFlags() |= temporaryFlags;
1781 return writer(data<Char>(), size());
1782 }
1783
1784 static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
1785 QString *errorString)
1786 {
1787#if QT_CONFIG(temporaryfile)
1788 QSaveFile cacheFile(outputFileName);
1789 if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
1790 || cacheFile.write(data, size) != size
1791 || !cacheFile.commit()) {
1792 *errorString = cacheFile.errorString();
1793 return false;
1794 }
1795
1796 errorString->clear();
1797 return true;
1798#else
1799 Q_UNUSED(outputFileName);
1800 *errorString = QStringLiteral("features.temporaryfile is disabled.");
1801 return false;
1802#endif
1803 }
1804
1805private:
1806 const Unit *unit;
1807 quint32 temporaryFlags;
1808
1809 quint32_le &mutableFlags() const
1810 {
1811 return const_cast<Unit *>(unit)->flags;
1812 }
1813
1814 template<typename Char>
1815 const Char *data() const
1816 {
1817 Q_STATIC_ASSERT(sizeof(Char) == 1);
1818 const Char *dataPtr;
1819 memcpy(&dataPtr, &unit, sizeof(dataPtr));
1820 return dataPtr;
1821 }
1822
1823 quint32 size() const
1824 {
1825 return unit->unitSize;
1826 }
1827};
1828
1829
1830} // CompiledData namespace
1831} // QV4 namespace
1832
1833Q_DECLARE_OPERATORS_FOR_FLAGS(QV4::CompiledData::ParameterType::Flags);
1835
1837
1838#endif
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatetime.h:283
\inmodule QtCore
Definition qhash.h:820
iterator find(const int &key)
Returns an iterator pointing to the item with the key in the hash.
Definition qhash.h:1291
iterator Iterator
Qt-style synonym for QHash::iterator.
Definition qhash.h:1288
T value(const Key &key) const noexcept
Definition qhash.h:1054
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1216
iterator insert(const int &key, const TypeReference &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
\inmodule QtCore \reentrant
Definition qiodevice.h:34
Definition qlist.h:75
@ FloatingPointShortest
Definition qlocale.h:890
\inmodule QtCore
Definition qmetatype.h:341
The QQmlEngine class provides an environment for instantiating QML components.
Definition qqmlengine.h:57
QQmlPropertyCache::ConstPtr at(int index) const
QMetaType typeId() const
Definition qqmltype.cpp:668
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromRawData(const QChar *, qsizetype size)
Constructs a QString that uses the first size Unicode characters in the array unicode.
Definition qstring.cpp:9482
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:8084
\inmodule QtCore
static constexpr QTypeRevision zero()
Produces a QTypeRevision with major and minor version {0}.
\inmodule QtCore
Definition qurl.h:94
static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size, QString *errorString)
bool saveToDisk(const std::function< bool(const Char *, quint32)> &writer) const
SaveableUnitPointer(const Unit *unit, quint32 temporaryFlags=Unit::StaticData)
QHash< int, QWidget * > hash
[35multi]
QString str
[2]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QVector< const QQmlPropertyData * > BindingPropertyData
std::function< QByteArray()> DependentTypesHasher
static const char magic_str[]
uint Bool
constexpr Initialization Uninitialized
#define Q_STATIC_ASSERT(Condition)
Definition qassert.h:108
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QLEInteger< quint32 > quint32_le
Definition qendian.h:396
QLEInteger< quint64 > quint64_le
Definition qendian.h:397
QLEIntegerBitfieldUnion< uint, Accessors... > quint32_le_bitfield_union
Definition qendian_p.h:188
constexpr QSpecialIntegerBitfieldInitializer QSpecialIntegerBitfieldZero
Definition qendian_p.h:24
#define Q_DECLARE_FLAGS(Flags, Enum)
Definition qflags.h:174
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
Definition qflags.h:194
Flags
void(^ Block)(void)
static ControlElement< T > * ptr(QWidget *widget)
@ Alias
GLint location
GLboolean GLboolean GLboolean b
GLenum mode
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLuint GLuint end
GLenum GLuint id
[7]
GLuint object
[3]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLbitfield flags
GLenum GLuint GLintptr offset
GLenum GLenum GLsizei void GLsizei void * column
GLhandleARB obj
[2]
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
char Char
#define Q_UNUSED(x)
@ Q_PRIMITIVE_TYPE
Definition qtypeinfo.h:157
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
unsigned int quint32
Definition qtypes.h:50
unsigned short quint16
Definition qtypes.h:48
int qint32
Definition qtypes.h:49
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
unsigned char quint8
Definition qtypes.h:46
QList< QChar > characters
QSharedPointer< T > other(t)
[5]
\inmodule QtCore \reentrant
Definition qchar.h:18
void setIsAliasToLocalAlias(bool isAliasToLocalAlias)
void setTargetObjectId(quint32 targetObjectId)
quint32_le_bitfield_union< NameIndexField, FlagsField > nameIndexAndFlags
bool hasFlag(Flag flag) const
quint32_le_bitfield_union< IdIndexField, TargetObjectIdField, AliasToLocalAliasField > idIndexAndTargetObjectIdAndAliasToLocalAlias
void setNameIndex(quint32 nameIndex)
void setIdIndex(quint32 idIndex)
quint32_le_bitfield_member< 16, 16 > TypeField
quint32_le_bitfield_union< FlagsField, TypeField > flagsAndType
quint32_le_bitfield_member< 0, 16 > FlagsField
bool hasFlag(Flag flag) const
union QV4::CompiledData::Binding::@545 value
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
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
std::unique_ptr< QString > icRootName
Q_QML_EXPORT bool saveToDisk(const QUrl &unitUrl, QString *errorString)
ResolvedTypeReference * resolvedType(int id) const
const QQmlPrivate::AOTCompiledFunction * aotCompiledFunctions
CompilationUnit(const Unit *unitData, const QQmlPrivate::AOTCompiledFunction *aotCompiledFunctions, const QString &fileName=QString(), const QString &finalUrlString=QString())
QVector< QQmlRefPointer< QQmlScriptData > > dependentScripts
ResolvedTypeReferenceMap resolvedTypes
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const
Q_QML_EXPORT QStringList moduleRequests() const
QVector< BindingPropertyData > bindingPropertyDataPerObject
QQmlType qmlTypeForComponent(const QString &inlineComponentName=QString()) const
FunctionIterator objectFunctionsBegin(const CompiledObject *object) const
QQmlRefPointer< QQmlTypeNameCache > typeNameCache
void finalizeCompositeType(const QQmlType &type)
FunctionIterator objectFunctionsEnd(const CompiledObject *object) const
ListPropertyAssignBehavior listPropertyAssignBehavior() const
const CompiledObject * objectAt(int index) const
const CompiledData::Import * importAt(int index) const
static Q_QML_EXPORT QString localCacheFilePath(const QUrl &url)
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
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions, int labelInfoSize, int codeSize)
size_t lineAndStatementNumberOffset() const
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, int totalObjectCount, int totalBindingCount, int totalParserStatusCount)
void set(quint32 nameOffset, bool isAccessor)
static int calculateSize(int nMembers)
Location(quint32 l, quint32 c)
void set(quint32 line, quint32 column)
friend size_t qHash(const Location &location, size_t seed=0)
bool operator<(const Location &other) const
friend bool operator==(const Location &a, const Location &b)
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 setIsReadOnly(bool isReadOnly)
void setTypeNameIndex(int nameIndex)
quint32_le_bitfield_union< CommonTypeOrTypeNameIndexField, IsRequiredField, IsCommonTypeField, IsListField, IsReadOnlyField > data
void setIsRequired(bool isRequired)
const Object * objectAt(int idx) const
const Import * importAt(int idx) const
RegExp(quint32 flags, quint32 stringIndex)
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)
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
char libraryVersionHash[QmlCompileHashSpace]
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
QV4_NEARLY_ALWAYS_INLINE double doubleValue() const
static constexpr StaticValue fromReturnedValue(ReturnedValue val)
Definition moc.h:23