From f8e5cfcfc26499eef30fc222e24957a753651cbc Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 20 Jul 2015 18:09:42 +0200 Subject: Move profiler and engine control services into a plugin Change-Id: I12627a07ceedea4aceafa6f0e630c0cab69d156d Reviewed-by: Simon Hausmann --- src/qml/debugger/debugger.pri | 7 - src/qml/debugger/qqmldebugconnector.cpp | 5 +- src/qml/debugger/qqmlenginecontrolservice.cpp | 135 -------- src/qml/debugger/qqmlenginecontrolservice_p.h | 90 ------ src/qml/debugger/qqmlprofiler.cpp | 82 ----- src/qml/debugger/qqmlprofiler_p.h | 21 +- src/qml/debugger/qqmlprofilerservice.cpp | 434 -------------------------- src/qml/debugger/qqmlprofilerservice_p.h | 125 -------- src/qml/debugger/qv4profileradapter.cpp | 154 --------- src/qml/debugger/qv4profileradapter_p.h | 81 ----- 10 files changed, 4 insertions(+), 1130 deletions(-) delete mode 100644 src/qml/debugger/qqmlenginecontrolservice.cpp delete mode 100644 src/qml/debugger/qqmlenginecontrolservice_p.h delete mode 100644 src/qml/debugger/qqmlprofilerservice.cpp delete mode 100644 src/qml/debugger/qqmlprofilerservice_p.h delete mode 100644 src/qml/debugger/qv4profileradapter.cpp delete mode 100644 src/qml/debugger/qv4profileradapter_p.h (limited to 'src/qml/debugger') diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri index b401216d77..9734e07a1d 100644 --- a/src/qml/debugger/debugger.pri +++ b/src/qml/debugger/debugger.pri @@ -5,22 +5,17 @@ SOURCES += \ $$PWD/qqmldebugconnector.cpp \ $$PWD/qqmldebugservice.cpp \ $$PWD/qqmldebugserviceinterfaces.cpp \ - $$PWD/qqmlprofilerservice.cpp \ $$PWD/qqmlenginedebugservice.cpp \ $$PWD/qdebugmessageservice.cpp \ $$PWD/qv4debugservice.cpp \ - $$PWD/qqmlenginecontrolservice.cpp \ $$PWD/qqmlabstractprofileradapter.cpp \ - $$PWD/qv4profileradapter.cpp \ $$PWD/qqmlprofiler.cpp - HEADERS += \ $$PWD/qqmldebugconnector_p.h \ $$PWD/qqmldebugpluginmanager_p.h \ $$PWD/qqmldebugservice_p.h \ $$PWD/qqmldebugservicefactory_p.h \ - $$PWD/qqmlprofilerservice_p.h \ $$PWD/qqmldebugserviceinterfaces_p.h \ $$PWD/qqmldebugstatesdelegate_p.h \ $$PWD/qqmlenginedebugservice_p.h \ @@ -28,10 +23,8 @@ HEADERS += \ $$PWD/qdebugmessageservice_p.h \ $$PWD/qv4debugservice_p.h \ $$PWD/qqmlconfigurabledebugservice_p.h \ - $$PWD/qqmlenginecontrolservice_p.h \ $$PWD/qqmlprofilerdefinitions_p.h \ $$PWD/qqmlabstractprofileradapter_p.h \ - $$PWD/qv4profileradapter_p.h \ $$PWD/qqmlprofiler_p.h INCLUDEPATH += $$PWD diff --git a/src/qml/debugger/qqmldebugconnector.cpp b/src/qml/debugger/qqmldebugconnector.cpp index e1dabb439e..9565f19563 100644 --- a/src/qml/debugger/qqmldebugconnector.cpp +++ b/src/qml/debugger/qqmldebugconnector.cpp @@ -34,9 +34,7 @@ #include "qqmldebugpluginmanager_p.h" #include "qqmldebugconnector_p.h" #include "qdebugmessageservice_p.h" -#include "qqmlenginecontrolservice_p.h" #include "qqmlenginedebugservice_p.h" -#include "qqmlprofilerservice_p.h" #include "qv4debugservice_p.h" #include "qqmldebugservicefactory_p.h" #include @@ -56,6 +54,7 @@ Q_QML_IMPORT_DEBUG_PLUGIN(QQmlDebugServerFactory) Q_QML_DEBUG_PLUGIN_LOADER(QQmlDebugService) Q_QML_IMPORT_DEBUG_PLUGIN(QQmlInspectorServiceFactory) +Q_QML_IMPORT_DEBUG_PLUGIN(QQmlProfilerServiceFactory) struct QQmlDebugConnectorParams { QString pluginKey; @@ -121,9 +120,7 @@ QQmlDebugConnector *QQmlDebugConnector::instance() if (params->instance) { QQmlEngineDebugServiceImpl::instance(); QV4DebugServiceImpl::instance(); - QQmlProfilerServiceImpl::instance(); QDebugMessageService::instance(); - QQmlEngineControlService::instance(); foreach (const QJsonObject &object, metaDataForQQmlDebugService()) { foreach (const QJsonValue &key, object.value(QLatin1String("MetaData")).toObject() diff --git a/src/qml/debugger/qqmlenginecontrolservice.cpp b/src/qml/debugger/qqmlenginecontrolservice.cpp deleted file mode 100644 index eaf948426d..0000000000 --- a/src/qml/debugger/qqmlenginecontrolservice.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "qqmldebug.h" -#include "qqmlenginecontrolservice_p.h" - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(QQmlEngineControlService, qmlEngineControlService) - -QQmlEngineControlService::QQmlEngineControlService() : - QQmlDebugService(QStringLiteral("EngineControl"), 1) -{ -} - -QQmlEngineControlService *QQmlEngineControlService::instance() -{ - return qmlEngineControlService(); -} - -void QQmlEngineControlService::messageReceived(const QByteArray &message) -{ - QMutexLocker lock(&dataMutex); - QQmlDebugStream d(message); - int command; - int engineId; - d >> command >> engineId; - QQmlEngine *engine = qobject_cast(objectForId(engineId)); - if (command == StartWaitingEngine && startingEngines.contains(engine)) { - startingEngines.removeOne(engine); - emit attachedToEngine(engine); - } else if (command == StopWaitingEngine && stoppingEngines.contains(engine)) { - stoppingEngines.removeOne(engine); - emit detachedFromEngine(engine); - } -} - -void QQmlEngineControlService::engineAboutToBeAdded(QQmlEngine *engine) -{ - QMutexLocker lock(&dataMutex); - if (state() == Enabled) { - Q_ASSERT(!stoppingEngines.contains(engine)); - Q_ASSERT(!startingEngines.contains(engine)); - startingEngines.append(engine); - sendMessage(EngineAboutToBeAdded, engine); - } else { - emit attachedToEngine(engine); - } -} - -void QQmlEngineControlService::engineAboutToBeRemoved(QQmlEngine *engine) -{ - QMutexLocker lock(&dataMutex); - if (state() == Enabled) { - Q_ASSERT(!stoppingEngines.contains(engine)); - Q_ASSERT(!startingEngines.contains(engine)); - stoppingEngines.append(engine); - sendMessage(EngineAboutToBeRemoved, engine); - } else { - emit detachedFromEngine(engine); - } -} - -void QQmlEngineControlService::engineAdded(QQmlEngine *engine) -{ - if (state() == Enabled) { - QMutexLocker lock(&dataMutex); - Q_ASSERT(!startingEngines.contains(engine)); - Q_ASSERT(!stoppingEngines.contains(engine)); - sendMessage(EngineAdded, engine); - } -} - -void QQmlEngineControlService::engineRemoved(QQmlEngine *engine) -{ - if (state() == Enabled) { - QMutexLocker lock(&dataMutex); - Q_ASSERT(!startingEngines.contains(engine)); - Q_ASSERT(!stoppingEngines.contains(engine)); - sendMessage(EngineRemoved, engine); - } -} - -void QQmlEngineControlService::sendMessage(QQmlEngineControlService::MessageType type, QQmlEngine *engine) -{ - QByteArray message; - QQmlDebugStream d(&message, QIODevice::WriteOnly); - d << type << idForObject(engine); - emit messageToClient(name(), message); -} - -void QQmlEngineControlService::stateChanged(State) -{ - // We flush everything for any kind of state change, to avoid complicated timing issues. - QMutexLocker lock(&dataMutex); - foreach (QQmlEngine *engine, startingEngines) - emit attachedToEngine(engine); - startingEngines.clear(); - foreach (QQmlEngine *engine, stoppingEngines) - emit detachedFromEngine(engine); - stoppingEngines.clear(); -} - -QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlenginecontrolservice_p.h b/src/qml/debugger/qqmlenginecontrolservice_p.h deleted file mode 100644 index 2171937efe..0000000000 --- a/src/qml/debugger/qqmlenginecontrolservice_p.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLENGINECONTROLSERVICE_H -#define QQMLENGINECONTROLSERVICE_H - -#include -#include "qqmldebugservice_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. -// - -QT_BEGIN_NAMESPACE - -class QQmlEngineControlService : public QQmlDebugService -{ -public: - enum MessageType { - EngineAboutToBeAdded, - EngineAdded, - EngineAboutToBeRemoved, - EngineRemoved - }; - - enum CommandType { - StartWaitingEngine, - StopWaitingEngine - }; - - QQmlEngineControlService(); - - static QQmlEngineControlService *instance(); - -protected: - QMutex dataMutex; - QList startingEngines; - QList stoppingEngines; - - void messageReceived(const QByteArray &); - void engineAboutToBeAdded(QQmlEngine *); - void engineAboutToBeRemoved(QQmlEngine *); - void engineAdded(QQmlEngine *); - void engineRemoved(QQmlEngine *); - - void sendMessage(MessageType type, QQmlEngine *engine); - - void stateChanged(State); -}; - -QT_END_NAMESPACE - -#endif // QQMLENGINECONTROLSERVICE_H diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp index 30e089ac44..a6423d769a 100644 --- a/src/qml/debugger/qqmlprofiler.cpp +++ b/src/qml/debugger/qqmlprofiler.cpp @@ -32,92 +32,10 @@ ****************************************************************************/ #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), next(0) -{ - engine->enableProfiler(); - connect(this, SIGNAL(profilingEnabled(quint64)), engine->profiler, SLOT(startProfiling(quint64))); - connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)), - engine->profiler, SLOT(startProfiling(quint64)), 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(QElapsedTimer)), - engine->profiler, SLOT(setTimer(QElapsedTimer))); - connect(engine->profiler, SIGNAL(dataReady(QVector)), - this, SLOT(receiveData(QVector))); -} - -qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList &messages) -{ - while (next != data.length()) { - if (data[next].time > until) - return data[next].time; - data[next++].toByteArrays(messages); - } - - next = 0; - data.clear(); - return -1; -} - -void QQmlProfilerAdapter::receiveData(const QVector &new_data) -{ - if (data.isEmpty()) - data = new_data; - else - data.append(new_data); - service->dataReady(this); -} - - QQmlProfiler::QQmlProfiler() : featuresEnabled(0) { static int metatype = qRegisterMetaType >(); diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 67e6c9eda6..3c8337c969 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -68,8 +68,9 @@ QT_BEGIN_NAMESPACE // 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. +// independently when converting to QByteArrays. 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() {} @@ -103,8 +104,6 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData int x; //used by RangeLocation int y; //used by RangeLocation - - void toByteArrays(QList &messages) const; }; Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); @@ -178,20 +177,6 @@ protected: QVector 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 QVector &new_data); - -private: - QVector data; - int next; -}; - // // RAII helper structs // diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp deleted file mode 100644 index a858dcf915..0000000000 --- a/src/qml/debugger/qqmlprofilerservice.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qqmlprofilerservice_p.h" -#include "qv4profileradapter_p.h" -#include "qqmlprofiler_p.h" -#include "qqmldebugconnector_p.h" -#include - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(QQmlProfilerServiceImpl, profilerInstance) - -QQmlProfilerServiceImpl::QQmlProfilerServiceImpl() - : QQmlConfigurableDebugService(1), - m_waitingForStop(false) -{ - m_timer.start(); -} - -QQmlProfilerServiceImpl::~QQmlProfilerServiceImpl() -{ - // 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. - qDeleteAll(m_engineProfilers.values()); - qDeleteAll(m_globalProfilers); -} - -void QQmlProfilerServiceImpl::dataReady(QQmlAbstractProfilerAdapter *profiler) -{ - QMutexLocker lock(&m_configMutex); - bool dataComplete = true; - for (QMultiMap::iterator i(m_startTimes.begin()); i != m_startTimes.end();) { - if (i.value() == profiler) { - m_startTimes.erase(i++); - } else { - if (i.key() == -1) - dataComplete = false; - ++i; - } - } - m_startTimes.insert(0, profiler); - if (dataComplete) { - QList enginesToRelease; - foreach (QQmlEngine *engine, m_stoppingEngines) { - foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers.values(engine)) { - if (m_startTimes.values().contains(engineProfiler)) { - enginesToRelease.append(engine); - break; - } - } - } - sendMessages(); - foreach (QQmlEngine *engine, enginesToRelease) { - m_stoppingEngines.removeOne(engine); - emit detachedFromEngine(engine); - } - } -} - -QQmlProfilerServiceImpl *QQmlProfilerServiceImpl::instance() -{ - // just make sure that the service is properly registered - return profilerInstance(); -} - -void QQmlProfilerServiceImpl::engineAboutToBeAdded(QQmlEngine *engine) -{ - Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, - "QML profilers have to be added from the engine thread"); - - QMutexLocker lock(&m_configMutex); - QQmlProfilerAdapter *qmlAdapter = new QQmlProfilerAdapter(this, QQmlEnginePrivate::get(engine)); - QV4ProfilerAdapter *v4Adapter = new QV4ProfilerAdapter(this, QV8Engine::getV4(engine->handle())); - addEngineProfiler(qmlAdapter, engine); - addEngineProfiler(v4Adapter, engine); - QQmlConfigurableDebugService::engineAboutToBeAdded(engine); -} - -void QQmlProfilerServiceImpl::engineAdded(QQmlEngine *engine) -{ - Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, - "QML profilers have to be added from the engine thread"); - - QMutexLocker lock(&m_configMutex); - foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) - profiler->stopWaiting(); -} - -void QQmlProfilerServiceImpl::engineAboutToBeRemoved(QQmlEngine *engine) -{ - Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, - "QML profilers have to be removed from the engine thread"); - - QMutexLocker lock(&m_configMutex); - bool isRunning = false; - foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) { - if (profiler->isRunning()) - isRunning = true; - profiler->startWaiting(); - } - if (isRunning) { - m_stoppingEngines.append(engine); - stopProfiling(engine); - } else { - emit detachedFromEngine(engine); - } -} - -void QQmlProfilerServiceImpl::engineRemoved(QQmlEngine *engine) -{ - Q_ASSERT_X(QThread::currentThread() == engine->thread(), Q_FUNC_INFO, - "QML profilers have to be removed from the engine thread"); - - QMutexLocker lock(&m_configMutex); - foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) { - removeProfilerFromStartTimes(profiler); - delete profiler; - } - m_engineProfilers.remove(engine); -} - -void QQmlProfilerServiceImpl::addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine) -{ - profiler->moveToThread(thread()); - profiler->synchronize(m_timer); - m_engineProfilers.insert(engine, profiler); -} - -void QQmlProfilerServiceImpl::addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) -{ - QMutexLocker lock(&m_configMutex); - profiler->synchronize(m_timer); - m_globalProfilers.append(profiler); - // Global profiler, not connected to a specific engine. - // Global profilers are started whenever any engine profiler is started and stopped when - // all engine profilers are stopped. - quint64 features = 0; - foreach (QQmlAbstractProfilerAdapter *engineProfiler, m_engineProfilers) - features |= engineProfiler->features(); - - if (features != 0) - profiler->startProfiling(features); -} - -void QQmlProfilerServiceImpl::removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler) -{ - QMutexLocker lock(&m_configMutex); - removeProfilerFromStartTimes(profiler); - m_globalProfilers.removeOne(profiler); - delete profiler; -} - -void QQmlProfilerServiceImpl::removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler) -{ - for (QMultiMap::iterator i(m_startTimes.begin()); - i != m_startTimes.end();) { - if (i.value() == profiler) { - m_startTimes.erase(i++); - break; - } else { - ++i; - } - } -} - -/*! - * Start profiling the given \a engine. If \a engine is 0, start all engine profilers that aren't - * currently running. - * - * If any engine profiler is started like that also start all global profilers. - */ -void QQmlProfilerServiceImpl::startProfiling(QQmlEngine *engine, quint64 features) -{ - QMutexLocker lock(&m_configMutex); - - QByteArray message; - QQmlDebugStream d(&message, QIODevice::WriteOnly); - - d << m_timer.nsecsElapsed() << (int)Event << (int)StartTrace; - bool startedAny = false; - if (engine != 0) { - foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers.values(engine)) { - if (!profiler->isRunning()) { - profiler->startProfiling(features); - startedAny = true; - } - } - if (startedAny) - d << idForObject(engine); - } else { - QSet engines; - for (QMultiHash::iterator i(m_engineProfilers.begin()); - i != m_engineProfilers.end(); ++i) { - if (!i.value()->isRunning()) { - engines << i.key(); - i.value()->startProfiling(features); - startedAny = true; - } - } - foreach (QQmlEngine *profiledEngine, engines) - d << idForObject(profiledEngine); - } - - if (startedAny) { - foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) { - if (!profiler->isRunning()) - profiler->startProfiling(features); - } - - emit startFlushTimer(); - } - - emit messageToClient(name(), message); -} - -/*! - * Stop profiling the given \a engine. If \a engine is 0, stop all currently running engine - * profilers. - * - * If afterwards no more engine profilers are running, also stop all global profilers. Otherwise - * only make them report their data. - */ -void QQmlProfilerServiceImpl::stopProfiling(QQmlEngine *engine) -{ - QMutexLocker lock(&m_configMutex); - QList stopping; - QList reporting; - - bool stillRunning = false; - for (QMultiHash::iterator i(m_engineProfilers.begin()); - i != m_engineProfilers.end(); ++i) { - if (i.value()->isRunning()) { - if (engine == 0 || i.key() == engine) { - m_startTimes.insert(-1, i.value()); - stopping << i.value(); - } else { - stillRunning = true; - } - } - } - - if (stopping.isEmpty()) - return; - - foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) { - if (!profiler->isRunning()) - continue; - m_startTimes.insert(-1, profiler); - if (stillRunning) { - reporting << profiler; - } else { - stopping << profiler; - } - } - - emit stopFlushTimer(); - m_waitingForStop = true; - - foreach (QQmlAbstractProfilerAdapter *profiler, reporting) - profiler->reportData(); - - foreach (QQmlAbstractProfilerAdapter *profiler, stopping) - profiler->stopProfiling(); -} - -/* - Send the queued up messages. -*/ -void QQmlProfilerServiceImpl::sendMessages() -{ - QList messages; - - QByteArray data; - - if (m_waitingForStop) { - QQmlDebugStream traceEnd(&data, QIODevice::WriteOnly); - traceEnd << m_timer.nsecsElapsed() << (int)Event << (int)EndTrace; - - QSet seen; - foreach (QQmlAbstractProfilerAdapter *profiler, m_startTimes) { - for (QMultiHash::iterator i(m_engineProfilers.begin()); - i != m_engineProfilers.end(); ++i) { - if (i.value() == profiler && !seen.contains(i.key())) { - seen << i.key(); - traceEnd << idForObject(i.key()); - } - } - } - } - - while (!m_startTimes.empty()) { - QQmlAbstractProfilerAdapter *first = m_startTimes.begin().value(); - m_startTimes.erase(m_startTimes.begin()); - if (!m_startTimes.empty()) { - qint64 next = first->sendMessages(m_startTimes.begin().key(), messages); - if (next != -1) - m_startTimes.insert(next, first); - } else { - first->sendMessages(std::numeric_limits::max(), messages); - } - } - - if (m_waitingForStop) { - //indicate completion - messages << data; - data.clear(); - - QQmlDebugStream ds(&data, QIODevice::WriteOnly); - ds << (qint64)-1 << (int)Complete; - messages << data; - m_waitingForStop = false; - } - - emit messagesToClient(name(), messages); - - // Restart flushing if any profilers are still running - foreach (const QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) { - if (profiler->isRunning()) { - emit startFlushTimer(); - break; - } - } -} - -void QQmlProfilerServiceImpl::stateAboutToBeChanged(QQmlDebugService::State newState) -{ - QMutexLocker lock(&m_configMutex); - - if (state() == newState) - return; - - // Stop all profiling and send the data before we get disabled. - if (newState != Enabled) { - foreach (QQmlEngine *engine, m_engineProfilers.keys()) - stopProfiling(engine); - } -} - -void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message) -{ - QMutexLocker lock(&m_configMutex); - - QByteArray rwData = message; - QQmlDebugStream stream(&rwData, QIODevice::ReadOnly); - - int engineId = -1; - quint64 features = std::numeric_limits::max(); - bool enabled; - uint flushInterval = 0; - stream >> enabled; - if (!stream.atEnd()) - stream >> engineId; - if (!stream.atEnd()) - stream >> features; - if (!stream.atEnd()) { - stream >> flushInterval; - m_flushTimer.setInterval(flushInterval); - if (flushInterval > 0) { - connect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush())); - connect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start())); - connect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop())); - } else { - disconnect(&m_flushTimer, SIGNAL(timeout()), this, SLOT(flush())); - disconnect(this, SIGNAL(startFlushTimer()), &m_flushTimer, SLOT(start())); - disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop())); - } - } - - // If engineId == -1 objectForId() and then the cast will return 0. - if (enabled) - startProfiling(qobject_cast(objectForId(engineId)), features); - else - stopProfiling(qobject_cast(objectForId(engineId))); - - stopWaiting(); -} - -void QQmlProfilerServiceImpl::flush() -{ - QMutexLocker lock(&m_configMutex); - - foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) { - if (profiler->isRunning()) { - m_startTimes.insert(-1, profiler); - profiler->reportData(); - } - } - - foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) { - if (profiler->isRunning()) { - m_startTimes.insert(-1, profiler); - profiler->reportData(); - } - } -} - -QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h deleted file mode 100644 index ea73216010..0000000000 --- a/src/qml/debugger/qqmlprofilerservice_p.h +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLPROFILERSERVICE_P_H -#define QQMLPROFILERSERVICE_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 "qqmlconfigurabledebugservice_p.h" -#include "qqmldebugserviceinterfaces_p.h" -#include "qqmlprofilerdefinitions_p.h" -#include "qqmlabstractprofileradapter_p.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QUrl; -class QQmlEngine; - - -class Q_QML_PRIVATE_EXPORT QQmlProfilerServiceImpl : - public QQmlConfigurableDebugService, - public QQmlProfilerDefinitions -{ - Q_OBJECT -public: - - static QQmlProfilerServiceImpl *instance(); - void engineAboutToBeAdded(QQmlEngine *engine); - void engineAboutToBeRemoved(QQmlEngine *engine); - void engineAdded(QQmlEngine *engine); - void engineRemoved(QQmlEngine *engine); - - void addGlobalProfiler(QQmlAbstractProfilerAdapter *profiler); - void removeGlobalProfiler(QQmlAbstractProfilerAdapter *profiler); - - void startProfiling(QQmlEngine *engine, quint64 features = std::numeric_limits::max()); - void stopProfiling(QQmlEngine *engine); - - QQmlProfilerServiceImpl(); - ~QQmlProfilerServiceImpl(); - - void dataReady(QQmlAbstractProfilerAdapter *profiler); - -signals: - void startFlushTimer(); - void stopFlushTimer(); - -private slots: - void flush(); - -protected: - virtual void stateAboutToBeChanged(State state); - virtual void messageReceived(const QByteArray &); - -private: - - void sendMessages(); - void addEngineProfiler(QQmlAbstractProfilerAdapter *profiler, QQmlEngine *engine); - void removeProfilerFromStartTimes(const QQmlAbstractProfilerAdapter *profiler); - - QElapsedTimer m_timer; - QTimer m_flushTimer; - bool m_waitingForStop; - - QList m_globalProfilers; - QMultiHash m_engineProfilers; - QList m_stoppingEngines; - QMultiMap m_startTimes; -}; - -QT_END_NAMESPACE - -#endif // QQMLPROFILERSERVICE_P_H - diff --git a/src/qml/debugger/qv4profileradapter.cpp b/src/qml/debugger/qv4profileradapter.cpp deleted file mode 100644 index 0da8c47939..0000000000 --- a/src/qml/debugger/qv4profileradapter.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv4profileradapter_p.h" -#include "qqmlprofilerservice_p.h" -#include "qqmldebugservice_p.h" - -QT_BEGIN_NAMESPACE - -QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine) : - QQmlAbstractProfilerAdapter(service), dataPos(0), memoryPos(0) -{ - engine->enableProfiler(); - connect(this, SIGNAL(profilingEnabled(quint64)), - engine->profiler, SLOT(startProfiling(quint64))); - connect(this, SIGNAL(profilingEnabledWhileWaiting(quint64)), - engine->profiler, SLOT(startProfiling(quint64)), 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(QElapsedTimer)), - engine->profiler, SLOT(setTimer(QElapsedTimer))); - connect(engine->profiler, SIGNAL(dataReady(QVector, - QVector)), - this, SLOT(receiveData(QVector, - QVector))); -} - -qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList &messages) -{ - QByteArray message; - while (memory_data.length() > memoryPos && memory_data[memoryPos].timestamp <= until) { - QQmlDebugStream d(&message, QIODevice::WriteOnly); - QV4::Profiling::MemoryAllocationProperties &props = memory_data[memoryPos]; - d << props.timestamp << MemoryAllocation << props.type << props.size; - ++memoryPos; - messages.append(message); - } - return memory_data.length() == memoryPos ? -1 : memory_data[memoryPos].timestamp; -} - -qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList &messages, - qint64 callNext) -{ - if (callNext == -1) { - data.clear(); - dataPos = 0; - } - - qint64 memoryNext = appendMemoryEvents(until, messages); - - if (memoryNext == -1) { - memory_data.clear(); - memoryPos = 0; - return callNext; - } - - return callNext == -1 ? memoryNext : qMin(callNext, memoryNext); -} - -qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList &messages) -{ - QByteArray message; - while (true) { - while (!stack.isEmpty() && (dataPos == data.length() || - stack.top() <= data[dataPos].start)) { - if (stack.top() > until) - return finalizeMessages(until, messages, stack.top()); - - appendMemoryEvents(stack.top(), messages); - QQmlDebugStream d(&message, QIODevice::WriteOnly); - d << stack.pop() << RangeEnd << Javascript; - messages.append(message); - } - while (dataPos != data.length() && (stack.empty() || data[dataPos].start < stack.top())) { - const QV4::Profiling::FunctionCallProperties &props = data[dataPos]; - if (props.start > until) - return finalizeMessages(until, messages, props.start); - - appendMemoryEvents(props.start, messages); - - QQmlDebugStream d_start(&message, QIODevice::WriteOnly); - d_start << props.start << RangeStart << Javascript; - messages.push_back(message); - message.clear(); - QQmlDebugStream d_location(&message, QIODevice::WriteOnly); - d_location << props.start << RangeLocation << Javascript << props.file << props.line - << props.column; - messages.push_back(message); - message.clear(); - QQmlDebugStream d_data(&message, QIODevice::WriteOnly); - d_data << props.start << RangeData << Javascript << props.name; - messages.push_back(message); - message.clear(); - stack.push(props.end); - ++dataPos; - } - if (stack.empty() && dataPos == data.length()) - return finalizeMessages(until, messages, -1); - } -} - -void QV4ProfilerAdapter::receiveData( - const QVector &new_data, - const QVector &new_memory_data) -{ - // In rare cases it could be that another flush or stop event is processed while data from - // the previous one is still pending. In that case we just append the data. - - if (data.isEmpty()) - data = new_data; - else - data.append(new_data); - - if (memory_data.isEmpty()) - memory_data = new_memory_data; - else - memory_data.append(new_memory_data); - - service->dataReady(this); -} - -QT_END_NAMESPACE diff --git a/src/qml/debugger/qv4profileradapter_p.h b/src/qml/debugger/qv4profileradapter_p.h deleted file mode 100644 index 34c37baf59..0000000000 --- a/src/qml/debugger/qv4profileradapter_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** 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 The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV4PROFILERADAPTER_P_H -#define QV4PROFILERADAPTER_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 "qv4profiling_p.h" -#include "qqmlabstractprofileradapter_p.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -class QQmlProfilerService; -class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter { - Q_OBJECT - -public: - QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine); - - virtual qint64 sendMessages(qint64 until, QList &messages); - -public slots: - void receiveData(const QVector &, - const QVector &); - -private: - QVector data; - QVector memory_data; - int dataPos; - int memoryPos; - QStack stack; - qint64 appendMemoryEvents(qint64 until, QList &messages); - qint64 finalizeMessages(qint64 until, QList &messages, qint64 callNext); -}; - -QT_END_NAMESPACE - -#endif // QV4PROFILERADAPTER_P_H -- cgit v1.2.3