#define CARD_COUNT_BITS (32 - 9)
#define CARD_COUNT_IN_BYTES (1 << CARD_COUNT_BITS)
-
+#define CARD_MASK ((1 << CARD_COUNT_BITS) - 1)
static guint8 *cardtable;
+static mword
+cards_in_range (mword address, mword size)
+{
+ mword end = address + size;
+ return (end >> CARD_BITS) - (address >> CARD_BITS);
+}
+
+#ifdef SGEN_HAVE_OVERLAPPING_CARDS
+
guint8*
sgen_card_table_get_card_address (mword address)
{
- return cardtable + (address >> CARD_BITS);
+ return cardtable + ((address >> CARD_BITS) & CARD_MASK);
}
+static guint8 *shadow_cardtable;
-void
-sgen_card_table_mark_address (mword address)
+static guint8*
+sgen_card_table_get_shadow_card_address (mword address)
{
- *sgen_card_table_get_card_address (address) = 1;
+ return shadow_cardtable + ((address >> CARD_BITS) & CARD_MASK);
}
-static gboolean
-sgen_card_table_address_is_marked (mword address)
+gboolean
+sgen_card_table_card_begin_scanning (mword address)
{
- return *sgen_card_table_get_card_address (address) != 0;
+ return *sgen_card_table_get_shadow_card_address (address) != 0;
}
-void*
-sgen_card_table_align_pointer (void *ptr)
+gboolean
+sgen_card_table_region_begin_scanning (mword start, mword end)
{
- return (void*)((mword)ptr & ~(CARD_SIZE_IN_BYTES - 1));
+ while (start <= end) {
+ if (sgen_card_table_card_begin_scanning (start))
+ return TRUE;
+ start += CARD_SIZE_IN_BYTES;
+ }
+ return FALSE;
+}
+
+#else
+
+guint8*
+sgen_card_table_get_card_address (mword address)
+{
+ return cardtable + (address >> CARD_BITS);
}
gboolean
sgen_card_table_region_begin_scanning (mword start, mword size)
{
gboolean res = FALSE;
- mword old_start = start;
- mword end = start + size;
- while (start <= end) {
- if (sgen_card_table_address_is_marked (start)) {
+ guint8 *card = sgen_card_table_get_card_address (start);
+ guint8 *end = card + cards_in_range (start, size);
+
+ while (card != end) {
+ if (*card++) {
res = TRUE;
break;
}
- start += CARD_SIZE_IN_BYTES;
}
- memset (sgen_card_table_get_card_address (old_start), 0, size >> CARD_BITS);
+ memset (sgen_card_table_get_card_address (start), 0, size >> CARD_BITS);
return res;
}
+#endif
+
+static gboolean
+sgen_card_table_address_is_marked (mword address)
+{
+ return *sgen_card_table_get_card_address (address) != 0;
+}
+
+void
+sgen_card_table_mark_address (mword address)
+{
+ *sgen_card_table_get_card_address (address) = 1;
+}
+
+void*
+sgen_card_table_align_pointer (void *ptr)
+{
+ return (void*)((mword)ptr & ~(CARD_SIZE_IN_BYTES - 1));
+}
void
sgen_card_table_mark_range (mword address, mword size)
card_table_init (void)
{
cardtable = mono_sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE);
+
+#ifdef SGEN_HAVE_OVERLAPPING_CARDS
+ shadow_cardtable = mono_sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, TRUE);
+#endif
}
memset (sgen_card_table_get_card_address (start), 0, size >> CARD_BITS);
}
+#ifdef SGEN_HAVE_OVERLAPPING_CARDS
+
static void
-scan_from_card_tables (void *start_nursery, void *end_nursery, GrayQueue *queue)
+move_cards_to_shadow_table (mword start, mword size)
{
- if (use_cardtable) {
- major.scan_card_table (queue);
- los_scan_card_table (queue);
- }
+ guint8 *from = sgen_card_table_get_card_address (start);
+ guint8 *to = sgen_card_table_get_shadow_card_address (start);
+ size_t bytes = cards_in_range (start, size);
+ memcpy (to, from, bytes);
}
+#endif
+
static void
card_table_clear (void)
{
los_iterate_live_block_ranges (clear_cards);
}
}
+static void
+scan_from_card_tables (void *start_nursery, void *end_nursery, GrayQueue *queue)
+{
+ if (use_cardtable) {
+#ifdef SGEN_HAVE_OVERLAPPING_CARDS
+ /*First we copy*/
+ major.iterate_live_block_ranges (move_cards_to_shadow_table);
+ los_iterate_live_block_ranges (move_cards_to_shadow_table);
+
+ /*Then we clear*/
+ card_table_clear ();
+#endif
+ major.scan_card_table (queue);
+ los_scan_card_table (queue);
+ }
+}
guint8*
-mono_gc_get_card_table (int *shift_bits)
+mono_gc_get_card_table (int *shift_bits, gpointer *mask)
{
if (!use_cardtable)
return NULL;
g_assert (cardtable);
*shift_bits = CARD_BITS;
+#ifdef SGEN_HAVE_OVERLAPPING_CARDS
+ *mask = (gpointer)CARD_MASK;
+#else
+ *mask = NULL;
+#endif
return cardtable;
}
#define card_table_init()
guint8*
-mono_gc_get_card_table (int *shift_bits)
+mono_gc_get_card_table (int *shift_bits, gpointer *mask)
{
return NULL;
}
{
#ifdef HAVE_SGEN_GC
int card_table_shift_bits;
- guint8 *card_table = mono_gc_get_card_table (&card_table_shift_bits);
+ gpointer card_table_mask;
+ guint8 *card_table = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
MonoInst *dummy_use;
-#ifdef MONO_ARCH_HAVE_CARD_TABLE_WBARRIER
+#ifdef MONO_ARCH_HAVE_CARD_TABLE_WBARRIER__
int nursery_shift_bits;
size_t nursery_size;
int offset_reg = alloc_preg (cfg);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, offset_reg, ptr->dreg, card_table_shift_bits);
+ if (card_table_mask)
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, offset_reg, offset_reg, card_table_mask);
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PADD_IMM, offset_reg, offset_reg, card_table);
MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI1_MEMBASE_IMM, offset_reg, 0, 1);
}