static inline Partial_Reveal_Object *get_next_first_src_obj(Mspace *mspace) { Partial_Reveal_Object *first_src_obj; while(TRUE) { lock(current_dest_block.lock); Block_Header *next_dest_block = (Block_Header *)current_dest_block.block; if (!next_dest_block || !(first_src_obj = next_dest_block->src)) { next_dest_block = get_next_dest_block(mspace); if(!next_dest_block) { unlock(current_dest_block.lock); return NULL; } else if(next_dest_block == DEST_NOT_EMPTY) { unlock(current_dest_block.lock); while(check_dest_block(mspace)==DEST_NOT_EMPTY); continue; } first_src_obj = next_dest_block->src; if(next_dest_block->status == BLOCK_DEST) { assert(!next_dest_block->dest_counter); current_dest_block.block = next_dest_block; } } Partial_Reveal_Object *next_src_obj = GC_BLOCK_HEADER(first_src_obj)->next_src; if(next_src_obj && GC_BLOCK_HEADER(ref_to_obj_ptr((REF)get_obj_info_raw(next_src_obj))) != next_dest_block) { next_src_obj = NULL; } next_dest_block->src = next_src_obj; unlock(current_dest_block.lock); return first_src_obj; } }
static Block_Header *check_dest_block(Mspace *mspace) { Block_Header *cur_dest_block; if(next_block_for_dest) { cur_dest_block = (Block_Header*)next_block_for_dest; while(cur_dest_block->status == BLOCK_DEST) { cur_dest_block = cur_dest_block->next; } } else { cur_dest_block = blocked_space_block_iterator_get((Blocked_Space*)mspace); } unsigned int total_dest_counter = 0; Block_Header *last_dest_block = (Block_Header *)last_block_for_dest; for(; cur_dest_block < last_dest_block; cur_dest_block = cur_dest_block->next) { if(cur_dest_block->status == BLOCK_DEST) continue; if(cur_dest_block->dest_counter == 0 && cur_dest_block->src) { return cur_dest_block; } else if(cur_dest_block->dest_counter == 1 && GC_BLOCK_HEADER(cur_dest_block->src) == cur_dest_block) { return cur_dest_block; } else if(cur_dest_block->dest_counter == 0 && !cur_dest_block->src) { cur_dest_block->status = BLOCK_DEST; } else { total_dest_counter += cur_dest_block->dest_counter; } } if(total_dest_counter) return DEST_NOT_EMPTY; return NULL; }
static void mspace_sliding_compact(Collector* collector, Mspace* mspace) { void *start_pos; while(Partial_Reveal_Object *p_obj = get_next_first_src_obj(mspace)) { Block_Header *src_block = GC_BLOCK_HEADER(p_obj); assert(src_block->dest_counter); Partial_Reveal_Object *p_target_obj = obj_get_fw_in_oi(p_obj); Block_Header *dest_block = GC_BLOCK_HEADER(p_target_obj); /* We don't set start_pos as p_obj in case that memmove of this obj may overlap itself. * In that case we can't get the correct vt and obj_info. */ #ifdef USE_32BITS_HASHCODE start_pos = obj_end_extend(p_obj); #else start_pos = obj_end(p_obj); #endif do { assert(obj_is_marked_in_vt(p_obj)); #ifdef USE_32BITS_HASHCODE obj_clear_dual_bits_in_vt(p_obj); #else obj_unmark_in_vt(p_obj); #endif unsigned int obj_size = (unsigned int)((POINTER_SIZE_INT)start_pos - (POINTER_SIZE_INT)p_obj); if(p_obj != p_target_obj) { assert((((POINTER_SIZE_INT)p_target_obj) % GC_OBJECT_ALIGNMENT) == 0); memmove(p_target_obj, p_obj, obj_size); } set_obj_info(p_target_obj, 0); p_obj = block_get_next_marked_obj_after_prefetch(src_block, &start_pos); if(!p_obj) break; p_target_obj = obj_get_fw_in_oi(p_obj); } while(GC_BLOCK_HEADER(p_target_obj) == dest_block); atomic_dec32(&src_block->dest_counter); } }
static Block_Header *get_next_dest_block(Mspace *mspace) { Block_Header *cur_dest_block; if(next_block_for_dest) { cur_dest_block = (Block_Header*)next_block_for_dest; while(cur_dest_block->status == BLOCK_DEST) { cur_dest_block = cur_dest_block->next; if(!cur_dest_block) break; } next_block_for_dest = cur_dest_block; } else { cur_dest_block = set_next_block_for_dest(mspace); } unsigned int total_dest_counter = 0; /*For LOS_Shrink: last_dest_block might point to a fake block*/ Block_Header *last_dest_block = (Block_Header *)round_down_to_size((POINTER_SIZE_INT)(last_block_for_dest->base), GC_BLOCK_SIZE_BYTES); for(; cur_dest_block <= last_dest_block; cur_dest_block = cur_dest_block->next) { if(!cur_dest_block) return NULL; if(cur_dest_block->status == BLOCK_DEST) { continue; } if(cur_dest_block->dest_counter == 0 && cur_dest_block->src) { cur_dest_block->status = BLOCK_DEST; return cur_dest_block; } else if(cur_dest_block->dest_counter == 1 && GC_BLOCK_HEADER(cur_dest_block->src) == cur_dest_block) { return cur_dest_block; } else if(cur_dest_block->dest_counter == 0 && !cur_dest_block->src) { cur_dest_block->status = BLOCK_DEST; } else { total_dest_counter += cur_dest_block->dest_counter; } } if(total_dest_counter) return DEST_NOT_EMPTY; return NULL; }
static FORCE_INLINE void scan_object(Heap_Verifier* heap_verifier, Partial_Reveal_Object *p_obj) { GC_Verifier* gc_verifier = heap_verifier->gc_verifier; #if !defined(USE_UNIQUE_MARK_SWEEP_GC) && !defined(USE_UNIQUE_MOVE_COMPACT_GC) if(gc_verifier->is_before_fallback_collection) { if(obj_belongs_to_nos(p_obj) && obj_is_fw_in_oi(p_obj)){ assert(obj_get_vt(p_obj) == obj_get_vt(obj_get_fw_in_oi(p_obj))); p_obj = obj_get_fw_in_oi(p_obj); assert(p_obj); } } #endif if(!obj_mark_in_vt(p_obj)) return; if( !major_is_marksweep() && p_obj >= los_boundary ){ Block_Header* block = GC_BLOCK_HEADER(p_obj); if( heap_verifier->is_before_gc) block->num_live_objs++; /* we can't set block->num_live_objs = 0 if !is_before_gc, because the some blocks may be freed hence not visited after GC. So we should reset it in GC space reset functions. */ } verify_object_header(p_obj, heap_verifier); verifier_update_verify_info(p_obj, heap_verifier); /*FIXME: */ if (!object_has_ref_field(p_obj)) return; REF* p_ref; if (object_is_array(p_obj)) { Partial_Reveal_Array* array = (Partial_Reveal_Array*)p_obj; unsigned int array_length = array->array_len; p_ref = (REF*)((POINTER_SIZE_INT)array + (int)array_first_element_offset(array)); for (unsigned int i = 0; i < array_length; i++) { scan_slot(heap_verifier, p_ref+i); } }else{ unsigned int num_refs = object_ref_field_num(p_obj); int* ref_iterator = object_ref_iterator_init(p_obj); for(unsigned int i=0; i<num_refs; i++){ p_ref = object_ref_iterator_get(ref_iterator+i, p_obj); scan_slot(heap_verifier, p_ref); } #ifndef BUILD_IN_REFERENT WeakReferenceType type = special_reference_type(p_obj); if(type == SOFT_REFERENCE && verifier_collect_is_minor(gc_verifier)){ p_ref = obj_get_referent_field(p_obj); scan_slot(heap_verifier, p_ref); } #endif } return; }