From 2230f884deef9c53a816e21c7eec0c003ddb4703 Mon Sep 17 00:00:00 2001 From: Mark Probst Date: Tue, 6 Nov 2012 15:11:46 +0100 Subject: [PATCH] [sgen] Always allocate objects with a vtable. --- mono/metadata/sgen-alloc.c | 4 +-- mono/metadata/sgen-copy-object.h | 4 +-- mono/metadata/sgen-gc.h | 10 +++--- mono/metadata/sgen-major-copying.c | 8 +++-- mono/metadata/sgen-marksweep.c | 43 ++++++++------------------ mono/metadata/sgen-minor-copy-object.h | 2 +- mono/metadata/sgen-simple-nursery.c | 8 ++--- mono/metadata/sgen-split-nursery.c | 28 ++++++++++------- mono/metadata/sgen-workers.c | 1 + 9 files changed, 49 insertions(+), 59 deletions(-) diff --git a/mono/metadata/sgen-alloc.c b/mono/metadata/sgen-alloc.c index d3407efafaf..a1ac53df6e5 100644 --- a/mono/metadata/sgen-alloc.c +++ b/mono/metadata/sgen-alloc.c @@ -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); diff --git a/mono/metadata/sgen-copy-object.h b/mono/metadata/sgen-copy-object.h index 76a00e281ac..23f6d121e69 100644 --- a/mono/metadata/sgen-copy-object.h +++ b/mono/metadata/sgen-copy-object.h @@ -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); diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index cd20607b910..15d730a0183 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -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); diff --git a/mono/metadata/sgen-major-copying.c b/mono/metadata/sgen-major-copying.c index db1dcacc05f..ae1a83ed115 100644 --- a/mono/metadata/sgen-major-copying.c +++ b/mono/metadata/sgen-major-copying.c @@ -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); } diff --git a/mono/metadata/sgen-marksweep.c b/mono/metadata/sgen-marksweep.c index e1aa50fe592..03fd1020b85 100644 --- a/mono/metadata/sgen-marksweep.c +++ b/mono/metadata/sgen-marksweep.c @@ -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; diff --git a/mono/metadata/sgen-minor-copy-object.h b/mono/metadata/sgen-minor-copy-object.h index 5b03713840e..5fea758c0b4 100644 --- a/mono/metadata/sgen-minor-copy-object.h +++ b/mono/metadata/sgen-minor-copy-object.h @@ -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); diff --git a/mono/metadata/sgen-simple-nursery.c b/mono/metadata/sgen-simple-nursery.c index 1dc06202e5a..99115fcf7fa 100644 --- a/mono/metadata/sgen-simple-nursery.c +++ b/mono/metadata/sgen-simple-nursery.c @@ -29,15 +29,15 @@ #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* diff --git a/mono/metadata/sgen-split-nursery.c b/mono/metadata/sgen-split-nursery.c index 2d812767d3f..4b20be0dff9 100644 --- a/mono/metadata/sgen-split-nursery.c +++ b/mono/metadata/sgen-split-nursery.c @@ -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* diff --git a/mono/metadata/sgen-workers.c b/mono/metadata/sgen-workers.c index 240a81a49a0..e1d1ca462b3 100644 --- a/mono/metadata/sgen-workers.c +++ b/mono/metadata/sgen-workers.c @@ -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 -- 2.25.1