[sgen] Always allocate objects with a vtable.
authorMark Probst <mark.probst@gmail.com>
Tue, 6 Nov 2012 14:11:46 +0000 (15:11 +0100)
committerMark Probst <mark.probst@gmail.com>
Sun, 9 Dec 2012 14:02:46 +0000 (15:02 +0100)
mono/metadata/sgen-alloc.c
mono/metadata/sgen-copy-object.h
mono/metadata/sgen-gc.h
mono/metadata/sgen-major-copying.c
mono/metadata/sgen-marksweep.c
mono/metadata/sgen-minor-copy-object.h
mono/metadata/sgen-simple-nursery.c
mono/metadata/sgen-split-nursery.c
mono/metadata/sgen-workers.c

index d3407efafaf8423f5bb0152903f4f09c21653a04..a1ac53df6e5acdf444d28a7da4dcff1df706d00c 100644 (file)
@@ -570,7 +570,7 @@ mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size)
                p = sgen_los_alloc_large_inner (vtable, size);
        } else {
                SGEN_ASSERT (9, vtable->klass->inited, "class %s:%s is not initialized", vtable->klass->name_space, vtable->klass->name);
-               p = major_collector.alloc_small_pinned_obj (size, SGEN_VTABLE_HAS_REFERENCES (vtable));
+               p = major_collector.alloc_small_pinned_obj (vtable, size, SGEN_VTABLE_HAS_REFERENCES (vtable));
        }
        if (G_LIKELY (p)) {
                SGEN_LOG (6, "Allocated pinned object %p, vtable: %p (%s), size: %zd", p, vtable, vtable->klass->name, size);
@@ -579,7 +579,6 @@ mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size)
                else
                        MONO_GC_MAJOR_OBJ_ALLOC_PINNED ((mword)p, size, vtable->klass->name_space, vtable->klass->name);
                binary_protocol_alloc_pinned (p, vtable, size);
-               mono_atomic_store_seq (p, vtable);
        }
        UNLOCK_GC;
        return p;
@@ -592,7 +591,6 @@ mono_gc_alloc_mature (MonoVTable *vtable)
        size_t size = ALIGN_UP (vtable->klass->instance_size);
        LOCK_GC;
        res = alloc_degraded (vtable, size, TRUE);
-       mono_atomic_store_seq (res, vtable);
        UNLOCK_GC;
        if (G_UNLIKELY (vtable->klass->has_finalize))
                mono_object_register_finalizer ((MonoObject*)res);
index 76a00e281ac167469aa0d29a5e5376d791058913..23f6d121e69369c7aae95f79c93943604d0b245d 100644 (file)
@@ -107,7 +107,7 @@ copy_object_no_checks (void *obj, SgenGrayQueue *queue)
        MonoVTable *vt = ((MonoObject*)obj)->vtable;
        gboolean has_references = SGEN_VTABLE_HAS_REFERENCES (vt);
        mword objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj));
-       char *destination = COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION (obj, objsize, has_references);
+       char *destination = COLLECTOR_SERIAL_ALLOC_FOR_PROMOTION (vt, obj, objsize, has_references);
 
        if (G_UNLIKELY (!destination)) {
                collector_pin_object (obj, queue);
@@ -115,8 +115,8 @@ copy_object_no_checks (void *obj, SgenGrayQueue *queue)
                return obj;
        }
 
-       *(MonoVTable**)destination = vt;
        par_copy_object_no_checks (destination, vt, obj, objsize, has_references ? queue : NULL);
+       /* FIXME: mark mod union cards if necessary */
 
        /* set the forwarding pointer */
        SGEN_FORWARD_OBJECT (obj, destination);
