From 2c46d6a4c17f9f22c85507a122f37c2a05b3ace3 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Thu, 8 Jun 2023 14:22:18 -0700 Subject: [PATCH] libsysprof-analyze: add listmodel of stacktraces containing symbol --- src/libsysprof-analyze/sysprof-callgraph.c | 56 +++++++++++++++++++--- src/libsysprof-analyze/sysprof-callgraph.h | 13 +++-- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/libsysprof-analyze/sysprof-callgraph.c b/src/libsysprof-analyze/sysprof-callgraph.c index 56d5c8a0..927b7ee3 100644 --- a/src/libsysprof-analyze/sysprof-callgraph.c +++ b/src/libsysprof-analyze/sysprof-callgraph.c @@ -22,10 +22,13 @@ #include "sysprof-callgraph-private.h" #include "sysprof-callgraph-frame-private.h" +#include "sysprof-document-bitset-index-private.h" #include "sysprof-document-private.h" #include "sysprof-document-traceable.h" #include "sysprof-symbol-private.h" +#include "eggbitset.h" + #define MAX_STACK_DEPTH 1024 struct _SysprofCallgraph @@ -37,6 +40,8 @@ struct _SysprofCallgraph SysprofSymbol *everything; + GHashTable *symbol_to_bitset; + GHashTable *callers; gsize augment_size; @@ -123,6 +128,7 @@ sysprof_callgraph_finalize (GObject *object) SysprofCallgraph *self = (SysprofCallgraph *)object; g_clear_pointer (&self->callers, g_hash_table_unref); + g_clear_pointer (&self->symbol_to_bitset, g_hash_table_unref); g_clear_object (&self->document); g_clear_object (&self->traceables); @@ -147,12 +153,14 @@ sysprof_callgraph_init (SysprofCallgraph *self) { self->everything = _sysprof_symbol_new (g_ref_string_new_intern ("[Everything]"), NULL, NULL, 0, 0); self->callers = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)g_ptr_array_unref); + self->symbol_to_bitset = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)egg_bitset_unref); self->root.symbol = self->everything; } static void sysprof_callgraph_populate_callers (SysprofCallgraph *self, - SysprofCallgraphNode *node) + SysprofCallgraphNode *node, + guint list_model_index) { GHashTable *hash; @@ -166,6 +174,7 @@ sysprof_callgraph_populate_callers (SysprofCallgraph *self, iter = iter->parent) { GPtrArray *callers; + EggBitset *bitset; guint pos; if (!(callers = g_hash_table_lookup (hash, iter->symbol))) @@ -174,6 +183,14 @@ sysprof_callgraph_populate_callers (SysprofCallgraph *self, g_hash_table_insert (hash, iter->symbol, callers); } + if (!(bitset = g_hash_table_lookup (self->symbol_to_bitset, iter->symbol))) + { + bitset = egg_bitset_new_empty (); + g_hash_table_insert (self->symbol_to_bitset, iter->symbol, bitset); + } + + egg_bitset_add (bitset, list_model_index); + g_assert (iter->parent->symbol != NULL); if (!g_ptr_array_find (callers, iter->parent->symbol, &pos)) @@ -184,7 +201,8 @@ sysprof_callgraph_populate_callers (SysprofCallgraph *self, static SysprofCallgraphNode * sysprof_callgraph_add_trace (SysprofCallgraph *self, SysprofSymbol **symbols, - guint n_symbols) + guint n_symbols, + guint list_model_index) { SysprofCallgraphNode *parent = NULL; @@ -238,14 +256,15 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self, parent = node; } - sysprof_callgraph_populate_callers (self, parent); + sysprof_callgraph_populate_callers (self, parent, list_model_index); return parent; } static void sysprof_callgraph_add_traceable (SysprofCallgraph *self, - SysprofDocumentTraceable *traceable) + SysprofDocumentTraceable *traceable, + guint list_model_index) { SysprofAddressContext final_context; SysprofCallgraphNode *node; @@ -283,7 +302,7 @@ sysprof_callgraph_add_traceable (SysprofCallgraph *self, symbols[n_symbols++] = _sysprof_document_process_symbol (self->document, pid); symbols[n_symbols++] = self->everything; - node = sysprof_callgraph_add_trace (self, symbols, n_symbols); + node = sysprof_callgraph_add_trace (self, symbols, n_symbols, list_model_index); if (node && self->augment_func) self->augment_func (self, @@ -312,7 +331,7 @@ sysprof_callgraph_new_worker (GTask *task, { g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (self->traceables, i); - sysprof_callgraph_add_traceable (self, traceable); + sysprof_callgraph_add_traceable (self, traceable, i); } g_task_return_pointer (task, g_object_ref (self), g_object_unref); @@ -408,3 +427,28 @@ sysprof_callgraph_list_callers (SysprofCallgraph *self, return G_LIST_MODEL (store); } + +/** + * sysprof_callgraph_list_traceables_for_symbol: + * @self: a #SysprofCallgraph + * @symbol: a #SysprofSymbol + * + * Gets a list of all the #SysprofTraceable within the callgraph + * that contain @symbol. + * + * Returns: (transfer full): a #GListModel of #SysprofTraceable + */ +GListModel * +sysprof_callgraph_list_traceables_for_symbol (SysprofCallgraph *self, + SysprofSymbol *symbol) +{ + EggBitset *bitset; + + g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (self), NULL); + g_return_val_if_fail (SYSPROF_IS_SYMBOL (symbol), NULL); + + if ((bitset = g_hash_table_lookup (self->symbol_to_bitset, symbol))) + return _sysprof_document_bitset_index_new (self->traceables, bitset); + + return G_LIST_MODEL (g_list_store_new (SYSPROF_TYPE_DOCUMENT_TRACEABLE)); +} diff --git a/src/libsysprof-analyze/sysprof-callgraph.h b/src/libsysprof-analyze/sysprof-callgraph.h index 1ae27b46..97355731 100644 --- a/src/libsysprof-analyze/sysprof-callgraph.h +++ b/src/libsysprof-analyze/sysprof-callgraph.h @@ -57,12 +57,15 @@ typedef void (*SysprofAugmentationFunc) (SysprofCallgraph *callgraph, gpointer user_data); SYSPROF_AVAILABLE_IN_ALL -GListModel *sysprof_callgraph_list_callers (SysprofCallgraph *self, - SysprofCallgraphFrame *frame); +GListModel *sysprof_callgraph_list_callers (SysprofCallgraph *self, + SysprofCallgraphFrame *frame); SYSPROF_AVAILABLE_IN_ALL -gpointer sysprof_callgraph_get_augment (SysprofCallgraph *self, - SysprofCallgraphNode *node); +GListModel *sysprof_callgraph_list_traceables_for_symbol (SysprofCallgraph *self, + SysprofSymbol *symbol); SYSPROF_AVAILABLE_IN_ALL -SysprofCallgraphNode *sysprof_callgraph_node_parent (SysprofCallgraphNode *node); +gpointer sysprof_callgraph_get_augment (SysprofCallgraph *self, + SysprofCallgraphNode *node); +SYSPROF_AVAILABLE_IN_ALL +SysprofCallgraphNode *sysprof_callgraph_node_parent (SysprofCallgraphNode *node); G_END_DECLS