diff options
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 1 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofiler.cpp | 55 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofiler_p.h | 140 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 35 |
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); |