index cd20607b910b5fc4f7734674ed0d1bb3036b2274..15d730a0183483f2dff442e363263851d400d2cf 100644 (file)
@@ -640,8 +640,8 @@ sgen_nursery_is_object_alive (char *obj)
 }
 
 typedef struct {
-       char* (*alloc_for_promotion) (char *obj, size_t objsize, gboolean has_references);
-       char* (*par_alloc_for_promotion) (char *obj, size_t objsize, gboolean has_references);
+       char* (*alloc_for_promotion) (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references);
+       char* (*par_alloc_for_promotion) (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references);
 
        SgenObjectOperations serial_ops;
        SgenObjectOperations parallel_ops;
@@ -680,13 +680,13 @@ struct _SgenMajorCollector {
 
        void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits);
        gboolean (*is_object_live) (char *obj);
-       void* (*alloc_small_pinned_obj) (size_t size, gboolean has_references);
+       void* (*alloc_small_pinned_obj) (MonoVTable *vtable, size_t size, gboolean has_references);
        void* (*alloc_degraded) (MonoVTable *vtable, size_t size);
 
        SgenObjectOperations major_ops;
 
-       void* (*alloc_object) (int size, gboolean has_references);
-       void* (*par_alloc_object) (int size, gboolean has_references);
+       void* (*alloc_object) (MonoVTable *vtable, int size, gboolean has_references);
+       void* (*par_alloc_object) (MonoVTable *vtable, int size, gboolean has_references);
        void (*free_pinned_object) (char *obj, size_t size);
        void (*iterate_objects) (gboolean non_pinned, gboolean pinned, IterateObjectCallbackFunc callback, void *data);
        void (*free_non_pinned_object) (char *obj, size_t size);
index db1dcacc05fea04e804cd165065edcdfccd5c186..ae1a83ed1154d2415e57e80219cecadd6f979110 100644 (file)
@@ -178,7 +178,7 @@ to_space_expand (void)
 }
 
 static void*
-major_alloc_object (int size, gboolean has_references)
+major_alloc_object (MonoVTable *vtable, int size, gboolean has_references)
 {
        char *dest = to_space_bumper;
        /* Make sure we have enough space available */
@@ -190,6 +190,8 @@ major_alloc_object (int size, gboolean has_references)
        to_space_bumper += size;
        SGEN_ASSERT (8, to_space_bumper <= to_space_top, "to-space-bumper %p overflow to-space-top %p", to_space_bumper, to_space_top);
        to_space_section->scan_starts [(dest - (char*)to_space_section->data)/SGEN_SCAN_START_SIZE] = dest;
+       /* FIXME: write vtable */
+       g_assert_not_reached ();
        return dest;
 }
 
@@ -231,8 +233,10 @@ major_is_object_live (char *obj)
 
 /* size is a multiple of ALLOC_ALIGN */
 static void*
-major_alloc_small_pinned_obj (size_t size, gboolean has_references)
+major_alloc_small_pinned_obj (MonoVTable *vtable, size_t size, gboolean has_references)
 {
+       /* FIXME: write vtable */
+       g_assert_not_reached ();
        return sgen_alloc_pinned (&pinned_allocator, size);
 }
 
index e1aa50fe5927d1f9f099ae79bd7b0add0c967e62..03fd1020b854720d2fc6221eab2a72ca65d77dfa 100644 (file)
@@ -679,7 +679,7 @@ try_remove_block_from_free_list (MSBlockInfo *block, MSBlockInfo **free_blocks,
 }
 
 static void*
-alloc_obj_par (int size, gboolean pinned, gboolean has_references)
+alloc_obj_par (MonoVTable *vtable, int size, gboolean pinned, gboolean has_references)
 {
        int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size);
        MSBlockInfo **free_blocks_local = FREE_BLOCKS_LOCAL (pinned, has_references);
@@ -721,11 +721,7 @@ alloc_obj_par (int size, gboolean pinned, gboolean has_references)
                }
        }
 
-       /*
-        * FIXME: This should not be necessary because it'll be
-        * overwritten by the vtable immediately.
-        */
-       *(void**)obj = NULL;
+       *(MonoVTable**)obj = vtable;
 
 #ifdef SGEN_CONCURRENT_MARK
        g_assert_not_reached ();
@@ -735,14 +731,14 @@ alloc_obj_par (int size, gboolean pinned, gboolean has_references)
 }
 
 static void*
-major_par_alloc_object (int size, gboolean has_references)
+major_par_alloc_object (MonoVTable *vtable, int size, gboolean has_references)
 {
-       return alloc_obj_par (size, FALSE, has_references);
+       return alloc_obj_par (vtable, size, FALSE, has_references);
 }
 #endif
 
 static void*
