* sgen-gc.c: Kill use_cardtable and replace it with indirect calls thru a pointer table.
This might be a bit slower on some configurations but it make the whole thing a hell lot neater.
static long long last_major_scan_time;
static long long last_los_scan_time;
+static void sgen_card_tables_collect_stats (gboolean begin);
+
+
/*WARNING: This function returns the number of cards regardless of overflow in case of overlapping cards.*/
static mword
cards_in_range (mword address, mword size)
return (end >> CARD_BITS) - (address >> CARD_BITS) + 1;
}
-void
+static void
mono_sgen_card_table_wbarrier_set_field (MonoObject *obj, gpointer field_ptr, MonoObject* value)
{
*(void**)field_ptr = value;
mono_sgen_dummy_use (value);
}
-void
+static void
mono_sgen_card_table_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* value)
{
*(void**)slot_ptr = value;
mono_sgen_dummy_use (value);
}
-void
+static void
mono_sgen_card_table_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count)
{
gpointer *dest = dest_ptr;
}
}
-void
+static void
mono_sgen_card_table_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass)
{
size_t element_size = mono_class_value_size (klass, NULL);
#endif
}
-void
+static void
mono_sgen_card_table_wbarrier_object_copy (MonoObject* obj, MonoObject *src)
{
int size;
#endif
}
-void
+static void
mono_sgen_card_table_wbarrier_generic_nostore (gpointer ptr)
{
sgen_card_table_mark_address ((mword)ptr);
}
-void
-sgen_card_table_init (void)
+static void
+mono_sgen_card_table_record_pointer (gpointer address)
{
- sgen_cardtable = mono_sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE);
-
-#ifdef SGEN_HAVE_OVERLAPPING_CARDS
- sgen_shadow_cardtable = mono_sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE);
-#endif
-
-#ifdef HEAVY_STATISTICS
- mono_counters_register ("marked cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &marked_cards);
- mono_counters_register ("scanned cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &scanned_cards);
- mono_counters_register ("remarked cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &remarked_cards);
+ *sgen_card_table_get_card_address ((mword)address) = 1;
+}
- mono_counters_register ("los marked cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_marked_cards);
- mono_counters_register ("los array cards scanned ", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_array_cards);
- mono_counters_register ("los array remsets", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_array_remsets);
- mono_counters_register ("cardtable scanned objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &scanned_objects);
- mono_counters_register ("cardtable large objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &large_objects);
- mono_counters_register ("cardtable bloby objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &bloby_objects);
-#endif
- mono_counters_register ("cardtable major scan time", MONO_COUNTER_GC | MONO_COUNTER_LONG, &major_card_scan_time);
- mono_counters_register ("cardtable los scan time", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_card_scan_time);
+static gboolean
+mono_sgen_card_table_find_address (char *addr)
+{
+ return sgen_card_table_address_is_marked ((mword)addr);
}
#ifdef SGEN_HAVE_OVERLAPPING_CARDS
#endif
-void
+static void
mono_sgen_card_table_prepare_for_major_collection (void)
{
/*XXX we could do this in 2 ways. using mincore or iterating over all sections/los objects */
mono_sgen_los_iterate_live_block_ranges (clear_cards);
}
-void
+static void
mono_sgen_card_table_finish_minor_collection (void)
{
sgen_card_tables_collect_stats (FALSE);
}
-void
+static void
mono_sgen_card_table_finish_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue)
{
SGEN_TV_DECLARE (atv);
#endif
-void
+static void
sgen_card_tables_collect_stats (gboolean begin)
{
#ifdef CARDTABLE_STATS
#endif
}
+void
+sgen_card_table_init (SgenRemeberedSet *remset)
+{
+ sgen_cardtable = mono_sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE);
+
+#ifdef SGEN_HAVE_OVERLAPPING_CARDS
+ sgen_shadow_cardtable = mono_sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE);
+#endif
+
+#ifdef HEAVY_STATISTICS
+ mono_counters_register ("marked cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &marked_cards);
+ mono_counters_register ("scanned cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &scanned_cards);
+ mono_counters_register ("remarked cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &remarked_cards);
+
+ mono_counters_register ("los marked cards", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_marked_cards);
+ mono_counters_register ("los array cards scanned ", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_array_cards);
+ mono_counters_register ("los array remsets", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_array_remsets);
+ mono_counters_register ("cardtable scanned objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &scanned_objects);
+ mono_counters_register ("cardtable large objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &large_objects);
+ mono_counters_register ("cardtable bloby objects", MONO_COUNTER_GC | MONO_COUNTER_LONG, &bloby_objects);
+#endif
+ mono_counters_register ("cardtable major scan time", MONO_COUNTER_GC | MONO_COUNTER_LONG, &major_card_scan_time);
+ mono_counters_register ("cardtable los scan time", MONO_COUNTER_GC | MONO_COUNTER_LONG, &los_card_scan_time);
+
+
+ remset->wbarrier_set_field = mono_sgen_card_table_wbarrier_set_field;
+ remset->wbarrier_set_arrayref = mono_sgen_card_table_wbarrier_set_arrayref;
+ remset->wbarrier_arrayref_copy = mono_sgen_card_table_wbarrier_arrayref_copy;
+ remset->wbarrier_value_copy = mono_sgen_card_table_wbarrier_value_copy;
+ remset->wbarrier_object_copy = mono_sgen_card_table_wbarrier_object_copy;
+ remset->wbarrier_generic_nostore = mono_sgen_card_table_wbarrier_generic_nostore;
+ remset->record_pointer = mono_sgen_card_table_record_pointer;
+
+ remset->finish_scan_remsets = mono_sgen_card_table_finish_scan_remsets;
+
+ remset->finish_minor_collection = mono_sgen_card_table_finish_minor_collection;
+ remset->prepare_for_major_collection = mono_sgen_card_table_prepare_for_major_collection;
+
+ remset->find_address = mono_sgen_card_table_find_address;
+}
+
#else
void
void sgen_cardtable_scan_object (char *obj, mword obj_size, guint8 *cards, SgenGrayQueue *queue) MONO_INTERNAL;
gboolean sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards) MONO_INTERNAL;
-void mono_sgen_card_table_finish_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue) MONO_INTERNAL;
-void mono_sgen_card_table_prepare_for_major_collection (void) MONO_INTERNAL;
-void mono_sgen_card_table_finish_minor_collection (void) MONO_INTERNAL;
-void sgen_card_table_init (void) MONO_INTERNAL;
-
-void mono_sgen_card_table_wbarrier_set_field (MonoObject *obj, gpointer field_ptr, MonoObject* value) MONO_INTERNAL;
-void mono_sgen_card_table_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* value) MONO_INTERNAL;
-void mono_sgen_card_table_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count) MONO_INTERNAL;
-void mono_sgen_card_table_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass) MONO_INTERNAL;
-void mono_sgen_card_table_wbarrier_object_copy (MonoObject* obj, MonoObject *src) MONO_INTERNAL;
-void mono_sgen_card_table_wbarrier_generic_nostore (gpointer ptr) MONO_INTERNAL;
+
+void sgen_card_table_init (SgenRemeberedSet *remset) MONO_INTERNAL;
/*How many bytes a single card covers*/
#define CARD_BITS 9
*sgen_card_table_get_card_address (address) = 1;
}
-static inline void
-mono_sgen_card_table_record_pointer (gpointer address)
-{
- *sgen_card_table_get_card_address ((mword)address) = 1;
-}
-
#else /*if SGEN_HAVE_CARDTABLE */
static inline void
}
#define sgen_card_table_address_is_marked(p) FALSE
-#define mono_sgen_card_table_scan_from_remsets(start,end,queue)
-#define mono_sgen_card_table_prepare_for_major_collection()
-#define sgen_card_table_init()
+#define sgen_card_table_init(p)
guint8*
mono_gc_get_card_table (int *shift_bits, gpointer *mask)
return NULL;
}
-static void
-mono_sgen_card_table_record_pointer (gpointer address)
-{
- g_assert_not_reached ();
-}
-
#endif
-
-
#endif
#undef HANDLE_PTR
#define HANDLE_PTR(ptr,obj) do { \
if (*(ptr) && mono_sgen_ptr_in_nursery ((char*)*(ptr))) { \
- if (!mono_sgen_ssb_find_address ((char*)(ptr)) && (!use_cardtable || !sgen_card_table_address_is_marked ((mword)ptr))) { \
+ if (!mono_sgen_get_remset ()->find_address ((char*)(ptr))) { \
fprintf (gc_debug_file, "Oldspace->newspace reference %p at offset %td in object %p (%s.%s) not found in remsets.\n", *(ptr), (char*)(ptr) - (char*)(obj), (obj), ((MonoObject*)(obj))->vtable->klass->name_space, ((MonoObject*)(obj))->vtable->klass->name); \
binary_protocol_missing_remset ((obj), (gpointer)LOAD_VTABLE ((obj)), (char*)(ptr) - (char*)(obj), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
if (!object_is_pinned (*(ptr))) \
LOCK_DECLARE (gc_mutex);
static int gc_disabled = 0;
-gboolean use_cardtable;
+static gboolean use_cardtable;
#ifdef USER_CONFIG
SgenMajorCollector major_collector;
static GrayQueue gray_queue;
+static SgenRemeberedSet remset;
#define WORKERS_DISTRIBUTE_GRAY_QUEUE (mono_sgen_collection_is_parallel () ? mono_sgen_workers_get_distribute_gray_queue () : &gray_queue)
void
mono_sgen_add_to_global_remset (gpointer ptr)
{
- if (use_cardtable)
- mono_sgen_card_table_record_pointer (ptr);
- else
- mono_sgen_ssb_record_pointer (ptr);
+ remset.record_pointer (ptr);
}
/*
{
FinishRememberedSetScanJobData *job_data = job_data_untyped;
- if (use_cardtable)
- mono_sgen_card_table_finish_scan_remsets (job_data->heap_start, job_data->heap_end, mono_sgen_workers_get_job_gray_queue (worker_data));
- else
- mono_sgen_ssb_finish_scan_remsets (job_data->heap_start, job_data->heap_end, mono_sgen_workers_get_job_gray_queue (worker_data));
+ remset.finish_scan_remsets (job_data->heap_start, job_data->heap_end, mono_sgen_workers_get_job_gray_queue (worker_data));
}
typedef struct
stat_minor_gcs++;
mono_stats.minor_gc_count ++;
- if (!use_cardtable)
- mono_sgen_ssb_prepare_for_minor_collection ();
+ if (remset.prepare_for_minor_collection)
+ remset.prepare_for_minor_collection ();
process_fin_stage_entries ();
process_dislink_stage_entries ();
* Perform the sequential part of remembered set scanning.
* This usually involves scanning global information that might later be produced by evacuation.
*/
- if (!use_cardtable)
- mono_sgen_ssb_begin_scan_remsets (nursery_start, nursery_next, WORKERS_DISTRIBUTE_GRAY_QUEUE);
+ if (remset.begin_scan_remsets)
+ remset.begin_scan_remsets (nursery_start, nursery_next, WORKERS_DISTRIBUTE_GRAY_QUEUE);
mono_sgen_workers_start_marking ();
g_assert (mono_sgen_gray_object_queue_is_empty (&gray_queue));
- if (use_cardtable)
- mono_sgen_card_table_finish_minor_collection ();
+ if (remset.finish_minor_collection)
+ remset.finish_minor_collection ();
check_scan_starts ();
check_for_xdomain_refs ();
/* Remsets are not useful for a major collection */
- if (use_cardtable)
- mono_sgen_card_table_prepare_for_major_collection ();
- else
- mono_sgen_ssb_prepare_for_major_collection ();
+ remset.prepare_for_major_collection ();
process_fin_stage_entries ();
process_dislink_stage_entries ();
stack_end = info->stack_end;
#endif
- if (!use_cardtable)
- mono_sgen_ssb_register_thread (info);
+ if (remset.register_thread)
+ remset.register_thread (info);
DEBUG (3, fprintf (gc_debug_file, "registered thread %p (%p) stack end %p\n", info, (gpointer)mono_thread_info_get_tid (info), info->stack_end));
static void
mono_sgen_wbarrier_cleanup_thread (SgenThreadInfo *p)
{
- if (!use_cardtable)
- mono_sgen_ssb_cleanup_thread (p);
+ if (remset.cleanup_thread)
+ remset.cleanup_thread (p);
}
static void
if (value)
binary_protocol_wbarrier (field_ptr, value, value->vtable);
- if (use_cardtable)
- mono_sgen_card_table_wbarrier_set_field (obj, field_ptr, value);
- else
- mono_sgen_ssb_wbarrier_set_field (obj, field_ptr, value);
+ remset.wbarrier_set_field (obj, field_ptr, value);
}
void
if (value)
binary_protocol_wbarrier (slot_ptr, value, value->vtable);
- if (use_cardtable)
- mono_sgen_card_table_wbarrier_set_arrayref (arr, slot_ptr, value);
- else
- mono_sgen_ssb_wbarrier_set_arrayref (arr, slot_ptr, value);
+ remset.wbarrier_set_arrayref (arr, slot_ptr, value);
}
void
}
#endif
- if (use_cardtable)
- mono_sgen_card_table_wbarrier_arrayref_copy (dest_ptr, src_ptr, count);
- else
- mono_sgen_ssb_wbarrier_arrayref_copy (dest_ptr, src_ptr, count);
+ remset.wbarrier_arrayref_copy (dest_ptr, src_ptr, count);
}
static char *found_obj;
DEBUG (8, fprintf (gc_debug_file, "Adding remset at %p\n", ptr));
- if (use_cardtable)
- mono_sgen_card_table_wbarrier_generic_nostore (ptr);
- else
- mono_sgen_ssb_wbarrier_generic_nostore (ptr);
+ remset.wbarrier_generic_nostore (ptr);
}
void
}
#endif
- if (use_cardtable)
- mono_sgen_card_table_wbarrier_value_copy (dest, src, count, klass);
- else
- mono_sgen_ssb_wbarrier_value_copy (dest, src, count, klass);
+ remset.wbarrier_value_copy (dest, src, count, klass);
}
/**
scan_object_for_binary_protocol_copy_wbarrier (obj, (char*)src, (mword) src->vtable->gc_descr);
#endif
- if (use_cardtable)
- mono_sgen_card_table_wbarrier_object_copy (obj, src);
- else
- mono_sgen_ssb_wbarrier_object_copy (obj, src);
+ remset.wbarrier_object_copy (obj, src);
}
/*
{
return mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method);
}
-
+
void
mono_gc_base_init (void)
{
if (major_collector.post_param_init)
major_collector.post_param_init ();
+ memset (&remset, 0, sizeof (remset));
+
+#ifdef SGEN_HAVE_CARDTABLE
if (use_cardtable)
- sgen_card_table_init ();
+ sgen_card_table_init (&remset);
else
- mono_sgen_ssb_init ();
+#endif
+ mono_sgen_ssb_init (&remset);
+
+ if (remset.register_thread)
+ remset.register_thread (mono_thread_info_current ());
gc_initialized = 1;
}
UNLOCK_GC;
}
+SgenRemeberedSet*
+mono_sgen_get_remset (void)
+{
+ return &remset;
+}
+
#endif /* HAVE_SGEN_GC */
void mono_sgen_copying_init (SgenMajorCollector *collector) MONO_INTERNAL;
SgenMajorCollector* mono_sgen_get_major_collector (void) MONO_INTERNAL;
+
+typedef struct {
+ void (*wbarrier_set_field) (MonoObject *obj, gpointer field_ptr, MonoObject* value);
+ void (*wbarrier_set_arrayref) (MonoArray *arr, gpointer slot_ptr, MonoObject* value);
+ void (*wbarrier_arrayref_copy) (gpointer dest_ptr, gpointer src_ptr, int count);
+ void (*wbarrier_value_copy) (gpointer dest, gpointer src, int count, MonoClass *klass);
+ void (*wbarrier_object_copy) (MonoObject* obj, MonoObject *src);
+ void (*wbarrier_generic_nostore) (gpointer ptr);
+ void (*record_pointer) (gpointer ptr);
+
+ void (*begin_scan_remsets) (void *start_nursery, void *end_nursery, SgenGrayQueue *queue); /* OPTIONAL */
+ void (*finish_scan_remsets) (void *start_nursery, void *end_nursery, SgenGrayQueue *queue);
+
+ void (*register_thread) (SgenThreadInfo *p); /* OPTIONAL */
+ void (*cleanup_thread) (SgenThreadInfo *p); /* OPTIONAL */
+ void (*prepare_for_minor_collection) (void); /* OPTIONAL */
+ void (*prepare_for_major_collection) (void);
+
+ void (*finish_minor_collection) (void); /* OPTIONAL */
+ gboolean (*find_address) (char *addr);
+} SgenRemeberedSet;
+
+SgenRemeberedSet *mono_sgen_get_remset (void) MONO_INTERNAL;
+
static guint /*__attribute__((noinline)) not sure if this hint is a good idea*/
slow_object_get_size (MonoVTable *vtable, MonoObject* o)
{
extern LOCK_DECLARE (gc_mutex);
extern int do_pin_stats;
-extern gboolean use_cardtable;
/* Object Allocation */
-void
+static void
mono_sgen_ssb_wbarrier_set_field (MonoObject *obj, gpointer field_ptr, MonoObject* value)
{
RememberedSet *rs;
UNLOCK_GC;
}
-void
+static void
mono_sgen_ssb_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* value)
{
RememberedSet *rs;
UNLOCK_GC;
}
-void
+static void
mono_sgen_ssb_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count)
{
RememberedSet *rs;
UNLOCK_GC;
}
-void
+static void
mono_sgen_ssb_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass)
{
RememberedSet *rs;
UNLOCK_GC;
}
-void
+static void
mono_sgen_ssb_wbarrier_object_copy (MonoObject* obj, MonoObject *src)
{
int size;
UNLOCK_GC;
}
-void
+static void
mono_sgen_ssb_wbarrier_generic_nostore (gpointer ptr)
{
gpointer *buffer;
return NULL;
}
-void
+static void
mono_sgen_ssb_begin_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue)
{
RememberedSet *remset;
}
}
-void
+static void
mono_sgen_ssb_finish_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue)
{
int i;
}
-void
+static void
mono_sgen_ssb_cleanup_thread (SgenThreadInfo *p)
{
RememberedSet *rset;
*p->store_remset_buffer_addr = NULL;
}
-void
+static void
mono_sgen_ssb_register_thread (SgenThreadInfo *info)
{
#ifndef HAVE_KW_THREAD
STORE_REMSET_BUFFER_INDEX = 0;
}
-void
+static void
mono_sgen_ssb_prepare_for_minor_collection (void)
{
memset (global_remset_cache, 0, sizeof (global_remset_cache));
* the per-thread ones are not needed and the global ones will be reconstructed
* during the copy.
*/
-void
+static void
mono_sgen_ssb_prepare_for_major_collection (void)
{
SgenThreadInfo *info;
return TRUE;
}
-void
+static void
mono_sgen_ssb_record_pointer (gpointer ptr)
{
RememberedSet *rs;
UNLOCK_GLOBAL_REMSET;
}
-void
-mono_sgen_ssb_init (void)
-{
- LOCK_INIT (global_remset_mutex);
-
- global_remset = mono_sgen_alloc_remset (1024, NULL, FALSE);
- global_remset->next = NULL;
-
- mono_native_tls_alloc (&remembered_set_key, NULL);
-
-#ifdef HEAVY_STATISTICS
- mono_counters_register ("WBarrier generic store stored", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_generic_store_remset);
-
- mono_counters_register ("Store remsets", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_store_remsets);
- mono_counters_register ("Unique store remsets", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_store_remsets_unique);
- mono_counters_register ("Saved remsets 1", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_saved_remsets_1);
- mono_counters_register ("Saved remsets 2", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_saved_remsets_2);
- mono_counters_register ("Non-global remsets processed", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_local_remsets_processed);
- mono_counters_register ("Global remsets added", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_added);
- mono_counters_register ("Global remsets re-added", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_readded);
- mono_counters_register ("Global remsets processed", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_processed);
- mono_counters_register ("Global remsets discarded", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_discarded);
-#endif
-}
-
/*
* ######################################################################
* ######## Debug support
/*
* Return whenever ADDR occurs in the remembered sets
*/
-gboolean
+static gboolean
mono_sgen_ssb_find_address (char *addr)
{
int i;
return FALSE;
}
+
+void
+mono_sgen_ssb_init (SgenRemeberedSet *remset)
+{
+ LOCK_INIT (global_remset_mutex);
+
+ global_remset = mono_sgen_alloc_remset (1024, NULL, FALSE);
+ global_remset->next = NULL;
+
+ mono_native_tls_alloc (&remembered_set_key, NULL);
+
+#ifdef HEAVY_STATISTICS
+ mono_counters_register ("WBarrier generic store stored", MONO_COUNTER_GC | MONO_COUNTER_INT, &stat_wbarrier_generic_store_remset);
+
+ mono_counters_register ("Store remsets", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_store_remsets);
+ mono_counters_register ("Unique store remsets", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_store_remsets_unique);
+ mono_counters_register ("Saved remsets 1", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_saved_remsets_1);
+ mono_counters_register ("Saved remsets 2", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_saved_remsets_2);
+ mono_counters_register ("Non-global remsets processed", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_local_remsets_processed);
+ mono_counters_register ("Global remsets added", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_added);
+ mono_counters_register ("Global remsets re-added", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_readded);
+ mono_counters_register ("Global remsets processed", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_processed);
+ mono_counters_register ("Global remsets discarded", MONO_COUNTER_GC | MONO_COUNTER_LONG, &stat_global_remsets_discarded);
+#endif
+
+ remset->wbarrier_set_field = mono_sgen_ssb_wbarrier_set_field;
+ remset->wbarrier_set_arrayref = mono_sgen_ssb_wbarrier_set_arrayref;
+ remset->wbarrier_arrayref_copy = mono_sgen_ssb_wbarrier_arrayref_copy;
+ remset->wbarrier_value_copy = mono_sgen_ssb_wbarrier_value_copy;
+ remset->wbarrier_object_copy = mono_sgen_ssb_wbarrier_object_copy;
+ remset->wbarrier_generic_nostore = mono_sgen_ssb_wbarrier_generic_nostore;
+ remset->record_pointer = mono_sgen_ssb_record_pointer;
+
+ remset->begin_scan_remsets = mono_sgen_ssb_begin_scan_remsets;
+ remset->finish_scan_remsets = mono_sgen_ssb_finish_scan_remsets;
+
+ remset->register_thread = mono_sgen_ssb_register_thread;
+ remset->cleanup_thread = mono_sgen_ssb_cleanup_thread;
+ remset->prepare_for_minor_collection = mono_sgen_ssb_prepare_for_minor_collection;
+ remset->prepare_for_major_collection = mono_sgen_ssb_prepare_for_major_collection;
+
+ remset->find_address = mono_sgen_ssb_find_address;
+}
#endif
#ifndef __MONO_SGEN_SSB_H__
#define __MONO_SGEN_SSB_H__
-
-void mono_sgen_ssb_wbarrier_set_field (MonoObject *obj, gpointer field_ptr, MonoObject* value) MONO_INTERNAL;
-void mono_sgen_ssb_wbarrier_set_arrayref (MonoArray *arr, gpointer slot_ptr, MonoObject* value) MONO_INTERNAL;
-void mono_sgen_ssb_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count) MONO_INTERNAL;
-void mono_sgen_ssb_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass) MONO_INTERNAL;
-void mono_sgen_ssb_wbarrier_object_copy (MonoObject* obj, MonoObject *src) MONO_INTERNAL;
-void mono_sgen_ssb_wbarrier_generic_nostore (gpointer ptr) MONO_INTERNAL;
-
-void mono_sgen_ssb_finish_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue) MONO_INTERNAL;
-void mono_sgen_ssb_begin_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue) MONO_INTERNAL;
-
-void mono_sgen_ssb_cleanup_thread (SgenThreadInfo *p) MONO_INTERNAL;
-void mono_sgen_ssb_register_thread (SgenThreadInfo *p) MONO_INTERNAL;
-void mono_sgen_ssb_prepare_for_minor_collection (void) MONO_INTERNAL;
-void mono_sgen_ssb_prepare_for_major_collection (void) MONO_INTERNAL;
-void mono_sgen_ssb_init (void) MONO_INTERNAL;
-
-void mono_sgen_ssb_record_pointer (gpointer ptr) MONO_INTERNAL;
-
-gboolean mono_sgen_ssb_find_address (char *addr) MONO_INTERNAL;
+void mono_sgen_ssb_init (SgenRemeberedSet *remset) MONO_INTERNAL;
#endif