aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmltypeloader.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2014-03-29 10:05:09 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-29 21:20:22 +0100
commited9a71b85849a653a3cc710e59b885002fc6f506 (patch)
tree61ea8efcc39bca1e0d55f0b87e66164ef51d98b6 /src/qml/qml/qqmltypeloader.cpp
parent869a199da9ba173e2dea948ec132d089b2513128 (diff)
Make it possible to supply compilation units from plugins
This also cleans up the script and type initialization in the type loader, for example by getting rid of the m_irUnit member for scripts. Change-Id: I207afeb21c0bae9091d3c7b4cac2e80e9aae0ea3 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml/qqmltypeloader.cpp')
-rw-r--r--src/qml/qml/qqmltypeloader.cpp177
1 files changed, 141 insertions, 36 deletions
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 7f7ea1e5c1..c6693c2ae8 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -147,6 +147,7 @@ public:
void loadAsync(QQmlDataBlob *b);
void loadWithStaticData(QQmlDataBlob *b, const QByteArray &);
void loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &);
+ void loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
void callCompleted(QQmlDataBlob *b);
void callDownloadProgressChanged(QQmlDataBlob *b, qreal p);
void initializeEngine(QQmlExtensionInterface *, const char *);
@@ -157,6 +158,7 @@ protected:
private:
void loadThread(QQmlDataBlob *b);
void loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &);
+ void loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit);
void callCompletedMain(QQmlDataBlob *b);
void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p);
void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
@@ -777,6 +779,12 @@ void QQmlDataLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteA
postMethodToThread(&This::loadWithStaticDataThread, b, d);
}
+void QQmlDataLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
+{
+ b->addref();
+ callMethodInThread(&This::loadWithCachedUnitThread, b, unit);
+}
+
void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
{
b->addref();
@@ -815,6 +823,12 @@ void QQmlDataLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByte
b->release();
}
+void QQmlDataLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
+{
+ m_loader->loadWithCachedUnitThread(b, unit);
+ b->release();
+}
+
void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b)
{
QML_MEMORY_SCOPE_URL(b->url());
@@ -965,6 +979,28 @@ void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &da
}
}
+void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
+{
+#ifdef DATABLOB_DEBUG
+ qWarning("QQmlDataLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
+ m_thread->isThisThread()?"Compile":"Engine");
+#endif
+
+ blob->startLoading(this);
+
+ if (m_thread->isThisThread()) {
+ unlock();
+ loadWithCachedUnitThread(blob, unit);
+ lock();
+ } else {
+ unlock();
+ m_thread->loadWithCachedUnit(blob, unit);
+ lock();
+ if (!blob->isCompleteOrError())
+ blob->m_data.setIsAsync(true);
+ }
+}
+
void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
{
ASSERT_LOADTHREAD();
@@ -972,6 +1008,13 @@ void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArr
setData(blob, data);
}
+void QQmlDataLoader::loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
+{
+ ASSERT_LOADTHREAD();
+
+ setCachedUnit(blob, unit);
+}
+
void QQmlDataLoader::loadThread(QQmlDataBlob *blob)
{
ASSERT_LOADTHREAD();
@@ -1165,6 +1208,24 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
blob->tryDone();
}
+void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
+{
+ QML_MEMORY_SCOPE_URL(blob->url());
+ blob->m_inCallback = true;
+
+ blob->initializeFromCachedUnit(unit);
+
+ if (!blob->isError() && !blob->isWaiting())
+ blob->allDependenciesDone();
+
+ if (blob->status() != QQmlDataBlob::Error)
+ blob->m_data.setStatus(QQmlDataBlob::WaitingForDependencies);
+
+ blob->m_inCallback = false;
+
+ blob->tryDone();
+}
+
void QQmlDataLoader::shutdownThread()
{
if (!m_thread->isShutdown())
@@ -1539,7 +1600,11 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
typeData = new QQmlTypeData(url, this);
// TODO: if (compiledData == 0), is it safe to omit this insertion?
m_typeCache.insert(url, typeData);
- QQmlDataLoader::load(typeData, mode);
+ if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
+ QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit);
+ } else {
+ QQmlDataLoader::load(typeData, mode);
+ }
}
typeData->addref();
@@ -1577,7 +1642,12 @@ QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url)
if (!scriptBlob) {
scriptBlob = new QQmlScriptBlob(url, this);
m_scriptCache.insert(url, scriptBlob);
- QQmlDataLoader::load(scriptBlob);
+
+ if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
+ QQmlDataLoader::loadWithCachedUnit(scriptBlob, cachedUnit);
+ } else {
+ QQmlDataLoader::load(scriptBlob);
+ }
}
scriptBlob->addref();
@@ -2142,8 +2212,20 @@ void QQmlTypeData::dataReceived(const Data &data)
return;
}
- m_document->collectTypeReferences();
+ continueLoadFromIR();
+}
+void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
+{
+ QQmlEngine *qmlEngine = typeLoader()->engine();
+ m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
+ unit->loadIR(m_document.data(), unit);
+ continueLoadFromIR();
+}
+
+void QQmlTypeData::continueLoadFromIR()
+{
+ m_document->collectTypeReferences();
m_importCache.setBaseUrl(finalUrl(), finalUrlString());
// For remote URLs, we don't delay the loading of the implicit import
@@ -2192,7 +2274,6 @@ void QQmlTypeData::dataReceived(const Data &data)
return;
}
}
-
}
void QQmlTypeData::allDependenciesDone()
@@ -2570,7 +2651,6 @@ void QQmlScriptData::clear()
QQmlScriptBlob::QQmlScriptBlob(const QUrl &url, QQmlTypeLoader *loader)
: QQmlTypeLoader::Blob(url, JavaScriptFile, loader), m_scriptData(0)
-, m_irUnit(QV8Engine::getV4(loader->engine())->debugger != 0)
{
}
@@ -2591,12 +2671,10 @@ void QQmlScriptBlob::dataReceived(const Data &data)
{
QString source = QString::fromUtf8(data.data(), data.size());
- m_scriptData = new QQmlScriptData();
- m_scriptData->url = finalUrl();
- m_scriptData->urlString = finalUrlString();
-
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
+ QmlIR::Document irUnit(v4->debugger != 0);
QQmlError metaDataError;
- m_irUnit.extractScriptMetaData(source, &metaDataError);
+ irUnit.extractScriptMetaData(source, &metaDataError);
if (metaDataError.isValid()) {
metaDataError.setUrl(finalUrl());
setError(metaDataError);
@@ -2604,41 +2682,32 @@ void QQmlScriptBlob::dataReceived(const Data &data)
}
QList<QQmlError> errors;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
- m_scriptData->m_precompiledScript = QV4::Script::precompile(&m_irUnit.jsModule, &m_irUnit.jsGenerator, v4, m_scriptData->url, source, &errors);
- if (m_scriptData->m_precompiledScript)
- m_scriptData->m_precompiledScript->ref();
+ QV4::CompiledData::CompilationUnit *unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors);
+ if (unit)
+ unit->ref();
source.clear();
if (!errors.isEmpty()) {
+ if (unit)
+ unit->deref();
setError(errors);
return;
}
+ irUnit.javaScriptCompilationUnit = unit;
- m_irUnit.javaScriptCompilationUnit = m_scriptData->m_precompiledScript;
QmlIR::QmlUnitGenerator qmlGenerator;
- QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(m_irUnit);
- if (m_scriptData->m_precompiledScript) {
- Q_ASSERT(!m_scriptData->m_precompiledScript->data);
- Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header);
- // The js unit owns the data and will free the qml unit.
- m_scriptData->m_precompiledScript->data = &qmlUnit->header;
- }
+ QV4::CompiledData::QmlUnit *qmlUnit = qmlGenerator.generate(irUnit);
+ Q_ASSERT(!unit->data);
+ Q_ASSERT((void*)qmlUnit == (void*)&qmlUnit->header);
+ // The js unit owns the data and will free the qml unit.
+ unit->data = &qmlUnit->header;
- m_importCache.setBaseUrl(finalUrl(), finalUrlString());
+ initializeFromCompilationUnit(unit);
+ unit->deref();
+}
- for (quint32 i = 0; i < qmlUnit->nImports; ++i) {
- const QV4::CompiledData::Import *import = qmlUnit->importAt(i);
- if (!addImport(import, &errors)) {
- Q_ASSERT(errors.size());
- QQmlError error(errors.takeFirst());
- error.setUrl(m_importCache.baseUrl());
- error.setLine(import->location.line);
- error.setColumn(import->location.column);
- errors.prepend(error); // put it back on the list after filling out information.
- setError(errors);
- return;
- }
- }
+void QQmlScriptBlob::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit)
+{
+ initializeFromCompilationUnit(unit->createCompilationUnit());
}
void QQmlScriptBlob::done()
@@ -2699,6 +2768,37 @@ void QQmlScriptBlob::scriptImported(QQmlScriptBlob *blob, const QV4::CompiledDat
m_scripts << ref;
}
+void QQmlScriptBlob::initializeFromCompilationUnit(QV4::CompiledData::CompilationUnit *unit)
+{
+ Q_ASSERT(!m_scriptData);
+ m_scriptData = new QQmlScriptData();
+ m_scriptData->url = finalUrl();
+ m_scriptData->urlString = finalUrlString();
+ m_scriptData->m_precompiledScript = unit;
+ if (m_scriptData->m_precompiledScript)
+ m_scriptData->m_precompiledScript->ref();
+
+ m_importCache.setBaseUrl(finalUrl(), finalUrlString());
+
+ Q_ASSERT(m_scriptData->m_precompiledScript->data->flags & QV4::CompiledData::Unit::IsQml);
+ const QV4::CompiledData::QmlUnit *qmlUnit = reinterpret_cast<const QV4::CompiledData::QmlUnit*>(m_scriptData->m_precompiledScript->data);
+
+ QList<QQmlError> errors;
+ for (quint32 i = 0; i < qmlUnit->nImports; ++i) {
+ const QV4::CompiledData::Import *import = qmlUnit->importAt(i);
+ if (!addImport(import, &errors)) {
+ Q_ASSERT(errors.size());
+ QQmlError error(errors.takeFirst());
+ error.setUrl(m_importCache.baseUrl());
+ error.setLine(import->location.line);
+ error.setColumn(import->location.column);
+ errors.prepend(error); // put it back on the list after filling out information.
+ setError(errors);
+ return;
+ }
+ }
+}
+
QQmlQmldirData::QQmlQmldirData(const QUrl &url, QQmlTypeLoader *loader)
: QQmlTypeLoader::Blob(url, QmldirFile, loader), m_import(0), m_priority(0)
{
@@ -2734,6 +2834,11 @@ void QQmlQmldirData::dataReceived(const Data &data)
m_content = QString::fromUtf8(data.data(), data.size());
}
+void QQmlQmldirData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *)
+{
+ Q_UNIMPLEMENTED();
+}
+
QT_END_NAMESPACE
#include "qqmltypeloader.moc"