aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2019-05-13 11:07:39 +0200
committerUlf Hermann <ulf.hermann@qt.io>2019-05-17 10:34:31 +0000
commitae1c2375f596258c878933adc46a19a541a43a6c (patch)
treee5559a91634354657c270fed2ae59ca92f1552cc
parentf228af06c2c712302ee1dcdaf761cd24504b473e (diff)
Add abstraction for temporarily setting StaticData when saving
The StaticData flag needs to be saved to disk, but removed again afterwards so that we can free() the malloc'd data. This also allows us to avoid copying all the data into a byte array before saving. Change-Id: I96513f8d98acf0ea0b4514d96376b487e8444917 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp3
-rw-r--r--src/qml/compiler/qv4compileddata.cpp19
-rw-r--r--src/qml/compiler/qv4compileddata_p.h43
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp36
4 files changed, 60 insertions, 41 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index e63aa3b66d..6f46648572 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1565,9 +1565,6 @@ void QmlUnitGenerator::generate(Document &output, const QV4::CompiledData::Depen
break;
}
}
- // This unit's memory was allocated with malloc on the heap, so it's
- // definitely not suitable for StaticData access.
- createdUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
if (dependencyHasher) {
const QByteArray checksum = dependencyHasher();
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 091c29c8c7..71015107ad 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -82,14 +82,8 @@ CompilationUnit::~CompilationUnit()
free(const_cast<QmlUnit *>(qmlData));
qmlData = nullptr;
-#ifndef V4_BOOTSTRAP
if (!(data->flags & QV4::CompiledData::Unit::StaticData))
free(const_cast<Unit *>(data));
-#else
- // Unconditionally free the memory. In the dev tools we create units that have
- // the flag set and will be saved to disk, so intended to persist later.
- free(const_cast<Unit *>(data));
-#endif
}
data = nullptr;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
@@ -113,16 +107,9 @@ bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorSt
return false;
}
- QByteArray modifiedUnit;
- modifiedUnit.resize(data->unitSize);
- memcpy(modifiedUnit.data(), data, data->unitSize);
- const char *dataPtr = modifiedUnit.data();
- Unit *unitPtr;
- memcpy(&unitPtr, &dataPtr, sizeof(unitPtr));
- unitPtr->flags |= Unit::StaticData;
-
- qint64 headerWritten = cacheFile.write(modifiedUnit);
- if (headerWritten != modifiedUnit.size()) {
+ SaveableUnitPointer saveable(this);
+ qint64 headerWritten = cacheFile.write(saveable.data<char>(), saveable.size());
+ if (headerWritten != saveable.size()) {
*errorString = cacheFile.errorString();
return false;
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 9301939bff..629adf8231 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -1158,6 +1158,49 @@ 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)
+ {
+ quint32_le &unitFlags = mutableFlags();
+ quint32 origFlags = unitFlags;
+ unitFlags |= temporaryFlags;
+ changedFlags = origFlags ^ unitFlags;
+ }
+
+ ~SaveableUnitPointer()
+ {
+ mutableFlags() ^= changedFlags;
+ }
+
+ const CompilationUnit *operator->() const { return unit; }
+ const CompilationUnit &operator*() const { return *unit; }
+ operator const CompilationUnit *() { return unit; }
+
+ template<typename Char>
+ const Char *data() const
+ {
+ Q_STATIC_ASSERT(sizeof(Char) == 1);
+ const Char *dataPtr;
+ memcpy(&dataPtr, &unit->data, sizeof(dataPtr));
+ return dataPtr;
+ }
+
+ quint32 size() const
+ {
+ return unit->data->unitSize;
+ }
+
+private:
+ quint32_le &mutableFlags() { return const_cast<Unit *>(unit->unitData())->flags; };
+ const CompilationUnit *unit;
+ quint32 changedFlags;
+};
+
+
} // CompiledData namespace
} // QV4 namespace
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 63be5c5ec4..7b4135e1f8 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -169,7 +169,7 @@ static bool checkArgumentsObjectUseInSignalHandlers(const QmlIR::Document &doc,
return true;
}
-using SaveFunction = std::function<bool (const QV4::CompiledData::CompilationUnit &, QString *)>;
+using SaveFunction = std::function<bool(const QV4::CompiledData::SaveableUnitPointer &, QString *)>;
static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFunction, Error *error)
{
@@ -229,11 +229,13 @@ static bool compileQmlFile(const QString &inputFileName, SaveFunction saveFuncti
QmlIR::QmlUnitGenerator generator;
irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false);
generator.generate(irDocument);
- QV4::CompiledData::Unit *unit = const_cast<QV4::CompiledData::Unit*>(irDocument.javaScriptCompilationUnit.data);
- unit->flags |= QV4::CompiledData::Unit::StaticData;
- unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation;
- if (!saveFunction(irDocument.javaScriptCompilationUnit, &error->message))
+ const quint32 saveFlags
+ = QV4::CompiledData::Unit::StaticData
+ | QV4::CompiledData::Unit::PendingTypeCompilation;
+ QV4::CompiledData::SaveableUnitPointer saveable(&irDocument.javaScriptCompilationUnit,
+ saveFlags);
+ if (!saveFunction(saveable, &error->message))
return false;
}
return true;
@@ -321,17 +323,15 @@ static bool compileJSFile(const QString &inputFileName, const QString &inputFile
irDocument.javaScriptCompilationUnit = v4CodeGen.generateCompilationUnit(/*generate unit*/false);
QmlIR::QmlUnitGenerator generator;
generator.generate(irDocument);
- QV4::CompiledData::Unit *unitData = const_cast<QV4::CompiledData::Unit*>(irDocument.javaScriptCompilationUnit.data);
- unitData->flags |= QV4::CompiledData::Unit::StaticData;
unit = std::move(irDocument.javaScriptCompilationUnit);
}
}
- return saveFunction(unit, &error->message);
+ return saveFunction(QV4::CompiledData::SaveableUnitPointer(&unit), &error->message);
}
static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFileName,
- const QV4::CompiledData::CompilationUnit &unit,
+ const QV4::CompiledData::SaveableUnitPointer &unit,
QString *errorString)
{
QSaveFile f(outputFileName);
@@ -368,17 +368,9 @@ static bool saveUnitAsCpp(const QString &inputFileName, const QString &outputFil
QByteArray hexifiedData;
{
- QByteArray modifiedUnit;
- modifiedUnit.resize(unit.data->unitSize);
- memcpy(modifiedUnit.data(), unit.data, unit.data->unitSize);
- const char *dataPtr = modifiedUnit.data();
- QV4::CompiledData::Unit *unitPtr;
- memcpy(&unitPtr, &dataPtr, sizeof(unitPtr));
- unitPtr->flags |= QV4::CompiledData::Unit::StaticData;
-
QTextStream stream(&hexifiedData);
- const uchar *begin = reinterpret_cast<const uchar *>(modifiedUnit.constData());
- const uchar *end = begin + unit.data->unitSize;
+ const uchar *begin = unit.data<uchar>();
+ const uchar *end = begin + unit.size();
stream << hex;
int col = 0;
for (const uchar *data = begin; data < end; ++data, ++col) {
@@ -527,15 +519,15 @@ int main(int argc, char **argv)
inputFileUrl = QStringLiteral("qrc://") + inputResourcePath;
saveFunction = [inputResourcePath, outputFileName](
- const QV4::CompiledData::CompilationUnit &unit,
+ const QV4::CompiledData::SaveableUnitPointer &unit,
QString *errorString) {
return saveUnitAsCpp(inputResourcePath, outputFileName, unit, errorString);
};
} else {
- saveFunction = [outputFileName](const QV4::CompiledData::CompilationUnit &unit,
+ saveFunction = [outputFileName](const QV4::CompiledData::SaveableUnitPointer &unit,
QString *errorString) {
- return unit.saveToDisk(outputFileName, errorString);
+ return unit->saveToDisk(outputFileName, errorString);
};
}