-alloc_obj (int size, gboolean pinned, gboolean has_references)
+alloc_obj (MonoVTable *vtable, int size, gboolean pinned, gboolean has_references)
 {
        int size_index = MS_BLOCK_OBJ_SIZE_INDEX (size);
        MSBlockInfo **free_blocks = FREE_BLOCKS (pinned, has_references);
@@ -762,11 +758,7 @@ alloc_obj (int size, gboolean pinned, gboolean has_references)
 
        obj = unlink_slot_from_free_list_uncontested (free_blocks, size_index);
 
-       /*
-        * FIXME: This should not be necessary because it'll be
-        * overwritten by the vtable immediately.
-        */
-       *(void**)obj = NULL;
+       *(MonoVTable**)obj = vtable;
 
 #ifdef SGEN_CONCURRENT_MARK
        if (obj && sgen_remember_major_object_for_concurrent_mark (obj)) {
@@ -782,9 +774,9 @@ alloc_obj (int size, gboolean pinned, gboolean has_references)
 }
 
 static void*
-major_alloc_object (int size, gboolean has_references)
+major_alloc_object (MonoVTable *vtable, int size, gboolean has_references)
 {
-       return alloc_obj (size, FALSE, has_references);
+       return alloc_obj (vtable, size, FALSE, has_references);
 }
 
 /*
@@ -826,19 +818,19 @@ major_free_non_pinned_object (char *obj, size_t size)
 
 /* size is a multiple of SGEN_ALLOC_ALIGN */
 static void*
-major_alloc_small_pinned_obj (size_t size, gboolean has_references)
+major_alloc_small_pinned_obj (MonoVTable *vtable, size_t size, gboolean has_references)
 {
        void *res;
 
        ms_wait_for_sweep_done ();
 
-       res = alloc_obj (size, TRUE, has_references);
+       res = alloc_obj (vtable, size, TRUE, has_references);
         /*If we failed to alloc memory, we better try releasing memory
          *as pinned alloc is requested by the runtime.
          */
         if (!res) {
                sgen_perform_collection (0, GENERATION_OLD, "pinned alloc failure", TRUE);
-               res = alloc_obj (size, TRUE, has_references);
+               res = alloc_obj (vtable, size, TRUE, has_references);
         }
         return res;
 }
@@ -862,9 +854,8 @@ major_alloc_degraded (MonoVTable *vtable, size_t size)
 
        old_num_sections = num_major_sections;
 
-       obj = alloc_obj (size, FALSE, SGEN_VTABLE_HAS_REFERENCES (vtable));
+       obj = alloc_obj (vtable, size, FALSE, SGEN_VTABLE_HAS_REFERENCES (vtable));
        if (G_LIKELY (obj)) {
-               *(MonoVTable**)obj = vtable;
                HEAVY_STAT (++stat_objects_alloced_degraded);
                HEAVY_STAT (stat_bytes_alloced_degraded += size);
                g_assert (num_major_sections >= old_num_sections);
@@ -1173,7 +1164,7 @@ major_copy_or_mark_object (void **ptr, SgenGrayQueue *queue)
                objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj));
                has_references = SGEN_VTABLE_HAS_REFERENCES (vt);
 
