X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fsgen-cardtable.c;h=3b57a1a974a786f1261dc15fe1f7fc4961827180;hb=badcf364580fa262d91db8357daf6094ce4f3204;hp=d41cbc66eae77bf2c1f423471ead98391798e307;hpb=4d2de5c6abdc30ff973eb5f1987f3e5e52288e8b;p=mono.git diff --git a/mono/metadata/sgen-cardtable.c b/mono/metadata/sgen-cardtable.c index d41cbc66eae..3b57a1a974a 100644 --- a/mono/metadata/sgen-cardtable.c +++ b/mono/metadata/sgen-cardtable.c @@ -45,28 +45,30 @@ #endif #include +#define ARRAY_OBJ_INDEX(ptr,array,elem_size) (((char*)(ptr) - ((char*)(array) + G_STRUCT_OFFSET (MonoArray, vector))) / (elem_size)) + guint8 *sgen_cardtable; static gboolean need_mod_union; #ifdef HEAVY_STATISTICS -long long marked_cards; -long long scanned_cards; -long long scanned_objects; -long long remarked_cards; +guint64 marked_cards; +guint64 scanned_cards; +guint64 scanned_objects; +guint64 remarked_cards; -static long long los_marked_cards; -static long long large_objects; -static long long bloby_objects; -static long long los_array_cards; -static long long los_array_remsets; +static guint64 los_marked_cards; +static guint64 large_objects; +static guint64 bloby_objects; +static guint64 los_array_cards; +static guint64 los_array_remsets; #endif -static long long major_card_scan_time; -static long long los_card_scan_time; +static guint64 major_card_scan_time; +static guint64 los_card_scan_time; -static long long last_major_scan_time; -static long long last_los_scan_time; +static guint64 last_major_scan_time; +static guint64 last_los_scan_time; static void sgen_card_tables_collect_stats (gboolean begin); @@ -111,7 +113,7 @@ sgen_card_table_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int for (; dest >= start; --src, --dest) { gpointer value = *src; - *dest = value; + SGEN_UPDATE_REFERENCE_ALLOW_NULL (dest, value); if (need_mod_union || sgen_ptr_in_nursery (value)) sgen_card_table_mark_address ((mword)dest); sgen_dummy_use (value); @@ -120,7 +122,7 @@ sgen_card_table_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int gpointer *end = dest + count; for (; dest < end; ++src, ++dest) { gpointer value = *src; - *dest = value; + SGEN_UPDATE_REFERENCE_ALLOW_NULL (dest, value); if (need_mod_union || sgen_ptr_in_nursery (value)) sgen_card_table_mark_address ((mword)dest); sgen_dummy_use (value); @@ -184,10 +186,11 @@ guint8 *sgen_shadow_cardtable; #define SGEN_CARDTABLE_END (sgen_cardtable + CARD_COUNT_IN_BYTES) static gboolean -sgen_card_table_region_begin_scanning (mword start, mword end) +sgen_card_table_region_begin_scanning (mword start, mword size) { + mword end = start + size; /*XXX this can be improved to work on words and have a single loop induction var */ - while (start <= end) { + while (start < end) { if (sgen_card_table_card_begin_scanning (start)) return TRUE; start += CARD_SIZE_IN_BYTES; @@ -238,7 +241,7 @@ sgen_card_table_get_card_data (guint8 *data_dest, mword address, mword cards) #endif } - return mask; + return mask != 0; } void* @@ -287,9 +290,8 @@ sgen_card_table_find_address_with_cards (char *cards_start, guint8 *cards, char } static void -update_mod_union (guint8 *dest, gboolean init, guint8 *start_card, guint8 *end_card) +update_mod_union (guint8 *dest, gboolean init, guint8 *start_card, size_t num_cards) { - size_t num_cards = end_card - start_card; if (init) { memcpy (dest, start_card, num_cards); } else { @@ -305,41 +307,51 @@ alloc_mod_union (size_t num_cards) return sgen_alloc_internal_dynamic (num_cards, INTERNAL_MEM_CARDTABLE_MOD_UNION, TRUE); } +guint8* +sgen_card_table_update_mod_union_from_cards (guint8 *dest, guint8 *start_card, size_t num_cards) +{ + gboolean init = dest == NULL; + + if (init) + dest = alloc_mod_union (num_cards); + + update_mod_union (dest, init, start_card, num_cards); + + return dest; +} + guint8* sgen_card_table_update_mod_union (guint8 *dest, char *obj, mword obj_size, size_t *out_num_cards) { - guint8 *result = dest; guint8 *start_card = sgen_card_table_get_card_address ((mword)obj); +#ifndef SGEN_HAVE_OVERLAPPING_CARDS guint8 *end_card = sgen_card_table_get_card_address ((mword)obj + obj_size - 1) + 1; - gboolean init = dest == NULL; +#endif size_t num_cards; + guint8 *result = NULL; #ifdef SGEN_HAVE_OVERLAPPING_CARDS - if (end_card < start_card) { - guint8 *edge_card = sgen_cardtable + CARD_COUNT_IN_BYTES; - size_t num_cards_to_edge = edge_card - start_card; - - num_cards = (end_card + CARD_COUNT_IN_BYTES) - start_card; - if (init) { - result = dest = alloc_mod_union (num_cards); - //g_print ("%d cards for %d bytes: %p\n", num_cards, num_bytes, dest); - } - - update_mod_union (dest, init, start_card, edge_card); + size_t rest; - SGEN_ASSERT (0, num_cards == (edge_card - start_card) + (end_card - sgen_cardtable), "wrong number of cards"); + rest = num_cards = cards_in_range ((mword) obj, obj_size); - dest += num_cards_to_edge; + while (start_card + rest > SGEN_CARDTABLE_END) { + size_t count = SGEN_CARDTABLE_END - start_card; + dest = sgen_card_table_update_mod_union_from_cards (dest, start_card, count); + if (!result) + result = dest; + dest += count; + rest -= count; start_card = sgen_cardtable; - } else -#endif - { - num_cards = end_card - start_card; - if (init) - result = dest = alloc_mod_union (num_cards); } + num_cards = rest; +#else + num_cards = end_card - start_card; +#endif - update_mod_union (dest, init, start_card, end_card); + dest = sgen_card_table_update_mod_union_from_cards (dest, start_card, num_cards); + if (!result) + result = dest; if (out_num_cards) *out_num_cards = num_cards; @@ -356,7 +368,9 @@ move_cards_to_shadow_table (mword start, mword size) guint8 *to = sgen_card_table_get_shadow_card_address (start); size_t bytes = cards_in_range (start, size); - if (to + bytes > SGEN_SHADOW_CARDTABLE_END) { + if (bytes >= CARD_COUNT_IN_BYTES) { + memcpy (sgen_shadow_cardtable, sgen_cardtable, CARD_COUNT_IN_BYTES); + } else if (to + bytes > SGEN_SHADOW_CARDTABLE_END) { size_t first_chunk = SGEN_SHADOW_CARDTABLE_END - to; size_t second_chunk = MIN (CARD_COUNT_IN_BYTES, bytes) - first_chunk; @@ -373,7 +387,9 @@ clear_cards (mword start, mword size) guint8 *addr = sgen_card_table_get_card_address (start); size_t bytes = cards_in_range (start, size); - if (addr + bytes > SGEN_CARDTABLE_END) { + if (bytes >= CARD_COUNT_IN_BYTES) { + memset (sgen_cardtable, 0, CARD_COUNT_IN_BYTES); + } else if (addr + bytes > SGEN_CARDTABLE_END) { size_t first_chunk = SGEN_CARDTABLE_END - addr; memset (addr, 0, first_chunk); @@ -396,7 +412,7 @@ clear_cards (mword start, mword size) #endif static void -sgen_card_table_prepare_for_major_collection (void) +sgen_card_table_clear_cards (void) { /*XXX we could do this in 2 ways. using mincore or iterating over all sections/los objects */ sgen_major_collector_iterate_live_block_ranges (clear_cards); @@ -410,7 +426,7 @@ sgen_card_table_finish_minor_collection (void) } static void -sgen_card_table_finish_scan_remsets (void *start_nursery, void *end_nursery, SgenGrayQueue *queue) +sgen_card_table_scan_remsets (SgenGrayQueue *queue) { SGEN_TV_DECLARE (atv); SGEN_TV_DECLARE (btv); @@ -424,7 +440,7 @@ sgen_card_table_finish_scan_remsets (void *start_nursery, void *end_nursery, Sge sgen_los_iterate_live_block_ranges (move_cards_to_shadow_table); /*Then we clear*/ - sgen_card_table_prepare_for_major_collection (); + sgen_card_table_clear_cards (); #endif SGEN_TV_GETTIME (atv); sgen_major_collector_scan_card_table (queue); @@ -440,6 +456,9 @@ sgen_card_table_finish_scan_remsets (void *start_nursery, void *end_nursery, Sge guint8* mono_gc_get_card_table (int *shift_bits, gpointer *mask) { +#ifndef MANAGED_WBARRIER + return NULL; +#else if (!sgen_cardtable) return NULL; @@ -451,6 +470,7 @@ mono_gc_get_card_table (int *shift_bits, gpointer *mask) #endif return sgen_cardtable; +#endif } gboolean @@ -460,22 +480,6 @@ mono_gc_card_table_nursery_check (void) } #if 0 -static void -collect_faulted_cards (void) -{ -#define CARD_PAGES (CARD_COUNT_IN_BYTES / 4096) - int i, count = 0; - unsigned char faulted [CARD_PAGES] = { 0 }; - mincore (sgen_cardtable, CARD_COUNT_IN_BYTES, faulted); - - for (i = 0; i < CARD_PAGES; ++i) { - if (faulted [i]) - ++count; - } - - printf ("TOTAL card pages %d faulted %d\n", CARD_PAGES, count); -} - void sgen_card_table_dump_obj_card (char *object, size_t size, void *dummy) { @@ -572,7 +576,7 @@ sgen_cardtable_scan_object (char *obj, mword block_obj_size, guint8 *cards, gboo mword obj_size = sgen_par_object_get_size (vt, (MonoObject*)obj); char *obj_end = obj + obj_size; size_t card_count; - int extra_idx = 0; + size_t extra_idx = 0; MonoArray *arr = (MonoArray*)obj; mword desc = (mword)klass->element_class->gc_descr; @@ -611,8 +615,8 @@ LOOP_HEAD: card_data = find_next_card (card_data, card_data_end); for (; card_data < card_data_end; card_data = find_next_card (card_data + 1, card_data_end)) { - int index; - int idx = (card_data - card_base) + extra_idx; + size_t index; + size_t idx = (card_data - card_base) + extra_idx; char *start = (char*)(obj_start + idx * CARD_SIZE_IN_BYTES); char *card_end = start + CARD_SIZE_IN_BYTES; char *first_elem, *elem; @@ -668,9 +672,9 @@ LOOP_HEAD: HEAVY_STAT (++bloby_objects); if (cards) { if (sgen_card_table_is_range_marked (cards, (mword)obj, block_obj_size)) - sgen_get_current_object_ops ()->scan_object (obj, queue); + sgen_get_current_object_ops ()->scan_object (obj, sgen_obj_get_descriptor (obj), queue); } else if (sgen_card_table_region_begin_scanning ((mword)obj, block_obj_size)) { - sgen_get_current_object_ops ()->scan_object (obj, queue); + sgen_get_current_object_ops ()->scan_object (obj, sgen_obj_get_descriptor (obj), queue); } binary_protocol_card_scan (obj, sgen_safe_object_get_size ((MonoObject*)obj)); @@ -735,13 +739,13 @@ sgen_card_tables_collect_stats (gboolean begin) printf ("cards major (t %d m %d g %d r %d) los (t %d m %d g %d r %d) major_scan %.2fms los_scan %.2fms\n", major_stats.total, major_stats.marked, major_stats.gc_marked, major_stats.remarked, los_stats.total, los_stats.marked, los_stats.gc_marked, los_stats.remarked, - last_major_scan_time / 1000.0, last_los_scan_time / 1000.0); + last_major_scan_time / 10000.0f, last_los_scan_time / 10000.0f); } #endif } void -sgen_card_table_init (SgenRemeberedSet *remset) +sgen_card_table_init (SgenRememberedSet *remset) { sgen_cardtable = sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE, "card table"); @@ -750,19 +754,19 @@ sgen_card_table_init (SgenRemeberedSet *remset) #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); + mono_counters_register ("marked cards", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &marked_cards); + mono_counters_register ("scanned cards", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &scanned_cards); + mono_counters_register ("remarked cards", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &remarked_cards); + + mono_counters_register ("los marked cards", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_marked_cards); + mono_counters_register ("los array cards scanned ", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_cards); + mono_counters_register ("los array remsets", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &los_array_remsets); + mono_counters_register ("cardtable scanned objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &scanned_objects); + mono_counters_register ("cardtable large objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &large_objects); + mono_counters_register ("cardtable bloby objects", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &bloby_objects); #endif - mono_counters_register ("cardtable major scan time", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &major_card_scan_time); - mono_counters_register ("cardtable los scan time", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &los_card_scan_time); + mono_counters_register ("cardtable major scan time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &major_card_scan_time); + mono_counters_register ("cardtable los scan time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &los_card_scan_time); remset->wbarrier_set_field = sgen_card_table_wbarrier_set_field; @@ -773,10 +777,10 @@ sgen_card_table_init (SgenRemeberedSet *remset) remset->wbarrier_generic_nostore = sgen_card_table_wbarrier_generic_nostore; remset->record_pointer = sgen_card_table_record_pointer; - remset->finish_scan_remsets = sgen_card_table_finish_scan_remsets; + remset->scan_remsets = sgen_card_table_scan_remsets; remset->finish_minor_collection = sgen_card_table_finish_minor_collection; - remset->prepare_for_major_collection = sgen_card_table_prepare_for_major_collection; + remset->clear_cards = sgen_card_table_clear_cards; remset->find_address = sgen_card_table_find_address; remset->find_address_with_cards = sgen_card_table_find_address_with_cards;