[runtime] Move profiler allocation reporting to GC implementations.
authorAlex Rønne Petersen <alexrp@xamarin.com>
Wed, 13 May 2015 11:53:52 +0000 (13:53 +0200)
committerAlex Rønne Petersen <alexrp@xamarin.com>
Fri, 15 May 2015 13:16:09 +0000 (15:16 +0200)
By reporting allocations in the GC implementations, we significantly reduce the
odds of someone forgetting to add a mono_profiler_allocation () call. These
previously had to be placed at all call sites of mono_gc_alloc_* () which was
in some cases forgotten, resulting in the profiler seeing objects in GC events
which appeared to not have been allocated.

mono/metadata/boehm-gc.c
mono/metadata/gc-internal.h
mono/metadata/null-gc.c
mono/metadata/object.c
mono/metadata/profiler-private.h
mono/metadata/profiler.c
mono/metadata/sgen-mono.c

index 3030ce8ade3f342f376718d524c3886c7608df86..9fa40cb0beaf98a091e00e34b8272e4d34d2c6fb 100644 (file)
@@ -460,6 +460,14 @@ mono_gc_enable_events (void)
        GC_on_heap_resize = on_gc_heap_resize;
 }
 
+static gboolean alloc_events = FALSE;
+
+void
+mono_gc_enable_alloc_events (void)
+{
+       alloc_events = TRUE;
+}
+
 int
 mono_gc_register_root (char *start, size_t size, void *descr)
 {
@@ -595,6 +603,9 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
                obj->vtable = vtable;
        }
 
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
        return obj;
 }
 
@@ -620,6 +631,9 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
 
        obj->max_length = max_length;
 
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&obj->obj);
+
        return obj;
 }
 
@@ -648,6 +662,9 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
        if (bounds_size)
                obj->bounds = (MonoArrayBounds *) ((char *) obj + size - bounds_size);
 
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&obj->obj);
+
        return obj;
 }
 
@@ -661,6 +678,9 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
        obj->length = len;
        obj->chars [len] = 0;
 
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&obj->object);
+
        return obj;
 }
 
index 5b8e22ea2ee981a06e0ab68c39dad1693f103624..fb92eb0754b5c29ec9d901859186f4f63a59067b 100644 (file)
@@ -102,6 +102,7 @@ gboolean mono_object_is_alive (MonoObject* obj);
 gboolean mono_gc_is_finalizer_thread (MonoThread *thread);
 gpointer mono_gc_out_of_memory (size_t size);
 void     mono_gc_enable_events (void);
+void     mono_gc_enable_alloc_events (void);
 
 /* disappearing link functionality */
 void        mono_gc_weak_link_add    (void **link_addr, MonoObject *obj, gboolean track);
index d16c6aab36c6f00f6e7a9becb335e49e9ca7aaa9..e43ca5017dd472b5360045aa8425989f04f6bebd 100644 (file)
@@ -106,6 +106,11 @@ mono_gc_enable_events (void)
 {
 }
 
+void
+mono_gc_enable_alloc_events (void)
+{
+}
+
 int
 mono_gc_register_root (char *start, size_t size, void *descr)
 {
index a86dd7286789a83c0e64d21204bc3d147d1b3d8e..5aea823b48b27b068991d15c1b7b1200b2cf0d83 100644 (file)
@@ -70,8 +70,6 @@ mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s,
 #define ldstr_unlock() mono_mutex_unlock (&ldstr_section)
 static mono_mutex_t ldstr_section;
 
-static gboolean profile_allocs = TRUE;
-
 void
 mono_runtime_object_init (MonoObject *this)
 {
@@ -4420,9 +4418,6 @@ mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *p
 {
        *pass_size_in_words = FALSE;
 
-       if (!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
-               profile_allocs = FALSE;
-
        if (mono_class_has_finalizer (vtable->klass) || mono_class_is_marshalbyref (vtable->klass) || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
                return mono_object_new_specific;
 
@@ -4488,9 +4483,6 @@ mono_object_clone (MonoObject *obj)
        /* If the object doesn't contain references this will do a simple memmove. */
        mono_gc_wbarrier_object_copy (o, obj);
 
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, obj->vtable->klass);
-
        if (obj->vtable->klass->has_finalize)
                mono_object_register_finalizer (o);
        return o;
@@ -4713,9 +4705,6 @@ mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *leng
                }
        }
 
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, array_class);
-
        return array;
 }
 
@@ -4765,9 +4754,6 @@ mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
        o = mono_gc_alloc_vector (vtable, byte_len, n);
        ao = (MonoArray*)o;
 
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (o, vtable->klass);
-
        return ao;
 }
 
