void wspace_compact(Collector *collector, Wspace *wspace) { Chunk_Header *least_free_chunk, *most_free_chunk; Pool *pfc_pool = wspace_grab_next_pfc_pool(wspace); for(; pfc_pool; pfc_pool = wspace_grab_next_pfc_pool(wspace)){ if(pool_is_empty(pfc_pool)) continue; Boolean pfc_pool_need_compact = pfc_pool_roughly_sort(pfc_pool, &least_free_chunk, &most_free_chunk); if(!pfc_pool_need_compact) continue; Chunk_Header *dest = get_least_free_chunk(&least_free_chunk, &most_free_chunk); Chunk_Header *src = get_most_free_chunk(&least_free_chunk, &most_free_chunk); Boolean src_is_new = TRUE; while(dest && src){ if(src_is_new) src->slot_index = 0; //chunk_depad_last_index_word(src); move_obj_between_chunks(wspace, &dest, src); if(!dest) dest = get_least_free_chunk(&least_free_chunk, &most_free_chunk); if(!src->alloc_num){ collector_add_free_chunk(collector, (Free_Chunk*)src); src = get_most_free_chunk(&least_free_chunk, &most_free_chunk); src_is_new = TRUE; } else { src_is_new = FALSE; } } /* Rebuild the pfc_pool */ if(dest) wspace_put_pfc(wspace, dest); if(src){ //chunk_pad_last_index_word(src, cur_alloc_mask); pfc_reset_slot_index(src); wspace_put_pfc(wspace, src); } } }
/*Concurrent Sweep: The mark bit and alloc bit is exchanged before entering this function. This function is to clear the mark bit and merge the free chunks concurrently. */ void wspace_sweep_concurrent(Conclctor* sweeper) { GC *gc = sweeper->gc; Wspace *wspace = gc_get_wspace(gc); sweeper->live_obj_size = 0; sweeper->live_obj_num = 0; Pool* used_chunk_pool = wspace->used_chunk_pool; Chunk_Header_Basic* chunk_to_sweep; /*1. Grab chunks from used list, sweep the chunk and push back to PFC backup list & free list.*/ chunk_to_sweep = chunk_pool_get_chunk(used_chunk_pool); while(chunk_to_sweep != NULL){ wspace_sweep_chunk_con(wspace, sweeper, chunk_to_sweep); chunk_to_sweep = chunk_pool_get_chunk(used_chunk_pool); } /*2. Grab chunks from PFC list, sweep the chunk and push back to PFC backup list & free list.*/ Pool* pfc_pool = wspace_grab_next_pfc_pool(wspace); while(pfc_pool != NULL){ if(!pool_is_empty(pfc_pool)){ /*sweep the chunks in pfc_pool. push back to pfc backup list*/ chunk_to_sweep = chunk_pool_get_chunk(pfc_pool); while(chunk_to_sweep != NULL){ assert(chunk_to_sweep->status == (CHUNK_NORMAL | CHUNK_NEED_ZEROING)); chunk_to_sweep->status = CHUNK_NORMAL | CHUNK_USED; wspace_sweep_chunk_con(wspace, sweeper, chunk_to_sweep); chunk_to_sweep = chunk_pool_get_chunk(pfc_pool); } } /*grab more pfc pools*/ pfc_pool = wspace_grab_next_pfc_pool(wspace); } }
//final work should be done by the last sweeper void wspace_last_sweeper_work( Conclctor *last_sweeper ) { GC *gc = last_sweeper->gc; Wspace *wspace = gc_get_wspace(gc); Chunk_Header_Basic* chunk_to_sweep; Pool* used_chunk_pool = wspace->used_chunk_pool; /* all but one sweeper finishes its job*/ state_transformation( gc, GC_CON_SWEEPING, GC_CON_SWEEP_DONE ); /*3. Check the local chunk of mutator*/ gc_sweep_mutator_local_chunks(wspace->gc); /*4. Sweep gloabl alloc normal chunks again*/ gc_set_sweep_global_normal_chunk(); gc_wait_mutator_signal(wspace->gc, HSIG_MUTATOR_SAFE); wspace_init_pfc_pool_iterator(wspace); Pool* pfc_pool = wspace_grab_next_pfc_pool(wspace); while(pfc_pool != NULL){ if(!pool_is_empty(pfc_pool)){ chunk_to_sweep = chunk_pool_get_chunk(pfc_pool); while(chunk_to_sweep != NULL){ assert(chunk_to_sweep->status == (CHUNK_NORMAL | CHUNK_NEED_ZEROING)); chunk_to_sweep->status = CHUNK_NORMAL | CHUNK_USED; wspace_sweep_chunk_con(wspace, last_sweeper, chunk_to_sweep); chunk_to_sweep = chunk_pool_get_chunk(pfc_pool); } } /*grab more pfc pools*/ pfc_pool = wspace_grab_next_pfc_pool(wspace); } /*5. Check the used list again.*/ chunk_to_sweep = chunk_pool_get_chunk(used_chunk_pool); while(chunk_to_sweep != NULL){ wspace_sweep_chunk_con(wspace, last_sweeper, chunk_to_sweep); chunk_to_sweep = chunk_pool_get_chunk(used_chunk_pool); } /*6. Switch the PFC backup list to PFC list.*/ wspace_exchange_pfc_pool(wspace); gc_unset_sweep_global_normal_chunk(); /*7. Put back live abnormal chunk and normal unreusable chunk*/ Chunk_Header* used_abnormal_chunk = wspace_get_live_abnormal_chunk(wspace); while(used_abnormal_chunk){ used_abnormal_chunk->status = CHUNK_USED | CHUNK_ABNORMAL; wspace_reg_used_chunk(wspace,used_abnormal_chunk); used_abnormal_chunk = wspace_get_live_abnormal_chunk(wspace); } pool_empty(wspace->live_abnormal_chunk_pool); Chunk_Header* unreusable_normal_chunk = wspace_get_unreusable_normal_chunk(wspace); while(unreusable_normal_chunk){ unreusable_normal_chunk->status = CHUNK_USED | CHUNK_NORMAL; wspace_reg_used_chunk(wspace,unreusable_normal_chunk); unreusable_normal_chunk = wspace_get_unreusable_normal_chunk(wspace); } pool_empty(wspace->unreusable_normal_chunk_pool); /*8. Merge free chunks from sweepers*/ Free_Chunk_List *free_list_from_sweeper = wspace_collect_free_chunks_from_sweepers(gc); wspace_merge_free_list(wspace, free_list_from_sweeper); /* last sweeper will transform the state to before_finish */ state_transformation( gc, GC_CON_SWEEP_DONE, GC_CON_BEFORE_FINISH ); }