-               destination = sgen_minor_collector.par_alloc_for_promotion (obj, objsize, has_references);
+               destination = sgen_minor_collector.par_alloc_for_promotion (vt, obj, objsize, has_references);
                if (G_UNLIKELY (!destination)) {
                        if (!sgen_ptr_in_nursery (obj)) {
                                int size_index;
@@ -1187,14 +1178,6 @@ major_copy_or_mark_object (void **ptr, SgenGrayQueue *queue)
                        return;
                }
 
-               /*
-                * We do this before the CAS because we want to make
-                * sure that if another thread sees the destination
-                * pointer the VTable is already in place.  Not doing
-                * this can crash binary protocols.
-                */
-               *(MonoVTable**)destination = vt;
-
                if (SGEN_CAS_PTR (obj, (void*)((mword)destination | SGEN_FORWARDED_BIT), vt) == vt) {
                        gboolean was_marked;
 
index 5b03713840e3fd0ed329dd5fc85230e223779a64..5fea758c0b4894eb2c375a4ab1793b114e223d9c 100644 (file)
@@ -227,7 +227,7 @@ PARALLEL_COPY_OBJECT (void **obj_slot, SgenGrayQueue *queue)
        objsize = SGEN_ALIGN_UP (sgen_par_object_get_size (vt, (MonoObject*)obj));
        has_references = SGEN_VTABLE_HAS_REFERENCES (vt);
 
-       destination = COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION (obj, objsize, has_references);
+       destination = COLLECTOR_PARALLEL_ALLOC_FOR_PROMOTION (vt, obj, objsize, has_references);
 
        if (G_UNLIKELY (!destination)) {
                sgen_parallel_pin_or_update (obj_slot, obj, vt, queue);
index 1dc06202e5aa03095983567a2472f8f784d6c485..99115fcf7faa1b7d0eb690dd037f4b1baf66d594 100644 (file)
 #include "metadata/sgen-protocol.h"
 
 static inline char*
-alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
+alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references)
 {
-       return major_collector.alloc_object (objsize, has_references);
+       return major_collector.alloc_object (vtable, objsize, has_references);
 }
 
 static inline char*
-par_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
+par_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references)
 {
-       return major_collector.par_alloc_object (objsize, has_references);
+       return major_collector.par_alloc_object (vtable, objsize, has_references);
 }
 
 static SgenFragment*
index 2d812767d3f97d438cb20f366634ae538cfe6c15..4b20be0dff925a6b39c3c5c10164b4397e7127bf 100644 (file)
@@ -265,14 +265,14 @@ alloc_for_promotion_slow_path (int age, size_t objsize)
 }
 
 static inline char*
-alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
+alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references)
 {
        char *p = NULL;
        int age;
 
        age = get_object_age (obj);
        if (age >= promote_age)
-               return major_collector.alloc_object (objsize, has_references);
+               return major_collector.alloc_object (vtable, objsize, has_references);
 
        /* Promote! */
        ++age;
@@ -283,9 +283,11 @@ alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
        } else {
                p = alloc_for_promotion_slow_path (age, objsize);
                if (!p)
-                       p = major_collector.alloc_object (objsize, has_references);
+                       return major_collector.alloc_object (vtable, objsize, has_references);
        }
 
+       *(MonoVTable**)p = vtable;
+
        return p;
 }
 
@@ -335,14 +337,14 @@ restart:
 }
 
 static inline char*
-par_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
+par_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references)
 {
        char *p;
        int age;
 
        age = get_object_age (obj);
        if (age >= promote_age)
-               return major_collector.par_alloc_object (objsize, has_references);
+               return major_collector.par_alloc_object (vtable, objsize, has_references);
 
 restart:
        p = age_alloc_buffers [age].next;
@@ -357,34 +359,36 @@ restart:
 
                /* Have we failed to promote to the nursery, lets just evacuate it to old gen. */
                if (!p)
-                       p = major_collector.par_alloc_object (objsize, has_references);                 
+                       return major_collector.par_alloc_object (vtable, objsize, has_references);
        }
 
+       *(MonoVTable**)p = vtable;
+
        return p;
 }
 
 static char*
-minor_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
+minor_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references)
 {
        /*
        We only need to check for a non-nursery object if we're doing a major collection.
        */
        if (!sgen_ptr_in_nursery (obj))
-               return major_collector.alloc_object (objsize, has_references);
+               return major_collector.alloc_object (vtable, objsize, has_references);
 
-       return alloc_for_promotion (obj, objsize, has_references);
+       return alloc_for_promotion (vtable, obj, objsize, has_references);
 }
 
 static char*
-minor_par_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references)
+minor_par_alloc_for_promotion (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references)
 {
        /*
        We only need to check for a non-nursery object if we're doing a major collection.
        */
        if (!sgen_ptr_in_nursery (obj))
-               return major_collector.par_alloc_object (objsize, has_references);
+               return major_collector.par_alloc_object (vtable, objsize, has_references);
 
-       return par_alloc_for_promotion (obj, objsize, has_references);
+       return par_alloc_for_promotion (vtable, obj, objsize, has_references);
 }
 
 static SgenFragment*
index 240a81a49a0e82bc8710a5ac6f62bf757dc32ff4..e1d1ca462b3fbaa8303b88aed3f57b5c17ba27f4 100644 (file)
@@ -297,6 +297,7 @@ static void
 concurrent_enqueue_check (SgenGrayQueue *queue, char *obj)
 {
        g_assert (!sgen_ptr_in_nursery (obj));
+       g_assert (SGEN_LOAD_VTABLE (obj));
 }
 
 static void