Add support for card overlapping.
authorRodrigo Kumpera <kumpera@gmail.com>
Thu, 26 Aug 2010 14:59:03 +0000 (11:59 -0300)
committerRodrigo Kumpera <kumpera@gmail.com>
Mon, 30 Aug 2010 20:50:41 +0000 (17:50 -0300)
* sgen-cardtable.c: In order to support cardtables with 64bits we
allow cards to overlap each other. Cards are copied to a shadow
cardtable at the beginning of the scanning.

* gc-internals.h: Change signature of mono_gc_get_card_table to
return the card table mask.

* mini.h: Add PAND_IMM.

* method-to-ir.c: Handle card table masks.

* mini-x86.c: Ditto.

mono/metadata/gc-internal.h
mono/metadata/sgen-cardtable.c
mono/mini/method-to-ir.c
mono/mini/mini-x86.c
mono/mini/mini.h

index 1ccab14bc0bd1693631a58392a899c695023a292..3ac6ecc7727a8ca85c8f6c8f6be0bdad43d8fd93 100644 (file)
@@ -250,7 +250,7 @@ void* mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data) MO
 #ifdef HAVE_SGEN_GC
 int mono_gc_get_los_limit (void) MONO_INTERNAL;
 
-guint8* mono_gc_get_card_table (int *shift_bits) MONO_INTERNAL;
+guint8* mono_gc_get_card_table (int *shift_bits, gpointer *card_mask) MONO_INTERNAL;
 
 void* mono_gc_get_nursery (int *shift_bits, size_t *size) MONO_INTERNAL;
 #endif
index 9286ad9f7aee5fa940f41fa21032f52ff2991c83..af6a6d480785d91782ebfbc589bfd0b5a2f817ac 100644 (file)
 
 #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
@@ -80,21 +103,40 @@ 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)
@@ -110,6 +152,10 @@ static void
 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
 }
 
 
@@ -123,15 +169,19 @@ clear_cards (mword start, mword size)
        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)
 {
@@ -141,15 +191,36 @@ 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;
 }
@@ -190,7 +261,7 @@ sgen_card_table_mark_range (mword address, mword size)
 #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;
 }
index 8faab0bb3ae3e52f75a767ada525ed74b2fbf120..9ff9d0642b3a30bd7a0a98d7ae5dd656e47b66e4 100644 (file)
@@ -2595,10 +2595,11 @@ emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value, int value_
 {
 #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;
 
@@ -2620,6 +2621,8 @@ emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value, int value_
                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);
        }
index b01299e2cebb393febda951056df574ec526e908..a7abb8871295253d2edf10a64cafa3fd6f66739d 100644 (file)
@@ -4009,8 +4009,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        int value = ins->sreg2;
                        guchar *br;
                        int nursery_shift, card_table_shift;
+                       gpointer card_table_mask;
                        size_t nursery_size;
-                       gulong card_table = (gulong)mono_gc_get_card_table (&card_table_shift);
+                       gulong card_table = (gulong)mono_gc_get_card_table (&card_table_shift, &card_table_mask);
                        gulong nursery_start = (gulong)mono_gc_get_nursery (&nursery_shift, &nursery_size);
 
                        /*
index 5059104e6dc57f5bef9c6de1f19d17df09ce7ef1..c9f86b42b40bdfa5f6a629a4284034ca613a4b94 100644 (file)
@@ -1276,6 +1276,7 @@ enum {
 #define OP_PCONST OP_I8CONST
 #define OP_PADD OP_LADD
 #define OP_PADD_IMM OP_LADD_IMM
+#define OP_PAND_IMM OP_LAND_IMM
 #define OP_PSUB OP_LSUB
 #define OP_PMUL OP_LMUL
 #define OP_PMUL_IMM OP_LMUL_IMM
@@ -1298,6 +1299,7 @@ enum {
 #define OP_PCONST OP_ICONST
 #define OP_PADD OP_IADD
 #define OP_PADD_IMM OP_IADD_IMM
+#define OP_PAND_IMM OP_IAND_IMM
 #define OP_PSUB OP_ISUB
 #define OP_PMUL OP_IMUL
 #define OP_PMUL_IMM OP_IMUL_IMM