[dtrace] Probe for pinning of objects.
[mono.git] / mono / metadata / sgen-marksweep.c
index 0da8af8f2e3ea296e09540bcb52623d9db7f98b4..72cd5c5b4a3732615761733183e2e4c8c6620a8f 100644 (file)
@@ -42,6 +42,7 @@
 #include "metadata/sgen-gc.h"
 #include "metadata/sgen-protocol.h"
 #include "metadata/sgen-cardtable.h"
+#include "metadata/sgen-memory-governor.h"
 #include "metadata/gc-internal.h"
 
 #define MS_BLOCK_SIZE  (16*1024)
@@ -100,7 +101,7 @@ struct _MSBlockInfo {
 };
 
 #ifdef FIXED_HEAP
-static int ms_heap_num_blocks = MS_DEFAULT_HEAP_NUM_BLOCKS;
+static mword ms_heap_num_blocks = MS_DEFAULT_HEAP_NUM_BLOCKS;
 
 static char *ms_heap_start;
 static char *ms_heap_end;
@@ -303,18 +304,18 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
        char *nursery_start;
        mword major_heap_size = ms_heap_num_blocks * MS_BLOCK_SIZE;
        mword alloc_size = nursery_size + major_heap_size;
-       int i;
+       mword i;
 
        g_assert (ms_heap_num_blocks > 0);
        g_assert (nursery_size % MS_BLOCK_SIZE == 0);
        if (nursery_align)
                g_assert (nursery_align % MS_BLOCK_SIZE == 0);
 
-       nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, TRUE);
+       nursery_start = sgen_alloc_os_memory_aligned (alloc_size, nursery_align ? nursery_align : MS_BLOCK_SIZE, TRUE, TRUE, "heap");
        ms_heap_start = nursery_start + nursery_size;
        ms_heap_end = ms_heap_start + major_heap_size;
 
-       block_infos = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo) * ms_heap_num_blocks, INTERNAL_MEM_MS_BLOCK_INFO);
+       block_infos = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo) * ms_heap_num_blocks, INTERNAL_MEM_MS_BLOCK_INFO, TRUE);
 
        for (i = 0; i < ms_heap_num_blocks; ++i) {
                block_infos [i].block = ms_heap_start + i * MS_BLOCK_SIZE;
@@ -335,9 +336,9 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
 {
        char *start;
        if (nursery_align)
-               start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE);
+               start = sgen_alloc_os_memory_aligned (nursery_size, nursery_align, TRUE, TRUE, "nursery");
        else
-               start = sgen_alloc_os_memory (nursery_size, TRUE);
+               start = sgen_alloc_os_memory (nursery_size, TRUE, TRUE, "nursery");
 
        return start;
 }
@@ -376,7 +377,7 @@ ms_free_block (MSBlockInfo *block)
        empty_blocks = block;
        block->used = FALSE;
        block->zeroed = FALSE;
-       sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+       sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
 }
 #else
 static void*
