static void major_sweep (void) { int i; #ifdef FIXED_HEAP int j; #else MSBlockInfo **iter; #endif /* clear all the free lists */ for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i) { MSBlockInfo **free_blocks = free_block_lists [i]; int j; for (j = 0; j < num_block_obj_sizes; ++j) free_blocks [j] = NULL; } /* traverse all blocks, free and zero unmarked objects */ #ifdef FIXED_HEAP for (j = 0; j < ms_heap_num_blocks; ++j) { MSBlockInfo *block = &block_infos [j]; #else iter = &all_blocks; while (*iter) { MSBlockInfo *block = *iter; #endif int count; gboolean have_live = FALSE; int obj_index; #ifdef FIXED_HEAP if (!block->used) continue; #endif count = MS_BLOCK_FREE / block->obj_size; block->free_list = NULL; for (obj_index = 0; obj_index < count; ++obj_index) { int word, bit; void *obj = MS_BLOCK_OBJ (block, obj_index); MS_CALC_MARK_BIT (word, bit, obj); if (MS_MARK_BIT (block, word, bit)) { DEBUG (9, g_assert (MS_OBJ_ALLOCED (obj, block))); have_live = TRUE; } else { /* an unmarked object */ if (MS_OBJ_ALLOCED (obj, block)) { binary_protocol_empty (obj, block->obj_size); memset (obj, 0, block->obj_size); } *(void**)obj = block->free_list; block->free_list = obj; } } /* reset mark bits */ memset (block->mark_words, 0, sizeof (mword) * MS_NUM_MARK_WORDS); /* * FIXME: reverse free list so that it's in address * order */ if (have_live) { #ifndef FIXED_HEAP iter = &block->next; #endif /* * If there are free slots in the block, add * the block to the corresponding free list. */ if (block->free_list) { MSBlockInfo **free_blocks = FREE_BLOCKS (block->pinned, block->has_references); int index = MS_BLOCK_OBJ_SIZE_INDEX (block->obj_size); block->next_free = free_blocks [index]; free_blocks [index] = block; } } else { /* * Blocks without live objects are removed from the * block list and freed. */ #ifdef FIXED_HEAP ms_free_block (block); #else *iter = block->next; ms_free_block (block->block); mono_sgen_free_internal (block, INTERNAL_MEM_MS_BLOCK_INFO); #endif --num_major_sections; } } } static int count_pinned_ref; static int count_pinned_nonref; static int count_nonpinned_ref; static int count_nonpinned_nonref; static void count_nonpinned_callback (char *obj, size_t size, void *data) { MonoVTable *vtable = (MonoVTable*)LOAD_VTABLE (obj); if (vtable->klass->has_references) ++count_nonpinned_ref; else ++count_nonpinned_nonref; }
static void ms_sweep (void) { int i; MSBlockInfo **iter; /* statistics for evacuation */ int *slots_available = alloca (sizeof (int) * num_block_obj_sizes); int *slots_used = alloca (sizeof (int) * num_block_obj_sizes); int *num_blocks = alloca (sizeof (int) * num_block_obj_sizes); for (i = 0; i < num_block_obj_sizes; ++i) slots_available [i] = slots_used [i] = num_blocks [i] = 0; /* clear all the free lists */ for (i = 0; i < MS_BLOCK_TYPE_MAX; ++i) { MSBlockInfo **free_blocks = free_block_lists [i]; int j; for (j = 0; j < num_block_obj_sizes; ++j) free_blocks [j] = NULL; } /* traverse all blocks, free and zero unmarked objects */ iter = &all_blocks; while (*iter) { MSBlockInfo *block = *iter; int count; gboolean have_live = FALSE; gboolean has_pinned; int obj_index; int obj_size_index; obj_size_index = block->obj_size_index; has_pinned = block->has_pinned; block->has_pinned = block->pinned; block->is_to_space = FALSE; count = MS_BLOCK_FREE / block->obj_size; block->free_list = NULL; for (obj_index = 0; obj_index < count; ++obj_index) { int word, bit; void *obj = MS_BLOCK_OBJ (block, obj_index); MS_CALC_MARK_BIT (word, bit, obj); if (MS_MARK_BIT (block, word, bit)) { DEBUG (9, g_assert (MS_OBJ_ALLOCED (obj, block))); have_live = TRUE; if (!has_pinned) ++slots_used [obj_size_index]; } else { /* an unmarked object */ if (MS_OBJ_ALLOCED (obj, block)) { binary_protocol_empty (obj, block->obj_size); memset (obj, 0, block->obj_size); } *(void**)obj = block->free_list; block->free_list = obj; } } /* reset mark bits */ memset (block->mark_words, 0, sizeof (mword) * MS_NUM_MARK_WORDS); /* * FIXME: reverse free list so that it's in address * order */ if (have_live) { if (!has_pinned) { ++num_blocks [obj_size_index]; slots_available [obj_size_index] += count; } iter = &block->next; /* * If there are free slots in the block, add * the block to the corresponding free list. */ if (block->free_list) { MSBlockInfo **free_blocks = FREE_BLOCKS (block->pinned, block->has_references); int index = MS_BLOCK_OBJ_SIZE_INDEX (block->obj_size); block->next_free = free_blocks [index]; free_blocks [index] = block; } update_heap_boundaries_for_block (block); } else { /* * Blocks without live objects are removed from the * block list and freed. */ *iter = block->next; #ifdef FIXED_HEAP ms_free_block (block); #else ms_free_block (block->block); mono_sgen_free_internal (block, INTERNAL_MEM_MS_BLOCK_INFO); #endif --num_major_sections; } } for (i = 0; i < num_block_obj_sizes; ++i) { float usage = (float)slots_used [i] / (float)slots_available [i]; if (num_blocks [i] > 5 && usage < evacuation_threshold) { evacuate_block_obj_sizes [i] = TRUE; /* g_print ("slot size %d - %d of %d used\n", block_obj_sizes [i], slots_used [i], slots_available [i]); */ } else { evacuate_block_obj_sizes [i] = FALSE; } } have_swept = TRUE; }