diff options
Diffstat (limited to 'src/qml/debugger')
-rw-r--r-- | src/qml/debugger/debugger.pri | 27 | ||||
-rw-r--r-- | src/qml/debugger/qqmlabstractprofileradapter_p.h | 10 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebug.cpp | 17 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebug.h | 3 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugconnector_p.h | 25 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugservice.cpp | 33 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugservice_p.h | 20 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugserviceinterfaces_p.h | 57 | ||||
-rw-r--r-- | src/qml/debugger/qqmldebugstatesdelegate_p.h | 7 | ||||
-rw-r--r-- | src/qml/debugger/qqmlmemoryprofiler.cpp | 157 | ||||
-rw-r--r-- | src/qml/debugger/qqmlmemoryprofiler_p.h | 96 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofiler.cpp | 18 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofiler_p.h | 94 | ||||
-rw-r--r-- | src/qml/debugger/qqmlprofilerdefinitions_p.h | 4 |
14 files changed, 456 insertions, 112 deletions
diff --git a/src/qml/debugger/debugger.pri b/src/qml/debugger/debugger.pri index 30a44eedd1..da1ab867d4 100644 --- a/src/qml/debugger/debugger.pri +++ b/src/qml/debugger/debugger.pri @@ -1,21 +1,28 @@ -contains(QT_CONFIG, no-qml-debug):DEFINES += QT_NO_QML_DEBUGGER +contains(QT_CONFIG, no-qml-debug) { + DEFINES += QT_NO_QML_DEBUGGER + MODULE_DEFINES += QT_NO_QML_DEBUGGER +} else { + HEADERS += \ + $$PWD/qqmldebugpluginmanager_p.h \ + $$PWD/qqmldebugservicefactory_p.h -SOURCES += \ - $$PWD/qqmldebug.cpp \ - $$PWD/qqmldebugconnector.cpp \ - $$PWD/qqmldebugservice.cpp \ - $$PWD/qqmldebugserviceinterfaces.cpp \ - $$PWD/qqmlabstractprofileradapter.cpp \ - $$PWD/qqmlprofiler.cpp + SOURCES += \ + $$PWD/qqmldebug.cpp \ + $$PWD/qqmldebugconnector.cpp \ + $$PWD/qqmldebugservice.cpp \ + $$PWD/qqmlabstractprofileradapter.cpp \ + $$PWD/qqmlmemoryprofiler.cpp \ + $$PWD/qqmlprofiler.cpp \ + $$PWD/qqmldebugserviceinterfaces.cpp +} HEADERS += \ $$PWD/qqmldebugconnector_p.h \ - $$PWD/qqmldebugpluginmanager_p.h \ $$PWD/qqmldebugservice_p.h \ - $$PWD/qqmldebugservicefactory_p.h \ $$PWD/qqmldebugserviceinterfaces_p.h \ $$PWD/qqmldebugstatesdelegate_p.h \ $$PWD/qqmldebug.h \ + $$PWD/qqmlmemoryprofiler_p.h \ $$PWD/qqmlprofilerdefinitions_p.h \ $$PWD/qqmlabstractprofileradapter_p.h \ $$PWD/qqmlprofiler_p.h diff --git a/src/qml/debugger/qqmlabstractprofileradapter_p.h b/src/qml/debugger/qqmlabstractprofileradapter_p.h index 1104608055..6a05a80f37 100644 --- a/src/qml/debugger/qqmlabstractprofileradapter_p.h +++ b/src/qml/debugger/qqmlabstractprofileradapter_p.h @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_QML_DEBUGGER + class QQmlProfilerService; class Q_QML_PRIVATE_EXPORT QQmlAbstractProfilerAdapter : public QObject, public QQmlProfilerDefinitions { Q_OBJECT @@ -71,13 +73,13 @@ public: virtual ~QQmlAbstractProfilerAdapter() {} void setService(QQmlProfilerService *new_service) { service = new_service; } - virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0; + virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) = 0; void startProfiling(quint64 features); void stopProfiling(); - void reportData() { emit dataRequested(); } + void reportData(bool trackLocations) { emit dataRequested(trackLocations); } void stopWaiting() { waiting = false; } void startWaiting() { waiting = true; } @@ -94,7 +96,7 @@ signals: void profilingDisabled(); void profilingDisabledWhileWaiting(); - void dataRequested(); + void dataRequested(bool trackLocations); void referenceTimeKnown(const QElapsedTimer &timer); protected: @@ -114,6 +116,8 @@ public: #define QQmlAbstractProfilerAdapterFactory_iid "org.qt-project.Qt.QQmlAbstractProfilerAdapterFactory" +#endif // QT_NO_QML_DEBUGGER + QT_END_NAMESPACE #endif // QQMLABSTRACTPROFILERADAPTER_P_H diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp index 557cce08d5..b2c4b139ee 100644 --- a/src/qml/debugger/qqmldebug.cpp +++ b/src/qml/debugger/qqmldebug.cpp @@ -47,15 +47,11 @@ QT_BEGIN_NAMESPACE QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning) { -#ifndef QQML_NO_DEBUG_PROTOCOL if (!QQmlEnginePrivate::qml_debugging_enabled && printWarning) { qDebug("QML debugging is enabled. Only use this in a safe environment."); } QQmlEnginePrivate::qml_debugging_enabled = true; -#else - Q_UNUSED(printWarning); -#endif } /*! @@ -105,11 +101,7 @@ QStringList QQmlDebuggingEnabler::profilerServices() */ void QQmlDebuggingEnabler::setServices(const QStringList &services) { -#ifndef QQML_NO_DEBUG_PROTOCOL QQmlDebugConnector::setServices(services); -#else - Q_UNUSED(services); -#endif } /*! @@ -172,16 +164,9 @@ bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName, const QVariantHash &configuration) { -#ifndef QQML_NO_DEBUG_PROTOCOL QQmlDebugConnector::setPluginKey(pluginName); QQmlDebugConnector *connector = QQmlDebugConnector::instance(); - if (connector) - return connector->open(configuration); -#else - Q_UNUSED(pluginName); - Q_UNUSED(configuration); -#endif - return false; + return connector ? connector->open(configuration) : false; } enum { HookCount = 3 }; diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h index 660b9e4d46..fb41039867 100644 --- a/src/qml/debugger/qqmldebug.h +++ b/src/qml/debugger/qqmldebug.h @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_QML_DEBUGGER struct Q_QML_EXPORT QQmlDebuggingEnabler { @@ -77,6 +78,8 @@ static QQmlDebuggingEnabler qQmlEnableDebuggingHelper(false); static QQmlDebuggingEnabler qQmlEnableDebuggingHelper(true); #endif +#endif + QT_END_NAMESPACE #endif // QQMLDEBUG_H diff --git a/src/qml/debugger/qqmldebugconnector_p.h b/src/qml/debugger/qqmldebugconnector_p.h index 05755250bd..0d3e2e2e47 100644 --- a/src/qml/debugger/qqmldebugconnector_p.h +++ b/src/qml/debugger/qqmldebugconnector_p.h @@ -59,6 +59,29 @@ QT_BEGIN_NAMESPACE +#ifdef QT_NO_QML_DEBUGGER + +class Q_QML_PRIVATE_EXPORT QQmlDebugConnector +{ +public: + static QQmlDebugConnector *instance() { return nullptr; } + + template<class Service> + static Service *service() { return nullptr; } + + bool hasEngine(QJSEngine *) const { return false; } + void addEngine(QJSEngine *) {} + void removeEngine(QJSEngine *) {} + + bool open(const QVariantHash &configuration = QVariantHash()) + { + Q_UNUSED(configuration); + return false; + } +}; + +#else + class QQmlDebugService; class Q_QML_PRIVATE_EXPORT QQmlDebugConnector : public QObject { @@ -106,6 +129,8 @@ public: #define QQmlDebugConnectorFactory_iid "org.qt-project.Qt.QQmlDebugConnectorFactory" +#endif + QT_END_NAMESPACE #endif // QQMLDEBUGCONNECTOR_H diff --git a/src/qml/debugger/qqmldebugservice.cpp b/src/qml/debugger/qqmldebugservice.cpp index b780735f48..b576c3bb85 100644 --- a/src/qml/debugger/qqmldebugservice.cpp +++ b/src/qml/debugger/qqmldebugservice.cpp @@ -132,7 +132,6 @@ public: int nextId; -private slots: void remove(QObject *obj); }; } @@ -163,7 +162,7 @@ int QQmlDebugService::idForObject(QObject *object) int id = hash->nextId++; hash->ids.insert(id, object); iter = hash->objects.insert(object, id); - connect(object, SIGNAL(destroyed(QObject*)), hash, SLOT(remove(QObject*))); + connect(object, &QObject::destroyed, hash, &ObjectReferenceHash::remove); } return iter.value(); } @@ -176,36 +175,6 @@ const QHash<int, QObject *> &QQmlDebugService::objectsForIds() return objectReferenceHash()->ids; } -void QQmlDebugService::stateAboutToBeChanged(State) -{ -} - -void QQmlDebugService::stateChanged(State) -{ -} - -void QQmlDebugService::messageReceived(const QByteArray &) -{ -} - -void QQmlDebugService::engineAboutToBeAdded(QJSEngine *engine) -{ - emit attachedToEngine(engine); -} - -void QQmlDebugService::engineAboutToBeRemoved(QJSEngine *engine) -{ - emit detachedFromEngine(engine); -} - -void QQmlDebugService::engineAdded(QJSEngine *) -{ -} - -void QQmlDebugService::engineRemoved(QJSEngine *) -{ -} - QT_END_NAMESPACE #include "qqmldebugservice.moc" diff --git a/src/qml/debugger/qqmldebugservice_p.h b/src/qml/debugger/qqmldebugservice_p.h index 9ddc692ecc..42a57a39f2 100644 --- a/src/qml/debugger/qqmldebugservice_p.h +++ b/src/qml/debugger/qqmldebugservice_p.h @@ -58,6 +58,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_QML_DEBUGGER + class QJSEngine; class QQmlDebugServicePrivate; @@ -65,7 +67,6 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugService : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QQmlDebugService) - Q_DISABLE_COPY(QQmlDebugService) public: ~QQmlDebugService(); @@ -77,14 +78,15 @@ public: State state() const; void setState(State newState); - virtual void stateAboutToBeChanged(State); - virtual void stateChanged(State); - virtual void messageReceived(const QByteArray &); + virtual void stateAboutToBeChanged(State) {} + virtual void stateChanged(State) {} + virtual void messageReceived(const QByteArray &) {} + + virtual void engineAboutToBeAdded(QJSEngine *engine) { emit attachedToEngine(engine); } + virtual void engineAboutToBeRemoved(QJSEngine *engine) { emit detachedFromEngine(engine); } - virtual void engineAboutToBeAdded(QJSEngine *); - virtual void engineAboutToBeRemoved(QJSEngine *); - virtual void engineAdded(QJSEngine *); - virtual void engineRemoved(QJSEngine *); + virtual void engineAdded(QJSEngine *) {} + virtual void engineRemoved(QJSEngine *) {} static const QHash<int, QObject *> &objectsForIds(); static int idForObject(QObject *); @@ -101,6 +103,8 @@ signals: void messagesToClient(const QString &name, const QList<QByteArray> &messages); }; +#endif + QT_END_NAMESPACE #endif // QQMLDEBUGSERVICE_H diff --git a/src/qml/debugger/qqmldebugserviceinterfaces_p.h b/src/qml/debugger/qqmldebugserviceinterfaces_p.h index 8f66779872..ca6293c3ec 100644 --- a/src/qml/debugger/qqmldebugserviceinterfaces_p.h +++ b/src/qml/debugger/qqmldebugserviceinterfaces_p.h @@ -62,7 +62,46 @@ QT_BEGIN_NAMESPACE -class Q_QML_PRIVATE_EXPORT QV4DebugService : protected QQmlDebugService +class QWindow; +class QQuickWindow; + +#ifdef QT_NO_QML_DEBUGGER + +struct QV4DebugService +{ + void signalEmitted(const QString &) {} +}; + +struct QQmlProfilerService +{ + void startProfiling(QJSEngine *engine, quint64 features = std::numeric_limits<quint64>::max()) + { + Q_UNUSED(engine); + Q_UNUSED(features); + } + + void stopProfiling(QJSEngine *) {} +}; + +struct QQmlEngineDebugService +{ + void objectCreated(QJSEngine *, QObject *) {} + virtual void setStatesDelegate(QQmlDebugStatesDelegate *) {} +}; + +struct QQmlInspectorService { + void addWindow(QQuickWindow *) {} + void setParentWindow(QQuickWindow *, QWindow *) {} + void removeWindow(QQuickWindow *) {} +}; + +struct QDebugMessageService {}; +struct QQmlEngineControlService {}; +struct QQmlNativeDebugService {}; + +#else + +class Q_QML_PRIVATE_EXPORT QV4DebugService : public QQmlDebugService { Q_OBJECT public: @@ -77,7 +116,7 @@ protected: QQmlDebugService(s_key, version, parent) {} }; -class Q_QML_PRIVATE_EXPORT QQmlProfilerService : protected QQmlDebugService +class Q_QML_PRIVATE_EXPORT QQmlProfilerService : public QQmlDebugService { Q_OBJECT public: @@ -99,7 +138,7 @@ protected: QQmlDebugService(s_key, version, parent) {} }; -class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : protected QQmlDebugService +class Q_QML_PRIVATE_EXPORT QQmlEngineDebugService : public QQmlDebugService { Q_OBJECT public: @@ -117,9 +156,7 @@ protected: QQmlBoundSignal *nextSignal(QQmlBoundSignal *prev) { return prev->m_nextSignal; } }; -class QWindow; -class QQuickWindow; -class Q_QML_PRIVATE_EXPORT QQmlInspectorService : protected QQmlDebugService +class Q_QML_PRIVATE_EXPORT QQmlInspectorService : public QQmlDebugService { Q_OBJECT public: @@ -136,7 +173,7 @@ protected: QQmlDebugService(s_key, version, parent) {} }; -class Q_QML_PRIVATE_EXPORT QDebugMessageService : protected QQmlDebugService +class Q_QML_PRIVATE_EXPORT QDebugMessageService : public QQmlDebugService { Q_OBJECT public: @@ -151,7 +188,7 @@ protected: QQmlDebugService(s_key, version, parent) {} }; -class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : protected QQmlDebugService +class Q_QML_PRIVATE_EXPORT QQmlEngineControlService : public QQmlDebugService { Q_OBJECT public: @@ -165,7 +202,7 @@ protected: }; -class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : protected QQmlDebugService +class Q_QML_PRIVATE_EXPORT QQmlNativeDebugService : public QQmlDebugService { Q_OBJECT @@ -178,6 +215,8 @@ protected: static const QString s_key; }; +#endif + QT_END_NAMESPACE #endif // QQMLDEBUGSERVICEINTERFACES_P_H diff --git a/src/qml/debugger/qqmldebugstatesdelegate_p.h b/src/qml/debugger/qqmldebugstatesdelegate_p.h index 42c4e94b50..95f727fb2d 100644 --- a/src/qml/debugger/qqmldebugstatesdelegate_p.h +++ b/src/qml/debugger/qqmldebugstatesdelegate_p.h @@ -57,6 +57,11 @@ QT_BEGIN_NAMESPACE +#ifdef QT_NO_QML_DEBUGGER + +class QQmlDebugStatesDelegate {}; + +#else class QQmlContext; class QQmlProperty; @@ -90,6 +95,8 @@ private: Q_DISABLE_COPY(QQmlDebugStatesDelegate) }; +#endif + QT_END_NAMESPACE #endif // QQMLDEBUGSTATESDELEGATE_P_H diff --git a/src/qml/debugger/qqmlmemoryprofiler.cpp b/src/qml/debugger/qqmlmemoryprofiler.cpp new file mode 100644 index 0000000000..60f6d96eaf --- /dev/null +++ b/src/qml/debugger/qqmlmemoryprofiler.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqmlmemoryprofiler_p.h" +#include <QUrl> + +QT_BEGIN_NAMESPACE + +enum LibraryState +{ + Unloaded, + Failed, + Loaded +}; + +static LibraryState state = Unloaded; + +typedef void (qmlmemprofile_stats)(int *allocCount, int *bytesAllocated); +typedef void (qmlmemprofile_clear)(); +typedef void (qmlmemprofile_enable)(); +typedef void (qmlmemprofile_disable)(); +typedef void (qmlmemprofile_push_location)(const char *filename, int lineNumber); +typedef void (qmlmemprofile_pop_location)(); +typedef void (qmlmemprofile_save)(const char *filename); +typedef int (qmlmemprofile_is_enabled)(); + +static qmlmemprofile_stats *memprofile_stats; +static qmlmemprofile_clear *memprofile_clear; +static qmlmemprofile_enable *memprofile_enable; +static qmlmemprofile_disable *memprofile_disable; +static qmlmemprofile_push_location *memprofile_push_location; +static qmlmemprofile_pop_location *memprofile_pop_location; +static qmlmemprofile_save *memprofile_save; +static qmlmemprofile_is_enabled *memprofile_is_enabled; + +#ifndef QT_NO_LIBRARY +extern QFunctionPointer qt_linux_find_symbol_sys(const char *symbol); +#endif + +static bool openLibrary() +{ +#if defined(Q_OS_LINUX) && !defined(QT_NO_LIBRARY) + if (state == Unloaded) { + memprofile_stats = (qmlmemprofile_stats *) qt_linux_find_symbol_sys("qmlmemprofile_stats"); + memprofile_clear = (qmlmemprofile_clear *) qt_linux_find_symbol_sys("qmlmemprofile_clear"); + memprofile_enable = (qmlmemprofile_enable *) qt_linux_find_symbol_sys("qmlmemprofile_enable"); + memprofile_disable = (qmlmemprofile_disable *) qt_linux_find_symbol_sys("qmlmemprofile_disable"); + memprofile_push_location = (qmlmemprofile_push_location *) qt_linux_find_symbol_sys("qmlmemprofile_push_location"); + memprofile_pop_location = (qmlmemprofile_pop_location *) qt_linux_find_symbol_sys("qmlmemprofile_pop_location"); + memprofile_save = (qmlmemprofile_save *) qt_linux_find_symbol_sys("qmlmemprofile_save"); + memprofile_is_enabled = (qmlmemprofile_is_enabled *) qt_linux_find_symbol_sys("qmlmemprofile_is_enabled"); + + if (memprofile_stats && memprofile_clear && memprofile_enable && memprofile_disable && + memprofile_push_location && memprofile_pop_location && memprofile_save && memprofile_is_enabled) + state = Loaded; + else + state = Failed; + } +#endif // Q_OS_LINUX + + return state == Loaded; +} + +QQmlMemoryScope::QQmlMemoryScope(const QUrl &url) + : QQmlMemoryScope(url.path().toUtf8().constData()) +{ +} + +QQmlMemoryScope::QQmlMemoryScope(const char *string) : pushed(false) +{ + if (openLibrary() && memprofile_is_enabled()) { + memprofile_push_location(string, 0); + pushed = true; + } +} + +QQmlMemoryScope::~QQmlMemoryScope() +{ + if (pushed) + memprofile_pop_location(); +} + +bool QQmlMemoryProfiler::isEnabled() +{ + if (openLibrary()) + return memprofile_is_enabled(); + + return false; +} + +void QQmlMemoryProfiler::enable() +{ + if (openLibrary()) + memprofile_enable(); +} + +void QQmlMemoryProfiler::disable() +{ + if (openLibrary()) + memprofile_disable(); +} + +void QQmlMemoryProfiler::clear() +{ + if (openLibrary()) + memprofile_clear(); +} + +void QQmlMemoryProfiler::stats(int *allocCount, int *bytesAllocated) +{ + if (openLibrary()) + memprofile_stats(allocCount, bytesAllocated); +} + +void QQmlMemoryProfiler::save(const char *filename) +{ + if (openLibrary()) + memprofile_save(filename); +} + +QT_END_NAMESPACE diff --git a/src/qml/debugger/qqmlmemoryprofiler_p.h b/src/qml/debugger/qqmlmemoryprofiler_p.h new file mode 100644 index 0000000000..59f08704ca --- /dev/null +++ b/src/qml/debugger/qqmlmemoryprofiler_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQMLMEMORYPROFILER_H +#define QQMLMEMORYPROFILER_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 <private/qtqmlglobal_p.h> + +QT_BEGIN_NAMESPACE + +#ifdef QT_NO_QML_DEBUGGER + +#define QML_MEMORY_SCOPE_URL(url) +#define QML_MEMORY_SCOPE_STRING(s) + +#else + +class QUrl; + +class Q_QML_PRIVATE_EXPORT QQmlMemoryScope +{ +public: + explicit QQmlMemoryScope(const QUrl &url); + explicit QQmlMemoryScope(const char *string); + ~QQmlMemoryScope(); + +private: + bool pushed; +}; + +class Q_QML_PRIVATE_EXPORT QQmlMemoryProfiler +{ +public: + static void enable(); + static void disable(); + static bool isEnabled(); + + static void clear(); + static void stats(int *allocCount, int *bytesAllocated); + static void save(const char *filename); +}; + +#define QML_MEMORY_SCOPE_URL(url) QQmlMemoryScope _qml_memory_scope(url) +#define QML_MEMORY_SCOPE_STRING(s) QQmlMemoryScope _qml_memory_scope(s) + +#endif + +QT_END_NAMESPACE +#endif // QQMLMEMORYPROFILER_H diff --git a/src/qml/debugger/qqmlprofiler.cpp b/src/qml/debugger/qqmlprofiler.cpp index 629d5cb7b8..ffba731b13 100644 --- a/src/qml/debugger/qqmlprofiler.cpp +++ b/src/qml/debugger/qqmlprofiler.cpp @@ -59,19 +59,21 @@ void QQmlProfiler::startProfiling(quint64 features) void QQmlProfiler::stopProfiling() { featuresEnabled = false; - reportData(); + reportData(true); + m_locations.clear(); } -void QQmlProfiler::reportData() +void QQmlProfiler::reportData(bool trackLocations) { LocationHash resolved; resolved.reserve(m_locations.size()); - for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it) - resolved.insert(it.key(), it.value()); - - // This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's - // a good idea to release the memory before creating the packets to be sent. - m_locations.clear(); + for (auto it = m_locations.begin(), end = m_locations.end(); it != end; ++it) { + if (!trackLocations || !it->sent) { + resolved.insert(it.key(), it.value()); + if (trackLocations) + it->sent = true; + } + } QVector<QQmlProfilerData> data; data.swap(m_data); diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 1380599fb7..6643695d11 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -55,7 +55,6 @@ #include <private/qqmlboundsignal_p.h> #include <private/qfinitestack_p.h> #include <private/qqmlbinding_p.h> -#include <private/qqmlcompiler_p.h> #include "qqmlprofilerdefinitions_p.h" #include "qqmlabstractprofileradapter_p.h" @@ -64,6 +63,54 @@ QT_BEGIN_NAMESPACE +#ifdef QT_NO_QML_DEBUGGER + +#define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code) +#define Q_QML_PROFILE(feature, profiler, Method) +#define Q_QML_OC_PROFILE(member, Code) + +struct QQmlProfiler {}; + +struct QQmlBindingProfiler +{ + QQmlBindingProfiler(quintptr, QQmlBinding *, QV4::FunctionObject *) {} +}; + +struct QQmlHandlingSignalProfiler +{ + QQmlHandlingSignalProfiler(quintptr, QQmlBoundSignalExpression *) {} +}; + +struct QQmlCompilingProfiler +{ + QQmlCompilingProfiler(quintptr, QQmlDataBlob *) {} +}; + +struct QQmlVmeProfiler { + QQmlVmeProfiler() {} + + void init(quintptr, int) {} + + const QV4::CompiledData::Object *pop() { return nullptr; } + void push(const QV4::CompiledData::Object *) {} + + static const quintptr profiler = 0; +}; + +struct QQmlObjectCreationProfiler +{ + QQmlObjectCreationProfiler(quintptr, const QV4::CompiledData::Object *) {} + void update(QV4::CompiledData::CompilationUnit *, const QV4::CompiledData::Object *, + const QString &, const QUrl &) {} +}; + +struct QQmlObjectCompletionProfiler +{ + QQmlObjectCompletionProfiler(QQmlVmeProfiler *) {} +}; + +#else + #define Q_QML_PROFILE_IF_ENABLED(feature, profiler, Code)\ if (profiler && (profiler->featuresEnabled & (1 << feature))) {\ Code;\ @@ -73,6 +120,9 @@ QT_BEGIN_NAMESPACE #define Q_QML_PROFILE(feature, profiler, Method)\ Q_QML_PROFILE_IF_ENABLED(feature, profiler, profiler->Method) +#define Q_QML_OC_PROFILE(member, Code)\ + Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code) + // 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 @@ -95,7 +145,7 @@ struct Q_AUTOTEST_EXPORT QQmlProfilerData : public QQmlProfilerDefinitions Q_DECLARE_TYPEINFO(QQmlProfilerData, Q_MOVABLE_TYPE); -class QQmlProfiler : public QObject, public QQmlProfilerDefinitions { +class Q_QML_PRIVATE_EXPORT QQmlProfiler : public QObject, public QQmlProfilerDefinitions { Q_OBJECT public: @@ -146,26 +196,27 @@ public: // Unfortunately we have to resolve the locations right away because the QML context might not // be available anymore when we send the data. struct RefLocation : public Location { - RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr) + RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr), sent(false) {} RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) : Location(function->sourceLocation()), locationType(Binding), - ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt) + ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt), sent(false) {} - RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj, + RefLocation(QV4::CompiledData::CompilationUnit *ref, const QUrl &url, const QV4::CompiledData::Object *obj, const QString &type) : Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url), - locationType(Creating), ref(ref) + locationType(Creating), ref(ref), sent(false) {} RefLocation(QQmlBoundSignalExpression *ref) : - Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref) + Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref), sent(false) {} RefLocation(QQmlDataBlob *ref) : - Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref) + Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref), + sent(false) {} bool isValid() const @@ -175,6 +226,7 @@ public: RangeType locationType; QQmlRefPointer<QQmlRefCount> ref; + bool sent; }; typedef QHash<quintptr, Location> LocationHash; @@ -217,11 +269,6 @@ public: location = RefLocation(expression); } - void startCreating() - { - m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating)); - } - void startCreating(const QV4::CompiledData::Object *obj) { m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), @@ -229,14 +276,10 @@ public: Creating, id(obj))); } - void updateCreating(const QV4::CompiledData::Object *obj, QQmlCompiledData *ref, + void updateCreating(const QV4::CompiledData::Object *obj, QV4::CompiledData::CompilationUnit *ref, const QUrl &url, const QString &type) { quintptr locationId(id(obj)); - m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), - (1 << RangeLocation | 1 << RangeData), - Creating, locationId)); - RefLocation &location = m_locations[locationId]; if (!location.isValid()) location = RefLocation(ref, url, obj, type); @@ -258,10 +301,9 @@ public: return reinterpret_cast<quintptr>(pointer); } -public slots: void startProfiling(quint64 features); void stopProfiling(); - void reportData(); + void reportData(bool trackLocations); void setTimer(const QElapsedTimer &timer) { m_timer = timer; } signals: @@ -357,15 +399,13 @@ private: QFiniteStack<const QV4::CompiledData::Object *> ranges; }; -#define Q_QML_OC_PROFILE(member, Code)\ - Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, member.profiler, Code) - class QQmlObjectCreationProfiler { public: - QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler) + QQmlObjectCreationProfiler(QQmlProfiler *profiler, const QV4::CompiledData::Object *obj) + : profiler(profiler) { - Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating()); + Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating(obj)); } ~QQmlObjectCreationProfiler() @@ -373,7 +413,7 @@ public: Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, endRange<QQmlProfilerDefinitions::Creating>()); } - void update(QQmlCompiledData *ref, const QV4::CompiledData::Object *obj, + void update(QV4::CompiledData::CompilationUnit *ref, const QV4::CompiledData::Object *obj, const QString &typeName, const QUrl &url) { profiler->updateCreating(obj, ref, url, typeName); @@ -406,4 +446,6 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QVector<QQmlProfilerData>) Q_DECLARE_METATYPE(QQmlProfiler::LocationHash) +#endif // QT_NO_QML_DEBUGGER + #endif // QQMLPROFILER_P_H diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h index 2b2eda22e1..c6ae4593a9 100644 --- a/src/qml/debugger/qqmlprofilerdefinitions_p.h +++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h @@ -56,6 +56,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_QML_DEBUGGER + struct QQmlProfilerDefinitions { enum Message { Event, @@ -161,6 +163,8 @@ struct QQmlProfilerDefinitions { }; }; +#endif // QT_NO_QML_DEBUGGER + QT_END_NAMESPACE #endif |