aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/imports/qtquick2/plugins.qmltypes1
-rw-r--r--src/imports/statemachine/signaltransition.cpp8
-rw-r--r--src/imports/statemachine/signaltransition.h4
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp2
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp68
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp13
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h1
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp34
-rw-r--r--src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h3
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp8
-rw-r--r--src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h2
-rw-r--r--src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp2
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp39
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h33
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp341
-rw-r--r--src/qml/compiler/qqmltypecompiler_p.h47
-rw-r--r--src/qml/compiler/qv4compileddata.cpp32
-rw-r--r--src/qml/compiler/qv4compileddata_p.h56
-rw-r--r--src/qml/debugger/qqmlabstractprofileradapter_p.h6
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp18
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h28
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp21
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h12
-rw-r--r--src/qml/jsruntime/qv4profiling.cpp17
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h49
-rw-r--r--src/qml/memory/qv4mm.cpp79
-rw-r--r--src/qml/qml/qqmlcompileddata.cpp19
-rw-r--r--src/qml/qml/qqmlcompiler_p.h22
-rw-r--r--src/qml/qml/qqmlcontext.cpp45
-rw-r--r--src/qml/qml/qqmlcontext_p.h11
-rw-r--r--src/qml/qml/qqmlcustomparser_p.h2
-rw-r--r--src/qml/qml/qqmlengine.cpp10
-rw-r--r--src/qml/qml/qqmlmetatype.cpp2
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp134
-rw-r--r--src/qml/qml/qqmlobjectcreator_p.h8
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp5
-rw-r--r--src/qml/types/qqmlconnections.cpp10
-rw-r--r--src/qml/types/qqmlconnections_p.h2
-rw-r--r--src/qml/types/qqmllistmodel.cpp6
-rw-r--r--src/qml/types/qqmllistmodel_p.h2
-rw-r--r--src/qmldebug/qqmlprofilerclient.cpp21
-rw-r--r--src/qmldebug/qqmlprofilerclient_p_p.h8
-rw-r--r--src/quick/items/qquickevents.cpp22
-rw-r--r--src/quick/items/qquickevents_p_p.h67
-rw-r--r--src/quick/items/qquickitem.cpp6
-rw-r--r--src/quick/items/qquickitem_p.h2
-rw-r--r--src/quick/items/qquickmousearea.cpp29
-rw-r--r--src/quick/items/qquickmousearea_p_p.h3
-rw-r--r--src/quick/items/qquickopenglshadereffectnode.cpp2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp13
-rw-r--r--src/quick/items/qquickwindow_p.h2
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp2
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp2
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp2
-rw-r--r--src/quick/util/qquickpixmapcache.cpp4
-rw-r--r--src/quick/util/qquickprofiler.cpp3
-rw-r--r--src/quick/util/qquickprofiler_p.h2
-rw-r--r--src/quick/util/qquickpropertychanges.cpp12
-rw-r--r--src/quick/util/qquickpropertychanges_p.h2
-rw-r--r--src/quick/util/qquicksmoothedanimation.cpp5
-rw-r--r--src/quick/util/qquickspringanimation.cpp3
-rw-r--r--tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.cpp10
-rw-r--r--tests/auto/qml/qqmllanguage/testtypes.h10
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp14
m---------tests/manual/v4/test2620
70 files changed, 934 insertions, 529 deletions
diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes
index a1a3723600..c3a14254f3 100644
--- a/src/imports/qtquick2/plugins.qmltypes
+++ b/src/imports/qtquick2/plugins.qmltypes
@@ -4628,6 +4628,7 @@ Module {
Property { name: "pixelDelta"; type: "QPoint"; isReadonly: true }
Property { name: "buttons"; type: "int"; isReadonly: true }
Property { name: "modifiers"; type: "int"; isReadonly: true }
+ Property { name: "inverted"; type: "bool" }
Property { name: "accepted"; type: "bool" }
}
Component {
diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp
index 47efc9ec15..4153c70fd0 100644
--- a/src/imports/statemachine/signaltransition.cpp
+++ b/src/imports/statemachine/signaltransition.cpp
@@ -145,7 +145,7 @@ void SignalTransition::invoke()
void SignalTransition::connectTriggered()
{
- if (!m_complete || !m_cdata)
+ if (!m_complete || !m_compilationUnit)
return;
QObject *target = senderObject();
@@ -165,7 +165,7 @@ void SignalTransition::connectTriggered()
QQmlBoundSignalExpression *expression = ctxtdata ?
new QQmlBoundSignalExpression(target, signalIndex,
- ctxtdata, this, m_cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
+ ctxtdata, this, m_compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
if (expression)
expression->setNotifyOnValueChanged(false);
m_signalExpression = expression;
@@ -190,10 +190,10 @@ void SignalTransitionParser::verifyBindings(const QV4::CompiledData::Unit *qmlUn
}
}
-void SignalTransitionParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
+void SignalTransitionParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
SignalTransition *st = qobject_cast<SignalTransition*>(object);
- st->m_cdata = cdata;
+ st->m_compilationUnit = compilationUnit;
st->m_bindings = bindings;
}
diff --git a/src/imports/statemachine/signaltransition.h b/src/imports/statemachine/signaltransition.h
index 3471aea0c8..4a246e165f 100644
--- a/src/imports/statemachine/signaltransition.h
+++ b/src/imports/statemachine/signaltransition.h
@@ -90,7 +90,7 @@ private:
QJSValue m_signal;
QQmlScriptString m_guard;
bool m_complete;
- QQmlRefPointer<QQmlCompiledData> m_cdata;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
QList<const QV4::CompiledData::Binding *> m_bindings;
QQmlBoundSignalExpressionPointer m_signalExpression;
};
@@ -99,7 +99,7 @@ class SignalTransitionParser : public QQmlCustomParser
{
public:
void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) Q_DECL_OVERRIDE;
- void applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
+ void applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
index a90d03b010..756b6b28be 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debuggeragent.cpp
@@ -114,7 +114,7 @@ void QV4DebuggerAgent::addDebugger(QV4Debugger *debugger)
debugger->setBreakOnThrow(m_breakOnThrow);
- foreach (const BreakPoint &breakPoint, m_breakPoints.values())
+ for (const BreakPoint &breakPoint : qAsConst(m_breakPoints))
if (breakPoint.enabled)
debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
index a193ddea0b..f161f988de 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.cpp
@@ -55,7 +55,7 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
connect(engine->profiler,
@@ -68,49 +68,65 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
// use of QDataStream can skew results
// (see tst_qqmldebugtrace::trace() benchmark)
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
- const QQmlProfiler::LocationHash &locations,
- QList<QByteArray> &messages)
+ QQmlProfiler::LocationHash &locations,
+ QList<QByteArray> &messages,
+ bool trackLocations)
{
QQmlDebugPacket ds;
Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
"You can use at most 31 message types.");
for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0;
++decodedMessageType) {
- if ((d.messageType & (1 << decodedMessageType)) == 0)
- continue;
-
- //### using QDataStream is relatively expensive
- ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
-
- QQmlProfiler::Location l = locations.value(d.locationId);
+ if (decodedMessageType == QQmlProfilerDefinitions::RangeData
+ || (d.messageType & (1 << decodedMessageType)) == 0) {
+ continue; // RangeData is sent together with RangeLocation
+ }
- switch (decodedMessageType) {
- case QQmlProfilerDefinitions::RangeStart:
- case QQmlProfilerDefinitions::RangeEnd:
- break;
- case QQmlProfilerDefinitions::RangeData:
- ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile);
- break;
- case QQmlProfilerDefinitions::RangeLocation:
- ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString())
- << static_cast<qint32>(l.location.line) << static_cast<qint32>(l.location.column);
- break;
- default:
- Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
- break;
+ if (decodedMessageType == QQmlProfilerDefinitions::RangeEnd
+ || decodedMessageType == QQmlProfilerDefinitions::RangeStart) {
+ ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
+ if (trackLocations && d.locationId != 0)
+ ds << static_cast<qint64>(d.locationId);
+ } else {
+ auto i = locations.find(d.locationId);
+ if (i != locations.end()) {
+ ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
+ ds << (i->url.isEmpty() ? i->location.sourceFile : i->url.toString())
+ << static_cast<qint32>(i->location.line)
+ << static_cast<qint32>(i->location.column);
+ if (d.messageType & (1 << QQmlProfilerDefinitions::RangeData)) {
+ // Send both, location and data ...
+ if (trackLocations)
+ ds << static_cast<qint64>(d.locationId);
+ messages.append(ds.squeezedData());
+ ds.clear();
+ ds << d.time << QQmlProfilerDefinitions::RangeData
+ << static_cast<quint32>(d.detailType)
+ << (i->location.sourceFile.isEmpty() ? i->url.toString() :
+ i->location.sourceFile);
+ }
+ if (trackLocations) {
+ ds << static_cast<qint64>(d.locationId);
+ locations.erase(i); // ... so that we can erase here without missing anything.
+ }
+ } else {
+ // Skip RangeData and RangeLocation: We've already sent them
+ continue;
+ }
}
messages.append(ds.squeezedData());
ds.clear();
}
}
-qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
+ bool trackLocations)
{
while (next != data.length()) {
const QQmlProfilerData &nextData = data.at(next);
if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
return nextData.time;
- qQmlProfilerDataToByteArrays(nextData, locations, messages);
+ qQmlProfilerDataToByteArrays(nextData, locations, messages, trackLocations);
++next;
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
index 7e13b6c479..96cdcd6d38 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofileradapter.h
@@ -60,7 +60,8 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
Q_OBJECT
public:
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE;
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
+ bool trackLocations) Q_DECL_OVERRIDE;
public slots:
void receiveData(const QVector<QQmlProfilerData> &new_data,
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
index a639cfb71e..a587188630 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.cpp
@@ -57,7 +57,7 @@ Q_QML_DEBUG_PLUGIN_LOADER(QQmlAbstractProfilerAdapter)
QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
- m_waitingForStop(false)
+ m_waitingForStop(false), m_useMessageTypes(false)
{
m_timer.start();
QQmlAbstractProfilerAdapter *quickAdapter =
@@ -309,7 +309,7 @@ void QQmlProfilerServiceImpl::stopProfiling(QJSEngine *engine)
m_waitingForStop = true;
foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
- profiler->reportData();
+ profiler->reportData(m_useMessageTypes);
foreach (QQmlAbstractProfilerAdapter *profiler, stopping)
profiler->stopProfiling();
@@ -343,7 +343,8 @@ void QQmlProfilerServiceImpl::sendMessages()
m_startTimes.erase(m_startTimes.begin());
qint64 next = first->sendMessages(m_startTimes.isEmpty() ?
std::numeric_limits<qint64>::max() :
- m_startTimes.begin().key(), messages);
+ m_startTimes.begin().key(), messages,
+ m_useMessageTypes);
if (next != -1)
m_startTimes.insert(next, first);
@@ -418,6 +419,8 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
}
}
+ if (!stream.atEnd())
+ stream >> m_useMessageTypes;
// If engineId == -1 objectForId() and then the cast will return 0.
if (enabled)
@@ -435,14 +438,14 @@ void QQmlProfilerServiceImpl::flush()
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
if (profiler->isRunning()) {
m_startTimes.insert(-1, profiler);
- profiler->reportData();
+ profiler->reportData(m_useMessageTypes);
}
}
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
if (profiler->isRunning()) {
m_startTimes.insert(-1, profiler);
- profiler->reportData();
+ profiler->reportData(m_useMessageTypes);
}
}
}
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
index 6490e77f44..42efdefd12 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qqmlprofilerservice.h
@@ -116,6 +116,7 @@ private:
QElapsedTimer m_timer;
QTimer m_flushTimer;
bool m_waitingForStop;
+ bool m_useMessageTypes;
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
index 68a71a5524..c3bbb86e3a 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.cpp
@@ -58,7 +58,7 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
+ connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
engine->profiler, SLOT(setTimer(QElapsedTimer)));
connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
@@ -105,13 +105,13 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
}
-qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
+ bool trackLocations)
{
QQmlDebugPacket d;
// Make it const, so that we cannot accidentally detach it.
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData;
- const QV4::Profiling::FunctionLocationHash &functionLocations = m_functionLocations;
while (true) {
while (!m_stack.isEmpty() &&
@@ -133,17 +133,27 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
return finalizeMessages(until, messages, props.start, d);
appendMemoryEvents(props.start, messages, d);
- auto location = functionLocations.constFind(props.id);
- Q_ASSERT(location != functionLocations.constEnd());
+ auto location = m_functionLocations.find(props.id);
d << props.start << RangeStart << Javascript;
- messages.push_back(d.squeezedData());
- d.clear();
- d << props.start << RangeLocation << Javascript << location->file << location->line
- << location->column;
- messages.push_back(d.squeezedData());
- d.clear();
- d << props.start << RangeData << Javascript << location->name;
+ if (trackLocations)
+ d << static_cast<qint64>(props.id);
+ if (location != m_functionLocations.end()) {
+ messages.push_back(d.squeezedData());
+ d.clear();
+ d << props.start << RangeLocation << Javascript << location->file << location->line
+ << location->column;
+ if (trackLocations)
+ d << static_cast<qint64>(props.id);
+ messages.push_back(d.squeezedData());
+ d.clear();
+ d << props.start << RangeData << Javascript << location->name;
+
+ if (trackLocations) {
+ d << static_cast<qint64>(props.id);
+ m_functionLocations.erase(location);
+ }
+ }
messages.push_back(d.squeezedData());
d.clear();
m_stack.push(props.end);
diff --git a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
index 968825c346..13a595f6eb 100644
--- a/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_profiler/qv4profileradapter.h
@@ -67,7 +67,8 @@ class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter {
public:
QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine);
- virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
+ bool trackLocations) override;
signals:
void v4ProfilingEnabled(quint64 v4Features);
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
index 9a2afd367d..bebf8806c6 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp
@@ -61,8 +61,8 @@ QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
- connect(this, SIGNAL(dataRequested()),
- QQuickProfiler::s_instance, SLOT(reportDataImpl()), Qt::DirectConnection);
+ connect(this, SIGNAL(dataRequested(bool)),
+ QQuickProfiler::s_instance, SLOT(reportDataImpl(bool)), Qt::DirectConnection);
connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
}
@@ -150,8 +150,10 @@ static void qQuickProfilerDataToByteArrays(const QQuickProfilerData &data,
}
}
-qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
+qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
+ bool trackLocations)
{
+ Q_UNUSED(trackLocations);
while (next < m_data.size()) {
if (m_data[next].time <= until && messages.length() <= s_numMessagesPerBatch)
qQuickProfilerDataToByteArrays(m_data[next++], messages);
diff --git a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
index 0983561d2c..f1ba411ac5 100644
--- a/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
+++ b/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.h
@@ -61,7 +61,7 @@ class QQuickProfilerAdapter : public QQmlAbstractProfilerAdapter {
public:
QQuickProfilerAdapter(QObject *parent = 0);
~QQuickProfilerAdapter();
- qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
+ qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) override;
public slots:
void receiveData(const QVector<QQuickProfilerData> &new_data);
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
index 44c2744978..067b0d35f6 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12renderloop.cpp
@@ -1089,7 +1089,7 @@ void QSGD3D12RenderLoop::polishAndSync(WindowData *w, bool inExpose)
}
// Flush pending touch events.
- QQuickWindowPrivate::get(window)->flushDelayedTouchEvent();
+ QQuickWindowPrivate::get(window)->flushFrameSynchronousEvents();
// The delivery of the event might have caused the window to stop rendering
w = windowFor(windows, window);
if (!w || !w->thread || !w->thread->exposedWindow) {
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index a1713dd809..c9a4e21ddd 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -72,23 +72,24 @@ using namespace QmlIR;
return false; \
}
-void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &loc)
+void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &loc)
{
inheritedTypeNameIndex = typeNameIndex;
location.line = loc.startLine;
location.column = loc.startColumn;
- idIndex = id;
+ idNameIndex = idIndex;
+ id = -1;
indexOfDefaultPropertyOrAlias = -1;
defaultPropertyIsAlias = false;
+ flags = QV4::CompiledData::Object::NoFlag;
properties = pool->New<PoolList<Property> >();
aliases = pool->New<PoolList<Alias> >();
qmlSignals = pool->New<PoolList<Signal> >();
bindings = pool->New<PoolList<Binding> >();
functions = pool->New<PoolList<Function> >();
functionsAndExpressions = pool->New<PoolList<CompiledFunctionOrExpression> >();
- runtimeFunctionIndices = 0;
declarationsOverride = 0;
}
@@ -1237,10 +1238,10 @@ bool IRBuilder::setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST
if (illegalNames.contains(idQString))
COMPILE_EXCEPTION(loc, tr( "ID illegally masks global JavaScript property"));
- if (_object->idIndex != emptyStringIndex)
+ if (_object->idNameIndex != emptyStringIndex)
COMPILE_EXCEPTION(idLocation, tr("Property value set multiple times"));
- _object->idIndex = registerString(idQString);
+ _object->idNameIndex = registerString(idQString);
_object->locationOfIdProperty.line = idLocation.startLine;
_object->locationOfIdProperty.column = idLocation.startColumn;
@@ -1368,12 +1369,12 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
const int importSize = sizeof(QV4::CompiledData::Import) * output.imports.count();
const int objectOffsetTableSize = output.objects.count() * sizeof(quint32);
- QHash<Object*, quint32> objectOffsets;
+ QHash<const Object*, quint32> objectOffsets;
int objectsSize = 0;
foreach (Object *o, output.objects) {
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
- objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
+ objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
int signalTableSize = 0;
for (const Signal *s = o->firstSignal(); s; s = s->next)
@@ -1413,14 +1414,17 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
// write objects
quint32 *objectTable = reinterpret_cast<quint32*>(data + qmlUnit->offsetToObjects);
char *objectPtr = data + qmlUnit->offsetToObjects + objectOffsetTableSize;
- foreach (Object *o, output.objects) {
+ for (int i = 0; i < output.objects.count(); ++i) {
+ const Object *o = output.objects.at(i);
*objectTable++ = objectOffsets.value(o);
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
- objectToWrite->idIndex = o->idIndex;
+ objectToWrite->flags = o->flags;
+ objectToWrite->idNameIndex = o->idNameIndex;
+ objectToWrite->id = o->id;
objectToWrite->location = o->location;
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
@@ -1446,9 +1450,13 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
objectToWrite->offsetToBindings = nextOffset;
nextOffset += objectToWrite->nBindings * sizeof(QV4::CompiledData::Binding);
+ objectToWrite->nNamedObjectsInComponent = o->namedObjectsInComponent.count;
+ objectToWrite->offsetToNamedObjectsInComponent = nextOffset;
+ nextOffset += objectToWrite->nNamedObjectsInComponent * sizeof(quint32);
+
quint32 *functionsTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToFunctions);
for (const Function *f = o->firstFunction(); f; f = f->next)
- *functionsTable++ = o->runtimeFunctionIndices->at(f->index);
+ *functionsTable++ = o->runtimeFunctionIndices.at(f->index);
char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties;
for (const Property *p = o->firstProperty(); p; p = p->next) {
@@ -1492,7 +1500,12 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
signalPtr += size;
}
- objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
+ quint32 *namedObjectInComponentPtr = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToNamedObjectsInComponent);
+ for (int i = 0; i < o->namedObjectsInComponent.count; ++i) {
+ *namedObjectInComponentPtr++ = o->namedObjectsInComponent.at(i);
+ }
+
+ objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
objectPtr += signalTableSize;
}
@@ -1509,7 +1522,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
return qmlUnit;
}
-char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter filter) const
+char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const
{
for (const Binding *b = o->firstBinding(); b; b = b->next) {
if (!(b->*(filter))())
@@ -1517,7 +1530,7 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter
QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr);
*bindingToWrite = *b;
if (b->type == QV4::CompiledData::Binding::Type_Script)
- bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices->at(b->value.compiledScriptIndex);
+ bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices.at(b->value.compiledScriptIndex);
bindingPtr += sizeof(QV4::CompiledData::Binding);
}
return bindingPtr;
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index c53004a331..db17c93222 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -170,7 +170,12 @@ class FixedPoolArray
public:
int count;
- void init(QQmlJS::MemoryPool *pool, const QVector<T> &vector)
+ FixedPoolArray()
+ : data(0)
+ , count(0)
+ {}
+
+ void allocate(QQmlJS::MemoryPool *pool, const QVector<T> &vector)
{
count = vector.count();
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
@@ -183,6 +188,16 @@ public:
}
}
+ template <typename Container>
+ void allocate(QQmlJS::MemoryPool *pool, const Container &container)
+ {
+ count = container.count();
+ data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
+ typename Container::ConstIterator it = container.constBegin();
+ for (int i = 0; i < count; ++i)
+ new (data + i) T(*it++);
+ }
+
const T &at(int index) const {
Q_ASSERT(index >= 0 && index < count);
return data[index];
@@ -274,9 +289,11 @@ struct Q_QML_PRIVATE_EXPORT Object
Q_DECLARE_TR_FUNCTIONS(Object)
public:
quint32 inheritedTypeNameIndex;
- quint32 idIndex;
- int indexOfDefaultPropertyOrAlias : 31;
- int defaultPropertyIsAlias : 1;
+ quint32 idNameIndex;
+ int id;
+ int indexOfDefaultPropertyOrAlias;
+ bool defaultPropertyIsAlias;
+ int flags;
QV4::CompiledData::Location location;
QV4::CompiledData::Location locationOfIdProperty;
@@ -296,7 +313,7 @@ public:
// specified object. Used for declarations inside group properties.
Object *declarationsOverride;
- void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation());
+ void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation());
QString sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
@@ -312,7 +329,9 @@ public:
QString bindingAsString(Document *doc, int scriptIndex) const;
PoolList<CompiledFunctionOrExpression> *functionsAndExpressions;
- FixedPoolArray<int> *runtimeFunctionIndices;
+ FixedPoolArray<int> runtimeFunctionIndices;
+
+ FixedPoolArray<quint32> namedObjectsInComponent;
private:
friend struct IRLoader;
@@ -467,7 +486,7 @@ struct Q_QML_PRIVATE_EXPORT QmlUnitGenerator
private:
typedef bool (Binding::*BindingFilter)() const;
- char *writeBindings(char *bindingPtr, Object *o, BindingFilter filter) const;
+ char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const;
};
#ifndef V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 0d98aa6e54..19beb13e45 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -65,16 +65,16 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlCompiledData *
bool QQmlTypeCompiler::compile()
{
- compiledData->importCache = new QQmlTypeNameCache;
+ importCache = new QQmlTypeNameCache;
foreach (const QString &ns, typeData->namespaces())
- compiledData->importCache->add(ns);
+ importCache->add(ns);
// Add any Composite Singletons that were used to the import cache
foreach (const QQmlTypeData::TypeReference &singleton, typeData->compositeSingletons())
- compiledData->importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
+ importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
- typeData->imports().populateCache(compiledData->importCache);
+ typeData->imports().populateCache(importCache.data());
const QHash<int, QQmlTypeData::TypeReference> &resolvedTypes = typeData->resolvedTypeRefs();
for (QHash<int, QQmlTypeData::TypeReference>::ConstIterator resolvedType = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
@@ -137,8 +137,6 @@ bool QQmlTypeCompiler::compile()
customParsers.insert(it.key(), customParser);
}
- compiledData->propertyCaches.reserve(document->objects.count());
-
{
QQmlPropertyCacheCreator propertyCacheBuilder(this);
if (!propertyCacheBuilder.buildMetaObjects())
@@ -174,7 +172,8 @@ bool QQmlTypeCompiler::compile()
// Collect imported scripts
const QList<QQmlTypeData::ScriptReference> &scripts = typeData->resolvedScripts();
- compiledData->scripts.reserve(scripts.count());
+ QVector<QQmlScriptData *> dependentScripts;
+ dependentScripts.reserve(scripts.count());
for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
@@ -187,10 +186,10 @@ bool QQmlTypeCompiler::compile()
qualifier = qualifier.mid(lastDotIndex+1);
}
- compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
+ importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
QQmlScriptData *scriptData = script.script->scriptData();
scriptData->addref();
- compiledData->scripts << scriptData;
+ dependentScripts << scriptData;
}
// Resolve component boundaries and aliases
@@ -202,6 +201,12 @@ bool QQmlTypeCompiler::compile()
return false;
}
+ {
+ QQmlDeferredAndCustomParserBindingScanner deferredAndCustomParserBindingScanner(this);
+ if (!deferredAndCustomParserBindingScanner.scanObject())
+ return false;
+ }
+
// Compile JS binding expressions and signal handlers
if (!document->javaScriptCompilationUnit) {
{
@@ -211,7 +216,7 @@ bool QQmlTypeCompiler::compile()
sss.scan();
}
- QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, compiledData->importCache, &document->jsGenerator.stringTable);
+ QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, importCache, &document->jsGenerator.stringTable);
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return false;
@@ -236,9 +241,12 @@ bool QQmlTypeCompiler::compile()
document->javaScriptCompilationUnit->data = qmlUnit;
compiledData->compilationUnit = document->javaScriptCompilationUnit;
+ compiledData->compilationUnit->propertyCaches = m_propertyCaches;
+ compiledData->compilationUnit->importCache = importCache;
+ compiledData->compilationUnit->dependentScripts = dependentScripts;
// Add to type registry of composites
- if (compiledData->isCompositeType())
+ if (compiledData->compilationUnit->isCompositeType())
engine->registerInternalCompositeType(compiledData);
else {
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
@@ -272,18 +280,18 @@ bool QQmlTypeCompiler::compile()
}
++objectCount;
if (typeRef->component) {
- bindingCount += typeRef->component->totalBindingsCount;
- parserStatusCount += typeRef->component->totalParserStatusCount;
- objectCount += typeRef->component->totalObjectCount;
+ bindingCount += typeRef->component->compilationUnit->totalBindingsCount;
+ parserStatusCount += typeRef->component->compilationUnit->totalParserStatusCount;
+ objectCount += typeRef->component->compilationUnit->totalObjectCount;
}
}
}
- compiledData->totalBindingsCount = bindingCount;
- compiledData->totalParserStatusCount = parserStatusCount;
- compiledData->totalObjectCount = objectCount;
+ compiledData->compilationUnit->totalBindingsCount = bindingCount;
+ compiledData->compilationUnit->totalParserStatusCount = parserStatusCount;
+ compiledData->compilationUnit->totalObjectCount = objectCount;
- Q_ASSERT(compiledData->propertyCaches.count() == static_cast<int>(compiledData->compilationUnit->data->nObjects));
+ Q_ASSERT(compiledData->compilationUnit->propertyCaches.count() == static_cast<int>(compiledData->compilationUnit->data->nObjects));
return errors.isEmpty();
}
@@ -337,28 +345,13 @@ int QQmlTypeCompiler::rootObjectIndex() const
void QQmlTypeCompiler::setPropertyCaches(const QQmlPropertyCacheVector &caches)
{
- compiledData->propertyCaches = caches;
+ m_propertyCaches = caches;
Q_ASSERT(caches.count() >= document->indexOfRootObject);
}
const QQmlPropertyCacheVector &QQmlTypeCompiler::propertyCaches() const
{
- return compiledData->propertyCaches;
-}
-
-QHash<int, int> *QQmlTypeCompiler::objectIndexToIdForRoot()
-{
- return &compiledData->objectIndexToIdForRoot;
-}
-
-QHash<int, QHash<int, int> > *QQmlTypeCompiler::objectIndexToIdPerComponent()
-{
- return &compiledData->objectIndexToIdPerComponent;
-}
-
-QHash<int, QBitArray> *QQmlTypeCompiler::customParserBindings()
-{
- return &compiledData->customParserBindings;
+ return m_propertyCaches;
}
QQmlJS::MemoryPool *QQmlTypeCompiler::memoryPool()
@@ -376,11 +369,6 @@ const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const
return &document->jsGenerator.stringTable;
}
-void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject)
-{
- compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
-}
-
void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
{
compiledData->compilationUnit->bindingPropertyDataPerObject = propertyData;
@@ -1324,11 +1312,8 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
, qmlObjects(typeCompiler->qmlObjects())
, indexOfRootObject(typeCompiler->rootObjectIndex())
, _componentIndex(-1)
- , _objectIndexToIdInScope(0)
, resolvedTypes(typeCompiler->resolvedTypes())
, propertyCaches(typeCompiler->propertyCaches())
- , objectIndexToIdForRoot(typeCompiler->objectIndexToIdForRoot())
- , objectIndexToIdPerComponent(typeCompiler->objectIndexToIdPerComponent())
{
}
@@ -1351,7 +1336,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
if (targetType->metaObject() == &QQmlComponent::staticMetaObject)
continue;
} else if (tr->component) {
- if (tr->component->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject)
+ if (tr->component->compilationUnit->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject)
continue;
}
@@ -1382,6 +1367,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>();
syntheticComponent->init(pool, compiler->registerString(QString::fromUtf8(componentType->typeName())), compiler->registerString(QString()));
syntheticComponent->location = binding->valueLocation;
+ syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
QQmlCompiledData::TypeReference *typeRef = new QQmlCompiledData::TypeReference;
@@ -1408,7 +1394,6 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
binding->value.objectIndex = componentIndex;
componentRoots.append(componentIndex);
- componentBoundaries.append(syntheticBinding->value.objectIndex);
}
}
@@ -1420,7 +1405,7 @@ bool QQmlComponentAndAliasResolver::resolve()
// on the left hand side is of QQmlComponent type.
const int objCountWithoutSynthesizedComponents = qmlObjects->count();
for (int i = 0; i < objCountWithoutSynthesizedComponents; ++i) {
- const QmlIR::Object *obj = qmlObjects->at(i);
+ QmlIR::Object *obj = qmlObjects->at(i);
QQmlPropertyCache *cache = propertyCaches.at(i).data();
if (obj->inheritedTypeNameIndex == 0 && !cache)
continue;
@@ -1439,7 +1424,7 @@ bool QQmlComponentAndAliasResolver::resolve()
continue;
}
- componentRoots.append(i);
+ obj->flags |= QV4::CompiledData::Object::IsComponent;
if (obj->functionCount() > 0)
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
@@ -1461,20 +1446,20 @@ bool QQmlComponentAndAliasResolver::resolve()
if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
- componentBoundaries.append(rootBinding->value.objectIndex);
- }
+ // We are going to collect ids/aliases and resolve them for the root object as a separate
+ // last pass.
+ if (i != indexOfRootObject)
+ componentRoots.append(i);
- std::sort(componentBoundaries.begin(), componentBoundaries.end());
+ }
for (int i = 0; i < componentRoots.count(); ++i) {
- const QmlIR::Object *component = qmlObjects->at(componentRoots.at(i));
+ QmlIR::Object *component = qmlObjects->at(componentRoots.at(i));
const QmlIR::Binding *rootBinding = component->firstBinding();
_componentIndex = i;
_idToObjectIndex.clear();
- _objectIndexToIdInScope = &(*objectIndexToIdPerComponent)[componentRoots.at(i)];
-
_objectsWithAliases.clear();
if (!collectIdsAndAliases(rootBinding->value.objectIndex))
@@ -1482,51 +1467,56 @@ bool QQmlComponentAndAliasResolver::resolve()
if (!resolveAliases())
return false;
+
+ component->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
}
// Collect ids and aliases for root
_componentIndex = -1;
_idToObjectIndex.clear();
- _objectIndexToIdInScope = objectIndexToIdForRoot;
_objectsWithAliases.clear();
collectIdsAndAliases(indexOfRootObject);
resolveAliases();
+ QmlIR::Object *rootComponent = qmlObjects->at(indexOfRootObject);
+ rootComponent->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
+
// Implicit component insertion may have added objects and thus we also need
// to extend the symmetric propertyCaches.
compiler->setPropertyCaches(propertyCaches);
+ compiler->setComponentRoots(componentRoots);
return true;
}
bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
{
- const QmlIR::Object *obj = qmlObjects->at(objectIndex);
+ QmlIR::Object *obj = qmlObjects->at(objectIndex);
- if (obj->idIndex != 0) {
- if (_idToObjectIndex.contains(obj->idIndex)) {
+ if (obj->idNameIndex != 0) {
+ if (_idToObjectIndex.contains(obj->idNameIndex)) {
recordError(obj->locationOfIdProperty, tr("id is not unique"));
return false;
}
- _idToObjectIndex.insert(obj->idIndex, objectIndex);
- _objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
+ obj->id = _idToObjectIndex.count();
+ _idToObjectIndex.insert(obj->idNameIndex, objectIndex);
}
if (obj->aliasCount() > 0)
_objectsWithAliases.append(objectIndex);
+ // Stop at Component boundary
+ if (obj->flags & QV4::CompiledData::Object::IsComponent && objectIndex != compiler->rootObjectIndex())
+ return true;
+
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
if (binding->type != QV4::CompiledData::Binding::Type_Object
&& binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
&& binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
continue;
- // Stop at Component boundary
- if (std::binary_search(componentBoundaries.constBegin(), componentBoundaries.constEnd(), binding->value.objectIndex))
- continue;
-
if (!collectIdsAndAliases(binding->value.objectIndex))
return false;
}
@@ -1555,8 +1545,9 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
}
Q_ASSERT(!(alias->flags & QV4::CompiledData::Alias::Resolved));
alias->flags |= QV4::CompiledData::Alias::Resolved;
- Q_ASSERT(_objectIndexToIdInScope->contains(targetObjectIndex));
- alias->targetObjectId = _objectIndexToIdInScope->value(targetObjectIndex);
+ const QmlIR::Object *targetObject = qmlObjects->at(targetObjectIndex);
+ Q_ASSERT(targetObject->id >= 0);
+ alias->targetObjectId = targetObject->id;
const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
@@ -1668,6 +1659,126 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
return true;
}
+QQmlDeferredAndCustomParserBindingScanner::QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler)
+ : QQmlCompilePass(typeCompiler)
+ , qmlObjects(typeCompiler->qmlObjects())
+ , propertyCaches(typeCompiler->propertyCaches())
+ , customParsers(typeCompiler->customParserCache())
+ , _seenObjectWithId(false)
+{
+}
+
+bool QQmlDeferredAndCustomParserBindingScanner::scanObject()
+{
+ return scanObject(compiler->rootObjectIndex());
+}
+
+bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
+{
+ QmlIR::Object *obj = qmlObjects->at(objectIndex);
+ if (obj->idNameIndex != 0)
+ _seenObjectWithId = true;
+
+ if (obj->flags & QV4::CompiledData::Object::IsComponent) {
+ Q_ASSERT(obj->bindingCount() == 1);
+ const QV4::CompiledData::Binding *componentBinding = obj->firstBinding();
+ Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
+ return scanObject(componentBinding->value.objectIndex);
+ }
+
+ QQmlPropertyCache *propertyCache = propertyCaches.at(objectIndex).data();
+ if (!propertyCache)
+ return true;
+
+ QString defaultPropertyName;
+ QQmlPropertyData *defaultProperty = 0;
+ if (obj->indexOfDefaultPropertyOrAlias != -1) {
+ QQmlPropertyCache *cache = propertyCache->parent();
+ defaultPropertyName = cache->defaultPropertyName();
+ defaultProperty = cache->defaultProperty();
+ } else {
+ defaultPropertyName = propertyCache->defaultPropertyName();
+ defaultProperty = propertyCache->defaultProperty();
+ }
+
+ QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex);
+
+ QmlIR::PropertyResolver propertyResolver(propertyCache);
+
+ QStringList deferredPropertyNames;
+ {
+ const QMetaObject *mo = propertyCache->firstCppMetaObject();
+ const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
+ if (namesIndex != -1) {
+ QMetaClassInfo classInfo = mo->classInfo(namesIndex);
+ deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
+ }
+ }
+
+ for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
+ QQmlPropertyData *pd = 0;
+ QString name = stringAt(binding->propertyNameIndex);
+
+ if (customParser) {
+ if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
+ if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
+ binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
+ obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
+ continue;
+ }
+ } else if (QmlIR::IRBuilder::isSignalPropertyName(name)
+ && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
+ obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
+ binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
+ continue;
+ }
+ }
+
+ if (name.isEmpty()) {
+ pd = defaultProperty;
+ name = defaultPropertyName;
+ } else {
+ if (name.constData()->isUpper())
+ continue;
+
+ bool notInRevision = false;
+ pd = propertyResolver.property(name, &notInRevision, QmlIR::PropertyResolver::CheckRevision);
+ }
+
+ bool seenSubObjectWithId = false;
+
+ if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
+ qSwap(_seenObjectWithId, seenSubObjectWithId);
+ const bool subObjectValid = scanObject(binding->value.objectIndex);
+ qSwap(_seenObjectWithId, seenSubObjectWithId);
+ if (!subObjectValid)
+ return false;
+ _seenObjectWithId |= seenSubObjectWithId;
+ }
+
+ if (!seenSubObjectWithId
+ && !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
+
+ binding->flags |= QV4::CompiledData::Binding::IsDeferredBinding;
+ obj->flags |= QV4::CompiledData::Object::HasDeferredBindings;
+ }
+
+ if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
+ || binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
+ continue;
+
+ if (!pd) {
+ if (customParser) {
+ obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
+ binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
+ }
+ }
+ }
+
+ return true;
+}
+
+
QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
: QQmlCompilePass(typeCompiler)
, enginePrivate(typeCompiler->enginePrivate())
@@ -1675,9 +1786,6 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
, resolvedTypes(*typeCompiler->resolvedTypes())
, customParsers(typeCompiler->customParserCache())
, propertyCaches(typeCompiler->propertyCaches())
- , objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
- , customParserBindingsPerObject(typeCompiler->customParserBindings())
- , _seenObjectWithId(false)
{
}
@@ -1686,7 +1794,6 @@ bool QQmlPropertyValidator::validate()
_bindingPropertyDataPerObject.resize(qmlUnit->nObjects);
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
return false;
- compiler->setDeferredBindingsPerObject(_deferredBindingsPerObject);
compiler->setBindingPropertyDataPerObject(_bindingPropertyDataPerObject);
return true;
}
@@ -1717,10 +1824,8 @@ struct BindingFinder
bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
- if (obj->idIndex != 0)
- _seenObjectWithId = true;
- if (isComponent(objectIndex)) {
+ if (obj->flags & QV4::CompiledData::Object::IsComponent) {
Q_ASSERT(obj->nBindings == 1);
const QV4::CompiledData::Binding *componentBinding = obj->bindingTable();
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
@@ -1764,9 +1869,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
groupProperties.insert(pos, binding);
}
- QBitArray customParserBindings(obj->nBindings);
- QBitArray deferredBindings;
-
QmlIR::PropertyResolver propertyResolver(propertyCache);
QString defaultPropertyName;
@@ -1790,13 +1892,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
customBindings << binding;
- customParserBindings.setBit(i);
continue;
}
} else if (QmlIR::IRBuilder::isSignalPropertyName(name)
&& !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
customBindings << binding;
- customParserBindings.setBit(i);
continue;
}
}
@@ -1845,24 +1945,10 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
return false;
}
- bool seenSubObjectWithId = false;
-
if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
- qSwap(_seenObjectWithId, seenSubObjectWithId);
const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
- qSwap(_seenObjectWithId, seenSubObjectWithId);
if (!subObjectValid)
return false;
- _seenObjectWithId |= seenSubObjectWithId;
- }
-
- if (!seenSubObjectWithId
- && !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
-
- if (deferredBindings.isEmpty())
- deferredBindings.resize(obj->nBindings);
-
- deferredBindings.setBit(i);
}
// Signal handlers were resolved and checked earlier in the signal handler conversion pass.
@@ -1947,7 +2033,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
} else {
if (customParser) {
customBindings << binding;
- customParserBindings.setBit(i);
continue;
}
if (bindingToDefaultProperty) {
@@ -1958,7 +2043,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
- if (obj->idIndex) {
+ if (obj->idNameIndex) {
bool notInRevision = false;
collectedBindingPropertyData << propertyResolver.property(QStringLiteral("id"), &notInRevision);
}
@@ -1972,7 +2057,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
customParser->validator = 0;
customParser->engine = 0;
customParser->imports = (QQmlImports*)0;
- customParserBindingsPerObject->insert(objectIndex, customParserBindings);
const QList<QQmlError> parserErrors = customParser->errors();
if (!parserErrors.isEmpty()) {
foreach (const QQmlError &error, parserErrors)
@@ -1981,9 +2065,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
}
}
- if (!deferredBindings.isEmpty())
- _deferredBindingsPerObject.insert(objectIndex, deferredBindings);
-
_bindingPropertyDataPerObject[objectIndex] = collectedBindingPropertyData;
return true;
@@ -2328,7 +2409,7 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
}
}
return true;
- } else if (isComponent(binding->value.objectIndex)) {
+ } else if (qmlUnit->objectAt(binding->value.objectIndex)->flags & QV4::CompiledData::Object::IsComponent) {
return true;
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
return true;
@@ -2365,7 +2446,6 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen)
: QQmlCompilePass(typeCompiler)
- , objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
, resolvedTypes(*typeCompiler->resolvedTypes())
, customParsers(typeCompiler->customParserCache())
, qmlObjects(*typeCompiler->qmlObjects())
@@ -2376,46 +2456,40 @@ QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::
bool QQmlJSCodeGenerator::generateCodeForComponents()
{
- const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent = *compiler->objectIndexToIdPerComponent();
- for (QHash<int, QHash<int, int> >::ConstIterator component = objectIndexToIdPerComponent.constBegin(), end = objectIndexToIdPerComponent.constEnd();
- component != end; ++component) {
- if (!compileComponent(component.key(), component.value()))
+ const QVector<quint32> &componentRoots = compiler->componentRoots();
+ for (int i = 0; i < componentRoots.count(); ++i) {
+ if (!compileComponent(componentRoots.at(i)))
return false;
}
- return compileComponent(compiler->rootObjectIndex(), *compiler->objectIndexToIdForRoot());
+ return compileComponent(compiler->rootObjectIndex());
}
-bool QQmlJSCodeGenerator::compileComponent(int contextObject, const QHash<int, int> &objectIndexToId)
+bool QQmlJSCodeGenerator::compileComponent(int contextObject)
{
- if (isComponent(contextObject)) {
- const QmlIR::Object *component = qmlObjects.at(contextObject);
- Q_ASSERT(component->bindingCount() == 1);
- const QV4::CompiledData::Binding *componentBinding = component->firstBinding();
+ const QmlIR::Object *obj = qmlObjects.at(contextObject);
+ if (obj->flags & QV4::CompiledData::Object::IsComponent) {
+ Q_ASSERT(obj->bindingCount() == 1);
+ const QV4::CompiledData::Binding *componentBinding = obj->firstBinding();
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
contextObject = componentBinding->value.objectIndex;
}
QmlIR::JSCodeGen::ObjectIdMapping idMapping;
- if (!objectIndexToId.isEmpty()) {
- idMapping.reserve(objectIndexToId.count());
-
- for (QHash<int, int>::ConstIterator idIt = objectIndexToId.constBegin(), end = objectIndexToId.constEnd();
- idIt != end; ++idIt) {
-
- const int objectIndex = idIt.key();
- QmlIR::JSCodeGen::IdMapping m;
- const QmlIR::Object *obj = qmlObjects.at(objectIndex);
- m.name = stringAt(obj->idIndex);
- m.idIndex = idIt.value();
- m.type = propertyCaches.at(objectIndex).data();
+ idMapping.reserve(obj->namedObjectsInComponent.count);
+ for (int i = 0; i < obj->namedObjectsInComponent.count; ++i) {
+ const int objectIndex = obj->namedObjectsInComponent.at(i);
+ QmlIR::JSCodeGen::IdMapping m;
+ const QmlIR::Object *obj = qmlObjects.at(objectIndex);
+ m.name = stringAt(obj->idNameIndex);
+ m.idIndex = obj->id;
+ m.type = propertyCaches.at(objectIndex).data();
- QQmlCompiledData::TypeReference *tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
- if (tref && tref->isFullyDynamicType)
- m.type = 0;
+ QQmlCompiledData::TypeReference *tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
+ if (tref && tref->isFullyDynamicType)
+ m.type = 0;
- idMapping << m;
- }
+ idMapping << m;
}
v4CodeGen->beginContextScope(idMapping, propertyCaches.at(contextObject).data());
@@ -2427,10 +2501,10 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject, const QHash<int, i
bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex)
{
- if (isComponent(objectIndex))
+ QmlIR::Object *object = qmlObjects.at(objectIndex);
+ if (object->flags & QV4::CompiledData::Object::IsComponent)
return true;
- QmlIR::Object *object = qmlObjects.at(objectIndex);
if (object->functionsAndExpressions->count > 0) {
QQmlPropertyCache *scopeObject = propertyCaches.at(scopeObjectIndex).data();
v4CodeGen->beginObjectScope(scopeObject);
@@ -2451,8 +2525,7 @@ bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIn
}
QQmlJS::MemoryPool *pool = compiler->memoryPool();
- object->runtimeFunctionIndices = pool->New<QmlIR::FixedPoolArray<int> >();
- object->runtimeFunctionIndices->init(pool, runtimeFunctionIndices);
+ object->runtimeFunctionIndices.allocate(pool, runtimeFunctionIndices);
}
for (const QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
@@ -2551,7 +2624,7 @@ void QQmlJavaScriptBindingExpressionSimplificationPass::reduceTranslationBinding
if (binding->type != QV4::CompiledData::Binding::Type_Script)
continue;
- const int irFunctionIndex = obj->runtimeFunctionIndices->at(binding->value.compiledScriptIndex);
+ const int irFunctionIndex = obj->runtimeFunctionIndices.at(binding->value.compiledScriptIndex);
QV4::IR::Function *irFunction = jsModule->functions.at(irFunctionIndex);
if (simplifyBinding(irFunction, binding)) {
irFunctionsToRemove.append(irFunctionIndex);
@@ -2838,10 +2911,8 @@ void QQmlIRFunctionCleanser::clean()
}
foreach (QmlIR::Object *obj, *compiler->qmlObjects()) {
- if (!obj->runtimeFunctionIndices)
- continue;
- for (int i = 0; i < obj->runtimeFunctionIndices->count; ++i)
- (*obj->runtimeFunctionIndices)[i] = newFunctionIndices[obj->runtimeFunctionIndices->at(i)];
+ for (int i = 0; i < obj->runtimeFunctionIndices.count; ++i)
+ obj->runtimeFunctionIndices[i] = newFunctionIndices[obj->runtimeFunctionIndices.at(i)];
}
}
diff --git a/src/qml/compiler/qqmltypecompiler_p.h b/src/qml/compiler/qqmltypecompiler_p.h
index 968902dae1..5abfc7c18d 100644
--- a/src/qml/compiler/qqmltypecompiler_p.h
+++ b/src/qml/compiler/qqmltypecompiler_p.h
@@ -101,13 +101,11 @@ public:
int rootObjectIndex() const;
void setPropertyCaches(const QQmlPropertyCacheVector &caches);
const QQmlPropertyCacheVector &propertyCaches() const;
- QHash<int, int> *objectIndexToIdForRoot();
- QHash<int, QHash<int, int> > *objectIndexToIdPerComponent();
- QHash<int, QBitArray> *customParserBindings();
+ void setComponentRoots(const QVector<quint32> &roots) { m_componentRoots = roots; }
+ const QVector<quint32> &componentRoots() const { return m_componentRoots; }
QQmlJS::MemoryPool *memoryPool();
QStringRef newStringRef(const QString &string);
const QV4::Compiler::StringTableGenerator *stringPool() const;
- void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
@@ -119,9 +117,14 @@ private:
QQmlEnginePrivate *engine;
QQmlCompiledData *compiledData;
QQmlTypeData *typeData;
+ QQmlRefPointer<QQmlTypeNameCache> importCache;
QmlIR::Document *document;
// index is string index of type name (use obj->inheritedTypeNameIndex)
QHash<int, QQmlCustomParser*> customParsers;
+
+ // index in first hash is component index, vector inside contains object indices of objects with id property
+ QVector<quint32> m_componentRoots;
+ QQmlPropertyCacheVector m_propertyCaches;
};
struct QQmlCompilePass
@@ -268,20 +271,31 @@ protected:
const int indexOfRootObject;
// indices of the objects that are actually Component {}
- QVector<int> componentRoots;
- // indices of objects that are the beginning of a new component
- // scope. This is sorted and used for binary search.
- QVector<quint32> componentBoundaries;
+ QVector<quint32> componentRoots;
int _componentIndex;
QHash<int, int> _idToObjectIndex;
- QHash<int, int> *_objectIndexToIdInScope;
QList<int> _objectsWithAliases;
QHash<int, QQmlCompiledData::TypeReference*> *resolvedTypes;
QQmlPropertyCacheVector propertyCaches;
- QHash<int, int> *objectIndexToIdForRoot;
- QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
+};
+
+class QQmlDeferredAndCustomParserBindingScanner : public QQmlCompilePass
+{
+public:
+ QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler);
+
+ bool scanObject();
+
+private:
+ bool scanObject(int objectIndex);
+
+ QList<QmlIR::Object*> *qmlObjects;
+ QQmlPropertyCacheVector propertyCaches;
+ const QHash<int, QQmlCustomParser*> &customParsers;
+
+ bool _seenObjectWithId;
};
class QQmlPropertyValidator : public QQmlCompilePass
@@ -300,8 +314,6 @@ private:
bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const;
bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const;
- bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
-
bool canCoerce(int to, QQmlPropertyCache *fromMo) const;
QQmlEnginePrivate *enginePrivate;
@@ -309,12 +321,8 @@ private:
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
const QHash<int, QQmlCustomParser*> &customParsers;
const QQmlPropertyCacheVector &propertyCaches;
- const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
- QHash<int, QBitArray> *customParserBindingsPerObject;
// collected state variables, essentially write-only
- mutable QHash<int, QBitArray> _deferredBindingsPerObject;
- mutable bool _seenObjectWithId;
mutable QVector<QV4::CompiledData::BindingPropertyData> _bindingPropertyDataPerObject;
};
@@ -327,12 +335,9 @@ public:
bool generateCodeForComponents();
private:
- bool compileComponent(int componentRoot, const QHash<int, int> &objectIndexToId);
+ bool compileComponent(int componentRoot);
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
- bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
-
- const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent;
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
const QHash<int, QQmlCustomParser*> &customParsers;
const QList<QmlIR::Object*> &qmlObjects;
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index ded2c1a9f8..dc29d1b941 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -47,6 +47,7 @@
#include <private/qv4lookup_p.h>
#include <private/qv4regexpobject_p.h>
#include <private/qqmlpropertycache_p.h>
+#include <private/qqmltypeloader_p.h>
#endif
#include <private/qqmlirbuilder_p.h>
#include <QCoreApplication>
@@ -67,6 +68,9 @@ CompilationUnit::CompilationUnit()
, runtimeLookups(0)
, runtimeRegularExpressions(0)
, runtimeClasses(0)
+ , totalBindingsCount(0)
+ , totalParserStatusCount(0)
+ , totalObjectCount(0)
{}
CompilationUnit::~CompilationUnit()
@@ -165,6 +169,18 @@ void CompilationUnit::unlink()
{
if (engine)
engine->compilationUnits.erase(engine->compilationUnits.find(this));
+
+ for (int ii = 0; ii < propertyCaches.count(); ++ii)
+ if (propertyCaches.at(ii).data())
+ propertyCaches.at(ii)->release();
+ propertyCaches.clear();
+
+ for (int ii = 0; ii < dependentScripts.count(); ++ii)
+ dependentScripts.at(ii)->release();
+ dependentScripts.clear();
+
+ importCache = nullptr;
+
engine = 0;
free(runtimeStrings);
runtimeStrings = 0;
@@ -189,6 +205,22 @@ void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
}
}
+IdentifierHash<int> CompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
+{
+ auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
+ if (it == namedObjectsPerComponentCache.end()) {
+ IdentifierHash<int> namedObjectCache(engine);
+ const CompiledData::Object *component = data->objectAt(componentObjectIndex);
+ const quint32 *namedObjectIndexPtr = component->namedObjectsInComponentTable();
+ for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
+ const CompiledData::Object *namedObject = data->objectAt(*namedObjectIndexPtr);
+ namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
+ }
+ it = namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
+ }
+ return *it;
+}
+
#endif // V4_BOOTSTRAP
Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 3c2d895bff..8beb932fc8 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -60,11 +60,22 @@
#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>
+#ifndef V4_BOOTSTRAP
+#include <private/qqmltypenamecache_p.h>
+#endif
QT_BEGIN_NAMESPACE
class QQmlPropertyCache;
class QQmlPropertyData;
+class QQmlTypeNameCache;
+class QQmlScriptData;
+
+// The vector is indexed by QV4::CompiledData::Object index and the flag
+// indicates whether instantiation of the object requires a VME meta-object.
+typedef QVector<QFlagPointer<QQmlPropertyCache>> QQmlPropertyCacheVector;
namespace QmlIR {
struct Document;
@@ -234,7 +245,9 @@ struct Q_QML_PRIVATE_EXPORT Binding
InitializerForReadOnlyDeclaration = 0x8,
IsResolvedEnum = 0x10,
IsListItem = 0x20,
- IsBindingToAlias = 0x40
+ IsBindingToAlias = 0x40,
+ IsDeferredBinding = 0x80,
+ IsCustomParserBinding = 0x100,
};
quint32 flags : 16;
@@ -391,13 +404,22 @@ struct Alias {
struct Object
{
+ enum Flags {
+ NoFlag = 0x0,
+ IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
+ HasDeferredBindings = 0x2, // any of the bindings are deferred
+ HasCustomParserBindings = 0x4
+ };
+
// Depending on the use, this may be the type name to instantiate before instantiating this
// object. For grouped properties the type name will be empty and for attached properties
// it will be the name of the attached type.
quint32 inheritedTypeNameIndex;
- quint32 idIndex;
- qint32 indexOfDefaultPropertyOrAlias : 31; // -1 means no default property declared in this object
+ quint32 idNameIndex;
+ qint32 id : 16;
+ qint32 flags : 15;
quint32 defaultPropertyIsAlias : 1;
+ qint32 indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
quint32 nFunctions;
quint32 offsetToFunctions;
quint32 nProperties;
@@ -408,6 +430,8 @@ struct Object
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
quint32 nBindings;
quint32 offsetToBindings;
+ quint32 nNamedObjectsInComponent;
+ quint32 offsetToNamedObjectsInComponent;
Location location;
Location locationOfIdProperty;
// Function[]
@@ -415,7 +439,7 @@ struct Object
// Signal[]
// Binding[]
- static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings)
+ static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings, int nNamedObjectsInComponent)
{
return ( sizeof(Object)
+ nFunctions * sizeof(quint32)
@@ -423,6 +447,7 @@ struct Object
+ nAliases * sizeof(Alias)
+ nSignals * sizeof(quint32)
+ nBindings * sizeof(Binding)
+ + nNamedObjectsInComponent * sizeof(int)
+ 0x7
) & ~0x7;
}
@@ -453,6 +478,11 @@ struct Object
const uint offset = offsetTable[idx];
return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
}
+
+ const quint32 *namedObjectsInComponentTable() const
+ {
+ return reinterpret_cast<const quint32*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
+ }
};
struct Import
@@ -641,11 +671,29 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QVector<QV4::Function *> runtimeFunctions;
mutable QQmlNullableValue<QUrl> m_url;
+ // QML specific fields
+ QQmlPropertyCacheVector propertyCaches;
+ QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(data->indexOfRootObject).data(); }
+ bool isCompositeType() const { return propertyCaches.at(data->indexOfRootObject).flag(); }
+
+ QQmlRefPointer<QQmlTypeNameCache> importCache;
+
// index is object index. This allows fast access to the
// property data when initializing bindings, avoiding expensive
// lookups by string (property name).
QVector<BindingPropertyData> bindingPropertyDataPerObject;
+ // mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
+ // this is initialized on-demand by QQmlContextData
+ QHash<int, IdentifierHash<int>> namedObjectsPerComponentCache;
+ IdentifierHash<int> namedObjectsPerComponent(int componentObjectIndex);
+
+ int totalBindingsCount; // Number of bindings used in this type
+ int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
+ int totalObjectCount; // Number of objects explicitly instantiated
+
+ QVector<QQmlScriptData *> dependentScripts;
+
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h
index 1104608055..8820c4311a 100644
--- a/src/qml/debugger/qqmlabstractprofileradapter_p.h
+++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h
@@ -71,13 +71,13 @@ public:
virtual ~QQmlAbstractProfilerAdapter() {}
void setService(QQmlProfilerService *new_service) { service = new_service; }
- virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
+ virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) = 0;
void startProfiling(quint64 features);
void stopProfiling();
- void reportData() { emit dataRequested(); }
+ void reportData(bool trackLocations) { emit dataRequested(trackLocations); }
void stopWaiting() { waiting = false; }
void startWaiting() { waiting = true; }
@@ -94,7 +94,7 @@ signals:
void profilingDisabled();
void profilingDisabledWhileWaiting();
- void dataRequested();
+ void dataRequested(bool trackLocations);
void referenceTimeKnown(const QElapsedTimer &timer);
protected:
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index 629d5cb7b8..ffba731b13 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -59,19 +59,21 @@ void QQmlProfiler::startProfiling(quint64 features)
void QQmlProfiler::stopProfiling()
{
featuresEnabled = false;
- reportData();
+ reportData(true);
+ m_locations.clear();
}
-void QQmlProfiler::reportData()
+void QQmlProfiler::reportData(bool trackLocations)
{
LocationHash resolved;
resolved.reserve(m_locations.size());
- for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it)
- resolved.insert(it.key(), it.value());
-
- // This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's
- // a good idea to release the memory before creating the packets to be sent.
- m_locations.clear();
+ for (auto it = m_locations.begin(), end = m_locations.end(); it != end; ++it) {
+ if (!trackLocations || !it->sent) {
+ resolved.insert(it.key(), it.value());
+ if (trackLocations)
+ it->sent = true;
+ }
+ }
QVector<QQmlProfilerData> data;
data.swap(m_data);
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 1380599fb7..60851ac444 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -146,26 +146,27 @@ public:
// Unfortunately we have to resolve the locations right away because the QML context might not
// be available anymore when we send the data.
struct RefLocation : public Location {
- RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr)
+ RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr), sent(false)
{}
RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
Location(function->sourceLocation()), locationType(Binding),
- ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt)
+ ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt), sent(false)
{}
RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
const QString &type) :
Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
- locationType(Creating), ref(ref)
+ locationType(Creating), ref(ref), sent(false)
{}
RefLocation(QQmlBoundSignalExpression *ref) :
- Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref)
+ Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref), sent(false)
{}
RefLocation(QQmlDataBlob *ref) :
- Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref)
+ Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref),
+ sent(false)
{}
bool isValid() const
@@ -175,6 +176,7 @@ public:
RangeType locationType;
QQmlRefPointer<QQmlRefCount> ref;
+ bool sent;
};
typedef QHash<quintptr, Location> LocationHash;
@@ -217,11 +219,6 @@ public:
location = RefLocation(expression);
}
- void startCreating()
- {
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating));
- }
-
void startCreating(const QV4::CompiledData::Object *obj)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
@@ -233,10 +230,6 @@ public:
const QUrl &url, const QString &type)
{
quintptr locationId(id(obj));
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
- (1 << RangeLocation | 1 << RangeData),
- Creating, locationId));
-
RefLocation &location = m_locations[locationId];
if (!location.isValid())
location = RefLocation(ref, url, obj, type);
@@ -261,7 +254,7 @@ public:
public slots:
void startProfiling(quint64 features);
void stopProfiling();
- void reportData();
+ void reportData(bool trackLocations);
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
@@ -363,9 +356,10 @@ private:
class QQmlObjectCreationProfiler {
public:
- QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
+ QQmlObjectCreationProfiler(QQmlProfiler *profiler, const QV4::CompiledData::Object *obj)
+ : profiler(profiler)
{
- Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating());
+ Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating(obj));
}
~QQmlObjectCreationProfiler()
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index 626648067f..6260fd0cc8 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -64,12 +64,33 @@ IdentifierHashData::IdentifierHashData(int numBits)
memset(entries, 0, alloc*sizeof(IdentifierHashEntry));
}
+IdentifierHashData::IdentifierHashData(IdentifierHashData *other)
+ : size(other->size)
+ , numBits(other->numBits)
+ , identifierTable(other->identifierTable)
+{
+ refCount.store(1);
+ alloc = other->alloc;
+ entries = (IdentifierHashEntry *)malloc(alloc*sizeof(IdentifierHashEntry));
+ memcpy(entries, other->entries, alloc*sizeof(IdentifierHashEntry));
+}
+
IdentifierHashBase::IdentifierHashBase(ExecutionEngine *engine)
{
d = new IdentifierHashData(3);
d->identifierTable = engine->identifierTable;
}
+void IdentifierHashBase::detach()
+{
+ if (!d || d->refCount == 1)
+ return;
+ IdentifierHashData *newData = new IdentifierHashData(d);
+ if (d && !d->refCount.deref())
+ delete d;
+ d = newData;
+}
+
IdentifierHashEntry *IdentifierHashBase::addEntry(const Identifier *identifier)
{
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index a3abfd8e13..2695bbc875 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -85,6 +85,7 @@ struct IdentifierHashEntry {
struct IdentifierHashData
{
IdentifierHashData(int numBits);
+ explicit IdentifierHashData(IdentifierHashData *other);
~IdentifierHashData() {
free(entries);
}
@@ -115,6 +116,8 @@ struct IdentifierHashBase
bool contains(const QString &str) const;
bool contains(String *str) const;
+ void detach();
+
protected:
IdentifierHashEntry *addEntry(const Identifier *i);
const IdentifierHashEntry *lookup(const Identifier *identifier) const;
@@ -141,6 +144,7 @@ struct IdentifierHash : public IdentifierHashBase
}
void add(const QString &str, const T &value);
+ void add(Heap::String *str, const T &value);
inline T value(const QString &str) const;
inline T value(String *str) const;
@@ -198,6 +202,13 @@ void IdentifierHash<T>::add(const QString &str, const T &value)
}
template<typename T>
+void IdentifierHash<T>::add(Heap::String *str, const T &value)
+{
+ IdentifierHashEntry *e = addEntry(toIdentifier(str));
+ e->value = value;
+}
+
+template<typename T>
inline T IdentifierHash<T>::value(const QString &str) const
{
return IdentifierHashEntry::get(lookup(str), (T*)0);
@@ -223,7 +234,6 @@ QString IdentifierHash<T>::findId(T value) const
return QString();
}
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4profiling.cpp b/src/qml/jsruntime/qv4profiling.cpp
index 72475c5416..349ec48e06 100644
--- a/src/qml/jsruntime/qv4profiling.cpp
+++ b/src/qml/jsruntime/qv4profiling.cpp
@@ -78,7 +78,8 @@ Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(
void Profiler::stopProfiling()
{
featuresEnabled = 0;
- reportData();
+ reportData(true);
+ m_sentLocations.clear();
}
bool operator<(const FunctionCall &call1, const FunctionCall &call2)
@@ -88,7 +89,7 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2)
(call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
}
-void Profiler::reportData()
+void Profiler::reportData(bool trackLocations)
{
std::sort(m_data.begin(), m_data.end());
QVector<FunctionCallProperties> properties;
@@ -97,9 +98,15 @@ void Profiler::reportData()
foreach (const FunctionCall &call, m_data) {
properties.append(call.properties());
- FunctionLocation &location = locations[properties.constLast().id];
- if (!location.isValid())
- location = call.resolveLocation();
+ Function *function = call.function();
+ SentMarker &marker = m_sentLocations[reinterpret_cast<quintptr>(function)];
+ if (!trackLocations || !marker.isValid()) {
+ FunctionLocation &location = locations[properties.constLast().id];
+ if (!location.isValid())
+ location = call.resolveLocation();
+ if (trackLocations)
+ marker.setFunction(function);
+ }
}
emit dataReady(locations, properties, m_memory_data);
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index bb128b7cf3..01fdf2951e 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -134,6 +134,11 @@ public:
return *this;
}
+ Function *function() const
+ {
+ return m_function;
+ }
+
FunctionLocation resolveLocation() const;
FunctionCallProperties properties() const;
@@ -165,6 +170,46 @@ class Q_QML_EXPORT Profiler : public QObject {
Q_OBJECT
Q_DISABLE_COPY(Profiler)
public:
+ struct SentMarker {
+ SentMarker() : m_function(nullptr) {}
+
+ SentMarker(const SentMarker &other) : m_function(other.m_function)
+ {
+ if (m_function)
+ m_function->compilationUnit->addref();
+ }
+
+ ~SentMarker()
+ {
+ if (m_function)
+ m_function->compilationUnit->release();
+ }
+
+ SentMarker &operator=(const SentMarker &other)
+ {
+ if (&other != this) {
+ if (m_function)
+ m_function->compilationUnit->release();
+ m_function = other.m_function;
+ m_function->compilationUnit->addref();
+ }
+ return *this;
+ }
+
+ void setFunction(Function *function)
+ {
+ Q_ASSERT(m_function == nullptr);
+ m_function = function;
+ m_function->compilationUnit->addref();
+ }
+
+ bool isValid() const
+ { return m_function != nullptr; }
+
+ private:
+ Function *m_function;
+ };
+
Profiler(QV4::ExecutionEngine *engine);
size_t trackAlloc(size_t size, MemoryType type)
@@ -186,7 +231,7 @@ public:
public slots:
void stopProfiling();
void startProfiling(quint64 features);
- void reportData();
+ void reportData(bool trackLocations);
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
signals:
@@ -199,6 +244,7 @@ private:
QElapsedTimer m_timer;
QVector<FunctionCall> m_data;
QVector<MemoryAllocationProperties> m_memory_data;
+ QHash<quintptr, SentMarker> m_sentLocations;
friend class FunctionCallProfiler;
};
@@ -237,6 +283,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QV4::Profiling::Profiler::SentMarker, Q_MOVABLE_TYPE);
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
diff --git a/src/qml/memory/qv4mm.cpp b/src/qml/memory/qv4mm.cpp
index fe94a11082..4fb2acebc5 100644
--- a/src/qml/memory/qv4mm.cpp
+++ b/src/qml/memory/qv4mm.cpp
@@ -68,7 +68,7 @@
#include <pthread_np.h>
#endif
-#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT (std::size_t)128*1024
+#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT std::size_t(128 * 1024)
using namespace WTF;
@@ -108,29 +108,20 @@ using namespace QV4;
struct MemoryManager::Data
{
+ const size_t pageSize;
+
struct ChunkHeader {
Heap::Base freeItems;
ChunkHeader *nextNonFull;
char *itemStart;
char *itemEnd;
- int itemSize;
+ unsigned itemSize;
};
- bool gcBlocked;
- bool aggressiveGC;
- bool gcStats;
ExecutionEngine *engine;
- enum { MaxItemSize = 512 };
- ChunkHeader *nonFullChunks[MaxItemSize/16];
- uint nChunks[MaxItemSize/16];
- uint availableItems[MaxItemSize/16];
- uint allocCount[MaxItemSize/16];
- int totalItems;
- int totalAlloc;
- uint maxShift;
std::size_t maxChunkSize;
- QVector<PageAllocation> heapChunks;
+ std::vector<PageAllocation> heapChunks;
std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
std::size_t unmanagedHeapSizeGCLimit;
@@ -147,24 +138,39 @@ struct MemoryManager::Data
LargeItem *largeItems;
std::size_t totalLargeItemsAllocated;
+ enum { MaxItemSize = 512 };
+ ChunkHeader *nonFullChunks[MaxItemSize/16];
+ uint nChunks[MaxItemSize/16];
+ uint availableItems[MaxItemSize/16];
+ uint allocCount[MaxItemSize/16];
+ int totalItems;
+ int totalAlloc;
+ uint maxShift;
+
+ bool gcBlocked;
+ bool aggressiveGC;
+ bool gcStats;
+ bool unused; // suppress padding warning
+
// statistics:
#ifdef DETAILED_MM_STATS
QVector<unsigned> allocSizeCounters;
#endif // DETAILED_MM_STATS
Data()
- : gcBlocked(false)
- , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
- , gcStats(!qEnvironmentVariableIsEmpty("QV4_MM_STATS"))
+ : pageSize(WTF::pageSize())
, engine(0)
- , totalItems(0)
- , totalAlloc(0)
- , maxShift(maxShiftValue())
, maxChunkSize(maxChunkSizeValue())
, unmanagedHeapSize(0)
, unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
, largeItems(0)
, totalLargeItemsAllocated(0)
+ , totalItems(0)
+ , totalAlloc(0)
+ , maxShift(maxShiftValue())
+ , gcBlocked(false)
+ , aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
+ , gcStats(!qEnvironmentVariableIsEmpty("QV4_MM_STATS"))
{
memset(nonFullChunks, 0, sizeof(nonFullChunks));
memset(nChunks, 0, sizeof(nChunks));
@@ -174,7 +180,7 @@ struct MemoryManager::Data
~Data()
{
- for (QVector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
+ for (std::vector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
i->deallocate();
}
@@ -198,7 +204,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
// qDebug("chunk @ %p, in use: %s, mark bit: %s",
// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false"));
- Q_ASSERT((qintptr) item % 16 == 0);
+ Q_ASSERT(qintptr(item) % 16 == 0);
if (m->isMarked()) {
Q_ASSERT(m->inUse());
@@ -324,14 +330,15 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
if (shift > m_d->maxShift)
shift = m_d->maxShift;
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
- allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
+ allocSize = roundUpToMultipleOf(m_d->pageSize, allocSize);
PageAllocation allocation = PageAllocation::allocate(
Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
- m_d->heapChunks.append(allocation);
+ m_d->heapChunks.push_back(allocation);
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
- header->itemSize = int(size);
+ Q_ASSERT(size <= UINT_MAX);
+ header->itemSize = unsigned(size);
header->itemStart = reinterpret_cast<char *>(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader));
header->itemEnd = reinterpret_cast<char *>(allocation.base()) + allocation.size() - header->itemSize;
@@ -347,7 +354,8 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
}
last->setNextFree(0);
m = header->freeItems.nextFree();
- const size_t increase = (header->itemEnd - header->itemStart) / header->itemSize;
+ Q_ASSERT(header->itemEnd >= header->itemStart);
+ const size_t increase = quintptr(header->itemEnd - header->itemStart) / header->itemSize;
m_d->availableItems[pos] += uint(increase);
m_d->totalItems += int(increase);
#ifdef V4_USE_VALGRIND
@@ -465,22 +473,23 @@ void MemoryManager::sweep(bool lastSweep)
}
}
- bool *chunkIsEmpty = (bool *)alloca(m_d->heapChunks.size() * sizeof(bool));
+ bool *chunkIsEmpty = static_cast<bool *>(alloca(m_d->heapChunks.size() * sizeof(bool)));
uint itemsInUse[MemoryManager::Data::MaxItemSize/16];
memset(itemsInUse, 0, sizeof(itemsInUse));
memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks));
- for (int i = 0; i < m_d->heapChunks.size(); ++i) {
+ for (size_t i = 0; i < m_d->heapChunks.size(); ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
}
- QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
- for (int i = 0; i < m_d->heapChunks.size(); ++i) {
+ std::vector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
+ for (size_t i = 0; i < m_d->heapChunks.size(); ++i) {
Q_ASSERT(chunkIter != m_d->heapChunks.end());
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(chunkIter->base());
const size_t pos = header->itemSize >> 4;
- const size_t decrease = (header->itemEnd - header->itemStart) / header->itemSize;
+ Q_ASSERT(header->itemEnd >= header->itemStart);
+ const size_t decrease = quintptr(header->itemEnd - header->itemStart) / header->itemSize;
// Release that chunk if it could have been spared since the last GC run without any difference.
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
@@ -561,7 +570,7 @@ void MemoryManager::runGC()
t.restart();
const size_t usedBefore = getUsedMem();
const size_t largeItemsBefore = getLargeItemsMem();
- int chunksBefore = m_d->heapChunks.size();
+ size_t chunksBefore = m_d->heapChunks.size();
sweep();
const size_t usedAfter = getUsedMem();
const size_t largeItemsAfter = getLargeItemsMem();
@@ -589,11 +598,11 @@ void MemoryManager::runGC()
size_t MemoryManager::getUsedMem() const
{
size_t usedMem = 0;
- for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
+ for (std::vector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
- Q_ASSERT((qintptr) item % 16 == 0);
+ Q_ASSERT(qintptr(item) % 16 == 0);
if (m->inUse())
usedMem += header->itemSize;
}
@@ -604,7 +613,7 @@ size_t MemoryManager::getUsedMem() const
size_t MemoryManager::getAllocatedMem() const
{
size_t total = 0;
- for (int i = 0; i < m_d->heapChunks.size(); ++i)
+ for (size_t i = 0; i < m_d->heapChunks.size(); ++i)
total += m_d->heapChunks.at(i).size();
return total;
}
diff --git a/src/qml/qml/qqmlcompileddata.cpp b/src/qml/qml/qqmlcompileddata.cpp
index 1037b5da51..b25792054c 100644
--- a/src/qml/qml/qqmlcompileddata.cpp
+++ b/src/qml/qml/qqmlcompileddata.cpp
@@ -55,8 +55,7 @@
QT_BEGIN_NAMESPACE
QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
-: engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false),
- totalBindingsCount(0), totalParserStatusCount(0)
+: engine(engine), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false)
{
Q_ASSERT(engine);
}
@@ -85,16 +84,6 @@ QQmlCompiledData::~QQmlCompiledData()
}
qDeleteAll(resolvedTypes);
resolvedTypes.clear();
-
- for (int ii = 0; ii < scripts.count(); ++ii)
- scripts.at(ii)->release();
-
- if (importCache)
- importCache->release();
-
- for (int ii = 0; ii < propertyCaches.count(); ++ii)
- if (propertyCaches.at(ii).data())
- propertyCaches.at(ii)->release();
}
void QQmlCompiledData::clear()
@@ -109,7 +98,7 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
if (type)
return typePropertyCache;
else
- return component->rootPropertyCache();
+ return component->compilationUnit->rootPropertyCache();
}
/*!
@@ -124,7 +113,7 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngi
typePropertyCache->addref();
return typePropertyCache;
} else {
- return component->rootPropertyCache();
+ return component->compilationUnit->rootPropertyCache();
}
}
@@ -146,7 +135,7 @@ void QQmlCompiledData::TypeReference::doDynamicTypeCheck()
else if (type)
mo = type->metaObject();
else if (component)
- mo = component->rootPropertyCache()->firstCppMetaObject();
+ mo = component->compilationUnit->rootPropertyCache()->firstCppMetaObject();
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
}
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index c2b244f5e3..2c9e04d5e0 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -80,10 +80,6 @@ class QQmlComponent;
class QQmlContext;
class QQmlContextData;
-// The vector is indexed by QV4::CompiledData::Object index and the flag
-// indicates whether instantiation of the object requires a VME meta-object.
-typedef QVector<QFlagPointer<QQmlPropertyCache>> QQmlPropertyCacheVector;
-
// ### Merge with QV4::CompiledData::CompilationUnit
class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
{
@@ -93,8 +89,6 @@ public:
QQmlEngine *engine;
- QQmlTypeNameCache *importCache;
-
int metaTypeId;
int listMetaTypeId;
bool isRegisteredWithEngine;
@@ -126,23 +120,7 @@ public:
// map from name index
QHash<int, TypeReference*> resolvedTypes;
- QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(compilationUnit->data->indexOfRootObject).data(); }
- QQmlPropertyCacheVector propertyCaches;
- QList<QQmlScriptData *> scripts;
-
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
- // index in first hash is component index, hash inside maps from object index in that scope to integer id
- QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
- QHash<int, int> objectIndexToIdForRoot;
- // hash key is object index, value is indicies of bindings covered by custom parser
- QHash<int, QBitArray> customParserBindings;
- QHash<int, QBitArray> deferredBindingsPerObject; // index is object index
- int totalBindingsCount; // Number of bindings used in this type
- int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
- int totalObjectCount; // Number of objects explicitly instantiated
-
- bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
- bool isCompositeType() const { return propertyCaches.at(compilationUnit->data->indexOfRootObject).flag(); }
bool isInitialized() const { return hasEngine(); }
void initialize(QQmlEngine *);
diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp
index af06405376..b3081ddbe6 100644
--- a/src/qml/qml/qqmlcontext.cpp
+++ b/src/qml/qml/qqmlcontext.cpp
@@ -310,7 +310,7 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
}
}
- QV4::IdentifierHash<int> &properties = data->propertyNames();
+ QV4::IdentifierHash<int> &properties = data->detachedPropertyNames();
int idx = properties.value(name);
if (idx == -1) {
properties.add(name, data->idValueCount + d->propertyValues.count());
@@ -346,7 +346,7 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value)
return;
}
- QV4::IdentifierHash<int> &properties = data->propertyNames();
+ QV4::IdentifierHash<int> &properties = data->detachedPropertyNames();
int idx = properties.value(name);
if (idx == -1) {
@@ -523,7 +523,7 @@ QQmlContextData::QQmlContextData()
QQmlContextData::QQmlContextData(QQmlContext *ctxt)
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
- publicContext(ctxt), activeVMEData(0),
+ publicContext(ctxt), activeVMEData(0), componentObjectIndex(-1),
contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
componentAttached(0)
@@ -760,15 +760,6 @@ void QQmlContextData::setIdProperty(int idx, QObject *obj)
idValues[idx].context = this;
}
-void QQmlContextData::setIdPropertyData(const QHash<int, int> &data)
-{
- Q_ASSERT(objectIndexToId.isEmpty());
- objectIndexToId = data;
- Q_ASSERT(propertyNameCache.isEmpty());
- idValueCount = data.count();
- idValues = new ContextGuard[idValueCount];
-}
-
QString QQmlContextData::findObjectId(const QObject *obj) const
{
const QV4::IdentifierHash<int> &properties = propertyNames();
@@ -804,21 +795,33 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
return QQmlContextPrivate::get(asQQmlContext());
}
-QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
+void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex)
+{
+ typeCompilationUnit = unit;
+ componentObjectIndex = subComponentIndex == -1 ? typeCompilationUnit->data->indexOfRootObject : subComponentIndex;
+ Q_ASSERT(!idValues);
+ idValueCount = typeCompilationUnit->data->objectAt(componentObjectIndex)->nNamedObjectsInComponent;
+ idValues = new ContextGuard[idValueCount];
+}
+
+const QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
{
if (propertyNameCache.isEmpty()) {
- propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
- for (QHash<int, int>::ConstIterator it = objectIndexToId.cbegin(), end = objectIndexToId.cend();
- it != end; ++it) {
- const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key());
- const QString name = typeCompilationUnit->data->stringAt(obj->idIndex);
- propertyNameCache.add(name, it.value());
- }
- objectIndexToId.clear();
+ if (typeCompilationUnit)
+ propertyNameCache = typeCompilationUnit->namedObjectsPerComponent(componentObjectIndex);
+ else
+ propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine));
}
return propertyNameCache;
}
+QV4::IdentifierHash<int> &QQmlContextData::detachedPropertyNames()
+{
+ propertyNames();
+ propertyNameCache.detach();
+ return propertyNameCache;
+}
+
QUrl QQmlContextData::url() const
{
if (typeCompilationUnit)
diff --git a/src/qml/qml/qqmlcontext_p.h b/src/qml/qml/qqmlcontext_p.h
index 48d596418d..05ce39401e 100644
--- a/src/qml/qml/qqmlcontext_p.h
+++ b/src/qml/qml/qqmlcontext_p.h
@@ -151,9 +151,15 @@ public:
// Compilation unit for contexts that belong to a compiled type.
QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit;
- mutable QHash<int, int> objectIndexToId;
+ // object index in CompiledData::Unit to component that created this context
+ int componentObjectIndex;
+
+ void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex);
+
+ // flag indicates whether the context owns the cache (after mutation) or not.
mutable QV4::IdentifierHash<int> propertyNameCache;
- QV4::IdentifierHash<int> &propertyNames() const;
+ const QV4::IdentifierHash<int> &propertyNames() const;
+ QV4::IdentifierHash<int> &detachedPropertyNames();
// Context object
QObject *contextObject;
@@ -201,7 +207,6 @@ public:
ContextGuard *idValues;
int idValueCount;
void setIdProperty(int, QObject *);
- void setIdPropertyData(const QHash<int, int> &);
// Linked contexts. this owns linkedContext.
QQmlContextData *linkedContext;
diff --git a/src/qml/qml/qqmlcustomparser_p.h b/src/qml/qml/qqmlcustomparser_p.h
index d8e25c55fd..9aa052c1ad 100644
--- a/src/qml/qml/qqmlcustomparser_p.h
+++ b/src/qml/qml/qqmlcustomparser_p.h
@@ -82,7 +82,7 @@ public:
Flags flags() const { return m_flags; }
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) = 0;
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
QList<QQmlError> errors() const { return exceptions; }
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 2baca619cc..fd1795499e 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -2227,7 +2227,7 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
Locker locker(this);
QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->rootPropertyCache());
+ return QQmlMetaObject((*iter)->compilationUnit->rootPropertyCache());
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type?type->baseMetaObject():0);
@@ -2239,7 +2239,7 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
Locker locker(this);
QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return QQmlMetaObject((*iter)->rootPropertyCache());
+ return QQmlMetaObject((*iter)->compilationUnit->rootPropertyCache());
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
return QQmlMetaObject(type?type->metaObject():0);
@@ -2251,7 +2251,7 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
Locker locker(this);
QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->rootPropertyCache();
+ return (*iter)->compilationUnit->rootPropertyCache();
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
locker.unlock();
@@ -2264,7 +2264,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
Locker locker(this);
QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
if (iter != m_compositeTypes.cend()) {
- return (*iter)->rootPropertyCache();
+ return (*iter)->compilationUnit->rootPropertyCache();
} else {
QQmlType *type = QQmlMetaType::qmlType(t);
locker.unlock();
@@ -2274,7 +2274,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
{
- QByteArray name = data->rootPropertyCache()->className();
+ QByteArray name = data->compilationUnit->rootPropertyCache()->className();
QByteArray ptr = name + '*';
QByteArray lst = "QQmlListProperty<" + name + '>';
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index f3f4c41775..1b3997baae 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -494,7 +494,7 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
if (!td || !td->isComplete())
return 0;
QQmlCompiledData *cd = td->compiledData();
- const QMetaObject *mo = cd->rootPropertyCache()->firstCppMetaObject();
+ const QMetaObject *mo = cd->compilationUnit->rootPropertyCache()->firstCppMetaObject();
return QQmlMetaType::qmlType(mo);
}
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 86693af3d3..dcd35bccad 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -73,7 +73,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
: phase(Startup)
, compiledData(compiledData)
, resolvedTypes(compiledData->resolvedTypes)
- , propertyCaches(compiledData->propertyCaches)
+ , propertyCaches(compiledData->compilationUnit->propertyCaches)
, activeVMEDataForRootContext(activeVMEDataForRootContext)
{
init(parentContext);
@@ -81,23 +81,23 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
sharedState = new QQmlObjectCreatorSharedState;
topLevelCreator = true;
sharedState->componentAttached = 0;
- sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
- sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
- sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount);
+ sharedState->allCreatedBindings.allocate(compiledData->compilationUnit->totalBindingsCount);
+ sharedState->allParserStatusCallbacks.allocate(compiledData->compilationUnit->totalParserStatusCount);
+ sharedState->allCreatedObjects.allocate(compiledData->compilationUnit->totalObjectCount);
sharedState->allJavaScriptObjects = 0;
sharedState->creationContext = creationContext;
sharedState->rootContext = 0;
QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
- sharedState->profiler.init(profiler, compiledData->totalParserStatusCount));
+ sharedState->profiler.init(profiler, compiledData->compilationUnit->totalParserStatusCount));
}
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
: phase(Startup)
, compiledData(compiledData)
, resolvedTypes(compiledData->resolvedTypes)
- , propertyCaches(compiledData->propertyCaches)
+ , propertyCaches(compiledData->compilationUnit->propertyCaches)
, activeVMEDataForRootContext(0)
{
init(parentContext);
@@ -158,19 +158,17 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
int objectToCreate;
if (subComponentIndex == -1) {
- objectIndexToId = compiledData->objectIndexToIdForRoot;
objectToCreate = qmlUnit->indexOfRootObject;
} else {
- objectIndexToId = compiledData->objectIndexToIdPerComponent[subComponentIndex];
const QV4::CompiledData::Object *compObj = qmlUnit->objectAt(subComponentIndex);
objectToCreate = compObj->bindingTable()->value.objectIndex;
}
context = new QQmlContextData;
context->isInternal = true;
- context->imports = compiledData->importCache;
+ context->imports = compiledData->compilationUnit->importCache;
context->imports->addref();
- context->typeCompilationUnit = compiledData->compilationUnit;
+ context->initFromTypeCompilationUnit(compiledData->compilationUnit, subComponentIndex);
context->setParent(parentContext);
if (!sharedState->rootContext) {
@@ -183,16 +181,14 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
if (topLevelCreator)
- sharedState->allJavaScriptObjects = scope.alloc(compiledData->totalObjectCount);
+ sharedState->allJavaScriptObjects = scope.alloc(compiledData->compilationUnit->totalObjectCount);
- context->setIdPropertyData(objectIndexToId);
-
- if (subComponentIndex == -1 && compiledData->scripts.count()) {
- QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
+ if (subComponentIndex == -1 && compiledData->compilationUnit->dependentScripts.count()) {
+ QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->compilationUnit->dependentScripts.count()));
context->importedScripts.set(v4, scripts);
QV4::ScopedValue v(scope);
- for (int i = 0; i < compiledData->scripts.count(); ++i) {
- QQmlScriptData *s = compiledData->scripts.at(i);
+ for (int i = 0; i < compiledData->compilationUnit->dependentScripts.count(); ++i) {
+ QQmlScriptData *s = compiledData->compilationUnit->dependentScripts.at(i);
scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
}
} else if (sharedState->creationContext) {
@@ -240,7 +236,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
Q_ASSERT(topLevelCreator);
Q_ASSERT(!sharedState->allJavaScriptObjects);
- sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount);
+ sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->compilationUnit->totalObjectCount);
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
@@ -259,11 +255,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
qSwap(_bindingTarget, bindingTarget);
qSwap(_vmeMetaObject, vmeMetaObject);
- QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(_compiledObjectIndex);
- for (int i = 0; i < bindingSkipList.count(); ++i)
- bindingSkipList.setBit(i, !bindingSkipList.testBit(i));
-
- setupBindings(bindingSkipList);
+ setupBindings(/*applyDeferredBindings=*/true);
qSwap(_vmeMetaObject, vmeMetaObject);
qSwap(_bindingTarget, bindingTarget);
@@ -630,14 +622,14 @@ static QQmlType *qmlTypeForObject(QObject *object)
return type;
}
-void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
+void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
{
QQmlListProperty<void> savedList;
qSwap(_currentList, savedList);
const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
- if (_compiledObject->idIndex) {
+ if (_compiledObject->idNameIndex) {
const QQmlPropertyData *idProperty = propertyData.last();
Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
@@ -645,7 +637,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
idBinding.propertyNameIndex = 0; // Not used
idBinding.flags = 0;
idBinding.type = QV4::CompiledData::Binding::Type_String;
- idBinding.stringIndex = _compiledObject->idIndex;
+ idBinding.stringIndex = _compiledObject->idNameIndex;
idBinding.location = _compiledObject->location; // ###
setPropertyValue(idProperty, &idBinding);
}
@@ -681,9 +673,17 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
- if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i))
+ if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding)
continue;
+ if (binding->flags & QV4::CompiledData::Binding::IsDeferredBinding) {
+ if (!applyDeferredBindings)
+ continue;
+ } else {
+ if (applyDeferredBindings)
+ continue;
+ }
+
const QQmlPropertyData *property = propertyData.at(i);
if (property && property->isQList()) {
@@ -1005,11 +1005,10 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
errors << error;
}
-void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject *instance) const
+void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const
{
- QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(objectIndex);
- if (idEntry != objectIndexToId.constEnd())
- context->setIdProperty(idEntry.value(), instance);
+ if (object->id >= 0)
+ context->setIdProperty(object->id, instance);
}
QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
@@ -1022,7 +1021,9 @@ QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
{
- QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
+ QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
+
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
bool isComponent = false;
@@ -1032,8 +1033,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
QQmlParserStatus *parserStatus = 0;
bool installPropertyCache = true;
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
- if (compiledData->isComponent(index)) {
+ if (obj->flags & QV4::CompiledData::Object::IsComponent) {
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
@@ -1125,28 +1125,26 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (isContextObject)
context->contextObject = instance;
- QBitArray bindingsToSkip;
- if (customParser) {
- QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index);
- if (customParserBindings != compiledData->customParserBindings.constEnd()) {
- customParser->engine = QQmlEnginePrivate::get(engine);
- customParser->imports = compiledData->importCache;
-
- QList<const QV4::CompiledData::Binding *> bindings;
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
- for (int i = 0; i < customParserBindings->count(); ++i)
- if (customParserBindings->testBit(i))
- bindings << obj->bindingTable() + i;
- customParser->applyBindings(instance, compiledData, bindings);
-
- customParser->engine = 0;
- customParser->imports = (QQmlTypeNameCache*)0;
- bindingsToSkip = *customParserBindings;
+ if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
+ customParser->engine = QQmlEnginePrivate::get(engine);
+ customParser->imports = compiledData->compilationUnit->importCache;
+
+ QList<const QV4::CompiledData::Binding *> bindings;
+ const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
+ const QV4::CompiledData::Binding *binding = obj->bindingTable();
+ for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
+ if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding) {
+ bindings << binding;
+ }
}
+ customParser->applyBindings(instance, compiledData->compilationUnit.data(), bindings);
+
+ customParser->engine = 0;
+ customParser->imports = (QQmlTypeNameCache*)0;
}
if (isComponent) {
- registerObjectWithContextById(index, instance);
+ registerObjectWithContextById(obj, instance);
return instance;
}
@@ -1171,7 +1169,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
qSwap(_qmlContext, qmlContext);
- bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0, bindingsToSkip);
+ bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0);
qSwap(_qmlContext, qmlContext);
qSwap(_scopeObject, scopeObject);
@@ -1266,7 +1264,7 @@ void QQmlObjectCreator::clear()
phase = Done;
}
-bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
+bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty)
{
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
@@ -1298,33 +1296,23 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
}
- registerObjectWithContextById(_compiledObjectIndex, _qobject);
+ registerObjectWithContextById(_compiledObject, _qobject);
qSwap(_propertyCache, cache);
qSwap(_vmeMetaObject, vmeMetaObject);
- QBitArray bindingSkipList = bindingsToSkip;
- {
- QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.constFind(_compiledObjectIndex);
- if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
- if (bindingSkipList.isEmpty())
- bindingSkipList.resize(deferredBindings->count());
-
- for (int i = 0; i < deferredBindings->count(); ++i)
- if (deferredBindings->testBit(i))
- bindingSkipList.setBit(i);
- QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
- deferData->deferredIdx = _compiledObjectIndex;
- deferData->compiledData = compiledData;
- deferData->compiledData->addref();
- deferData->context = context;
- _ddata->deferredData = deferData;
- }
+ if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) {
+ QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
+ deferData->deferredIdx = _compiledObjectIndex;
+ deferData->compiledData = compiledData;
+ deferData->compiledData->addref();
+ deferData->context = context;
+ _ddata->deferredData = deferData;
}
if (_compiledObject->nFunctions > 0)
setupFunctions();
- setupBindings(bindingSkipList);
+ setupBindings();
qSwap(_vmeMetaObject, vmeMetaObject);
qSwap(_bindingTarget, bindingTarget);
diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h
index 8045281cbb..f51cf3a2ca 100644
--- a/src/qml/qml/qqmlobjectcreator_p.h
+++ b/src/qml/qml/qqmlobjectcreator_p.h
@@ -111,10 +111,9 @@ private:
QObject *createInstance(int index, QObject *parent = 0, bool isContextObject = false);
bool populateInstance(int index, QObject *instance,
- QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty,
- const QBitArray &bindingsToSkip = QBitArray());
+ QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty);
- void setupBindings(const QBitArray &bindingsToSkip);
+ void setupBindings(bool applyDeferredBindings = false);
bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
void setupFunctions();
@@ -122,7 +121,7 @@ private:
QString stringAt(int idx) const { return qmlUnit->stringAt(idx); }
void recordError(const QV4::CompiledData::Location &location, const QString &description);
- void registerObjectWithContextById(int objectIndex, QObject *instance) const;
+ void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
QV4::Heap::QmlContext *currentQmlContext();
@@ -143,7 +142,6 @@ private:
QQmlContextData *context;
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
const QQmlPropertyCacheVector &propertyCaches;
- QHash<int, int> objectIndexToId;
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
bool topLevelCreator;
void *activeVMEDataForRootContext;
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index 4ac13d1cb4..08d51ecfa1 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -452,7 +452,12 @@ QQmlPropertyCache *QQmlPropertyCache::parent() const
void QQmlPropertyCache::setParent(QQmlPropertyCache *newParent)
{
+ if (_parent == newParent)
+ return;
+ if (_parent)
+ _parent->release();
_parent = newParent;
+ _parent->addref();
}
// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp
index a16acac3ab..6f7f13823e 100644
--- a/src/qml/types/qqmlconnections.cpp
+++ b/src/qml/types/qqmlconnections.cpp
@@ -67,7 +67,7 @@ public:
bool ignoreUnknownSignals;
bool componentcomplete;
- QQmlRefPointer<QQmlCompiledData> cdata;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QList<const QV4::CompiledData::Binding *> bindings;
};
@@ -258,11 +258,11 @@ void QQmlConnectionsParser::verifyBindings(const QV4::CompiledData::Unit *qmlUni
}
}
-void QQmlConnectionsParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQmlConnectionsParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQmlConnectionsPrivate *p =
static_cast<QQmlConnectionsPrivate *>(QObjectPrivate::get(object));
- p->cdata = cdata;
+ p->compilationUnit = compilationUnit;
p->bindings = bindings;
}
@@ -278,7 +278,7 @@ void QQmlConnections::connectSignals()
QQmlData *ddata = QQmlData::get(this);
QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0;
- const QV4::CompiledData::Unit *qmlUnit = d->cdata->compilationUnit->data;
+ const QV4::CompiledData::Unit *qmlUnit = d->compilationUnit->data;
foreach (const QV4::CompiledData::Binding *binding, d->bindings) {
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
QString propName = qmlUnit->stringAt(binding->propertyNameIndex);
@@ -291,7 +291,7 @@ void QQmlConnections::connectSignals()
QQmlBoundSignalExpression *expression = ctxtdata ?
new QQmlBoundSignalExpression(target, signalIndex,
- ctxtdata, this, d->cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
+ ctxtdata, this, d->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
signal->takeExpression(expression);
d->boundsignals += signal;
} else {
diff --git a/src/qml/types/qqmlconnections_p.h b/src/qml/types/qqmlconnections_p.h
index ff128a0ca6..d454affba8 100644
--- a/src/qml/types/qqmlconnections_p.h
+++ b/src/qml/types/qqmlconnections_p.h
@@ -99,7 +99,7 @@ class QQmlConnectionsParser : public QQmlCustomParser
{
public:
virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
- virtual void applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings);
+ virtual void applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
};
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index 9cbda4516e..69066d1c69 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -2401,7 +2401,7 @@ bool QQmlListModelParser::verifyProperty(const QV4::CompiledData::Unit *qmlUnit,
listElementTypeName = objName; // cache right name for next time
}
- if (!qmlUnit->stringAt(target->idIndex).isEmpty()) {
+ if (!qmlUnit->stringAt(target->idNameIndex).isEmpty()) {
error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
return false;
}
@@ -2508,13 +2508,13 @@ void QQmlListModelParser::verifyBindings(const QV4::CompiledData::Unit *qmlUnit,
}
}
-void QQmlListModelParser::applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQmlListModelParser::applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
rv->m_engine = QV8Engine::getV4(qmlEngine(rv));
- const QV4::CompiledData::Unit *qmlUnit = cdata->compilationUnit->data;
+ const QV4::CompiledData::Unit *qmlUnit = compilationUnit->data;
bool setRoles = false;
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index e71b1e24b8..220b0e54b5 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -188,7 +188,7 @@ public:
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
- void applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
+ void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
private:
bool verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
diff --git a/src/qmldebug/qqmlprofilerclient.cpp b/src/qmldebug/qqmlprofilerclient.cpp
index 6f6b04ade9..29ccbb33b6 100644
--- a/src/qmldebug/qqmlprofilerclient.cpp
+++ b/src/qmldebug/qqmlprofilerclient.cpp
@@ -70,7 +70,7 @@ void QQmlProfilerClient::sendRecordingStatus(bool record, int engineId, quint32
Q_D(const QQmlProfilerClient);
QPacket stream(d->connection->currentDataStreamVersion());
- stream << record << engineId << d->features << flushInterval;
+ stream << record << engineId << d->features << flushInterval << true;
sendMessage(stream.data());
}
@@ -205,7 +205,7 @@ inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
void QQmlProfilerClient::messageReceived(const QByteArray &data)
{
- Q_D(const QQmlProfilerClient);
+ Q_D(QQmlProfilerClient);
QPacket stream(d->connection->currentDataStreamVersion(), data);
@@ -333,12 +333,25 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
!(d->features & one << featureFromRangeType(rangeType)))
return;
+ qint64 typeId = 0;
if (messageType == QQmlProfilerDefinitions::RangeStart) {
rangeStart(rangeType, time);
+ if (!stream.atEnd()) {
+ stream >> typeId;
+ auto i = d->types.constFind(typeId);
+ if (i != d->types.constEnd()) {
+ rangeLocation(rangeType, time, i->location);
+ rangeData(rangeType, time, i->name);
+ }
+ }
} else if (messageType == QQmlProfilerDefinitions::RangeData) {
QString data;
stream >> data;
rangeData(rangeType, time, data);
+ if (!stream.atEnd()) {
+ stream >> typeId;
+ d->types[typeId].name = data;
+ }
} else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
QQmlEventLocation location;
stream >> location.filename >> location.line;
@@ -347,6 +360,10 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
stream >> location.column;
rangeLocation(rangeType, time, location);
+ if (!stream.atEnd()) {
+ stream >> typeId;
+ d->types[typeId].location = location;
+ }
} else if (messageType == QQmlProfilerDefinitions::RangeEnd) {
rangeEnd(rangeType, time);
} else {
diff --git a/src/qmldebug/qqmlprofilerclient_p_p.h b/src/qmldebug/qqmlprofilerclient_p_p.h
index 8238c97dd8..9c44113aa8 100644
--- a/src/qmldebug/qqmlprofilerclient_p_p.h
+++ b/src/qmldebug/qqmlprofilerclient_p_p.h
@@ -56,12 +56,20 @@
QT_BEGIN_NAMESPACE
+struct QQmlProfilerRangeType
+{
+ QQmlEventLocation location;
+ QString name;
+};
+
class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
{
Q_DECLARE_PUBLIC(QQmlProfilerClient)
public:
QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
quint64 features;
+
+ QHash<qint64, QQmlProfilerRangeType> types;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 5061c19f1e..14c0adf393 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -415,4 +415,26 @@ Item {
\endqml
*/
+/*!
+ \qmlproperty int QtQuick::WheelEvent::inverted
+
+ Returns whether the delta values delivered with the event are inverted.
+
+ Normally, a vertical wheel will produce a WheelEvent with positive delta
+ values if the top of the wheel is rotating away from the hand operating it.
+ Similarly, a horizontal wheel movement will produce a QWheelEvent with
+ positive delta values if the top of the wheel is moved to the left.
+
+ However, on some platforms this is configurable, so that the same
+ operations described above will produce negative delta values (but with the
+ same magnitude). For instance, in a QML component (such as a tumbler or a
+ slider) where it is appropriate to synchronize the movement or rotation of
+ an item with the direction of the wheel, regardless of the system settings,
+ the wheel event handler can use the inverted property to decide whether to
+ negate the angleDelta or pixelDelta values.
+
+ \note Many platforms provide no such information. On such platforms
+ \l inverted always returns false.
+*/
+
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index b28ab555b0..6d4b49b3cd 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -73,10 +73,22 @@ class QQuickKeyEvent : public QObject
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
public:
- QQuickKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
- : event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
- QQuickKeyEvent(const QKeyEvent &ke)
- : event(ke) { event.setAccepted(false); }
+ QQuickKeyEvent()
+ : event(QEvent::None, 0, 0)
+ {}
+
+ void reset(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+ const QString &text = QString(), bool autorep = false, ushort count = 1)
+ {
+ event = QKeyEvent(type, key, modifiers, text, autorep, count);
+ event.setAccepted(false);
+ }
+
+ void reset(const QKeyEvent &ke)
+ {
+ event = ke;
+ event.setAccepted(false);
+ }
int key() const { return event.key(); }
QString text() const { return event.text(); }
@@ -109,10 +121,21 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseEvent : public QObject
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
public:
- QQuickMouseEvent(qreal x, qreal y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
- , bool isClick=false, bool wasHeld=false)
- : _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
- , _source(Qt::MouseEventNotSynthesized), _wasHeld(wasHeld), _isClick(isClick), _accepted(true) {}
+ QQuickMouseEvent() {}
+
+ void reset(qreal x, qreal y, Qt::MouseButton button, Qt::MouseButtons buttons,
+ Qt::KeyboardModifiers modifiers, bool isClick = false, bool wasHeld = false)
+ {
+ _x = x;
+ _y = y;
+ _button = button;
+ _buttons = buttons;
+ _modifiers = modifiers;
+ _source = Qt::MouseEventNotSynthesized;
+ _wasHeld = wasHeld;
+ _isClick = isClick;
+ _accepted = true;
+ }
qreal x() const { return _x; }
qreal y() const { return _y; }
@@ -139,9 +162,9 @@ private:
Qt::MouseButtons _buttons;
Qt::KeyboardModifiers _modifiers;
Qt::MouseEventSource _source;
- bool _wasHeld;
- bool _isClick;
- bool _accepted;
+ bool _wasHeld : 1;
+ bool _isClick : 1;
+ bool _accepted : 1;
};
class QQuickWheelEvent : public QObject
@@ -153,13 +176,24 @@ class QQuickWheelEvent : public QObject
Q_PROPERTY(QPoint pixelDelta READ pixelDelta)
Q_PROPERTY(int buttons READ buttons)
Q_PROPERTY(int modifiers READ modifiers)
+ Q_PROPERTY(bool inverted READ inverted)
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
public:
- QQuickWheelEvent(qreal x, qreal y, const QPoint& angleDelta, const QPoint& pixelDelta,
- Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
- : _x(x), _y(y), _angleDelta(angleDelta), _pixelDelta(pixelDelta), _buttons(buttons),
- _modifiers(modifiers), _accepted(true) {}
+ QQuickWheelEvent() {}
+
+ void reset(qreal x, qreal y, const QPoint &angleDelta, const QPoint &pixelDelta,
+ Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, bool inverted)
+ {
+ _x = x;
+ _y = y;
+ _angleDelta = angleDelta;
+ _pixelDelta = pixelDelta;
+ _buttons = buttons;
+ _modifiers = modifiers;
+ _accepted = true;
+ _inverted = inverted;
+ }
qreal x() const { return _x; }
qreal y() const { return _y; }
@@ -167,7 +201,7 @@ public:
QPoint pixelDelta() const { return _pixelDelta; }
int buttons() const { return _buttons; }
int modifiers() const { return _modifiers; }
-
+ bool inverted() const { return _inverted; }
bool isAccepted() { return _accepted; }
void setAccepted(bool accepted) { _accepted = accepted; }
@@ -178,6 +212,7 @@ private:
QPoint _pixelDelta;
Qt::MouseButtons _buttons;
Qt::KeyboardModifiers _modifiers;
+ bool _inverted;
bool _accepted;
};
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index d0d10a5849..9a13198d7d 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -1355,7 +1355,8 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
d->inPress = false;
}
- QQuickKeyEvent ke(*event);
+ QQuickKeyEvent &ke = d->theKeyEvent;
+ ke.reset(*event);
QByteArray keySignal = keyToSignal(event->key());
if (!keySignal.isEmpty()) {
keySignal += "(QQuickKeyEvent*)";
@@ -1398,7 +1399,8 @@ void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
d->inRelease = false;
}
- QQuickKeyEvent ke(*event);
+ QQuickKeyEvent &ke = d->theKeyEvent;
+ ke.reset(*event);
emit released(&ke);
event->setAccepted(ke.isAccepted());
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 846063a58b..477071f7b3 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -56,6 +56,7 @@
#include "qquickanchors_p.h"
#include "qquickanchors_p_p.h"
#include "qquickitemchangelistener_p.h"
+#include "qquickevents_p_p.h"
#include "qquickwindow_p.h"
@@ -777,6 +778,7 @@ public:
QQuickItem *imeItem;
QList<QQuickItem *> targets;
QQuickItem *item;
+ QQuickKeyEvent theKeyEvent;
};
class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp
index 920a86881b..66aff5c2f4 100644
--- a/src/quick/items/qquickmousearea.cpp
+++ b/src/quick/items/qquickmousearea.cpp
@@ -40,7 +40,6 @@
#include "qquickmousearea_p.h"
#include "qquickmousearea_p_p.h"
#include "qquickwindow.h"
-#include "qquickevents_p_p.h"
#include "qquickdrag_p.h"
#include <private/qqmldata_p.h>
@@ -761,7 +760,8 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
}
#endif
- QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ QQuickMouseEvent &me = d->quickMouseEvent;
+ me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
me.setSource(event->source());
emit mouseXChanged(&me);
me.setPosition(d->lastPos);
@@ -802,7 +802,8 @@ void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
Q_D(QQuickMouseArea);
if (d->enabled) {
d->saveEvent(event);
- QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
+ QQuickMouseEvent &me = d->quickMouseEvent;
+ me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
me.setSource(event->source());
me.setAccepted(d->isDoubleClickConnected());
emit this->doubleClicked(&me);
@@ -822,7 +823,8 @@ void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
d->lastPos = event->posF();
d->lastModifiers = event->modifiers();
setHovered(true);
- QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
+ QQuickMouseEvent &me = d->quickMouseEvent;
+ me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
emit mouseXChanged(&me);
me.setPosition(d->lastPos);
emit mouseYChanged(&me);
@@ -835,10 +837,11 @@ void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
Q_D(QQuickMouseArea);
if (!d->enabled && !d->pressed) {
QQuickItem::hoverMoveEvent(event);
- } else {
+ } else if (d->lastPos != event->posF()) {
d->lastPos = event->posF();
d->lastModifiers = event->modifiers();
- QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
+ QQuickMouseEvent &me = d->quickMouseEvent;
+ me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
emit mouseXChanged(&me);
me.setPosition(d->lastPos);
emit mouseYChanged(&me);
@@ -865,8 +868,9 @@ void QQuickMouseArea::wheelEvent(QWheelEvent *event)
return;
}
- QQuickWheelEvent we(event->posF().x(), event->posF().y(), event->angleDelta(),
- event->pixelDelta(), event->buttons(), event->modifiers());
+ QQuickWheelEvent &we = d->quickWheelEvent;
+ we.reset(event->posF().x(), event->posF().y(), event->angleDelta(), event->pixelDelta(),
+ event->buttons(), event->modifiers(), event->inverted());
we.setAccepted(d->isWheelConnected());
emit wheel(&we);
if (!we.isAccepted())
@@ -997,7 +1001,8 @@ void QQuickMouseArea::timerEvent(QTimerEvent *event)
#endif
if (d->pressed && dragged == false && d->hovered == true) {
d->longPress = true;
- QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
+ QQuickMouseEvent &me = d->quickMouseEvent;
+ me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
me.setSource(Qt::MouseEventSynthesizedByQt);
me.setAccepted(d->isPressAndHoldConnected());
emit pressAndHold(&me);
@@ -1078,8 +1083,7 @@ void QQuickMouseArea::setHoverEnabled(bool h)
\qmlproperty bool QtQuick::MouseArea::containsMouse
This property holds whether the mouse is currently inside the mouse area.
- \warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
- In addition, if hoverEnabled is false, containsMouse will only be valid
+ \warning If hoverEnabled is false, containsMouse will only be valid
when the mouse is pressed while the mouse cursor is inside the MouseArea.
*/
bool QQuickMouseArea::hovered() const
@@ -1175,7 +1179,8 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
Qt::MouseButtons oldPressed = d->pressed;
if (wasPressed != p) {
- QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
+ QQuickMouseEvent &me = d->quickMouseEvent;
+ me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
me.setSource(source);
if (p) {
d->pressed |= button;
diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h
index 2d841b9ae1..794a8cc6ff 100644
--- a/src/quick/items/qquickmousearea_p_p.h
+++ b/src/quick/items/qquickmousearea_p_p.h
@@ -52,6 +52,7 @@
//
#include "qquickitem_p.h"
+#include "qquickevents_p_p.h"
#include <QtGui/qevent.h>
#include <QtCore/qbasictimer.h>
@@ -107,6 +108,8 @@ public:
#ifndef QT_NO_CURSOR
QCursor *cursor;
#endif
+ QQuickMouseEvent quickMouseEvent;
+ QQuickWheelEvent quickWheelEvent;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickopenglshadereffectnode.cpp b/src/quick/items/qquickopenglshadereffectnode.cpp
index c4dd8d5c63..02b76b2dbc 100644
--- a/src/quick/items/qquickopenglshadereffectnode.cpp
+++ b/src/quick/items/qquickopenglshadereffectnode.cpp
@@ -456,7 +456,7 @@ void QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache()
{
QQuickOpenGLShaderEffectMaterialCache *cache = QQuickOpenGLShaderEffectMaterialCache::get(false);
if (cache) {
- qDeleteAll(cache->cache.values());
+ qDeleteAll(cache->cache);
delete cache;
}
}
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index ec9a104812..dbe1add345 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -254,7 +254,7 @@ void QQuickRenderControl::polishItems()
return;
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
- cd->flushDelayedTouchEvent();
+ cd->flushFrameSynchronousEvents();
if (!d->window)
return;
cd->polishItems();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index b9fb0721b3..6333bf704a 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2028,7 +2028,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
}
}
-void QQuickWindowPrivate::flushDelayedTouchEvent()
+void QQuickWindowPrivate::flushFrameSynchronousEvents()
{
if (delayedTouch) {
deliverDelayedTouchEvent();
@@ -2039,6 +2039,17 @@ void QQuickWindowPrivate::flushDelayedTouchEvent()
if (ut && ut->hasStartAnimationPending())
ut->startAnimations();
}
+
+ // Once per frame, send a synthetic hover, in case items have changed position.
+ // For instance, during animation (including the case of a ListView
+ // whose delegates contain MouseAreas), a MouseArea needs to know
+ // whether it has moved into a position where it is now under the cursor.
+ if (!mouseGrabberItem && !lastMousePosition.isNull()) {
+ bool accepted = false;
+ bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), accepted);
+ if (!delivered)
+ clearHover(); // take care of any exits
+ }
}
void QQuickWindowPrivate::reallyDeliverTouchEvent(QTouchEvent *event)
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 1486e20e1e..daff9ef473 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -160,7 +160,7 @@ public:
void reallyDeliverTouchEvent(QTouchEvent *);
bool deliverTouchCancelEvent(QTouchEvent *);
void deliverDelayedTouchEvent();
- void flushDelayedTouchEvent();
+ void flushFrameSynchronousEvents();
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered);
static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
index bfcc99c4c2..300ce6920c 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
@@ -126,7 +126,7 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
data.updatePending = false;
if (!data.grabOnly) {
- cd->flushDelayedTouchEvent();
+ cd->flushFrameSynchronousEvents();
// Event delivery/processing triggered the window to be deleted or stop rendering.
if (!m_windows.contains(window))
return;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index 5af79747a7..e8e1ec7db6 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -846,7 +846,7 @@ Renderer::~Renderer()
for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this);
}
- foreach (Node *n, m_nodes.values())
+ for (Node *n : qAsConst(m_nodes))
m_nodeAllocator.release(n);
// Remaining elements...
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index cb8f1399a4..1a9b576af4 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -382,7 +382,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
return;
if (!data.grabOnly) {
- cd->flushDelayedTouchEvent();
+ cd->flushFrameSynchronousEvents();
// Event delivery/processing triggered the window to be deleted or stop rendering.
if (!m_windows.contains(window))
return;
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 1feba32ab2..3ff32b360d 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -1142,7 +1142,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
}
// Flush pending touch events.
- QQuickWindowPrivate::get(window)->flushDelayedTouchEvent();
+ QQuickWindowPrivate::get(window)->flushFrameSynchronousEvents();
// The delivery of the event might have caused the window to stop rendering
w = windowFor(m_windows, window);
if (!w || !w->thread || !w->thread->window) {
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 5e025e9761..371f512c6e 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -445,7 +445,7 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
}
}
- d->flushDelayedTouchEvent();
+ d->flushFrameSynchronousEvents();
// Event delivery or processing has caused the window to stop rendering.
if (!windowData(window))
return;
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 597613c9fd..dc4b27d738 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -922,15 +922,13 @@ QQuickPixmapStore::~QQuickPixmapStore()
#ifndef QT_NO_DEBUG
int leakedPixmaps = 0;
#endif
- QList<QQuickPixmapData*> cachedData = m_cache.values();
-
// Prevent unreferencePixmap() from assuming it needs to kick
// off the cache expiry timer, as we're shrinking the cache
// manually below after releasing all the pixmaps.
m_timerId = -2;
// unreference all (leaked) pixmaps
- foreach (QQuickPixmapData* pixmap, cachedData) {
+ for (auto *pixmap : qAsConst(m_cache)) {
int currRefCount = pixmap->refCount;
if (currRefCount) {
#ifndef QT_NO_DEBUG
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index f8d090cc2c..659ffe1d84 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -110,8 +110,9 @@ void QQuickProfiler::stopProfilingImpl()
m_data.clear();
}
-void QQuickProfiler::reportDataImpl()
+void QQuickProfiler::reportDataImpl(bool trackLocations)
{
+ Q_UNUSED(trackLocations);
QMutexLocker lock(&m_dataMutex);
emit dataReady(m_data);
m_data.clear();
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index b58d4f47c1..f1af87f4e6 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -353,7 +353,7 @@ signals:
protected slots:
void startProfilingImpl(quint64 features);
void stopProfilingImpl();
- void reportDataImpl();
+ void reportDataImpl(bool trackLocations);
void setTimer(const QElapsedTimer &t);
};
diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp
index 0119aecb7e..bd556444de 100644
--- a/src/quick/util/qquickpropertychanges.cpp
+++ b/src/quick/util/qquickpropertychanges.cpp
@@ -202,7 +202,7 @@ public:
QPointer<QObject> object;
QList<const QV4::CompiledData::Binding *> bindings;
- QQmlRefPointer<QQmlCompiledData> cdata;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
bool decoded : 1;
bool restore : 1;
@@ -258,7 +258,7 @@ void QQuickPropertyChangesPrivate::decode()
return;
foreach (const QV4::CompiledData::Binding *binding, bindings)
- decodeBinding(QString(), cdata->compilationUnit->data, binding);
+ decodeBinding(QString(), compilationUnit->data, binding);
bindings.clear();
@@ -288,7 +288,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
handler->property = prop;
handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(),
- QQmlContextData::get(qmlContext(q)), object, cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]));
+ QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]));
signalReplacements << handler;
return;
}
@@ -338,12 +338,12 @@ void QQuickPropertyChangesParser::verifyBindings(const QV4::CompiledData::Unit *
verifyList(qmlUnit, props.at(ii));
}
-void QQuickPropertyChangesParser::applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
+void QQuickPropertyChangesParser::applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
QQuickPropertyChangesPrivate *p =
static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj));
p->bindings = bindings;
- p->cdata = cdata;
+ p->compilationUnit = compilationUnit;
p->decoded = false;
}
@@ -456,7 +456,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
QQmlBinding *newBinding = 0;
if (e.id != QQmlBinding::Invalid) {
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->cdata->compilationUnit->runtimeFunctions[e.id]));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->compilationUnit->runtimeFunctions[e.id]));
newBinding = new QQmlBinding(function, object(), context);
}
// QQmlBinding *newBinding = e.id != QQmlBinding::Invalid ? QQmlBinding::createBinding(e.id, object(), qmlContext(this)) : 0;
diff --git a/src/quick/util/qquickpropertychanges_p.h b/src/quick/util/qquickpropertychanges_p.h
index 9d086b7688..0537750338 100644
--- a/src/quick/util/qquickpropertychanges_p.h
+++ b/src/quick/util/qquickpropertychanges_p.h
@@ -104,7 +104,7 @@ public:
void verifyList(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
- virtual void applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings);
+ virtual void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
};
diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp
index d4956983fb..569cb37c95 100644
--- a/src/quick/util/qquicksmoothedanimation.cpp
+++ b/src/quick/util/qquicksmoothedanimation.cpp
@@ -392,7 +392,7 @@ QQuickSmoothedAnimationPrivate::~QQuickSmoothedAnimationPrivate()
void QQuickSmoothedAnimationPrivate::updateRunningAnimations()
{
- foreach(QSmoothedAnimation* ease, activeAnimations.values()){
+ for (QSmoothedAnimation *ease : qAsConst(activeAnimations)) {
ease->maximumEasingTime = anim->maximumEasingTime;
ease->reversingMode = anim->reversingMode;
ease->velocity = anim->velocity;
@@ -444,7 +444,8 @@ QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &a
anims.insert(ease);
}
- foreach (QSmoothedAnimation *ease, d->activeAnimations.values()){
+ const auto copy = d->activeAnimations;
+ for (QSmoothedAnimation *ease : copy) {
if (!anims.contains(ease)) {
ease->clearTemplate();
d->activeAnimations.remove(ease->target);
diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp
index df077350e9..d2bc3b4ece 100644
--- a/src/quick/util/qquickspringanimation.cpp
+++ b/src/quick/util/qquickspringanimation.cpp
@@ -585,7 +585,8 @@ QAbstractAnimationJob* QQuickSpringAnimation::transition(QQuickStateActions &act
animation->restart();
anims.insert(animation);
}
- foreach (QSpringAnimation *anim, d->activeAnimations.values()){
+ const auto copy = d->activeAnimations;
+ for (QSpringAnimation *anim : copy) {
if (!anims.contains(anim)) {
anim->clearTemplate();
d->activeAnimations.remove(anim->target);
diff --git a/tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml b/tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml
new file mode 100644
index 0000000000..dd653352d9
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/rootItemIsComponent.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+Component {
+ QtObject {
+ id: blah
+ }
+}
diff --git a/tests/auto/qml/qqmllanguage/testtypes.cpp b/tests/auto/qml/qqmllanguage/testtypes.cpp
index cc39422dce..ccfcfc098e 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.cpp
+++ b/tests/auto/qml/qqmllanguage/testtypes.cpp
@@ -110,11 +110,11 @@ QVariant myCustomVariantTypeConverter(const QString &data)
}
-void CustomBindingParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
+void CustomBindingParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
{
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
Q_ASSERT(customBinding);
- customBinding->cdata = cdata;
+ customBinding->compilationUnit = compilationUnit;
customBinding->bindings = bindings;
}
@@ -123,14 +123,14 @@ void CustomBinding::componentComplete()
Q_ASSERT(m_target);
foreach (const QV4::CompiledData::Binding *binding, bindings) {
- QString name = cdata->compilationUnit->data->stringAt(binding->propertyNameIndex);
+ QString name = compilationUnit->data->stringAt(binding->propertyNameIndex);
int bindingId = binding->value.compiledScriptIndex;
QQmlContextData *context = QQmlContextData::get(qmlContext(this));
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
- QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId]));
+ QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, compilationUnit->runtimeFunctions[bindingId]));
QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context);
QQmlProperty property(m_target, name, qmlContext(this));
@@ -169,7 +169,7 @@ void EnumSupportingCustomParser::verifyBindings(const QV4::CompiledData::Unit *q
}
}
-void SimpleObjectCustomParser::applyBindings(QObject *object, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &bindings)
+void SimpleObjectCustomParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &bindings)
{
SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
Q_ASSERT(o);
diff --git a/tests/auto/qml/qqmllanguage/testtypes.h b/tests/auto/qml/qqmllanguage/testtypes.h
index 2344b6a03b..788ae42726 100644
--- a/tests/auto/qml/qqmllanguage/testtypes.h
+++ b/tests/auto/qml/qqmllanguage/testtypes.h
@@ -733,14 +733,14 @@ class MyCustomParserTypeParser : public QQmlCustomParser
{
public:
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
};
class EnumSupportingCustomParser : public QQmlCustomParser
{
public:
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &);
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
};
class MyParserStatus : public QObject, public QQmlParserStatus
@@ -1170,7 +1170,7 @@ public:
void setTarget(QObject *newTarget) { m_target = newTarget; }
QPointer<QObject> m_target;
- QQmlRefPointer<QQmlCompiledData> cdata;
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
QList<const QV4::CompiledData::Binding*> bindings;
QByteArray m_bindingData;
};
@@ -1178,7 +1178,7 @@ public:
class CustomBindingParser : public QQmlCustomParser
{
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &);
};
class SimpleObjectWithCustomParser : public QObject
@@ -1224,7 +1224,7 @@ private:
class SimpleObjectCustomParser : public QQmlCustomParser
{
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
- virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
+ virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &);
};
class RootObjectInCreationTester : public QObject
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 5bb129fbb8..58a7c39760 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -108,6 +108,7 @@ private slots:
void bindTypeToJSValue();
void customParserTypes();
void rootAsQmlComponent();
+ void rootItemIsComponent();
void inlineQmlComponents();
void idProperty();
void autoNotifyConnection();
@@ -1195,6 +1196,19 @@ void tst_qqmllanguage::rootAsQmlComponent()
QCOMPARE(object->getChildren()->count(), 2);
}
+void tst_qqmllanguage::rootItemIsComponent()
+{
+ QQmlComponent component(&engine, testFileUrl("rootItemIsComponent.qml"));
+ VERIFY_ERRORS(0);
+ QScopedPointer<QObject> root(component.create());
+ QVERIFY(qobject_cast<QQmlComponent*>(root.data()));
+ QScopedPointer<QObject> other(qobject_cast<QQmlComponent*>(root.data())->create());
+ QVERIFY(!other.isNull());
+ QQmlContext *context = qmlContext(other.data());
+ QVERIFY(context);
+ QCOMPARE(context->nameForObject(other.data()), QStringLiteral("blah"));
+}
+
// Tests that components can be specified inline
void tst_qqmllanguage::inlineQmlComponents()
{
diff --git a/tests/manual/v4/test262 b/tests/manual/v4/test262
-Subproject 9741ac4655808ac46c127e3d1d8ba3d27ada618
+Subproject 0b5af3dcec772bb06b4d685a20b2859cda59d18