(Apply part of commit
dbf2db8 from 'paulbone/mercury7_4_pbone' branch.)
This can be used to do heap profiling, helping the developer work out which
objects are live or what kinds of objects account for a lot of their heap
space.
* alloc.c:
* include/gc.h:
* include/private/gc_priv.h:
* reclaim.c:
As above.
word GC_gc_no = 0;
+void (*GC_mercury_callback_reachable_object)(GC_word *, size_t) = NULL;
+ /* Callbacks for mercury to notify */
+ /* the runtime of certain events */
+
#ifndef GC_DISABLE_INCREMENTAL
GC_INNER int GC_incremental = 0; /* By default, stop the world. */
#endif
}
# endif
COND_DUMP;
+ if (GC_mercury_callback_reachable_object) {
+ GC_mercury_enumerate_reachable_objects();
+ }
if (GC_find_leak) {
/* Mark all objects on the free list. All objects should be */
/* marked when we're done. */
GC_API void GC_CALL GC_set_time_limit(unsigned long);
GC_API unsigned long GC_CALL GC_get_time_limit(void);
+GC_API void (*GC_mercury_callback_reachable_object)(GC_word *, size_t);
+ /* This object on the heap is reachable. */
+
/* Public procedures */
/* Set whether the GC will allocate executable memory pages or not. */
extern word GC_fo_entries; /* should be visible in extra/MacOS.c */
+GC_INNER void GC_mercury_enumerate_reachable_objects(void);
+
#ifdef KEEP_BACK_PTRS
GC_INNER void GC_store_back_pointer(ptr_t source, ptr_t dest);
GC_INNER void GC_marked_for_finalization(ptr_t dest);
}
}
#endif /* !EAGER_SWEEP && ENABLE_DISCLAIM */
+
+STATIC void GC_mercury_do_enumerate_reachable_objects(struct hblk *hbp,
+ word dummy)
+{
+ struct hblkhdr * hhdr = HDR(hbp);
+ size_t sz = hhdr -> hb_sz;
+ size_t bit_no;
+ char *p, *plim;
+
+ if (GC_block_empty(hhdr)) {
+ return;
+ }
+
+ p = hbp->hb_body;
+ bit_no = 0;
+ if (sz > MAXOBJBYTES) { /* one big object */
+ plim = p;
+ } else {
+ plim = hbp->hb_body + HBLKSIZE - sz;
+ }
+ /* Go through all words in block. */
+ while (p <= plim) {
+ if (mark_bit_from_hdr(hhdr, bit_no)) {
+ GC_mercury_callback_reachable_object((GC_word *)p,
+ BYTES_TO_WORDS(sz));
+ }
+ bit_no += MARK_BIT_OFFSET(sz);
+ p += sz;
+ }
+}
+
+GC_INNER void GC_mercury_enumerate_reachable_objects(void)
+{
+ GC_ASSERT(GC_mercury_callback_reachable_object);
+ GC_apply_to_all_blocks(GC_mercury_do_enumerate_reachable_objects, (word)0);
+}