libsysprof-analyze: implement basic callers listing

This doesn't give us augmentation data like we would have from the
existing callgraphs, but we can deal with that later.
This commit is contained in:
Christian Hergert
2023-06-06 17:30:13 -07:00
parent 434cc6ba22
commit 275869b198
2 changed files with 74 additions and 5 deletions

View File

@ -37,6 +37,8 @@ struct _SysprofCallgraph
SysprofSymbol *everything;
GHashTable *callers;
gsize augment_size;
SysprofAugmentationFunc augment_func;
gpointer augment_func_data;
@ -120,6 +122,8 @@ sysprof_callgraph_finalize (GObject *object)
{
SysprofCallgraph *self = (SysprofCallgraph *)object;
g_clear_pointer (&self->callers, g_hash_table_unref);
g_clear_object (&self->document);
g_clear_object (&self->traceables);
g_clear_object (&self->everything);
@ -142,15 +146,45 @@ static void
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->root.symbol = self->everything;
}
static void
sysprof_callgraph_populate_callers (SysprofCallgraph *self,
SysprofCallgraphNode *node)
{
GHashTable *hash;
g_assert (SYSPROF_IS_CALLGRAPH (self));
g_assert (node != NULL);
hash = self->callers;
for (const SysprofCallgraphNode *iter = node;
iter != NULL && iter->parent != NULL;
iter = iter->parent)
{
GPtrArray *callers;
if (!(callers = g_hash_table_lookup (hash, iter->symbol)))
{
callers = g_ptr_array_new ();
g_hash_table_insert (hash, iter->symbol, callers);
}
g_assert (iter->parent->symbol != NULL);
g_ptr_array_add (callers, iter->parent->symbol);
}
}
static SysprofCallgraphNode *
sysprof_callgraph_add_trace (SysprofCallgraph *self,
SysprofSymbol **symbols,
guint n_symbols)
{
SysprofCallgraphNode *parent;
SysprofCallgraphNode *parent = NULL;
g_assert (SYSPROF_IS_CALLGRAPH (self));
g_assert (n_symbols >= 2);
@ -202,6 +236,8 @@ sysprof_callgraph_add_trace (SysprofCallgraph *self,
parent = node;
}
sysprof_callgraph_populate_callers (self, parent);
return parent;
}
@ -341,3 +377,32 @@ sysprof_callgraph_node_parent (SysprofCallgraphNode *node)
{
return node->parent;
}
/**
* sysprof_callgraph_list_callers:
* @self: a #SysprofCallgraph
* @node: a #SysprofCallgraphFrame
*
* Gets a list of #SysprofSymbol that call @node.
*
* Returns: (trasfer full): a #GListModel of #SysprofSymbol
*/
GListModel *
sysprof_callgraph_list_callers (SysprofCallgraph *self,
SysprofCallgraphFrame *frame)
{
SysprofSymbol *symbol;
GListStore *store;
GPtrArray *callers;
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH (self), NULL);
g_return_val_if_fail (SYSPROF_IS_CALLGRAPH_FRAME (frame), NULL);
store = g_list_store_new (SYSPROF_TYPE_SYMBOL);
symbol = sysprof_callgraph_frame_get_symbol (frame);
if ((callers = g_hash_table_lookup (self->callers, symbol)))
g_list_store_splice (store, 0, 0, callers->pdata, callers->len);
return G_LIST_MODEL (store);
}

View File

@ -20,10 +20,11 @@
#pragma once
#include <glib-object.h>
#include <gio/gio.h>
#include <sysprof-capture.h>
#include "sysprof-callgraph-frame.h"
#include "sysprof-document-frame.h"
G_BEGIN_DECLS
@ -56,9 +57,12 @@ typedef void (*SysprofAugmentationFunc) (SysprofCallgraph *callgraph,
gpointer user_data);
SYSPROF_AVAILABLE_IN_ALL
gpointer sysprof_callgraph_get_augment (SysprofCallgraph *callgraph,
SysprofCallgraphNode *node);
GListModel *sysprof_callgraph_list_callers (SysprofCallgraph *self,
SysprofCallgraphFrame *frame);
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