@@ -388,7 +389,7 @@ ms_get_empty_block (void)
 
  retry:
        if (!empty_blocks) {
-               p = sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE);
+               p = sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * MS_BLOCK_ALLOC_NUM, MS_BLOCK_SIZE, TRUE, TRUE, "major heap section");
 
                for (i = 0; i < MS_BLOCK_ALLOC_NUM; ++i) {
                        block = p;
@@ -431,7 +432,7 @@ ms_free_block (void *block)
 {
        void *empty;
 
-       sgen_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+       sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
        memset (block, 0, MS_BLOCK_SIZE);
 
        do {
@@ -548,7 +549,7 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
        char *obj_start;
        int i;
 
-       if (!sgen_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
+       if (!sgen_memgov_try_alloc_space (MS_BLOCK_SIZE, SPACE_MAJOR))
                return FALSE;
 
 #ifdef FIXED_HEAP
@@ -801,8 +802,8 @@ major_alloc_small_pinned_obj (size_t size, gboolean has_references)
          *as pinned alloc is requested by the runtime.
          */
         if (!res) {
-                sgen_collect_major_no_lock ("pinned alloc failure");
-                res = alloc_obj (size, TRUE, has_references);
+               sgen_perform_collection (0, GENERATION_OLD, "pinned alloc failure");
+               res = alloc_obj (size, TRUE, has_references);
         }
         return res;
 }
@@ -934,6 +935,50 @@ major_is_valid_object (char *object)
        return FALSE;
 }
 
+
+static gboolean
+major_describe_pointer (char *ptr)
+{
+       MSBlockInfo *block;
+
+       FOREACH_BLOCK (block) {
+               int idx;
+               char *obj;
+               gboolean live;
+               MonoVTable *vtable;
+
+               if ((block->block > ptr) || ((block->block + MS_BLOCK_SIZE) <= ptr))
+                       continue;
+
+               fprintf (gc_debug_file, "major-ptr (block %p sz %d pin %d ref %d) ",
+                       block->block, block->obj_size, block->pinned, block->has_references);
+
+               idx = MS_BLOCK_OBJ_INDEX (ptr, block);
+               obj = (char*)MS_BLOCK_OBJ (block, idx);
+               live = MS_OBJ_ALLOCED (obj, block);
+               vtable = live ? (MonoVTable*)SGEN_LOAD_VTABLE (obj) : NULL;
+               
+               if (obj == ptr) {
+                       if (live)
+                               fprintf (gc_debug_file, "(object %s.%s)", vtable->klass->name_space, vtable->klass->name);
+                       else
+                               fprintf (gc_debug_file, "(dead-object)");
+               } else {
+                       if (live)
+                               fprintf (gc_debug_file, "(interior-ptr offset %td of %p %s.%s)",
+                                       ptr - obj,
+                                       obj, vtable->klass->name_space, vtable->klass->name);
+                       else
+                               fprintf (gc_debug_file, "(dead-interior-ptr to %td to %p)",
+                                       ptr - obj, obj);
+               }
+
+               return TRUE;
+       } END_FOREACH_BLOCK;
+
+       return FALSE;
+}
+
 static void
 major_check_scan_starts (void)
 {
@@ -1112,7 +1157,13 @@ major_copy_or_mark_object (void **ptr, SgenGrayQueue *queue)
                         *
                         * FIXME (2): We should rework this to avoid all those nursery checks.
                         */
-                       if (!sgen_ptr_in_nursery (obj)) { /*marking a nursery object is pretty stupid.*/
+                       /*
+                        * For the split nursery allocator the object
+                        * might still be in the nursery despite
+                        * having being promoted, in which case we
+                        * can't mark it.
+                        */
+                       if (!sgen_ptr_in_nursery (obj)) {
                                block = MS_BLOCK_FOR_OBJ (obj);
                                MS_CALC_MARK_BIT (word, bit, obj);
                                DEBUG (9, g_assert (!MS_MARK_BIT (block, word, bit)));
@@ -1249,7 +1300,12 @@ major_copy_or_mark_object (void **ptr, SgenGrayQueue *queue)
                 *
                 * FIXME (2): We should rework this to avoid all those nursery checks.
                 */
-               if (!sgen_ptr_in_nursery (obj)) { /*marking a nursery object is pretty stupid.*/
+               /*
+                * For the split nursery allocator the object might
+                * still be in the nursery despite having being
+                * promoted, in which case we can't mark it.
+                */
+               if (!sgen_ptr_in_nursery (obj)) {
                        block = MS_BLOCK_FOR_OBJ (obj);
                        MS_CALC_MARK_BIT (word, bit, obj);
                        DEBUG (9, g_assert (!MS_MARK_BIT (block, word, bit)));
@@ -1314,6 +1370,9 @@ major_copy_or_mark_object (void **ptr, SgenGrayQueue *queue)
                        if (SGEN_OBJECT_IS_PINNED (obj))
                                return;
                        binary_protocol_pin (obj, (gpointer)SGEN_LOAD_VTABLE (obj), sgen_safe_object_get_size ((MonoObject*)obj));
+                       if (MONO_GC_OBJ_PINNED_ENABLED ()) {
+                               MONO_GC_OBJ_PINNED (obj, sgen_safe_object_get_size (obj), NULL, GENERATION_OLD);
+                       }
                        SGEN_PIN_OBJECT (obj);
                        /* FIXME: only enqueue if object has references */
                        GRAY_OBJECT_ENQUEUE (queue, obj);
@@ -1400,7 +1459,14 @@ ms_sweep (void)
                        } else {
                                /* an unmarked object */
                                if (MS_OBJ_ALLOCED (obj, block)) {
+                                       /*
+                                        * FIXME: Merge consecutive
+                                        * slots for lower reporting
+                                        * overhead.  Maybe memset
+                                        * will also benefit?
+                                        */
                                        binary_protocol_empty (obj, block->obj_size);
+                                       MONO_GC_MAJOR_SWEEPED (obj, block->obj_size);
                                        memset (obj, 0, block->obj_size);
                                }
                                *(void**)obj = block->free_list;
@@ -1641,7 +1707,7 @@ major_have_computer_minor_collection_allowance (void)
 
        while (num_empty_blocks > section_reserve) {
                void *next = *(void**)empty_blocks;
-               sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE);
+               sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE, TRUE);
                empty_blocks = next;
                /*
                 * Needs not be atomic because this is running
@@ -1931,7 +1997,7 @@ alloc_free_block_lists (MSBlockInfo ***lists)
 {
        int i;
        for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i)
-               lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+               lists [i] = sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
 }
 
 #ifdef SGEN_PARALLEL_MARK
@@ -2013,10 +2079,10 @@ sgen_marksweep_init
 #endif
 
        num_block_obj_sizes = ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, NULL);
-       block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+       block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (int) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
        ms_calculate_block_obj_sizes (MS_BLOCK_OBJ_SIZE_FACTOR, block_obj_sizes);
 
-       evacuate_block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (gboolean) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES);
+       evacuate_block_obj_sizes = sgen_alloc_internal_dynamic (sizeof (gboolean) * num_block_obj_sizes, INTERNAL_MEM_MS_TABLES, TRUE);
        for (i = 0; i < num_block_obj_sizes; ++i)
                evacuate_block_obj_sizes [i] = FALSE;
 
@@ -2108,6 +2174,7 @@ sgen_marksweep_init
        collector->is_worker_thread = major_is_worker_thread;
        collector->post_param_init = post_param_init;
        collector->is_valid_object = major_is_valid_object;
+       collector->describe_pointer = major_describe_pointer;
 
        collector->major_ops.copy_or_mark_object = major_copy_or_mark_object;
        collector->major_ops.scan_object = major_scan_object;