From: Paolo Molaro Date: Tue, 2 Nov 2010 17:44:29 +0000 (+0100) Subject: Introduced a GC heap walk API. X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=aa765be136cdc33254d5e92a439647f064fa3837;p=mono.git Introduced a GC heap walk API. This API is currently only implemented for the sgen GC. It can be used to iterate over all the managed objects in the heap and it allows to also easily track object references. --- diff --git a/mono/metadata/boehm-gc.c b/mono/metadata/boehm-gc.c index efe635e4cf4..29ddb8a43a9 100644 --- a/mono/metadata/boehm-gc.c +++ b/mono/metadata/boehm-gc.c @@ -320,6 +320,12 @@ mono_object_is_alive (MonoObject* o) #endif } +int +mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data) +{ + return 1; +} + #ifdef USE_INCLUDED_LIBGC static gint64 gc_start_time; diff --git a/mono/metadata/mono-gc.h b/mono/metadata/mono-gc.h index 750b6540db6..a09f9a12ed7 100644 --- a/mono/metadata/mono-gc.h +++ b/mono/metadata/mono-gc.h @@ -9,6 +9,8 @@ MONO_BEGIN_DECLS +typedef int (*MonoGCReferences) (MonoObject *obj, MonoClass *klass, uintptr_t size, uintptr_t num, MonoObject **refs, void *data); + void mono_gc_collect (int generation); int mono_gc_max_generation (void); int mono_gc_get_generation (MonoObject *object); @@ -16,6 +18,8 @@ int mono_gc_collection_count (int generation); int64_t mono_gc_get_used_size (void); int64_t mono_gc_get_heap_size (void); int mono_gc_invoke_finalizers (void); +/* heap walking is only valid in the pre-stop-world event callback */ +int mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data); MONO_END_DECLS diff --git a/mono/metadata/null-gc.c b/mono/metadata/null-gc.c index 324d3d5c59c..0da8410c09d 100644 --- a/mono/metadata/null-gc.c +++ b/mono/metadata/null-gc.c @@ -80,6 +80,12 @@ mono_gc_register_thread (void *baseptr) return TRUE; } +int +mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data) +{ + return 1; +} + gboolean mono_object_is_alive (MonoObject* o) { diff --git a/mono/metadata/sgen-gc.c b/mono/metadata/sgen-gc.c index 9384e7e0698..e2a7ee99560 100644 --- a/mono/metadata/sgen-gc.c +++ b/mono/metadata/sgen-gc.c @@ -6192,6 +6192,82 @@ check_object (char *start) * ###################################################################### */ +#define REFS_SIZE 128 +typedef struct { + void *data; + MonoGCReferences callback; + int flags; + int count; + int called; + MonoObject *refs [REFS_SIZE]; +} HeapWalkInfo; + +#undef HANDLE_PTR +#define HANDLE_PTR(ptr,obj) do { \ + if (*(ptr)) { \ + if (hwi->count == REFS_SIZE) { \ + hwi->callback ((MonoObject*)start, mono_object_class (start), hwi->called? 0: size, hwi->count, hwi->refs, hwi->data); \ + hwi->count = 0; \ + hwi->called = 1; \ + } \ + hwi->refs [hwi->count++] = *(ptr); \ + } \ + } while (0) + +static void +collect_references (HeapWalkInfo *hwi, char *start, size_t size) +{ +#include "sgen-scan-object.h" +} + +static void +walk_references (char *start, size_t size, void *data) +{ + HeapWalkInfo *hwi = data; + hwi->called = 0; + hwi->count = 0; + collect_references (hwi, start, size); + if (hwi->count || !hwi->called) + hwi->callback ((MonoObject*)start, mono_object_class (start), hwi->called? 0: size, hwi->count, hwi->refs, hwi->data); +} + +/** + * mono_gc_walk_heap: + * @flags: flags for future use + * @callback: a function pointer called for each object in the heap + * @data: a user data pointer that is passed to callback + * + * This function can be used to iterate over all the live objects in the heap: + * for each object, @callback is invoked, providing info about the object's + * location in memory, its class, its size and the objects it references. + * The object references may be buffered, so the callback may be invoked + * multiple times for the same object: in all but the first call, the size + * argument will be zero. + * Note that this function can be only called in the #MONO_GC_EVENT_PRE_START_WORLD + * profiler event handler. + * + * Returns: a non-zero value if the GC doesn't support heap walking + */ +int +mono_gc_walk_heap (int flags, MonoGCReferences callback, void *data) +{ + HeapWalkInfo hwi; + LOSObject *bigobj; + + hwi.flags = flags; + hwi.callback = callback; + hwi.data = data; + + clear_nursery_fragments (nursery_next); + mono_sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, walk_references, &hwi); + + major_collector.iterate_objects (TRUE, TRUE, walk_references, &hwi); + + for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) + walk_references (bigobj->data, bigobj->size, &hwi); + return 0; +} + void mono_gc_collect (int generation) {