summaryrefslogtreecommitdiff
path: root/src/callgraph-store.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-11-30 14:57:09 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2007-11-30 14:57:09 +0000
commit5aa3917ceb81d494f4935f50521223b4e6ca81d3 (patch)
tree2f8698c06dc8d4f9242e49b8e9412db1ed8fe539 /src/callgraph-store.c
parentb3430df2df3a8c4e02b89c96c243c062e6764997 (diff)
Emit tree model signals in order.
Diffstat (limited to 'src/callgraph-store.c')
-rw-r--r--src/callgraph-store.c247
1 files changed, 153 insertions, 94 deletions
diff --git a/src/callgraph-store.c b/src/callgraph-store.c
index 38b0d99..869b0b3 100644
--- a/src/callgraph-store.c
+++ b/src/callgraph-store.c
@@ -29,6 +29,7 @@ typedef gboolean (*TraverseFunc) (CallGraphStore *, CallGraphFrame *, gpointer);
enum {
INSERTED = 1 << 0,
+ HAS_CHILD = 1 << 1,
};
static void
@@ -361,54 +362,66 @@ _call_graph_frame_key_cmp (gconstpointer A, gconstpointer B)
static CallGraphFrame *
_call_graph_frame_new (CallGraphStore *store,
- CallGraphFrame *parent,
- guint ip,
- const gchar *srcloc,
- const gchar *function)
+ const Allocator *A,
+ guint depth,
+ CallGraphFrame *parent)
{
CallGraphFrame *frame;
+ CallGraphFrame *node, **prev;
+ const AllocatorTime *At = A->time_tail;
+ guint index;
+ guint n, max;
frame = _call_graph_frame_alloc (store);
- frame->ip = ip;
- frame->frame = srcloc;
- frame->function = function;
+
+ frame->allocator = A;
+ frame->depth = depth;
+
+ frame->ip = A->ips[depth];
+ frame->frame = A->functions_srcloc[depth];
+ frame->function = A->functions[depth];
+
frame->parent = parent;
frame->next = store->frames;
store->frames = frame;
- if (parent != NULL) {
- CallGraphFrame *node, **prev;
- guint index;
-
- parent->children = _tree_insert (parent->children,
- &frame->node,
- _call_graph_frame_node_cmp);
-
- index = (ip ^ 6017773) % store->frames_by_ip.size;
- prev = &store->frames_by_ip.nodes[index];
- while ((node = *prev) != NULL && node->ip != ip)
- prev = &node->ht_next_by_ip;
- if (node != NULL) {
- frame->next_by_ip = node;
- *prev = node->ht_next_by_ip;
- node->ht_next_by_ip = NULL;
- }
- frame->ht_next_by_ip = store->frames_by_ip.nodes[index];
- store->frames_by_ip.nodes[index] = frame;
-
- index = (GPOINTER_TO_UINT (function) ^ 6017773) % store->frames_by_fn.size;
- prev = &store->frames_by_fn.nodes[index];
- while ((node = *prev) != NULL && node->function != function)
- prev = &node->ht_next_by_fn;
- if (node != NULL) {
- frame->next_by_fn = node;
- *prev = node->ht_next_by_fn;
- node->ht_next_by_fn = NULL;
- }
- frame->ht_next_by_fn = store->frames_by_fn.nodes[index];
- store->frames_by_fn.nodes[index] = frame;
+ frame->bytes = At->bytes;
+ frame->allocs = At->n_allocs;
+ frame->frees = At->n_frees;
+
+ max = At->max_size_alloc;
+ for (n = 0; n < max; n++)
+ frame->size_allocs[n] = At->size_allocs[n];
+
+
+ parent->children = _tree_insert (parent->children,
+ &frame->node,
+ _call_graph_frame_node_cmp);
+
+ index = (frame->ip ^ 6017773) % store->frames_by_ip.size;
+ prev = &store->frames_by_ip.nodes[index];
+ while ((node = *prev) != NULL && node->ip != frame->ip)
+ prev = &node->ht_next_by_ip;
+ if (node != NULL) {
+ frame->next_by_ip = node;
+ *prev = node->ht_next_by_ip;
+ node->ht_next_by_ip = NULL;
}
+ frame->ht_next_by_ip = store->frames_by_ip.nodes[index];
+ store->frames_by_ip.nodes[index] = frame;
+
+ index = (GPOINTER_TO_UINT (frame->function) ^ 6017773) % store->frames_by_fn.size;
+ prev = &store->frames_by_fn.nodes[index];
+ while ((node = *prev) != NULL && node->function != frame->function)
+ prev = &node->ht_next_by_fn;
+ if (node != NULL) {
+ frame->next_by_fn = node;
+ *prev = node->ht_next_by_fn;
+ node->ht_next_by_fn = NULL;
+ }
+ frame->ht_next_by_fn = store->frames_by_fn.nodes[index];
+ store->frames_by_fn.nodes[index] = frame;
return frame;
}
@@ -509,7 +522,7 @@ _call_graph_store_get_iter (GtkTreeModel *tree_model,
depth = gtk_tree_path_get_depth (path);
i = gtk_tree_path_get_indices (path);
- frame = self->root;
+ frame = &self->root;
for (n = 1; n < depth; n++) {
if ((guint) i[n] >= frame->n_filter)
return FALSE;
@@ -611,7 +624,7 @@ _call_graph_store_iter_children (GtkTreeModel *tree_model,
iter->user_data = frame->filter[0];
} else
- iter->user_data = self->root;
+ iter->user_data = &self->root;
return TRUE;
}
@@ -650,7 +663,7 @@ _call_graph_store_iter_nth_child (GtkTreeModel *tree_model,
if (n >= 1)
return FALSE;
iter->stamp = self->stamp;
- iter->user_data = self->root;
+ iter->user_data = &self->root;
return TRUE;
}
@@ -707,8 +720,9 @@ simple_hash_table_init (SimpleHashTable *ht, guint size)
static void
call_graph_store_init (CallGraphStore *self)
{
- self->root = _call_graph_frame_new (self, NULL, 0,
- "Everything", "Everything");
+ self->root.frame = self->root.function = "Everything";
+ self->root.depth = -1;
+ self->frames = &self->root;
/* XXX */
simple_hash_table_init (&self->frames_by_ip, 20000);
@@ -743,35 +757,22 @@ emit_tree_model_reorder (CallGraphFrame *frame,
{
gint new_order_stack[1024];
gint *new_order;
- guint n;
-
- g_print ("reorder\n");
+ guint n, m;
if (frame->old_n_filter > G_N_ELEMENTS (new_order_stack))
new_order = g_new (gint, frame->old_n_filter);
else
new_order = new_order_stack;
- for (n = 0; n < frame->old_n_filter; n++)
- new_order[n] = frame->old_filter[n]->index;
-
- /* exclude children we haven't inserted yet */
- if (frame->old_n_filter != frame->n_filter) {
- for (n = 0; n < frame->n_filter; n++) {
- if (! (frame->filter[n]->flags & INSERTED)) {
- guint m;
- for (m = 0; m < frame->old_n_filter; m++)
- if ((guint) new_order[m] >= frame->filter[n]->index)
- new_order[m]--;
- }
- }
- }
+ for (n = m = 0; n < frame->n_filter; n++)
+ if (frame->filter[n]->flags & INSERTED)
+ new_order[m++] = frame->filter[n]->old_index;
- /* XXX */
- n = frame->n_filter;
- frame->n_filter = frame->old_n_filter;
+ frame->n_filter = m;
- gtk_tree_model_rows_reordered (model, path, iter, new_order);
+ gtk_tree_model_rows_reordered (model, path,
+ frame->filter_parent == NULL ? NULL : iter,
+ new_order);
frame->n_filter = n;
@@ -785,14 +786,11 @@ emit_tree_model_signals (CallGraphFrame *frame, CallGraphStore *store)
GtkTreeModel *model = (GtkTreeModel *) store;
GtkTreeIter iter;
GtkTreePath *path;
+ guint n;
if (frame->stamp != store->stamp)
return;
- if (frame->is_alloc_fn)
- return _call_graph_frame_foreach_child (frame,
- (GFunc) emit_tree_model_signals, store);
-
iter.stamp = store->stamp;
iter.user_data = frame;
path = gtk_tree_model_get_path (model, &iter);
@@ -807,18 +805,76 @@ emit_tree_model_signals (CallGraphFrame *frame, CallGraphStore *store)
}
gtk_tree_model_row_changed (model, path, &iter);
+
+ if (! (frame->flags & HAS_CHILD) && frame->children != NULL) {
+ frame->flags |= HAS_CHILD;
+ gtk_tree_model_row_has_child_toggled (model, path, &iter);
+ }
} else {
- gtk_tree_model_row_inserted (model, path, &iter);
- if (frame->children != NULL)
+ if (frame->parent != NULL)
+ gtk_tree_model_row_inserted (model, path, &iter);
+ if (frame->children != NULL) {
+ frame->flags |= HAS_CHILD;
gtk_tree_model_row_has_child_toggled (model, path, &iter);
+ }
frame->flags |= INSERTED;
}
gtk_tree_path_free (path);
- _call_graph_frame_foreach_child (frame,
- (GFunc) emit_tree_model_signals, store);
+ for (n = 0; n < frame->n_filter; n++)
+ emit_tree_model_signals (frame->filter[n], store);
+}
+
+void
+call_graph_store_update_tree_model (CallGraphStore *store)
+{
+ CallGraphFrame *frame;
+
+ if (store->nodes == NULL)
+ return;
+
+ emit_tree_model_signals (&store->root, store);
+
+ for (frame = store->frames; frame != NULL; frame = frame->next) {
+ frame->old_filter = frame->filter;
+ frame->old_n_filter = frame->n_filter;
+ frame->old_index = frame->index;
+ }
+
+ g_free (store->old_nodes);
+ store->old_nodes = store->nodes;
+ store->nodes = NULL;
+}
+
+static void
+validate_sums (CallGraphFrame *frame)
+{
+ guint n;
+ guint allocs = 0, frees = 0;
+ guint64 bytes = 0;
+
+ for (n = 0; n < frame->n_filter; n++){
+ allocs += frame->filter[n]->allocs;
+ frees += frame->filter[n]->frees;
+ bytes += frame->filter[n]->bytes;
+ }
+
+ g_print ("%s\n", frame->frame);
+ g_print ("f->allocs=%d, f->frees=%d, f->bytes=%" G_GUINT64_FORMAT "\n",
+ frame->allocs, frame->frees, frame->bytes);
+ g_print ("allocs=%d, frees=%d, bytes=%" G_GUINT64_FORMAT "\n",
+ allocs, frees, bytes);
+
+ g_assert (allocs == frame->allocs);
+ g_assert (frees == frame->frees);
+ g_assert (bytes == frame->bytes);
+
+ g_assert (allocs >= frees);
+
+ for (n = 0; n < frame->n_filter; n++)
+ validate_sums (frame->filter[n]);
}
void
@@ -827,13 +883,11 @@ call_graph_store_update (CallGraphStore *store,
Allocator *allocators,
guint since)
{
- static AllocatorTime nil;
+ static const AllocatorTime nil;
Allocator *A;
CallGraphFrame *frame, *child, *eol;
guint n, new, updated;
- g_assert (store != NULL);
-
if (++store->stamp == 0)
store->stamp = 1;
@@ -853,7 +907,7 @@ call_graph_store_update (CallGraphStore *store,
if (At->max_size_alloc > store->max_size_alloc)
store->max_size_alloc = At->max_size_alloc;
- frame = store->root;
+ frame = &store->root;
_call_graph_frame_accumulate (frame, At, Ap);
frame->stamp = store->stamp;
for (n = 0; n < A->n_frames; n++) {
@@ -863,16 +917,17 @@ call_graph_store_update (CallGraphStore *store,
GUINT_TO_POINTER (A->ips[n]),
_call_graph_frame_key_cmp);
if (child == NULL) {
- child = _call_graph_frame_new (store, frame,
- A->ips[n],
- A->functions_srcloc[n],
- A->functions[n]);
+ child = _call_graph_frame_new (store, A, n, frame);
new++;
- }
+ } else
+ _call_graph_frame_accumulate (child, At, Ap);
+ child->stamp = store->stamp;
+
+ if (child->allocator == A)
+ break;
+ child->allocator = NULL;
+
frame = child;
- g_assert (frame != NULL);
- _call_graph_frame_accumulate (frame, At, Ap);
- frame->stamp = store->stamp;
}
updated++;
}
@@ -880,6 +935,8 @@ call_graph_store_update (CallGraphStore *store,
store->n_frames += new;
if (updated)
call_graph_store_filter (store, app);
+
+ validate_sums (&store->root);
}
static void
@@ -925,9 +982,11 @@ _call_graph_frame_add_children (CallGraphFrame *frame, CallGraphFrame *parent)
_call_graph_frame_foreach_child (frame,
(GFunc) _call_graph_frame_add_children, frame);
+#if 0
qsort (frame->filter,
frame->n_filter, sizeof (CallGraphFrame *),
_call_graph_frame_cmp);
+#endif
for (n = 0; n < frame->n_filter; n++)
frame->filter[n]->index = n;
@@ -952,21 +1011,22 @@ call_graph_store_filter (CallGraphStore *store, App *app)
guint serial = app_get_alloc_fns_serial (app);
guint n;
- root = store->root;
+ root = &store->root;
root->stamp = store->stamp; /* force an update of the root node */
//if (store->alloc_fns_serial != serial)
+#if 0
_call_graph_frame_foreach_child (root,
(GFunc) _call_graph_frame_is_alloc, app);
+#endif
store->alloc_fns_serial = serial;
- nodes = children = g_new (CallGraphFrame *, 2*store->n_frames);
+ nodes = store->nodes;
+ store->nodes = g_new (CallGraphFrame *, 2*store->n_frames);
+ children = store->nodes;
for (frame = store->frames; frame != NULL; frame = frame->next) {
- frame->old_filter = frame->filter;
- frame->old_n_filter = frame->n_filter;
-
if (frame->stamp == store->stamp) {
frame->n_filter = 0;
frame->filter = NULL;
@@ -986,24 +1046,23 @@ call_graph_store_filter (CallGraphStore *store, App *app)
children += frame->n_filter;
}
}
+ g_assert (children == store->nodes + store->n_frames);
+ g_free (nodes);
root->filter = children;
g_assert (root->n_filter == 0);
_call_graph_frame_foreach_child (root,
(GFunc) _call_graph_frame_add_filtered, root);
+#if 0
qsort (root->filter,
root->n_filter, sizeof (CallGraphFrame *),
_call_graph_frame_cmp);
+#endif
for (n = 0; n < root->n_filter; n++)
root->filter[n]->index = n;
- g_free (store->old_nodes);
- store->old_nodes = store->nodes;
- store->nodes = nodes;
-
- emit_tree_model_signals (store->root, store);
g_signal_emit (store, signals[FILTERED], 0);
}