aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@digia.com>2014-04-02 12:02:14 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-03 13:59:37 +0200
commitef2e5a39fa188c0fb229e7847b5ac3f177ba778e (patch)
tree0ceb8415472c281b5a6c88cd4b3ddf84945606ee
parentcf06b028f71fb80616be7fbb3ef3aaf7d5474eca (diff)
Use RAII for VME profiler
Now that object creation is done in nested function calls we can use an RAII-type profiler to trace it. This makes the profiling much simpler and more robust. Also, the stack of profiling data in the VME profiler has to match the stack of completion callbacks in the VME, so the push and pop operations are synchronized now. Task-number: QTBUG-37978 Change-Id: I1bc5e0665b88e5b3772e48c8676cdda3fae59e1b Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp1
-rw-r--r--src/qml/debugger/qqmlprofiler.cpp55
-rw-r--r--src/qml/debugger/qqmlprofiler_p.h140
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp35
4 files changed, 80 insertions, 151 deletions
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index b44d4e285a..087f8df8a5 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -1408,6 +1408,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;
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
QQmlCompiledData::TypeReference *typeRef = new QQmlCompiledData::TypeReference;
diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp
index a0b39744a0..99446e945e 100644
--- a/src/qml/debugger/qqmlprofiler.cpp
+++ b/src/qml/debugger/qqmlprofiler.cpp
@@ -147,59 +147,4 @@ void QQmlProfiler::reportData()
emit dataReady(result);
}
-/*!
- * \fn void QQmlVmeProfiler::Data::clear()
- * Resets the profiling data to defaults.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::startBackground(const QString &typeName)
- * If profiling is enabled clears the current range data, then stops the
- * profiler previously running in the foreground if any, then starts a new one
- * in the background, setting the given typeName. \a typeName is the type of
- * object being created.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::start(const QString &typeName, const QUrl &url, int line, int column)
- * If profiling is enabled clears the current range data, then stops the
- * profiler previously running in the foreground if any, then starts a new one
- * in the foreground, setting the given location. \a url is the URL of
- * file being executed, \a line is the current line in in that file, and
- * \a column is the current column in that file.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::pop()
- * Stops the currently running profiler, if any, then retrieves an old one from the stack
- * of paused profilers and starts that if possible.
- */
-
-/*!
- * \fn void QQmlVmeProfiler::push()
- * Pushes the currently running profiler on the stack of paused profilers. Note: The profiler
- * isn't paused here. That's a separate step. If it's never paused, but pop()'ed later that
- * won't do any harm, though.
- */
-
-/*!
- * \fn void QQmlVmeProfiler::clear(bool stopProfiling = false)
- * Stops the currently running (foreground and background) profilers and removes all saved
- * data about paused profilers.
- */
-
-/*!
- * \fn void QQmlVmeProfiler::stop()
- * Stop profiler running in the foreground, if any.
- */
-
-/*!
- * \fn bool QQmlVmeProfiler::foreground(const QUrl &url, int line, int column)
- * Stops the profiler currently running in the foreground, if any and puts the
- * next profiler from the background in its place if there are any profilers in
- * the background. Additionally the rangeLocation is set. \a url is the URL of
- * file being executed, \a line is the current line in in that file, and
- * \a column is the current column in that file.
- */
-
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h
index 6afdc1e73b..84001905ab 100644
--- a/src/qml/debugger/qqmlprofiler_p.h
+++ b/src/qml/debugger/qqmlprofiler_p.h
@@ -55,6 +55,7 @@
#include <private/qv4function_p.h>
#include <private/qqmlboundsignal_p.h>
+#include <private/qfinitestack_p.h>
#include "qqmlprofilerdefinitions_p.h"
#include "qqmlabstractprofileradapter_p.h"
@@ -142,6 +143,11 @@ public:
location.sourceFile, location.line, location.column));
}
+ void startCreating()
+ {
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, 1 << Creating));
+ }
+
void startCreating(const QString &typeName, const QUrl &fileName, int line, int column)
{
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
@@ -149,16 +155,11 @@ public:
1 << Creating, typeName, fileName, line, column));
}
- void startCreating(const QString &typeName)
- {
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeData),
- 1 << Creating, typeName));
- }
-
- void creatingLocation(const QUrl &fileName, int line, int column)
+ void updateCreating(const QString &typeName, const QUrl &fileName, int line, int column)
{
- m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeLocation, 1 << Creating,
- fileName, line, column));
+ m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
+ (1 << RangeLocation | 1 << RangeData),
+ 1 << Creating, typeName, fileName, line, column));
}
template<RangeType Range>
@@ -246,108 +247,91 @@ struct QQmlCompilingProfiler : public QQmlProfilerHelper {
}
};
-#define Q_QML_VME_PROFILE(profilerMember, Method) Q_QML_PROFILE_IF_ENABLED(profilerMember.profiler, profilerMember.Method)
-
struct QQmlVmeProfiler : public QQmlProfilerDefinitions {
public:
struct Data {
- Data() : line(0), column(0) {}
- QUrl url;
- int line;
- int column;
- QString typeName;
+ Data() : m_line(0), m_column(0) {}
+ QUrl m_url;
+ int m_line;
+ int m_column;
+ QString m_typeName;
};
- QQmlVmeProfiler() : profiler(0), running(false) {}
+ QQmlVmeProfiler() : profiler(0) {}
- void clear(bool stopProfiling = false)
+ void init(QQmlProfiler *p, int maxDepth)
{
- ranges.clear();
- if (running)
- profiler->endRange<Creating>();
- for (int i = 0; i < backgroundRanges.count(); ++i) {
- profiler->endRange<Creating>();
- }
- backgroundRanges.clear();
- running = false;
- if (stopProfiling) profiler = 0;
+ profiler = p;
+ ranges.allocate(maxDepth);
}
- void startBackground(const QString &typeName)
+ Data pop()
{
- if (running) {
- profiler->endRange<Creating>();
- running = false;
- }
- profiler->startCreating(typeName);
- backgroundRanges.push(typeName);
+ if (ranges.count() > 0)
+ return ranges.pop();
+ else
+ return Data();
}
- void start(const QString &typeName, const QUrl &url, int line, int column)
+ void push(const Data &data)
{
- switchRange();
- setCurrentRange(typeName, url, line, column);
- profiler->startCreating(typeName, url, line, column);
+ if (ranges.capacity() > ranges.count())
+ ranges.push(data);
}
- void stop()
- {
- if (running) {
- profiler->endRange<Creating>();
- running = false;
- }
- }
+ QQmlProfiler *profiler;
- void pop()
+private:
+ QFiniteStack<Data> ranges;
+};
+
+#define Q_QML_OC_PROFILE(profilerMember, Code)\
+ Q_QML_PROFILE_IF_ENABLED(profilerMember.profiler, Code)
+
+class QQmlObjectCreationProfiler : public QQmlVmeProfiler::Data {
+public:
+
+ QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
{
- if (ranges.count() > 0) {
- switchRange();
- currentRange = ranges.pop();
- profiler->startCreating(currentRange.typeName, currentRange.url,
- currentRange.line, currentRange.column);
- }
+ Q_QML_PROFILE(profiler, startCreating());
}
- void push()
+ ~QQmlObjectCreationProfiler()
{
- if (running)
- ranges.push(currentRange);
+ Q_QML_PROFILE(profiler, endRange<QQmlProfilerDefinitions::Creating>());
}
- void foreground(const QUrl &url, int line, int column)
+ void update(const QString &typeName, const QUrl &url, int line, int column)
{
- if (backgroundRanges.count() > 0) {
- switchRange();
- setCurrentRange(backgroundRanges.pop(), url, line, column);
- profiler->creatingLocation(url, line, column);
- }
+ profiler->updateCreating(typeName, url, line, column);
+ m_typeName = typeName;
+ m_url = url;
+ m_line = line;
+ m_column = column;
}
- QQmlProfiler *profiler;
-
private:
+ QQmlProfiler *profiler;
+};
- void switchRange()
+class QQmlObjectCompletionProfiler {
+public:
+ QQmlObjectCompletionProfiler(QQmlVmeProfiler *parent) :
+ profiler(parent->profiler)
{
- if (running)
- profiler->endRange<Creating>();
- else
- running = true;
+ Q_QML_PROFILE_IF_ENABLED(profiler, {
+ QQmlVmeProfiler::Data data = parent->pop();
+ profiler->startCreating(data.m_typeName, data.m_url, data.m_line, data.m_column);
+ });
}
- void setCurrentRange(const QString &typeName, const QUrl &url, int line, int column)
+ ~QQmlObjectCompletionProfiler()
{
- currentRange.typeName = typeName;
- currentRange.url = url;
- currentRange.line = line;
- currentRange.column = column;
+ Q_QML_PROFILE(profiler, endRange<QQmlProfilerDefinitions::Creating>());
}
-
- Data currentRange;
- QStack<Data> ranges;
- QStack<QString> backgroundRanges;
- bool running;
+private:
+ QQmlProfiler *profiler;
};
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index d0c635b007..2ebf90c9be 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -98,7 +98,10 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount);
sharedState->creationContext = creationContext;
sharedState->rootContext = 0;
- sharedState->profiler.profiler = QQmlEnginePrivate::get(engine)->profiler;
+
+ QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
+ Q_QML_PROFILE_IF_ENABLED(profiler,
+ sharedState->profiler.init(profiler, compiledData->totalParserStatusCount));
}
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
@@ -223,8 +226,6 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
ddata->compiledData->addref();
}
- Q_QML_VME_PROFILE(sharedState->profiler, stop());
-
phase = CreatingObjectsPhase2;
if (interrupt && interrupt->shouldInterrupt())
@@ -1014,6 +1015,7 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
{
+ QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
bool isComponent = false;
@@ -1023,21 +1025,23 @@ 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)) {
isComponent = true;
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(QStringLiteral("<component>"),
+ context->url, obj->location.line, obj->location.column));
QQmlComponentPrivate::get(component)->creationContext = context;
instance = component;
ddata = QQmlData::get(instance, /*create*/true);
} else {
- const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
-
QQmlCompiledData::TypeReference *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
installPropertyCache = !typeRef->isFullyDynamicType;
QQmlType *type = typeRef->type;
if (type) {
- Q_QML_VME_PROFILE(sharedState->profiler, start(type->qmlTypeName(), context->url, obj->location.line, obj->location.column));
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(type->qmlTypeName(),
+ context->url, obj->location.line, obj->location.column));
instance = type->create();
if (!instance) {
recordError(obj->location, tr("Unable to create object of type %1").arg(stringAt(obj->inheritedTypeNameIndex)));
@@ -1059,15 +1063,16 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
sharedState->allCreatedObjects.push(instance);
} else {
Q_ASSERT(typeRef->component);
+ Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(typeRef->component->name,
+ context->url, obj->location.line, obj->location.column));
if (typeRef->component->qmlUnit->isSingleton())
{
recordError(obj->location, tr("Composite Singleton Type %1 is not creatable").arg(stringAt(obj->inheritedTypeNameIndex)));
return 0;
}
- Q_QML_VME_PROFILE(sharedState->profiler, startBackground(typeRef->component->name));
+
QQmlObjectCreator subCreator(context, typeRef->component, sharedState.data());
instance = subCreator.create();
- Q_QML_VME_PROFILE(sharedState->profiler, foreground(context->url, obj->location.line, obj->location.column));
if (!instance) {
errors += subCreator.errors;
return 0;
@@ -1100,6 +1105,9 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
if (parserStatus) {
parserStatus->classBegin();
+ // push() the profiler state here, together with the parserStatus, as we'll pop() them
+ // together, too.
+ Q_QML_OC_PROFILE(sharedState->profiler, sharedState->profiler.push(profiler));
sharedState->allParserStatusCallbacks.push(parserStatus);
parserStatus->d = &sharedState->allParserStatusCallbacks.top();
}
@@ -1186,7 +1194,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
if (QQmlVME::componentCompleteEnabled()) { // the qml designer does the component complete later
QQmlTrace trace("VME Component Complete");
while (!sharedState->allParserStatusCallbacks.isEmpty()) {
- Q_QML_VME_PROFILE(sharedState->profiler, pop());
+ QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
QQmlParserStatus *status = sharedState->allParserStatusCallbacks.pop();
if (status && status->d) {
@@ -1197,7 +1205,6 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return 0;
}
- Q_QML_VME_PROFILE(sharedState->profiler, clear());
}
{
@@ -1246,20 +1253,12 @@ void QQmlObjectCreator::clear()
while (!sharedState->allCreatedObjects.isEmpty())
delete sharedState->allCreatedObjects.pop();
- // If profiling is switched off during a VME run and then switched back on
- // before or during the next run background ranges from the first run will
- // be reported in the second run because we don't clear() here. We accept
- // that as the collected data will be incomplete anyway and because not
- // calling clear() here is benefitial for the non-profiling case.
- Q_QML_VME_PROFILE(sharedState->profiler, clear(true));
-
phase = Done;
}
bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
{
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
- Q_QML_VME_PROFILE(sharedState->profiler, push());
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);