+/* Helper function for prune_overhead_list. See if SLOT is still marked and
+ remove it from hashtable if it is not. */
+static int
+ggc_prune_ptr (void **slot, void *b ATTRIBUTE_UNUSED)
+{
+ struct ptr_hash_entry *p = *slot;
+ if (!ggc_marked_p (p->ptr))
+ {
+ p->loc->collected += p->size;
+ htab_clear_slot (ptr_hash, slot);
+ free (p);
+ }
+ return 1;
+}
+
+/* After live values has been marked, walk all recorded pointers and see if
+ they are still live. */
+void
+ggc_prune_overhead_list (void)
+{
+ htab_traverse (ptr_hash, ggc_prune_ptr, NULL);
+}
+
+/* Notice that the pointer has been freed. */
+void
+ggc_free_overhead (void *ptr)
+{
+ PTR *slot = htab_find_slot_with_hash (ptr_hash, ptr, htab_hash_pointer (ptr),
+ NO_INSERT);
+ struct ptr_hash_entry *p = *slot;
+ p->loc->freed += p->size;
+ htab_clear_slot (ptr_hash, slot);
+ free (p);
+}
+
+/* Helper for qsort; sort descriptors by amount of memory consumed. */
+static int
+final_cmp_statistic (const void *loc1, const void *loc2)
+{
+ struct loc_descriptor *l1 = *(struct loc_descriptor **) loc1;
+ struct loc_descriptor *l2 = *(struct loc_descriptor **) loc2;
+ long diff;
+ diff = ((long)(l1->allocated + l1->overhead - l1->freed) -
+ (l2->allocated + l2->overhead - l2->freed));
+ return diff > 0 ? 1 : diff < 0 ? -1 : 0;
+}
+