@@ -4849,8 +4835,6 @@ mono_string_new_size (MonoDomain *domain, gint32 len)
        g_assert (vtable);
 
        s = mono_gc_alloc_string (vtable, size, len);
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation ((MonoObject*)s, mono_defaults.string_class);
 
        return s;
 }
@@ -4969,8 +4953,6 @@ mono_value_box (MonoDomain *domain, MonoClass *class, gpointer value)
                return NULL;
        size = mono_class_instance_size (class);
        res = mono_object_new_alloc_specific (vtable);
-       if (G_UNLIKELY (profile_allocs))
-               mono_profiler_allocation (res, class);
 
        size = size - sizeof (MonoObject);
 
index 9bf9c7bb8319304e0f99daf2a6f4d5a569b8eac1..ab329842c732fc60ec7dd3679e2c0fb34cfd7ea8 100644 (file)
@@ -34,7 +34,7 @@ void mono_profiler_method_start_invoke (MonoMethod *method);
 void mono_profiler_method_end_invoke   (MonoMethod *method);
 
 void mono_profiler_code_transition (MonoMethod *method, int result);
-void mono_profiler_allocation      (MonoObject *obj, MonoClass *klass);
+void mono_profiler_allocation      (MonoObject *obj);
 void mono_profiler_monitor_event   (MonoObject *obj, MonoProfilerMonitorEvent event);
 void mono_profiler_stat_hit        (guchar *ip, void *context);
 void mono_profiler_stat_call_chain (int call_chain_depth, guchar **ips, void *context);
index 6c99a60b788fcfcca60582a0e2c299c086f584e9..de98dda347697f2e233dd1a7aabf34d43bfc97ff 100644 (file)
@@ -261,6 +261,7 @@ mono_profiler_install_transition (MonoProfileMethodResult callback)
 void 
 mono_profiler_install_allocation (MonoProfileAllocFunc callback)
 {
+       mono_gc_enable_alloc_events ();
        if (!prof_list)
                return;
        prof_list->allocation_cb = callback;
@@ -500,12 +501,12 @@ mono_profiler_code_transition (MonoMethod *method, int result)
 }
 
 void 
-mono_profiler_allocation (MonoObject *obj, MonoClass *klass)
+mono_profiler_allocation (MonoObject *obj)
 {
        ProfilerDesc *prof;
        for (prof = prof_list; prof; prof = prof->next) {
                if ((prof->events & MONO_PROFILE_ALLOCATIONS) && prof->allocation_cb)
-                       prof->allocation_cb (prof->profiler, obj, klass);
+                       prof->allocation_cb (prof->profiler, obj, obj->vtable->klass);
        }
 }
 
index 9f4830236bf6bedc0531f278930117cbc6dcf3d1..dc99b32b28b92943a7488de5f61229713e0cecd5 100644 (file)
@@ -923,24 +923,47 @@ mono_gc_clear_domain (MonoDomain * domain)
  * Allocation
  */
 
+static gboolean alloc_events = FALSE;
+
+void
+mono_gc_enable_alloc_events (void)
+{
+       alloc_events = TRUE;
+}
+
 void*
 mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
 {
-       return sgen_alloc_obj (vtable, size);
+       MonoObject *obj = sgen_alloc_obj (vtable, size);
+
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
+       return obj;
 }
 
 void*
 mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size)
 {
-       return sgen_alloc_obj_pinned (vtable, size);
+       MonoObject *obj = sgen_alloc_obj_pinned (vtable, size);
+
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
+       return obj;
 }
 
 void*
 mono_gc_alloc_mature (MonoVTable *vtable)
 {
        MonoObject *obj = sgen_alloc_obj_mature (vtable, vtable->klass->instance_size);
+
        if (obj && G_UNLIKELY (obj->vtable->klass->has_finalize))
                mono_object_register_finalizer (obj);
+
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
        return obj;
 }
 
@@ -1688,6 +1711,9 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
        UNLOCK_GC;
 
  done:
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&arr->obj);
+
        SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size ((GCVTable*)vtable, (GCObject*)arr)), "Vector has incorrect size.");
        return arr;
 }
@@ -1733,6 +1759,9 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
        UNLOCK_GC;
 
  done:
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&arr->obj);
+
        SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size ((GCVTable*)vtable, (GCObject*)arr)), "Array has incorrect size.");
        return arr;
 }
@@ -1753,7 +1782,7 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
                /*This doesn't require fencing since EXIT_CRITICAL_REGION already does it for us*/
                str->length = len;
                EXIT_CRITICAL_REGION;
-               return str;
+               goto done;
        }
        EXIT_CRITICAL_REGION;
 #endif
@@ -1770,6 +1799,10 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
 
        UNLOCK_GC;
 
+ done:
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&str->object);
+
        return str;
 }