diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2007-11-30 14:57:09 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2007-11-30 14:57:09 +0000 |
commit | 5aa3917ceb81d494f4935f50521223b4e6ca81d3 (patch) | |
tree | 2f8698c06dc8d4f9242e49b8e9412db1ed8fe539 /src/callgraph-store.c | |
parent | b3430df2df3a8c4e02b89c96c243c062e6764997 (diff) |
Emit tree model signals in order.
Diffstat (limited to 'src/callgraph-store.c')
-rw-r--r-- | src/callgraph-store.c | 247 |
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); } |