From 72420889aa54342da4472683e67e2c70b76a170f Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 24 Jan 2014 12:44:49 +0100 Subject: Add dedicated QML profiler and adapter The remaining "profiling" parts of the QML profiler service are engine specific and are best accessed through their own adapter. Change-Id: Idb763104bdd80e4dabdf132ec1a496b9bc9f6f46 Reviewed-by: Kai Koehne --- src/qml/debugger/debugger.pri | 6 +- src/qml/debugger/qqmlprofiler.cpp | 205 +++++++++++++++++ src/qml/debugger/qqmlprofiler_p.h | 368 +++++++++++++++++++++++++++++++ src/qml/debugger/qqmlprofilerservice.cpp | 180 +-------------- src/qml/debugger/qqmlprofilerservice_p.h | 328 --------------------------- src/qml/qml/qqmlbinding.cpp | 6 +- src/qml/qml/qqmlboundsignal.cpp | 9 +- src/qml/qml/qqmlengine.cpp | 8 +- src/qml/qml/qqmlengine_p.h | 3 + src/qml/qml/qqmltypeloader.cpp | 4 +- src/qml/qml/qqmlvme.cpp | 20 +- src/qml/qml/qqmlvme_p.h | 2 +- 12 files changed, 611 insertions(+), 528 deletions(-) create mode 100644 src/qml/debugger/qqmlprofiler.cpp create mode 100644 src/qml/debugger/qqmlprofiler_p.h diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri index 514d8cdce2..27b72a320c 100644 --- a/src/qml/debugger/debugger.pri +++ b/src/qml/debugger/debugger.pri @@ -10,7 +10,8 @@ SOURCES += \ $$PWD/qqmlconfigurabledebugservice.cpp \ $$PWD/qqmlenginecontrolservice.cpp \ $$PWD/qqmlabstractprofileradapter.cpp \ - $$PWD/qv4profileradapter.cpp + $$PWD/qv4profileradapter.cpp \ + $$PWD/qqmlprofiler.cpp HEADERS += \ $$PWD/qqmldebugservice_p.h \ @@ -31,4 +32,5 @@ HEADERS += \ $$PWD/qqmlenginecontrolservice_p.h \ $$PWD/qqmlprofilerdefinitions_p.h \ $$PWD/qqmlabstractprofileradapter_p.h \ - $$PWD/qv4profileradapter_p.h + $$PWD/qv4profileradapter_p.h \ + $$PWD/qqmlprofiler_p.h diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp new file mode 100644 index 0000000000..f92d76cf5d --- /dev/null +++ b/src/qml/debugger/qqmlprofiler.cpp @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlprofiler_p.h" +#include "qqmlprofilerservice_p.h" +#include "qqmldebugservice_p.h" + +QT_BEGIN_NAMESPACE + +// convert to QByteArrays that can be sent to the debug client +// use of QDataStream can skew results +// (see tst_qqmldebugtrace::trace() benchmark) +void QQmlProfilerData::toByteArrays(QList &messages) const +{ + QByteArray data; + Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types."); + for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) { + if ((messageType & (1 << decodedMessageType)) == 0) + continue; + + for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) { + if ((detailType & (1 << decodedDetailType)) == 0) + continue; + + //### using QDataStream is relatively expensive + QQmlDebugStream ds(&data, QIODevice::WriteOnly); + ds << time << decodedMessageType << decodedDetailType; + + switch (decodedMessageType) { + case QQmlProfilerDefinitions::RangeStart: + if (decodedDetailType == (int)QQmlProfilerDefinitions::Binding) + ds << QQmlProfilerDefinitions::QmlBinding; + break; + case QQmlProfilerDefinitions::RangeData: + ds << detailString; + break; + case QQmlProfilerDefinitions::RangeLocation: + ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y; + break; + case QQmlProfilerDefinitions::RangeEnd: break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type."); + break; + } + messages << data; + data.clear(); + } + } +} + +QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine) : + QQmlAbstractProfilerAdapter(service) +{ + engine->enableProfiler(); + connect(this, SIGNAL(profilingEnabled()), engine->profiler, SLOT(startProfiling())); + connect(this, SIGNAL(profilingEnabledWhileWaiting()), + engine->profiler, SLOT(startProfiling()), Qt::DirectConnection); + 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(referenceTimeKnown(const QElapsedTimer &)), + engine->profiler, SLOT(setTimer(const QElapsedTimer &))); + connect(engine->profiler, SIGNAL(dataReady(const QList &)), + this, SLOT(receiveData(const QList &))); +} + +qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList &messages) +{ + while (!data.empty() && data.front().time <= until) { + data.front().toByteArrays(messages); + data.pop_front(); + } + return data.empty() ? -1 : data.front().time; +} + +void QQmlProfilerAdapter::receiveData(const QList &new_data) +{ + data = new_data; + service->dataReady(this); +} + + +QQmlProfiler::QQmlProfiler() : enabled(false) +{ + static int metatype = qRegisterMetaType >(); + Q_UNUSED(metatype); + m_timer.start(); +} + +void QQmlProfiler::startProfiling() +{ + enabled = true; +} + +void QQmlProfiler::stopProfiling() +{ + enabled = false; + reportData(); + m_data.clear(); +} + +void QQmlProfiler::reportData() +{ + QList result; + result.reserve(m_data.size()); + for (int i = 0; i < m_data.size(); ++i) + result.append(m_data[i]); + 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, \line 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() + * 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, \line 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 new file mode 100644 index 0000000000..ca464e86a3 --- /dev/null +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -0,0 +1,368 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLPROFILER_P_H +#define QQMLPROFILER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include "qqmlprofilerdefinitions_p.h" +#include "qqmlabstractprofileradapter_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +#define Q_QML_PROFILE_IF_ENABLED(profiler, Code)\ + if (profiler && profiler->enabled) {\ + Code;\ + } else\ + (void)0 + +#define Q_QML_PROFILE(profiler, Method)\ + Q_QML_PROFILE_IF_ENABLED(profiler, profiler->Method) + +// This struct is somewhat dangerous to use: +// The messageType is a bit field. You can pack multiple messages into +// one object, e.g. RangeStart and RangeLocation. Each one will be read +// independently by toByteArrays. Thus you can only pack messages if their data +// doesn't overlap. It's up to you to figure that out. +struct Q_AUTOTEST_EXPORT QQmlProfilerData +{ + QQmlProfilerData() {} + + QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url, + int x = 0, int y = 0) : + time(time), messageType(messageType), detailType(detailType), detailUrl(url), + x(x), y(y) {} + + QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str, + int x = 0, int y = 0) : + time(time), messageType(messageType), detailType(detailType),detailString(str), + x(x), y(y) {} + + QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str, + const QUrl &url, int x = 0, int y = 0) : + time(time), messageType(messageType), detailType(detailType), detailString(str), + detailUrl(url), x(x), y(y) {} + + + QQmlProfilerData(qint64 time, int messageType, int detailType) : + time(time), messageType(messageType), detailType(detailType) {} + + + qint64 time; + int messageType; //bit field of QQmlProfilerService::Message + int detailType; + + QString detailString; //used by RangeData and possibly by RangeLocation + QUrl detailUrl; //used by RangeLocation, overrides detailString + + int x; //used by RangeLocation + int y; //used by RangeLocation + + void toByteArrays(QList &messages) const; +}; + +Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); + +class QQmlProfiler : public QObject, public QQmlProfilerDefinitions { + Q_OBJECT +public: + void startBinding(const QString &fileName, int line, int column) + { + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), + (1 << RangeStart | 1 << RangeLocation), 1 << Binding, + fileName, line, column)); + } + + // Have toByteArrays() construct another RangeData event from the same QString later. + // This is somewhat pointless but important for backwards compatibility. + void startCompiling(const QString &name) + { + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), + (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), + 1 << Compiling, name, 1, 1)); + } + + void startHandlingSignal(const QString &fileName, int line, int column) + { + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), + (1 << RangeStart | 1 << RangeLocation), 1 << HandlingSignal, + fileName, line, column)); + } + + void startCreating(const QString &typeName, const QUrl &fileName, int line, int column) + { + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), + (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), + 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) + { + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeLocation, 1 << Creating, + fileName, line, column)); + } + + template + void endRange() + { + m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeEnd, 1 << Range)); + } + + QQmlProfiler(); + + bool enabled; + +public slots: + void startProfiling(); + void stopProfiling(); + void reportData(); + void setTimer(const QElapsedTimer &timer) { m_timer = timer; } + +signals: + void dataReady(const QList &); + +protected: + QElapsedTimer m_timer; + QVarLengthArray m_data; +}; + +class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter { + Q_OBJECT +public: + QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine); + qint64 sendMessages(qint64 until, QList &messages); + +public slots: + void receiveData(const QList &new_data); + +private: + QList data; +}; + +// +// RAII helper structs +// + +struct QQmlProfilerHelper : public QQmlProfilerDefinitions { + QQmlProfiler *profiler; + QQmlProfilerHelper(QQmlProfiler *profiler) : profiler(profiler) {} +}; + +struct QQmlBindingProfiler : public QQmlProfilerHelper { + QQmlBindingProfiler(QQmlProfiler *profiler, const QString &url, int line, int column) : + QQmlProfilerHelper(profiler) + { + Q_QML_PROFILE(profiler, startBinding(url, line, column)); + } + + ~QQmlBindingProfiler() + { + Q_QML_PROFILE(profiler, endRange()); + } +}; + +struct QQmlHandlingSignalProfiler : public QQmlProfilerHelper { + QQmlHandlingSignalProfiler(QQmlProfiler *profiler, QQmlBoundSignalExpression *expression) : + QQmlProfilerHelper(profiler) + { + Q_QML_PROFILE_IF_ENABLED(profiler, { + QV4::Function *function; + if (expression->sourceFile().isEmpty() && (function = expression->function())) { + profiler->startHandlingSignal( + function->sourceFile(), function->compiledFunction->location.line, + function->compiledFunction->location.column); + + } else { + profiler->startHandlingSignal( + expression->sourceFile(), expression->lineNumber(), + expression->columnNumber()); + } + }); + } + + ~QQmlHandlingSignalProfiler() + { + Q_QML_PROFILE(profiler, endRange()); + } +}; + +struct QQmlCompilingProfiler : public QQmlProfilerHelper { + QQmlCompilingProfiler(QQmlProfiler *profiler, const QString &name) : + QQmlProfilerHelper(profiler) + { + Q_QML_PROFILE(profiler, startCompiling(name)); + } + + ~QQmlCompilingProfiler() + { + Q_QML_PROFILE(profiler, endRange()); + } +}; + +#define Q_QML_VME_PROFILE(profiler, Method) Q_QML_PROFILE_IF_ENABLED(profiler.profiler, profiler.Method) + +struct QQmlVmeProfiler : public QQmlProfilerDefinitions { +public: + + struct Data { + Data() : line(0), column(0) {} + QUrl url; + int line; + int column; + QString typeName; + }; + + QQmlVmeProfiler() : profiler(0), running(false) {} + + void clear(bool stopProfiling = false) + { + ranges.clear(); + if (running) + profiler->endRange(); + for (int i = 0; i < backgroundRanges.count(); ++i) { + profiler->endRange(); + } + backgroundRanges.clear(); + running = false; + if (stopProfiling) profiler = 0; + } + + void startBackground(const QString &typeName) + { + if (running) { + profiler->endRange(); + running = false; + } + profiler->startCreating(typeName); + backgroundRanges.push(typeName); + } + + void start(const QString &typeName, const QUrl &url, int line, int column) + { + switchRange(); + setCurrentRange(typeName, url, line, column); + profiler->startCreating(typeName, url, line, column); + } + + void stop() + { + if (running) { + profiler->endRange(); + running = false; + } + } + + void pop() + { + if (ranges.count() > 0) { + switchRange(); + currentRange = ranges.pop(); + profiler->startCreating(currentRange.typeName, currentRange.url, + currentRange.line, currentRange.column); + } + } + + void push() + { + if (running) + ranges.push(currentRange); + } + + void foreground(const QUrl &url, int line, int column) + { + if (backgroundRanges.count() > 0) { + switchRange(); + setCurrentRange(backgroundRanges.pop(), url, line, column); + profiler->creatingLocation(url, line, column); + } + } + + QQmlProfiler *profiler; + +private: + + void switchRange() + { + if (running) + profiler->endRange(); + else + running = true; + } + + void setCurrentRange(const QString &typeName, const QUrl &url, int line, int column) + { + currentRange.typeName = typeName; + currentRange.url = url; + currentRange.line = line; + currentRange.column = column; + } + + Data currentRange; + QStack ranges; + QStack backgroundRanges; + bool running; +}; + +QT_END_NAMESPACE +Q_DECLARE_METATYPE(QList) + +#endif // QQMLPROFILER_P_H diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp index e4620a282a..5500b8f22c 100644 --- a/src/qml/debugger/qqmlprofilerservice.cpp +++ b/src/qml/debugger/qqmlprofilerservice.cpp @@ -42,6 +42,7 @@ #include "qqmlprofilerservice_p.h" #include "qqmldebugserver_p.h" #include "qv4profileradapter_p.h" +#include "qqmlprofiler_p.h" #include #include @@ -52,87 +53,7 @@ QT_BEGIN_NAMESPACE -// instance will be set, unset in constructor. Allows static methods to be inlined. -QQmlProfilerService *QQmlProfilerService::m_instance = 0; Q_GLOBAL_STATIC(QQmlProfilerService, profilerInstance) -bool QQmlProfilerService::enabled = false; - -// convert to QByteArrays that can be sent to the debug client -// use of QDataStream can skew results -// (see tst_qqmldebugtrace::trace() benchmark) -void QQmlProfilerData::toByteArrays(QList &messages) const -{ - QByteArray data; - Q_ASSERT_X(((messageType | detailType) & (1 << 31)) == 0, Q_FUNC_INFO, "You can use at most 31 message types and 31 detail types."); - for (uint decodedMessageType = 0; (messageType >> decodedMessageType) != 0; ++decodedMessageType) { - if ((messageType & (1 << decodedMessageType)) == 0) - continue; - - for (uint decodedDetailType = 0; (detailType >> decodedDetailType) != 0; ++decodedDetailType) { - if ((detailType & (1 << decodedDetailType)) == 0) - continue; - - //### using QDataStream is relatively expensive - QQmlDebugStream ds(&data, QIODevice::WriteOnly); - ds << time << decodedMessageType << decodedDetailType; - - switch (decodedMessageType) { - case QQmlProfilerService::Event: - if (decodedDetailType == (int)QQmlProfilerService::AnimationFrame) - ds << framerate << count; - break; - case QQmlProfilerService::RangeStart: - if (decodedDetailType == (int)QQmlProfilerService::Binding) - ds << bindingType; - break; - case QQmlProfilerService::RangeData: - ds << detailString; - break; - case QQmlProfilerService::RangeLocation: - ds << (detailUrl.isEmpty() ? detailString : detailUrl.toString()) << x << y; - break; - case QQmlProfilerService::RangeEnd: break; - case QQmlProfilerService::PixmapCacheEvent: - ds << detailUrl.toString(); - switch (decodedDetailType) { - case QQmlProfilerService::PixmapSizeKnown: ds << x << y; break; - case QQmlProfilerService::PixmapReferenceCountChanged: ds << count; break; - case QQmlProfilerService::PixmapCacheCountChanged: ds << count; break; - default: break; - } - break; - case QQmlProfilerService::SceneGraphFrame: - switch (decodedDetailType) { - // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime - case QQmlProfilerService::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break; - // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime - case QQmlProfilerService::SceneGraphAdaptationLayerFrame: ds << (int)subtime_1 << subtime_2 << subtime_3; break; - // ContextFrame: compiling material time - case QQmlProfilerService::SceneGraphContextFrame: ds << subtime_1; break; - // RenderLoop: syncTime, renderTime, swapTime - case QQmlProfilerService::SceneGraphRenderLoopFrame: ds << subtime_1 << subtime_2 << subtime_3; break; - // TexturePrepare: bind, convert, swizzle, upload, mipmap - case QQmlProfilerService::SceneGraphTexturePrepare: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4 << subtime_5; break; - // TextureDeletion: deletionTime - case QQmlProfilerService::SceneGraphTextureDeletion: ds << subtime_1; break; - // PolishAndSync: polishTime, waitTime, syncTime, animationsTime, - case QQmlProfilerService::SceneGraphPolishAndSync: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break; - // WindowsRenderLoop: GL time, make current time, SceneGraph time - case QQmlProfilerService::SceneGraphWindowsRenderShow: ds << subtime_1 << subtime_2 << subtime_3; break; - // WindowsAnimations: update time - case QQmlProfilerService::SceneGraphWindowsAnimations: ds << subtime_1; break; - // WindowsRenderWindow: polish time; always comes packed after a RenderLoop - case QQmlProfilerService::SceneGraphWindowsPolishFrame: ds << subtime_4; break; - default:break; - } - break; - case QQmlProfilerService::Complete: break; - } - messages << data; - data.clear(); - } - } -} QQmlProfilerService::QQmlProfilerService() : QQmlConfigurableDebugService(QStringLiteral("CanvasFrameRate"), 1) @@ -149,8 +70,6 @@ QQmlProfilerService::~QQmlProfilerService() { // No need to lock here. If any engine or global profiler is still trying to register at this // point we have a nasty bug anyway. - enabled = false; - m_instance = 0; qDeleteAll(m_engineProfilers.keys()); qDeleteAll(m_globalProfilers); } @@ -190,8 +109,7 @@ void QQmlProfilerService::dataReady(QQmlAbstractProfilerAdapter *profiler) QQmlProfilerService *QQmlProfilerService::instance() { // just make sure that the service is properly registered - m_instance = profilerInstance(); - return m_instance; + return profilerInstance(); } void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine) @@ -199,7 +117,7 @@ void QQmlProfilerService::engineAboutToBeAdded(QQmlEngine *engine) Q_ASSERT_X(QThread::currentThread() != thread(), Q_FUNC_INFO, "QML profilers have to be added from the engine thread"); QMutexLocker lock(configMutex()); - QQmlProfiler *qmlAdapter = new QQmlProfiler(this); + QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine)); QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle())); addEngineProfiler(qmlAdapter, engine); addEngineProfiler(v4Adapter, engine); @@ -329,43 +247,6 @@ void QQmlProfilerService::stopProfiling(QQmlEngine *engine) } } -QQmlProfiler::QQmlProfiler(QQmlProfilerService *service) : - QQmlAbstractProfilerAdapter(service), next(0) -{ - connect(this, SIGNAL(profilingEnabled()), this, SLOT(startProfiling())); - connect(this, SIGNAL(profilingEnabledWhileWaiting()), this, SLOT(startProfiling()), - Qt::DirectConnection); - connect(this, SIGNAL(profilingDisabled()), this, SLOT(stopProfiling())); - connect(this, SIGNAL(profilingDisabledWhileWaiting()), this, SLOT(stopProfiling()), - Qt::DirectConnection); -} - -qint64 QQmlProfiler::sendMessages(qint64 until, QList &messages) -{ - QMutexLocker lock(&QQmlProfilerService::instance()->m_dataMutex); - QVector *data = &(QQmlProfilerService::instance()->m_data); - while (next < data->size() && data->at(next).time <= until) { - data->at(next++).toByteArrays(messages); - } - return next < data->size() ? data->at(next).time : -1; -} - -void QQmlProfiler::startProfiling() -{ - if (!QQmlProfilerService::enabled) { - next = 0; - service->m_data.clear(); - QQmlProfilerService::enabled = true; - } -} - -void QQmlProfiler::stopProfiling() -{ - next = 0; - QQmlProfilerService::enabled = false; - service->dataReady(this); -} - /* Send the queued up messages. */ @@ -458,59 +339,4 @@ void QQmlProfilerService::messageReceived(const QByteArray &message) stopWaiting(); } -/*! - * \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, \line 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() - * 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, \line 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/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h index a5d85a76e6..9e05424ce1 100644 --- a/src/qml/debugger/qqmlprofilerservice_p.h +++ b/src/qml/debugger/qqmlprofilerservice_p.h @@ -58,7 +58,6 @@ #include "qqmlabstractprofileradapter_p.h" #include -#include #include #include @@ -67,94 +66,8 @@ #include #include -#define Q_QML_PROFILE_IF_ENABLED(Code)\ - if (QQmlProfilerService::enabled) {\ - Code;\ - } else\ - (void)0 - -#define Q_QML_PROFILE(Method)\ - Q_QML_PROFILE_IF_ENABLED(QQmlProfilerService::Method) - QT_BEGIN_NAMESPACE -// This struct is somewhat dangerous to use: -// You can save values either with 32 or 64 bit precision. toByteArrays will -// guess the precision from messageType. If you state the wrong messageType -// you will get undefined results. -// The messageType is itself a bit field. You can pack multiple messages into -// one object, e.g. RangeStart and RangeLocation. Each one will be read -// independently by toByteArrays. Thus you can only pack messages if their data -// doesn't overlap. Again, it's up to you to figure that out. -struct Q_AUTOTEST_EXPORT QQmlProfilerData -{ - QQmlProfilerData() {} - - QQmlProfilerData(qint64 time, int messageType, int detailType, const QUrl &url, - int x = 0, int y = 0, int framerate = 0, int count = 0, int bindingType = 0) : - time(time), messageType(messageType), detailType(detailType), detailUrl(url), - x(x), y(y), framerate(framerate), count(count), bindingType(bindingType) {} - - QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str, - int x = 0, int y = 0, int framerate = 0, int count = 0, int bindingType = 0) : - time(time), messageType(messageType), detailType(detailType),detailString(str), - x(x), y(y), framerate(framerate), count(count), bindingType(bindingType) {} - - QQmlProfilerData(qint64 time, int messageType, int detailType, const QString &str, - const QUrl &url, int x = 0, int y = 0, int framerate = 0, int count = 0, - int bindingType = 0) : - time(time), messageType(messageType), detailType(detailType), detailString(str), - detailUrl(url), x(x), y(y), framerate(framerate), count(count), bindingType(bindingType) {} - - - QQmlProfilerData(qint64 time, int messageType, int detailType) : - time(time), messageType(messageType), detailType(detailType) {} - - // Special ctor for scenegraph frames. Note that it's missing the QString/QUrl params. - // This is slightly ugly, but makes it easier to disambiguate between int and qint64 params. - QQmlProfilerData(qint64 time, int messageType, int detailType, - qint64 d1, qint64 d2, qint64 d3, qint64 d4, qint64 d5) : - time(time), messageType(messageType), detailType(detailType), - subtime_1(d1), subtime_2(d2), subtime_3(d3), subtime_4(d4), subtime_5(d5) {} - - - qint64 time; - int messageType; //bit field of QQmlProfilerService::Message - int detailType; - - QString detailString; //used by RangeData and possibly by RangeLocation - QUrl detailUrl; //used by RangeLocation, overrides detailString - - union { - qint64 subtime_1; - int x; //used by RangeLocation and for pixmaps - }; - - union { - qint64 subtime_2; - int y; //used by RangeLocation and for pixmaps - }; - - union { - qint64 subtime_3; - int framerate; //used by animation events - }; - - union { - qint64 subtime_4; - int count; //used by animation events and for pixmaps - }; - - union { - qint64 subtime_5; - int bindingType; - }; - - void toByteArrays(QList &messages) const; -}; - -Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); - class QUrl; class QQmlEngine; @@ -176,8 +89,6 @@ public: void startProfiling(QQmlEngine *engine); void stopProfiling(QQmlEngine *engine); - qint64 timestamp() {return m_timer.nsecsElapsed();} - QQmlProfilerService(); ~QQmlProfilerService(); @@ -189,254 +100,15 @@ protected: private: - static void startBinding(const QString &fileName, int line, int column, BindingType bindingType) - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), - (1 << RangeStart | 1 << RangeLocation), - 1 << Binding, fileName, line, column, 0, 0, - bindingType)); - } - - // Have toByteArrays() construct another RangeData event from the same QString later. - // This is somewhat pointless but important for backwards compatibility. - static void startCompiling(const QString &name) - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), - (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), 1 << Compiling, - name, 1, 1, 0, 0, QmlBinding)); - } - - static void startHandlingSignal(const QString &fileName, int line, int column) - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), - (1 << RangeStart | 1 << RangeLocation), - 1 << HandlingSignal, fileName, line, column, 0, 0, - QmlBinding)); - } - - static void startCreating(const QString &typeName, const QUrl &fileName, int line, int column) - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), - (1 << RangeStart | 1 << RangeLocation | 1 << RangeData), - 1 << Creating, typeName, fileName, line, column, - 0, 0, QmlBinding)); - } - - static void startCreating(const QString &typeName) - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), - (1 << RangeStart | 1 << RangeData), 1 << Creating, - typeName, 0, 0, 0, 0, QmlBinding)); - } - - static void creatingLocation(const QUrl &fileName, int line, int column) - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << RangeLocation, - 1 << Creating, fileName, line, column)); - } - - template - static void endRange() - { - m_instance->processMessage(QQmlProfilerData(m_instance->timestamp(), 1 << RangeEnd, - 1 << Range)); - } - void sendMessages(); void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine); - void processMessage(const QQmlProfilerData &message) - { - QMutexLocker locker(&m_dataMutex); - m_data.append(message); - } - -public: - static bool enabled; -private: QElapsedTimer m_timer; - QVector m_data; - QMutex m_dataMutex; QList m_globalProfilers; QMultiHash m_engineProfilers; QList m_stoppingEngines; QMultiMap m_startTimes; - - static QQmlProfilerService *m_instance; - - friend struct QQmlBindingProfiler; - friend struct QQmlHandlingSignalProfiler; - friend struct QQmlVmeProfiler; - friend struct QQmlCompilingProfiler; - friend class QQmlProfiler; -}; - -// Temporary shim around QQmlProfilerService to make it look like a QQmlAbstractProfilerAdapter. -class QQmlProfiler : public QQmlAbstractProfilerAdapter { - Q_OBJECT -public: - QQmlProfiler(QQmlProfilerService *service); - qint64 sendMessages(qint64 until, QList &messages); - -public slots: - void startProfiling(); - void stopProfiling(); -private: - int next; -}; - -// -// RAII helper structs -// - -struct QQmlBindingProfiler { - QQmlBindingProfiler(const QString &url, int line, int column, QQmlProfilerService::BindingType bindingType) - { - Q_QML_PROFILE(startBinding(url, line, column, bindingType)); - } - - ~QQmlBindingProfiler() - { - Q_QML_PROFILE(endRange()); - } -}; - -struct QQmlHandlingSignalProfiler { - QQmlHandlingSignalProfiler(QQmlBoundSignalExpression *expression) - { - Q_QML_PROFILE_IF_ENABLED({ - QV4::Function *function; - if (expression->sourceFile().isEmpty() && (function = expression->function())) { - QQmlProfilerService::startHandlingSignal( - function->sourceFile(), function->compiledFunction->location.line, - function->compiledFunction->location.column); - - } else { - QQmlProfilerService::startHandlingSignal( - expression->sourceFile(), expression->lineNumber(), - expression->columnNumber()); - } - }); - } - - ~QQmlHandlingSignalProfiler() - { - Q_QML_PROFILE(endRange()); - } -}; - -struct QQmlCompilingProfiler { - QQmlCompilingProfiler(const QString &name) - { - Q_QML_PROFILE(startCompiling(name)); - } - - ~QQmlCompilingProfiler() - { - Q_QML_PROFILE(endRange()); - } -}; - -#define Q_QML_VME_PROFILE(Method) Q_QML_PROFILE_IF_ENABLED(Method) - -struct QQmlVmeProfiler { -public: - - struct Data { - Data() : line(0), column(0) {} - QUrl url; - int line; - int column; - QString typeName; - }; - - QQmlVmeProfiler() : running(false) {} - - void clear() - { - ranges.clear(); - if (running) - QQmlProfilerService::m_instance->endRange(); - for (int i = 0; i < backgroundRanges.count(); ++i) { - QQmlProfilerService::m_instance->endRange(); - } - backgroundRanges.clear(); - running = false; - } - - void startBackground(const QString &typeName) - { - if (running) { - QQmlProfilerService::m_instance->endRange(); - running = false; - } - QQmlProfilerService::m_instance->startCreating(typeName); - backgroundRanges.push(typeName); - } - - void start(const QString &typeName, const QUrl &url, int line, int column) - { - switchRange(); - setCurrentRange(typeName, url, line, column); - QQmlProfilerService::m_instance->startCreating(typeName, url, line, column); - } - - void stop() - { - if (running) { - QQmlProfilerService::m_instance->endRange(); - running = false; - } - } - - void pop() - { - if (ranges.count() > 0) { - switchRange(); - currentRange = ranges.pop(); - QQmlProfilerService::m_instance->startCreating(currentRange.typeName, currentRange.url, - currentRange.line, currentRange.column); - } - } - - void push() - { - if (running) - ranges.push(currentRange); - } - - void foreground(const QUrl &url, int line, int column) - { - if (backgroundRanges.count() > 0) { - switchRange(); - setCurrentRange(backgroundRanges.pop(), url, line, column); - QQmlProfilerService::m_instance->creatingLocation(url, line, column); - } - } - -private: - - void switchRange() - { - if (running) - QQmlProfilerService::m_instance->endRange(); - else - running = true; - } - - void setCurrentRange(const QString &typeName, const QUrl &url, int line, int column) - { - currentRange.typeName = typeName; - currentRange.url = url; - currentRange.line = line; - currentRange.column = column; - } - - Data currentRange; - QStack ranges; - QStack backgroundRanges; - bool running; }; QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp index 9b83feebb4..11b9353dfe 100644 --- a/src/qml/qml/qqmlbinding.cpp +++ b/src/qml/qml/qqmlbinding.cpp @@ -46,7 +46,7 @@ #include "qqmlinfo.h" #include "qqmlcompiler_p.h" #include "qqmldata_p.h" -#include +#include #include #include #include @@ -226,7 +226,8 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) trace.addDetail("Column", columnNo); if (!updatingFlag()) { - QQmlBindingProfiler prof(m_url, lineNo, columnNo, QQmlProfilerService::QmlBinding); + QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); + QQmlBindingProfiler prof(ep->profiler, m_url, lineNo, columnNo); setUpdatingFlag(true); QQmlAbstractExpression::DeleteWatcher watcher(this); @@ -242,7 +243,6 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags) QMetaObject::metacall(*m_coreObject, QMetaObject::WriteProperty, idx, a); } else { - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context()->engine); QV4::Scope scope(ep->v4engine()); ep->referenceScarceResources(); diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp index d0476a92d4..e5a0df8c32 100644 --- a/src/qml/qml/qqmlboundsignal.cpp +++ b/src/qml/qml/qqmlboundsignal.cpp @@ -50,7 +50,7 @@ #include "qqml.h" #include "qqmlcontext.h" #include "qqmlglobal_p.h" -#include +#include #include #include "qqmlinfo.h" @@ -356,14 +356,13 @@ void QQmlBoundSignal_callback(QQmlNotifierEndpoint *e, void **a) if (QQmlDebugService::isDebuggingEnabled()) QV4DebugService::instance()->signalEmitted(QString::fromLatin1(QMetaObjectPrivate::signal(s->m_expression->target()->metaObject(), s->m_index).methodSignature())); - QQmlHandlingSignalProfiler prof(s->m_expression); - s->m_isEvaluating = true; - if (s->m_expression && s->m_expression->engine()) { + QQmlEngine *engine; + if (s->m_expression && (engine = s->m_expression->engine())) { + QQmlHandlingSignalProfiler prof(QQmlEnginePrivate::get(engine)->profiler, s->m_expression); s->m_expression->evaluate(a); if (s->m_expression && s->m_expression->hasError()) { - QQmlEngine *engine = s->m_expression->engine(); QQmlEnginePrivate::warning(engine, s->m_expression->error(engine)); } } diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 68d021b5cb..d373c00574 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -556,7 +556,7 @@ DEFINE_BOOL_CONFIG_OPTION(qmlUseNewCompiler, QML_NEW_COMPILER) QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e) : propertyCapture(0), rootContext(0), isDebugging(false), - outputWarningsToStdErr(true), + profiler(0), outputWarningsToStdErr(true), cleanup(0), erroredBindings(0), inProgressCreations(0), workerScriptEngine(0), activeVME(0), activeObjectCreator(0), @@ -595,6 +595,12 @@ QQmlEnginePrivate::~QQmlEnginePrivate() (*iter)->release(); for (QHash::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter) iter.value()->isRegisteredWithEngine = false; + delete profiler; +} + +void QQmlEnginePrivate::enableProfiler() +{ + profiler = new QQmlProfiler(); } void QQmlPrivate::qdeclarativeelement_destructor(QObject *o) diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index e292dbf6c0..d5ceea271e 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -102,6 +102,7 @@ class QQmlVME; class QmlObjectCreator; class QDir; class QQmlIncubator; +class QQmlProfiler; // This needs to be declared here so that the pool for it can live in QQmlEnginePrivate. // The inline method definitions are in qqmljavascriptexpression_p.h @@ -146,6 +147,8 @@ public: QQmlContext *rootContext; bool isDebugging; bool useNewCompiler; + QQmlProfiler *profiler; + void enableProfiler(); bool outputWarningsToStdErr; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 7c32d4f19c..1b947c421a 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -49,7 +49,7 @@ #include #include #include -#include +#include #include #include #include @@ -2304,7 +2304,7 @@ void QQmlTypeData::compile() m_compiledData->url = finalUrl(); m_compiledData->name = finalUrlString(); - QQmlCompilingProfiler prof(m_compiledData->name); + QQmlCompilingProfiler prof(QQmlEnginePrivate::get(typeLoader()->engine())->profiler, m_compiledData->name); if (m_useNewCompiler) { QQmlTypeCompiler compiler(QQmlEnginePrivate::get(typeLoader()->engine()), m_compiledData, this, parsedQML.data()); diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp index 54c70feecc..fb1dff49fd 100644 --- a/src/qml/qml/qqmlvme.cpp +++ b/src/qml/qml/qqmlvme.cpp @@ -129,6 +129,7 @@ void QQmlVME::init(QQmlContextData *ctxt, QQmlCompiledData *comp, int start, rootContext = 0; engine = ctxt->engine; + profiler.profiler = QQmlEnginePrivate::get(engine)->profiler; } bool QQmlVME::initDeferred(QObject *object) @@ -168,6 +169,7 @@ bool QQmlVME::initDeferred(QObject *object) rootContext = 0; engine = ctxt->engine; + profiler.profiler = QQmlEnginePrivate::get(engine)->profiler; return true; } @@ -503,7 +505,7 @@ QObject *QQmlVME::run(QList *errors, const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type); Q_ASSERT(type.component); - Q_QML_VME_PROFILE(profiler.startBackground(type.component->name)); + Q_QML_VME_PROFILE(profiler, startBackground(type.component->name)); states.push(State()); @@ -526,7 +528,7 @@ QObject *QQmlVME::run(QList *errors, QML_END_INSTR(CreateQMLObject) QML_BEGIN_INSTR(CompleteQMLObject) - Q_QML_VME_PROFILE(profiler.foreground(CTXT->url, instr.line, instr.column)); + Q_QML_VME_PROFILE(profiler, foreground(CTXT->url, instr.line, instr.column)); QObject *o = objects.top(); Q_ASSERT(o); @@ -570,7 +572,7 @@ QObject *QQmlVME::run(QList *errors, QML_BEGIN_INSTR(CreateCppObject) const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type); Q_ASSERT(type.type); - Q_QML_VME_PROFILE(profiler.start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column)); + Q_QML_VME_PROFILE(profiler, start(type.type->qmlTypeName(), CTXT->url, instr.line, instr.column)); QObject *o = 0; void *memory = 0; @@ -643,7 +645,7 @@ QObject *QQmlVME::run(QList *errors, QML_BEGIN_INSTR(CreateSimpleObject) const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type); - Q_QML_VME_PROFILE(profiler.start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column)); + Q_QML_VME_PROFILE(profiler, start(ref.type->qmlTypeName(), CTXT->url, instr.line, instr.column)); QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData)); ::memset(static_cast(o), 0, instr.typeSize + sizeof(QQmlData)); instr.create(o); @@ -823,7 +825,7 @@ QObject *QQmlVME::run(QList *errors, QML_END_INSTR(StoreScriptString) QML_BEGIN_INSTR(BeginObject) - Q_QML_VME_PROFILE(profiler.push()); + Q_QML_VME_PROFILE(profiler, push()); QObject *target = objects.top(); QQmlParserStatus *status = reinterpret_cast(reinterpret_cast(target) + instr.castValue); parserStatus.push(status); @@ -1087,7 +1089,7 @@ normalExit: objects.deallocate(); lists.deallocate(); states.clear(); - Q_QML_VME_PROFILE(profiler.stop()); + Q_QML_VME_PROFILE(profiler, stop()); return rv; } @@ -1131,7 +1133,7 @@ void QQmlVME::reset() // 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(profiler.clear()); + Q_QML_VME_PROFILE(profiler, clear(true)); } #ifdef QML_THREADED_VME_INTERPRETER @@ -1191,7 +1193,7 @@ QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt) if (componentCompleteEnabled()) { // the qml designer does the component complete later QQmlTrace trace("VME Component Complete"); while (!parserStatus.isEmpty()) { - Q_QML_VME_PROFILE(profiler.pop()); + Q_QML_VME_PROFILE(profiler, pop()); QQmlParserStatus *status = parserStatus.pop(); #ifdef QML_ENABLE_TRACE QQmlData *data = parserStatusData.pop(); @@ -1211,7 +1213,7 @@ QQmlContextData *QQmlVME::complete(const QQmlInstantiationInterrupt &interrupt) return 0; } parserStatus.deallocate(); - Q_QML_VME_PROFILE(profiler.clear()); + Q_QML_VME_PROFILE(profiler, clear()); } { diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h index 4da1aec74b..226d498d2c 100644 --- a/src/qml/qml/qqmlvme_p.h +++ b/src/qml/qml/qqmlvme_p.h @@ -68,7 +68,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE -- cgit v1.2.3