X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsgen-gc.h;h=25015bd1ae664996e4f2bdd0aaac0279fd1d9928;hb=9ac4b5b7a7062fd0b3d26e3bd0c9d426be904fc3;hp=0fa761304114da3fa34dfc4cd29ad74856d0b45c;hpb=100ecb4f0f7e901b593eaa35057a3f8aa2cdcaf7;p=mono.git diff --git a/mono/metadata/sgen-gc.h b/mono/metadata/sgen-gc.h index 0fa76130411..25015bd1ae6 100644 --- a/mono/metadata/sgen-gc.h +++ b/mono/metadata/sgen-gc.h @@ -34,7 +34,6 @@ typedef struct _SgenThreadInfo SgenThreadInfo; #ifdef HAVE_PTHREAD_H #include #endif -#include #include #include #include @@ -67,7 +66,6 @@ NurseryClearPolicy sgen_get_nursery_clear_policy (void) MONO_INTERNAL; #define SGEN_TV_DECLARE(name) gint64 name #define SGEN_TV_GETTIME(tv) tv = mono_100ns_ticks () #define SGEN_TV_ELAPSED(start,end) (int)((end-start)) -#define SGEN_TV_ELAPSED_MS(start,end) ((SGEN_TV_ELAPSED((start),(end)) + 5000) / 10000) #if !defined(__MACH__) && !MONO_MACH_ARCH_SUPPORTED && defined(HAVE_PTHREAD_KILL) #define SGEN_POSIX_STW 1 @@ -160,7 +158,6 @@ struct _GCMemSection { mono_mutex_lock (&gc_mutex); \ MONO_GC_LOCKED (); \ } while (0) -#define TRYLOCK_GC (mono_mutex_trylock (&gc_mutex) == 0) #define UNLOCK_GC do { sgen_gc_unlock (); } while (0) extern LOCK_DECLARE (sgen_interruption_mutex); @@ -190,10 +187,10 @@ extern LOCK_DECLARE (sgen_interruption_mutex); #endif #ifdef HEAVY_STATISTICS -extern long long stat_objects_alloced_degraded; -extern long long stat_bytes_alloced_degraded; -extern long long stat_copy_object_called_major; -extern long long stat_objects_copied_major; +extern guint64 stat_objects_alloced_degraded; +extern guint64 stat_bytes_alloced_degraded; +extern guint64 stat_copy_object_called_major; +extern guint64 stat_objects_copied_major; #endif #define SGEN_ASSERT(level, a, ...) do { \ @@ -213,11 +210,6 @@ extern long long stat_objects_copied_major; mono_gc_printf (gc_debug_file, format, ##__VA_ARGS__); \ } } while (0) -#define SGEN_LOG_DO(level, fun) do { \ - if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) { \ - fun; \ -} } while (0) - extern int gc_debug_level; extern FILE* gc_debug_file; @@ -310,27 +302,37 @@ typedef struct { mword desc; } GCVTable; -/* these bits are set in the object vtable: we could merge them since an object can be - * either pinned or forwarded but not both. - * We store them in the vtable slot because the bits are used in the sync block for - * other purposes: if we merge them and alloc the sync blocks aligned to 8 bytes, we can change +/* + * We use the lowest three bits in the vtable pointer of objects to tag whether they're + * forwarded, pinned, and/or cemented. These are the valid states: + * + * | State | bits | + * |------------------+------+ + * | default | 000 | + * | forwarded | 001 | + * | pinned | 010 | + * | pinned, cemented | 110 | + * + * We store them in the vtable slot because the bits are used in the sync block for other + * purposes: if we merge them and alloc the sync blocks aligned to 8 bytes, we can change * this and use bit 3 in the syncblock (with the lower two bits both set for forwarded, that * would be an invalid combination for the monitor and hash code). - * The values are already shifted. - * The forwarding address is stored in the sync block. */ -#define SGEN_VTABLE_BITS_MASK 0x3 - #include "sgen-tagged-pointer.h" +#define SGEN_VTABLE_BITS_MASK SGEN_TAGGED_POINTER_MASK + #define SGEN_POINTER_IS_TAGGED_FORWARDED(p) SGEN_POINTER_IS_TAGGED_1((p)) -#define SGEN_POINTER_TAG_FORWARDED(p) SGEN_POINTER_TAG_1((p)) +#define SGEN_POINTER_TAG_FORWARDED(p) SGEN_POINTER_TAG_1((p)) #define SGEN_POINTER_IS_TAGGED_PINNED(p) SGEN_POINTER_IS_TAGGED_2((p)) -#define SGEN_POINTER_TAG_PINNED(p) SGEN_POINTER_TAG_2((p)) +#define SGEN_POINTER_TAG_PINNED(p) SGEN_POINTER_TAG_2((p)) + +#define SGEN_POINTER_IS_TAGGED_CEMENTED(p) SGEN_POINTER_IS_TAGGED_4((p)) +#define SGEN_POINTER_TAG_CEMENTED(p) SGEN_POINTER_TAG_4((p)) -#define SGEN_POINTER_UNTAG_VTABLE(p) SGEN_POINTER_UNTAG_12((p)) +#define SGEN_POINTER_UNTAG_VTABLE(p) SGEN_POINTER_UNTAG_ALL((p)) /* returns NULL if not forwarded, or the forwarded address */ #define SGEN_VTABLE_IS_FORWARDED(vtable) (SGEN_POINTER_IS_TAGGED_FORWARDED ((vtable)) ? SGEN_POINTER_UNTAG_VTABLE ((vtable)) : NULL) @@ -339,6 +341,8 @@ typedef struct { #define SGEN_VTABLE_IS_PINNED(vtable) SGEN_POINTER_IS_TAGGED_PINNED ((vtable)) #define SGEN_OBJECT_IS_PINNED(obj) (SGEN_VTABLE_IS_PINNED (((mword*)(obj))[0])) +#define SGEN_OBJECT_IS_CEMENTED(obj) (SGEN_POINTER_IS_TAGGED_CEMENTED (((mword*)(obj))[0])) + /* set the forwarded address fw_addr for object obj */ #define SGEN_FORWARD_OBJECT(obj,fw_addr) do { \ *(void**)(obj) = SGEN_POINTER_TAG_FORWARDED ((fw_addr)); \ @@ -346,15 +350,19 @@ typedef struct { #define SGEN_PIN_OBJECT(obj) do { \ *(void**)(obj) = SGEN_POINTER_TAG_PINNED (*(void**)(obj)); \ } while (0) +#define SGEN_CEMENT_OBJECT(obj) do { \ + *(void**)(obj) = SGEN_POINTER_TAG_CEMENTED (*(void**)(obj)); \ + } while (0) +/* Unpins and uncements */ #define SGEN_UNPIN_OBJECT(obj) do { \ - *(void**)(obj) = SGEN_POINTER_UNTAG_2 (*(void**)(obj)); \ + *(void**)(obj) = SGEN_POINTER_UNTAG_VTABLE (*(void**)(obj)); \ } while (0) /* * Since we set bits in the vtable, use the macro to load it from the pointer to * an object that is potentially pinned. */ -#define SGEN_LOAD_VTABLE(addr) SGEN_POINTER_UNTAG_12 (*(void**)(addr)) +#define SGEN_LOAD_VTABLE(addr) SGEN_POINTER_UNTAG_ALL (*(void**)(addr)) /* List of what each bit on of the vtable gc bits means. @@ -437,6 +445,7 @@ enum { INTERNAL_MEM_TOGGLEREF_DATA, INTERNAL_MEM_CARDTABLE_MOD_UNION, INTERNAL_MEM_BINARY_PROTOCOL, + INTERNAL_MEM_TEMPORARY, INTERNAL_MEM_MAX }; @@ -609,6 +618,27 @@ extern SgenMinorCollector sgen_minor_collector; void sgen_simple_nursery_init (SgenMinorCollector *collector) MONO_INTERNAL; void sgen_split_nursery_init (SgenMinorCollector *collector) MONO_INTERNAL; +/* Updating references */ + +#ifdef SGEN_CHECK_UPDATE_REFERENCE +static inline void +sgen_update_reference (void **p, void *o, gboolean allow_null) +{ + if (!allow_null) + SGEN_ASSERT (0, o, "Cannot update a reference with a NULL pointer"); + SGEN_ASSERT (0, !sgen_is_worker_thread (mono_native_thread_id_get ()), "Can't update a reference in the worker thread"); + *p = o; +} + +#define SGEN_UPDATE_REFERENCE_ALLOW_NULL(p,o) sgen_update_reference ((void**)(p), (void*)(o), TRUE) +#define SGEN_UPDATE_REFERENCE(p,o) sgen_update_reference ((void**)(p), (void*)(o), FALSE) +#else +#define SGEN_UPDATE_REFERENCE_ALLOW_NULL(p,o) (*(void**)(p) = (void*)(o)) +#define SGEN_UPDATE_REFERENCE(p,o) SGEN_UPDATE_REFERENCE_ALLOW_NULL ((p), (o)) +#endif + +/* Major collector */ + typedef void (*sgen_cardtable_block_callback) (mword start, mword size); void sgen_major_collector_iterate_live_block_ranges (sgen_cardtable_block_callback callback) MONO_INTERNAL; @@ -622,6 +652,12 @@ typedef enum { ITERATE_OBJECTS_SWEEP_ALL = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_NON_PINNED | ITERATE_OBJECTS_PINNED } IterateObjectsFlags; +typedef struct +{ + size_t num_scanned_objects; + size_t num_unique_scanned_objects; +} ScannedObjectCounts; + typedef struct _SgenMajorCollector SgenMajorCollector; struct _SgenMajorCollector { size_t section_size; @@ -667,7 +703,8 @@ struct _SgenMajorCollector { void (*start_nursery_collection) (void); void (*finish_nursery_collection) (void); void (*start_major_collection) (void); - void (*finish_major_collection) (void); + void (*finish_major_collection) (ScannedObjectCounts *counts); + gboolean (*drain_gray_stack) (ScanCopyContext ctx); void (*have_computed_minor_collection_allowance) (void); gboolean (*ptr_is_in_non_pinned_space) (char *ptr, char **start); gboolean (*obj_is_from_pinned_alloc) (char *obj); @@ -727,7 +764,7 @@ slow_object_get_size (MonoVTable *vtable, MonoObject* o) * mono_array_length_fast not using the object's vtable. */ if (klass == mono_defaults.string_class) { - return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; + return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; } else if (klass->rank) { MonoArray *array = (MonoArray*)o; size_t size = sizeof (MonoArray) + klass->sizes.element_size * mono_array_length_fast (array); @@ -753,7 +790,7 @@ static inline mword sgen_obj_get_descriptor (char *obj) { MonoVTable *vtable = ((MonoObject*)obj)->vtable; - SGEN_ASSERT (0, !SGEN_POINTER_IS_TAGGED_1_OR_2 (vtable), "Object can't be tagged"); + SGEN_ASSERT (9, !SGEN_POINTER_IS_TAGGED_ANY (vtable), "Object can't be tagged"); return sgen_vtable_get_descriptor (vtable); } @@ -769,17 +806,18 @@ sgen_obj_get_descriptor_safe (char *obj) * vtable field, is not intact. This is necessary for the parallel * collector. */ -static inline mword +static MONO_NEVER_INLINE mword sgen_par_object_get_size (MonoVTable *vtable, MonoObject* o) { mword descr = (mword)vtable->gc_descr; - mword type = descr & 0x7; + mword type = descr & DESC_TYPE_MASK; - if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_BITMAP) { + if (type == DESC_TYPE_RUN_LENGTH || type == DESC_TYPE_SMALL_PTRFREE) { mword size = descr & 0xfff8; - if (size == 0) /* This is used to encode a string */ - return offsetof (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; + SGEN_ASSERT (9, size >= sizeof (MonoObject), "Run length object size to small"); return size; + } else if (descr == SGEN_DESC_STRING) { + return G_STRUCT_OFFSET (MonoString, chars) + 2 * mono_string_length_fast ((MonoString*) o) + 2; } else if (type == DESC_TYPE_VECTOR) { int element_size = ((descr) >> VECTOR_ELSIZE_SHIFT) & MAX_ELEMENT_SIZE; MonoArray *array = (MonoArray*)o; @@ -1119,7 +1157,7 @@ void sgen_check_major_refs (void); void sgen_check_whole_heap (gboolean allow_missing_pinning); void sgen_check_whole_heap_stw (void) MONO_INTERNAL; void sgen_check_objref (char *obj); -void sgen_check_major_heap_marked (void) MONO_INTERNAL; +void sgen_check_heap_marked (gboolean nursery_must_be_pinned) MONO_INTERNAL; void sgen_check_nursery_objects_pinned (gboolean pinned) MONO_INTERNAL; void sgen_scan_for_registered_roots_in_domain (MonoDomain *domain, int root_type) MONO_INTERNAL; void sgen_check_for_xdomain_refs (void) MONO_INTERNAL; @@ -1182,7 +1220,7 @@ gboolean nursery_canaries_enabled (void) MONO_INTERNAL; char* canary_ptr = (char*) (addr) + sgen_safe_object_get_size_unaligned ((MonoObject *) (addr)); \ if (!CANARY_VALID(canary_ptr)) { \ char canary_copy[CANARY_SIZE +1]; \ - strncpy (canary_copy, canary_ptr, 8); \ + strncpy (canary_copy, canary_ptr, CANARY_SIZE); \ canary_copy[CANARY_SIZE] = 0; \ g_error ("CORRUPT CANARY:\naddr->%p\ntype->%s\nexcepted->'%s'\nfound->'%s'\n", (char*) addr, ((MonoObject*)addr)->vtable->klass->name, CANARY_STRING, canary_copy); \ } }