Merge pull request #2869 from BrzVlad/feature-mod-union-opt
authorVlad Brezae <brezaevlad@gmail.com>
Thu, 21 Apr 2016 13:53:02 +0000 (16:53 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Thu, 21 Apr 2016 13:53:02 +0000 (16:53 +0300)
[sgen] Optimize mod union usage

mono/sgen/sgen-los.c
mono/sgen/sgen-marksweep.c

index 5cb3c71253d1bb6ce1cced697b7affe438d61067..c22afd22f21d01c67998ee4e75dadedc444eb737 100644 (file)
@@ -307,7 +307,8 @@ free_los_section_memory (LOSObject *obj, size_t size)
 void
 sgen_los_free_object (LOSObject *obj)
 {
-       SGEN_ASSERT (0, !obj->cardtable_mod_union, "We should never free a LOS object with a mod-union table.");
+       if (obj->cardtable_mod_union)
+               sgen_card_table_free_mod_union (obj->cardtable_mod_union, (char*)obj->data, sgen_los_object_size (obj));
 
 #ifndef LOS_DUMMY
        mword size = sgen_los_object_size (obj);
@@ -433,12 +434,13 @@ sgen_los_sweep (void)
        for (bigobj = los_object_list; bigobj;) {
                SGEN_ASSERT (0, !SGEN_OBJECT_IS_PINNED (bigobj->data), "Who pinned a LOS object?");
 
-               if (bigobj->cardtable_mod_union) {
-                       sgen_card_table_free_mod_union (bigobj->cardtable_mod_union, (char*)bigobj->data, sgen_los_object_size (bigobj));
-                       bigobj->cardtable_mod_union = NULL;
-               }
-
                if (sgen_los_object_is_pinned (bigobj->data)) {
+                       if (bigobj->cardtable_mod_union) {
+                               mword obj_size = sgen_los_object_size (bigobj);
+                               mword num_cards = sgen_card_table_number_of_cards_in_range ((mword) bigobj->data, obj_size);
+                               memset (bigobj->cardtable_mod_union, 0, num_cards);
+                       }
+
                        sgen_los_unpin_object (bigobj->data);
                        sgen_update_heap_boundaries ((mword)bigobj->data, (mword)bigobj->data + sgen_los_object_size (bigobj));
                } else {
index d2e3ccdd0093dcc9e68432ef1e8f20b9198651a2..4c63191ad447d0ea5c9fb76bf44f9eba3ee19b46 100644 (file)
@@ -375,11 +375,14 @@ ms_get_empty_block (void)
  * list, where it will either be freed later on, or reused in nursery collections.
  */
 static void
-ms_free_block (void *block)
+ms_free_block (MSBlockInfo *info)
 {
        void *empty;
+       char *block = MS_BLOCK_FOR_BLOCK_INFO (info);
 
        sgen_memgov_release_space (MS_BLOCK_SIZE, SPACE_MAJOR);
+       if (info->cardtable_mod_union)
+               sgen_card_table_free_mod_union (info->cardtable_mod_union, block, MS_BLOCK_SIZE);
        memset (block, 0, MS_BLOCK_SIZE);
 
        do {
@@ -1507,10 +1510,8 @@ ensure_block_is_checked_for_sweeping (guint32 block_index, gboolean wait, gboole
 
        count = MS_BLOCK_FREE / block->obj_size;
 
-       if (block->cardtable_mod_union) {
-               sgen_card_table_free_mod_union (block->cardtable_mod_union, MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE);
-               block->cardtable_mod_union = NULL;
-       }
+       if (block->cardtable_mod_union)
+               memset (block->cardtable_mod_union, 0, CARDS_PER_BLOCK);
 
        /* Count marked objects in the block */
        for (i = 0; i < MS_NUM_MARK_WORDS; ++i)
@@ -2484,10 +2485,21 @@ update_cardtable_mod_union (void)
        MSBlockInfo *block;
 
        FOREACH_BLOCK_NO_LOCK (block) {
-               size_t num_cards;
-               guint8 *mod_union = get_cardtable_mod_union_for_block (block, TRUE);
-               sgen_card_table_update_mod_union (mod_union, MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE, &num_cards);
-               SGEN_ASSERT (6, num_cards == CARDS_PER_BLOCK, "Number of cards calculation is wrong");
+               gpointer *card_start = (gpointer*) sgen_card_table_get_card_address ((mword)MS_BLOCK_FOR_BLOCK_INFO (block));
+               gboolean has_dirty_cards = FALSE;
+               int i;
+               for (i = 0; i < CARDS_PER_BLOCK / sizeof(gpointer); i++) {
+                       if (card_start [i]) {
+                               has_dirty_cards = TRUE;
+                               break;
+                       }
+               }
+               if (has_dirty_cards) {
+                       size_t num_cards;
+                       guint8 *mod_union = get_cardtable_mod_union_for_block (block, TRUE);
+                       sgen_card_table_update_mod_union (mod_union, MS_BLOCK_FOR_BLOCK_INFO (block), MS_BLOCK_SIZE, &num_cards);
+                       SGEN_ASSERT (6, num_cards == CARDS_PER_BLOCK, "Number of cards calculation is wrong");
+               }
        } END_FOREACH_BLOCK_NO_LOCK;
 }