diff --git a/src/sysprof/icons/scalable/actions/memory-leaks-symbolic.svg b/src/sysprof/icons/scalable/actions/memory-leaks-symbolic.svg
new file mode 100644
index 00000000..06f50b6a
--- /dev/null
+++ b/src/sysprof/icons/scalable/actions/memory-leaks-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/src/sysprof/sysprof-memory-section.c b/src/sysprof/sysprof-memory-section.c
index 1a02c9e4..3cc4899c 100644
--- a/src/sysprof/sysprof-memory-section.c
+++ b/src/sysprof/sysprof-memory-section.c
@@ -20,6 +20,14 @@
#include "config.h"
+#include
+
+#include "eggbitset.h"
+
+#include "sysprof-document-bitset-index-private.h"
+#include "sysprof-document-private.h"
+#include "sysprof-leak-detector-private.h"
+
#include "sysprof-chart.h"
#include "sysprof-column-layer.h"
#include "sysprof-memory-callgraph-view.h"
@@ -36,10 +44,19 @@ struct _SysprofMemorySection
SysprofSection parent_instance;
SysprofMemoryCallgraphView *callgraph_view;
+ GListModel *leaks;
};
G_DEFINE_FINAL_TYPE (SysprofMemorySection, sysprof_memory_section, SYSPROF_TYPE_SECTION)
+enum {
+ PROP_0,
+ PROP_LEAKS,
+ N_PROPS
+};
+
+static GParamSpec *properties[N_PROPS];
+
static char *
format_number (gpointer unused,
guint number)
@@ -49,6 +66,64 @@ format_number (gpointer unused,
return g_strdup_printf ("%'u", number);
}
+static void
+load_leaks_callgraph (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ SysprofMemorySection *self = (SysprofMemorySection *)object;
+ g_autoptr(GListModel) leaks = NULL;
+
+ g_assert (SYSPROF_IS_MEMORY_SECTION (self));
+ g_assert (G_IS_TASK (result));
+
+ if (!(leaks = g_task_propagate_pointer (G_TASK (result), NULL)))
+ return;
+
+ if (g_set_object (&self->leaks, leaks))
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LEAKS]);
+}
+
+static void
+sysprof_memory_section_leaks_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ g_autoptr(GListModel) res = NULL;
+ g_autoptr(EggBitset) allocs = NULL;
+ g_autoptr(EggBitset) leaks = NULL;
+ SysprofDocument *document = task_data;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (SYSPROF_IS_DOCUMENT (document));
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ allocs = _sysprof_document_get_allocations (document);
+ leaks = sysprof_leak_detector_detect (document, allocs);
+ res = _sysprof_document_bitset_index_new (G_LIST_MODEL (document), leaks);
+
+ g_task_return_pointer (task, g_steal_pointer (&res), g_object_unref);
+}
+
+static void
+sysprof_memory_section_session_set (SysprofSection *section,
+ SysprofSession *session)
+{
+ SysprofMemorySection *self = (SysprofMemorySection *)section;
+ g_autoptr(GTask) task = NULL;
+ SysprofDocument *document;
+
+ g_assert (SYSPROF_IS_MEMORY_SECTION (self));
+ g_assert (SYSPROF_IS_SESSION (session));
+
+ document = sysprof_session_get_document (session);
+
+ task = g_task_new (self, NULL, load_leaks_callgraph, NULL);
+ g_task_set_task_data (task, g_object_ref (document), g_object_unref);
+ g_task_run_in_thread (task, sysprof_memory_section_leaks_worker);
+}
+
static void
sysprof_memory_section_dispose (GObject *object)
{
@@ -59,13 +134,43 @@ sysprof_memory_section_dispose (GObject *object)
G_OBJECT_CLASS (sysprof_memory_section_parent_class)->dispose (object);
}
+static void
+sysprof_memory_section_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SysprofMemorySection *self = SYSPROF_MEMORY_SECTION (object);
+
+ switch (prop_id)
+ {
+ case PROP_LEAKS:
+ g_value_set_object (value, self->leaks);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
static void
sysprof_memory_section_class_init (SysprofMemorySectionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ SysprofSectionClass *section_class = SYSPROF_SECTION_CLASS (klass);
object_class->dispose = sysprof_memory_section_dispose;
+ object_class->get_property = sysprof_memory_section_get_property;
+
+ section_class->session_set = sysprof_memory_section_session_set;
+
+ properties [PROP_LEAKS] =
+ g_param_spec_object ("leaks", NULL, NULL,
+ G_TYPE_LIST_MODEL,
+ (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-memory-section.ui");
gtk_widget_class_bind_template_child (widget_class, SysprofMemorySection, callgraph_view);
diff --git a/src/sysprof/sysprof-memory-section.ui b/src/sysprof/sysprof-memory-section.ui
index 9b9c24f5..6ddaaa0c 100644
--- a/src/sysprof/sysprof-memory-section.ui
+++ b/src/sysprof/sysprof-memory-section.ui
@@ -75,41 +75,97 @@
-
+
+
+ true
+ stack
diff --git a/src/sysprof/sysprof.gresource.xml b/src/sysprof/sysprof.gresource.xml
index 0ee2de95..2077ada6 100644
--- a/src/sysprof/sysprof.gresource.xml
+++ b/src/sysprof/sysprof.gresource.xml
@@ -12,6 +12,7 @@
icons/scalable/actions/mark-table-symbolic.svg
icons/scalable/actions/mark-waterfall-symbolic.svg
icons/scalable/actions/memory-allocations-symbolic.svg
+ icons/scalable/actions/memory-leaks-symbolic.svg
icons/scalable/actions/metadata-symbolic.svg
icons/scalable/actions/process-mounts-symbolic.svg
icons/scalable/actions/storage-symbolic.svg