aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compileddata_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4compileddata_p.h')
-rw-r--r--src/qml/compiler/qv4compileddata_p.h266
1 files changed, 192 insertions, 74 deletions
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 63738d6002..f3d5de3db1 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -51,19 +51,17 @@
//
#include <QtCore/qstring.h>
-#include <QtCore/qcryptographichash.h>
-#include <QVector>
-#include <QStringList>
-#include <QHash>
-#include <QUrl>
-
-#include <private/qv4executableallocator_p.h>
-#include <private/qqmlrefcount_p.h>
-#include <private/qqmlnullablevalue_p.h>
-#include <private/qv4identifier_p.h>
-#include <private/qflagpointer_p.h>
+#include <QtCore/qscopeguard.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/qhash.h>
+
+#if QT_CONFIG(temporaryfile)
+#include <QtCore/qsavefile.h>
+#endif
+
#include <private/qendian_p.h>
-#include <private/qqmljsastfwd_p.h>
+#include <private/qv4staticvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -88,10 +86,10 @@ struct Document;
}
namespace QV4 {
-struct StaticValue;
-
namespace Heap {
struct Module;
+struct String;
+struct InternalClass;
};
struct Function;
@@ -128,8 +126,6 @@ struct Location
Location() : _dummy(0) { }
- Location &operator=(const QQmlJS::AST::SourceLocation &astLocation);
-
inline bool operator<(const Location &other) const {
return line < other.line ||
(line == other.line && column < other.column);
@@ -411,7 +407,7 @@ static_assert(sizeof(ImportEntry) == 16, "ImportEntry structure needs to have th
// Qml data structures
-struct Q_QML_EXPORT TranslationData
+struct TranslationData
{
quint32_le stringIndex;
quint32_le commentIndex;
@@ -420,7 +416,7 @@ struct Q_QML_EXPORT TranslationData
};
static_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");
-struct Q_QML_PRIVATE_EXPORT Binding
+struct Binding
{
quint32_le propertyNameIndex;
@@ -517,7 +513,48 @@ struct Q_QML_PRIVATE_EXPORT Binding
bool isFunctionExpression() const { return (flags & IsFunctionExpression); }
- static QString escapedString(const QString &string);
+ //reverse of Lexer::singleEscape()
+ static QString escapedString(const QString &string)
+ {
+ QString tmp = QLatin1String("\"");
+ for (int i = 0; i < string.length(); ++i) {
+ const QChar &c = string.at(i);
+ switch (c.unicode()) {
+ case 0x08:
+ tmp += QLatin1String("\\b");
+ break;
+ case 0x09:
+ tmp += QLatin1String("\\t");
+ break;
+ case 0x0A:
+ tmp += QLatin1String("\\n");
+ break;
+ case 0x0B:
+ tmp += QLatin1String("\\v");
+ break;
+ case 0x0C:
+ tmp += QLatin1String("\\f");
+ break;
+ case 0x0D:
+ tmp += QLatin1String("\\r");
+ break;
+ case 0x22:
+ tmp += QLatin1String("\\\"");
+ break;
+ case 0x27:
+ tmp += QLatin1String("\\\'");
+ break;
+ case 0x5C:
+ tmp += QLatin1String("\\\\");
+ break;
+ default:
+ tmp += c;
+ break;
+ }
+ }
+ tmp += QLatin1Char('\"');
+ return tmp;
+ }
bool isTranslationBinding() const { return type == Type_Translation || type == Type_TranslationById; }
bool evaluatesToString() const { return type == Type_String || isTranslationBinding(); }
@@ -565,14 +602,22 @@ struct Enum
};
static_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");
+enum class BuiltinType : unsigned int {
+ Var = 0, Variant, Int, Bool, Real, String, Url, Color,
+ Font, Time, Date, DateTime, Rect, Point, Size,
+ Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion, InvalidBuiltin
+};
+
struct Parameter
{
quint32_le nameIndex;
- quint32_le type;
- quint32_le customTypeNameIndex;
- Location location;
+ union {
+ quint32 _dummy;
+ quint32_le_bitfield<0, 1> indexIsBuiltinType;
+ quint32_le_bitfield<1, 31> typeNameIndexOrBuiltinType;
+ };
};
-static_assert(sizeof(Parameter) == 16, "Parameter structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_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");
struct Signal
{
@@ -601,24 +646,33 @@ static_assert(sizeof(Signal) == 12, "Signal structure needs to have the expected
struct Property
{
- enum Type : unsigned int { Var = 0, Variant, Int, Bool, Real, String, Url, Color,
- Font, Time, Date, DateTime, Rect, Point, Size,
- Vector2D, Vector3D, Vector4D, Matrix4x4, Quaternion,
- Custom, CustomList };
-
- enum Flags : unsigned int {
- IsReadOnly = 0x1
- };
-
quint32_le nameIndex;
union {
- quint32_le_bitfield<0, 31> type;
- quint32_le_bitfield<31, 1> flags; // readonly
+ quint32_le_bitfield<0, 29> builtinTypeOrTypeNameIndex;
+ quint32_le_bitfield<29, 1> isBuiltinType;
+ quint32_le_bitfield<30, 1> isList;
+ quint32_le_bitfield<31, 1> isReadOnly;
};
- quint32_le customTypeNameIndex; // If type >= Custom
+
Location location;
+
+ void setBuiltinType(BuiltinType t)
+ {
+ builtinTypeOrTypeNameIndex = static_cast<quint32>(t);
+ isBuiltinType = true;
+ }
+ BuiltinType builtinType() const {
+ if (isBuiltinType)
+ return static_cast<BuiltinType>(quint32(builtinTypeOrTypeNameIndex));
+ return BuiltinType::InvalidBuiltin;
+ }
+ void setCustomType(int nameIndex)
+ {
+ builtinTypeOrTypeNameIndex = nameIndex;
+ isBuiltinType = false;
+ }
};
-static_assert(sizeof(Property) == 16, "Property structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target");
+static_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");
struct Alias {
enum Flags : unsigned int {
@@ -815,7 +869,6 @@ static_assert(sizeof(QmlUnit) == 16, "QmlUnit structure needs to have the expect
enum { QmlCompileHashSpace = 48 };
static const char magic_str[] = "qv4cdata";
-extern const char qml_compile_hash[QmlCompileHashSpace + 1];
struct Unit
{
@@ -830,8 +883,6 @@ struct Unit
char libraryVersionHash[QmlCompileHashSpace];
char md5Checksum[16]; // checksum of all bytes following this field.
- void generateChecksum();
-
char dependencyMD5Checksum[16];
enum : unsigned int {
@@ -879,8 +930,6 @@ struct Unit
quint32_le offsetToQmlUnit;
- bool verifyHeader(QDateTime expectedSourceTimeStamp, QString *errorString) const;
-
/* QML specific fields */
const QmlUnit *qmlUnit() const {
@@ -1014,8 +1063,8 @@ struct TypeReferenceMap : QHash<int, TypeReference>
auto prop = obj->propertiesBegin();
auto propEnd = obj->propertiesEnd();
for ( ; prop != propEnd; ++prop) {
- if (prop->type >= QV4::CompiledData::Property::Custom) {
- TypeReference &r = this->add(prop->customTypeNameIndex, prop->location);
+ if (!prop->isBuiltinType) {
+ TypeReference &r = this->add(prop->builtinTypeOrTypeNameIndex, prop->location);
r.errorWhenNotFound = true;
}
}
@@ -1043,7 +1092,7 @@ typedef QVector<QQmlPropertyData*> BindingPropertyData;
// This is how this hooks into the existing structures:
-struct Q_QML_PRIVATE_EXPORT CompilationUnitBase
+struct CompilationUnitBase
{
Q_DISABLE_COPY(CompilationUnitBase)
@@ -1080,11 +1129,11 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnitBase
Q_STATIC_ASSERT(std::is_standard_layout<CompilationUnitBase>::value);
Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeStrings) == 0);
Q_STATIC_ASSERT(offsetof(CompilationUnitBase, constants) == sizeof(QV4::Heap::String **));
-Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offsetof(CompilationUnitBase, constants) + sizeof(const Value *));
-Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeClasses) == offsetof(CompilationUnitBase, runtimeRegularExpressions) + sizeof(const Value *));
-Q_STATIC_ASSERT(offsetof(CompilationUnitBase, imports) == offsetof(CompilationUnitBase, runtimeClasses) + sizeof(const Value *));
+Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeRegularExpressions) == offsetof(CompilationUnitBase, constants) + sizeof(const StaticValue *));
+Q_STATIC_ASSERT(offsetof(CompilationUnitBase, runtimeClasses) == offsetof(CompilationUnitBase, runtimeRegularExpressions) + sizeof(const StaticValue *));
+Q_STATIC_ASSERT(offsetof(CompilationUnitBase, imports) == offsetof(CompilationUnitBase, runtimeClasses) + sizeof(const StaticValue *));
-struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase
+struct CompilationUnit : public CompilationUnitBase
{
Q_DISABLE_COPY(CompilationUnit)
@@ -1094,8 +1143,31 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase
public:
using CompiledObject = CompiledData::Object;
- CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(), const QString &finalUrlString = QString());
- ~CompilationUnit();
+ CompilationUnit(const Unit *unitData = nullptr, const QString &fileName = QString(),
+ const QString &finalUrlString = QString())
+ {
+ setUnitData(unitData, nullptr, fileName, finalUrlString);
+ }
+
+ ~CompilationUnit()
+ {
+ if (data) {
+ if (data->qmlUnit() != qmlData)
+ free(const_cast<QmlUnit *>(qmlData));
+ qmlData = nullptr;
+
+ if (!(data->flags & QV4::CompiledData::Unit::StaticData))
+ free(const_cast<Unit *>(data));
+ }
+ data = nullptr;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ delete [] constants;
+ constants = nullptr;
+#endif
+
+ delete [] imports;
+ imports = nullptr;
+ }
CompilationUnit(CompilationUnit &&other) noexcept
{
@@ -1123,8 +1195,36 @@ public:
}
const Unit *unitData() const { return data; }
+
void setUnitData(const Unit *unitData, const QmlUnit *qmlUnit = nullptr,
- const QString &fileName = QString(), const QString &finalUrlString = QString());
+ const QString &fileName = QString(), const QString &finalUrlString = QString())
+ {
+ data = unitData;
+ qmlData = nullptr;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ delete [] constants;
+#endif
+ constants = nullptr;
+ m_fileName.clear();
+ m_finalUrlString.clear();
+ if (!data)
+ return;
+
+ qmlData = qmlUnit ? qmlUnit : data->qmlUnit();
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ StaticValue *bigEndianConstants = new StaticValue[data->constantTableSize];
+ const quint64_le *littleEndianConstants = data->constants();
+ for (uint i = 0; i < data->constantTableSize; ++i)
+ bigEndianConstants[i] = StaticValue::fromReturnedValue(littleEndianConstants[i]);
+ constants = bigEndianConstants;
+#else
+ constants = reinterpret_cast<const StaticValue*>(data->constants());
+#endif
+
+ m_fileName = !fileName.isEmpty() ? fileName : stringAt(data->sourceFileIndex);
+ m_finalUrlString = !finalUrlString.isEmpty() ? finalUrlString : stringAt(data->finalUrlIndex);
+ }
QString stringAt(int index) const
{
@@ -1139,58 +1239,76 @@ public:
Heap::Module *module() const { return m_module; }
void setModule(Heap::Module *module) { m_module = module; }
- void unlink();
-
private:
QString m_fileName; // initialized from data->sourceFileIndex
QString m_finalUrlString; // initialized from data->finalUrlIndex
Heap::Module *m_module = nullptr;
-
-public:
- bool saveToDisk(const QString &outputFileName, QString *errorString) const;
};
class SaveableUnitPointer
{
Q_DISABLE_COPY_MOVE(SaveableUnitPointer)
public:
- SaveableUnitPointer(const CompilationUnit *unit, quint32 temporaryFlags = Unit::StaticData) :
- unit(unit)
+ SaveableUnitPointer(const Unit *unit, quint32 temporaryFlags = Unit::StaticData) :
+ unit(unit),
+ temporaryFlags(temporaryFlags)
{
- quint32_le &unitFlags = mutableFlags();
- quint32 origFlags = unitFlags;
- unitFlags |= temporaryFlags;
- changedFlags = origFlags ^ unitFlags;
}
- ~SaveableUnitPointer()
+ ~SaveableUnitPointer() = default;
+
+ template<typename Char>
+ bool saveToDisk(const std::function<bool(const Char *, quint32)> &writer) const
{
- mutableFlags() ^= changedFlags;
+ auto cleanup = qScopeGuard([this]() { mutableFlags() ^= temporaryFlags; });
+ mutableFlags() |= temporaryFlags;
+ return writer(data<Char>(), size());
}
- const CompilationUnit *operator->() const { return unit; }
- const CompilationUnit &operator*() const { return *unit; }
- operator const CompilationUnit *() { return unit; }
+ static bool writeDataToFile(const QString &outputFileName, const char *data, quint32 size,
+ QString *errorString)
+ {
+#if QT_CONFIG(temporaryfile)
+ QSaveFile cacheFile(outputFileName);
+ if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)
+ || cacheFile.write(data, size) != size
+ || !cacheFile.commit()) {
+ *errorString = cacheFile.errorString();
+ return false;
+ }
+
+ errorString->clear();
+ return true;
+#else
+ Q_UNUSED(outputFileName)
+ *errorString = QStringLiteral("features.temporaryfile is disabled.");
+ return false;
+#endif
+ }
+
+private:
+ const Unit *unit;
+ quint32 temporaryFlags;
+
+ quint32_le &mutableFlags() const
+ {
+ return const_cast<Unit *>(unit)->flags;
+ }
template<typename Char>
const Char *data() const
{
Q_STATIC_ASSERT(sizeof(Char) == 1);
const Char *dataPtr;
- memcpy(&dataPtr, &unit->data, sizeof(dataPtr));
+ memcpy(&dataPtr, &unit, sizeof(dataPtr));
return dataPtr;
}
quint32 size() const
{
- return unit->data->unitSize;
+ return unit->unitSize;
}
-
-private:
- quint32_le &mutableFlags() { return const_cast<Unit *>(unit->unitData())->flags; };
- const CompilationUnit *unit;
- quint32 changedFlags;
};