Skip to content

g1 region Free_Region

wangkaiwu edited this page Feb 5, 2022 · 1 revision

Free Regions

_free_regions_at_end_of_collection

赋值过程

void G1Policy::record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark) {
    _free_regions_at_end_of_collection = _g1h->num_free_regions();
}
class G1CollectedHeap : public CollectedHeap {
    HeapRegionManager _hrm;
    uint num_free_regions() const { return _hrm.num_free_regions(); }
};
class HeapRegionManager: public CHeapObj<mtGC> {
    FreeRegionList _free_list;
    uint num_free_regions() const { 
        return _free_list.length();
    }
};
class FreeRegionList : public HeapRegionSetBase {
    FreeRegionList(const char* name, HeapRegionSetChecker* checker = NULL);
};
class HeapRegionSetBase {
    uint _length;
    uint length() const { return _length; }
};

_free_list._length

修改方法

add_list_common_end

void FreeRegionList::add_list_common_end(FreeRegionList* from_list) {
    _length += from_list->length();
}

clear

void FreeRegionList::clear() {
    _length = 0;
}

add

inline void HeapRegionSetBase::add(HeapRegion* hr) {
    _length++;
}

remove

inline void HeapRegionSetBase::remove(HeapRegion* hr) {
    _length--;
}

add_list_common_end

add_ordered

void FreeRegionList::add_ordered(FreeRegionList* from_list) {
    add_list_common_end(from_list);
}
class G1ReclaimEmptyRegionsClosure : public HeapRegionClosure {
    FreeRegionList* _local_cleanup_list;
    G1ReclaimEmptyRegionsClosure(G1CollectedHeap* g1h,
                                 FreeRegionList* local_cleanup_list) :
                                 _local_cleanup_list(local_cleanup_list){ }
    bool do_heap_region(HeapRegion *hr) {
        if (hr->used() > 0 && hr->max_live_bytes() == 0 && !hr->is_young() && !hr->is_closed_archive()) {
            if (hr->is_humongous()) {
                _humongous_regions_removed++;
                _g1h->free_humongous_region(hr, _local_cleanup_list);
            } else if (hr->is_open_archive()) {
                _archive_regions_removed++;
                _g1h->free_region(hr, _local_cleanup_list);
            } else {
                _old_regions_removed++;
                _g1h->free_region(hr, _local_cleanup_list);
            }
        }
    }
};
class G1ReclaimEmptyRegionsTask : public AbstractGangTask {
    FreeRegionList* _cleanup_list;
    G1ReclaimEmptyRegionsTask(G1CollectedHeap* g1h, FreeRegionList* cleanup_list, uint n_workers) :
        AbstractGangTask("G1 Cleanup"),
        _cleanup_list(cleanup_list){ }
    void work(uint worker_id) {
        FreeRegionList local_cleanup_list("Local Cleanup List");
        G1ReclaimEmptyRegionsClosure cl(_g1h, &local_cleanup_list);
        _g1h->heap_region_par_iterate_from_worker_offset(&cl, &_hrclaimer, worker_id);
        _cleanup_list->add_ordered(&local_cleanup_list);
    }
};
void G1ConcurrentMark::reclaim_empty_regions() {
    G1ReclaimEmptyRegionsTask cl(_g1h, &empty_regions_list, workers->active_workers());
    workers->run_task(&cl);
}
void G1ConcurrentMark::remark() {
    reclaim_empty_regions();
}

append_ordered

void FreeRegionList::append_ordered(FreeRegionList* from_list) {
    add_list_common_end(from_list);
}
class HeapRegionManager: public CHeapObj<mtGC> {
    FreeRegionList _free_list;
    void insert_list_into_free_list(FreeRegionList* list) {
        _free_list.add_ordered(list);
    }
};
void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) {
    MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag);
    _hrm.insert_list_into_free_list(list);
}
void G1ConcurrentMark::reclaim_empty_regions() {
    FreeRegionList empty_regions_list("Empty Regions After Mark List");
    
    G1ReclaimEmptyRegionsTask cl(_g1h, &empty_regions_list, workers->active_workers());
    workers->run_task(&cl);
    
    if (!empty_regions_list.is_empty()) {
        _g1h->prepend_to_freelist(&empty_regions_list);
    }
}
void G1ConcurrentMark::remark() {
    reclaim_empty_regions();
}

clear

abandon

void FreeRegionList::abandon() {
    clear();
}
void HeapRegionManager::rebuild_free_list(WorkGang* workers) {
    _free_list.abandon();
}
void G1CollectedHeap::rebuild_free_region_list() {
    _hrm.rebuild_free_list(workers());
}
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info,
                                                   G1RedirtyCardsQueueSet* rdcqs,
                                                   G1ParScanThreadStateSet* per_thread_states) {
    rebuild_free_region_list();
}
void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_pause_time_ms) {
    bool may_do_optional_evacuation = _collection_set.optional_region_length() != 0;
    if (may_do_optional_evacuation) {
          evacuate_optional_collection_set(&per_thread_states);
    }
}

remove_all

void FreeRegionList::remove_all() {
    clear();
}
class HeapRegionManager: public CHeapObj<mtGC> {
    FreeRegionList _free_list;
    void remove_all_free_regions() {
        _free_list.remove_all();
    }
};

prepare_heap_for_full_collection

void G1FullCollector::prepare_collection() {
    _heap->prepare_heap_for_full_collection();
}

shrink

void G1CollectedHeap::shrink(size_t shrink_bytes) {
    _hrm.remove_all_free_regions();
}
void G1CollectedHeap::resize_heap_if_necessary() {
    bool should_expand;
    size_t resize_amount = _heap_sizing_policy->full_collection_resize_amount(should_expand);
    if (resize_amount == 0) {
    } else if (should_expand) {
    } else {
        shrink(resize_amount);
    }
}
prepare_heap_for_mutators
void G1CollectedHeap::prepare_heap_for_mutators() {
    resize_heap_if_necessary();
}
void G1FullCollector::complete_collection() {
    _heap->prepare_heap_for_mutators();
}
bool G1CollectedHeap::do_full_collection(bool explicit_gc,
                                         bool clear_all_soft_refs,
                                         bool do_maximum_compaction) {
    G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs, do_maximum_compaction);
    collector.complete_collection();
}
remark
void G1ConcurrentMark::remark() {
    _g1h->resize_heap_if_necessary();
}

add

add_ordered

inline void FreeRegionList::add_ordered(HeapRegion* hr) {
    add(hr);
}

free_region

void G1CollectedHeap::free_region(HeapRegion* hr, FreeRegionList* free_list) {
    if (free_list != NULL) {
        free_list->add_ordered(hr);
    }
}
free_humongous_region
void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
                                            FreeRegionList* free_list) {
    free_region(hr, free_list);
}
G1ReclaimEmptyRegionsClosure
class G1ReclaimEmptyRegionsClosure : public HeapRegionClosure {
    bool do_heap_region(HeapRegion *hr) {
        if (hr->is_humongous()) {
          _humongous_regions_removed++;
          _g1h->free_humongous_region(hr, _local_cleanup_list);
        } else if (hr->is_open_archive()) {
          _archive_regions_removed++;
          _g1h->free_region(hr, _local_cleanup_list);
        } else {
          _old_regions_removed++;
          _g1h->free_region(hr, _local_cleanup_list);
        }
    }
};
void G1ConcurrentMark::remark() {
    reclaim_empty_regions();
}

insert_into_free_list

inline void HeapRegionManager::insert_into_free_list(HeapRegion* hr) {
    _free_list.add_ordered(hr);
}
RebuildRegionSetsClosure
class RebuildRegionSetsClosure : public HeapRegionClosure {
    bool do_heap_region(HeapRegion* r) {
        if (r->is_empty()) {
            _hrm->insert_into_free_list(r);
        }
    }
};
void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
    RebuildRegionSetsClosure cl(free_list_only,
                              &_old_set, &_archive_set, &_humongous_set,
                              &_hrm);
    heap_region_iterate(&cl);
}
prepare_heap_for_mutators
void G1CollectedHeap::prepare_heap_for_mutators() {
    rebuild_region_sets(false /* free_list_only */);
    resize_heap_if_necessary();
}
bool G1CollectedHeap::do_full_collection(bool explicit_gc,
                                         bool clear_all_soft_refs,
                                         bool do_maximum_compaction) {
    G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs, do_maximum_compaction);
    collector.complete_collection();
}
shrink
void G1CollectedHeap::shrink(size_t shrink_bytes) {
    _hrm.remove_all_free_regions();
    rebuild_region_sets(true /* free_list_only */);
}
void G1CollectedHeap::resize_heap_if_necessary() {
    bool should_expand;
    size_t resize_amount = _heap_sizing_policy->full_collection_resize_amount(should_expand);
    if (resize_amount == 0) {
    } else if (should_expand) {
    } else {
        shrink(resize_amount);
    }    
}
initialize_regions
void HeapRegionManager::initialize_regions(uint start, uint num_regions) {
    for (uint i = start; i < start + num_regions; i++) {
        HeapRegion* hr = at(i);
        insert_into_free_list(hr);
    }
}
activate_regions
void HeapRegionManager::activate_regions(uint start, uint num_regions) {
    initialize_regions(start, num_regions);
}
void HeapRegionManager::expand(uint start, uint num_regions, WorkGang* pretouch_gang) {
    activate_regions(start, num_regions);
}

####### expand_any

uint HeapRegionManager::expand_any(uint num_regions, WorkGang* pretouch_workers) {
    HeapRegionRange regions = _committed_map.next_committable_range(offset);
    expand(regions.start(), to_expand, pretouch_workers);
}
uint HeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers) {
    if (expanded < num_regions) {
        expanded += expand_any(num_regions - expanded, pretouch_workers);
    }
}
bool G1CollectedHeap::expand(size_t expand_bytes, WorkGang* pretouch_workers, double* expand_time_ms) {
    uint expanded_by = _hrm.expand_by(regions_to_expand, pretouch_workers);
}

######## expand_and_allocate

HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
    size_t expand_bytes = MAX2(word_size * HeapWordSize, MinHeapDeltaBytes);
    if (expand(expand_bytes, _workers)) {
    }
}
HeapWord* G1CollectedHeap::satisfy_failed_allocation_helper(size_t word_size,
                                                            bool do_gc,
                                                            bool maximum_compaction,
                                                            bool expect_null_mutator_alloc_region,
                                                            bool* gc_succeeded) {
    result = expand_and_allocate(word_size);
}

######## expand_heap_after_young_collection

void G1CollectedHeap::expand_heap_after_young_collection(){
    size_t expand_bytes = _heap_sizing_policy->young_collection_expansion_amount();
    if (expand_bytes > 0) {
        if (!expand(expand_bytes, _workers, &expand_ms)) {
            // We failed to expand the heap. Cannot do anything about it.
        }
    }
}
void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_pause_time_ms) {
    expand_heap_after_young_collection();
}

######## initialize

jint G1CollectedHeap::initialize() {
    size_t init_byte_size = InitialHeapSize;
    if (!expand(init_byte_size, _workers)) {
    }
}

######## resize_heap_if_necessary

void G1CollectedHeap::resize_heap_if_necessary() {
    bool should_expand;
    size_t resize_amount = _heap_sizing_policy->full_collection_resize_amount(should_expand);
    if (resize_amount == 0) {
    } else if (should_expand) {
        expand(resize_amount, _workers);
    } else {
        shrink(resize_amount);
    }    
}

####### expand_exact

void HeapRegionManager::expand_exact(uint start, uint num_regions, WorkGang* pretouch_workers) {
    uint end = start + num_regions;
    for (uint i = start; i < end; i++) {
        if (!_committed_map.active(i)) {
            expand(i, 1, pretouch_workers);
        }      
    }
}

######## allocate_containing_regions

bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* commit_count, WorkGang* pretouch_workers) {
    for (uint curr_index = start_index; curr_index <= last_index; curr_index++) {
        if (!is_available(curr_index)) {
            expand_exact(curr_index, 1, pretouch_workers);
        }
    }
}
bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges,
                                            size_t count,
                                            bool open) {
    if (!_hrm.allocate_containing_regions(curr_range, &commits, workers())) {
        return false;
    }
}

######## allocate_humongous_allow_expand

HeapRegion* HeapRegionManager::allocate_humongous_allow_expand(uint num_regions) {
    expand_exact(candidate, num_regions, G1CollectedHeap::heap()->workers());
}
HeapRegion* HeapRegionManager::expand_and_allocate_humongous(uint num_regions) {
    return allocate_humongous_allow_expand(num_regions);
}
HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
    humongous_start = _hrm.expand_and_allocate_humongous(obj_regions);
}

######## expand_on_preferred_node

uint HeapRegionManager::expand_on_preferred_node(uint preferred_index) {
    expand_exact(expand_candidate, 1, NULL);
}
bool G1CollectedHeap::expand_single_region(uint node_index) {
    uint expanded_by = _hrm.expand_on_preferred_node(node_index);
}
HeapRegion* G1CollectedHeap::new_region(size_t word_size,
                                        HeapRegionType type,
                                        bool do_expand,
                                        uint node_index) {
    HeapRegion* res = _hrm.allocate_free_region(type, node_index);
    if (res == NULL && do_expand && _expand_heap_after_alloc_failure) {
        if (expand_single_region(node_index)) {
        }
    }
}

######## find_highest_free

uint HeapRegionManager::find_highest_free(bool* expanded) {
    for (uint curr = reserved_length(); curr-- > 0;) {
        HeapRegion *hr = _regions.get_by_index(curr);
        if (hr == NULL || !is_available(curr)) {
            expand_exact(curr, 1, NULL);
        }
    }
}
HeapRegion* G1CollectedHeap::alloc_highest_free_region() {
    bool expanded = false;
    uint index = _hrm.find_highest_free(&expanded);
}
bool G1ArchiveAllocator::alloc_new_region() {
    HeapRegion* hr = _g1h->alloc_highest_free_region();
}
HeapWord* G1ArchiveAllocator::archive_mem_allocate(size_t word_size) {
    if (_allocation_region == NULL) {
        if (!alloc_new_region()) {
            return NULL;
        }
    }
}
reactivate_regions
void HeapRegionManager::reactivate_regions(uint start, uint num_regions) {
    initialize_regions(start, num_regions);
}

####### expand_exact

void HeapRegionManager::expand_exact(uint start, uint num_regions, WorkGang* pretouch_workers) {
    uint end = start + num_regions;
    for (uint i = start; i < end; i++) {
        if (_committed_map.inactive(i)) {
            if (_committed_map.inactive(i)) {
                reactivate_regions(i, 1);
            }
        }
    }
}

####### expand_inactive

uint HeapRegionManager::expand_inactive(uint num_regions) {
    reactivate_regions(regions.start(), to_expand); 
}

add_to_tail

inline void FreeRegionList::add_to_tail(HeapRegion* region_to_add) {
    add(region_to_add);
}
class G1RebuildFreeListTask : public AbstractGangTask {
    FreeRegionList*    _worker_freelists;
    FreeRegionList* worker_freelist(uint worker) {
        return &_worker_freelists[worker];
    }
    void work(uint worker_id) {
        uint start = worker_id * _worker_chunk_size;
        uint end = MIN2(start + _worker_chunk_size, _hrm->reserved_length());
        if (start > end) {
            return;
        }
        FreeRegionList *free_list = worker_freelist(worker_id);
        for (uint i = start; i < end; i++) {
            HeapRegion *region = _hrm->at_or_null(i);
            if (region != NULL && region->is_free()) {
                free_list->add_to_tail(region);
            }
        }
    }
};
void HeapRegionManager::rebuild_free_list(WorkGang* workers) {
    _free_list.abandon();
    G1RebuildFreeListTask task(this, num_workers);
    workers->run_task(&task, num_workers);
    for (uint worker = 0; worker < num_workers; worker++) {
        _free_list.append_ordered(task.worker_freelist(worker));
    }
}
void G1CollectedHeap::rebuild_free_region_list() {
    _hrm.rebuild_free_list(workers());
}
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info,
                                                   G1RedirtyCardsQueueSet* rdcqs,
                                                   G1ParScanThreadStateSet* per_thread_states) {
    rebuild_free_region_list();
}
void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_pause_time_ms) {
    post_evacuate_collection_set(evacuation_info, &rdcqs, &per_thread_states);
    policy()->record_collection_pause_end(pause_time_ms, concurrent_operation_is_full_mark);
}

remove

remove_starting_at

void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
    HeapRegion* curr = first;
    remove(curr);
}
inline HeapRegion* HeapRegionManager::allocate_free_regions_starting_at(uint first, uint num_regions) {
    HeapRegion* start = at(first);
    _free_list.remove_starting_at(start, num_regions);
    return start;
}

alloc_highest_free_region

HeapRegion* G1CollectedHeap::alloc_highest_free_region() {
    bool expanded = false;
    uint index = _hrm.find_highest_free(&expanded);
    if (index != G1_NO_HRM_INDEX) {
        return _hrm.allocate_free_regions_starting_at(index, 1);
    }
}

allocate_containing_regions

bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* commit_count, WorkGang* pretouch_workers) {
    allocate_free_regions_starting_at(start_index, (last_index - start_index) + 1);
}

allocate_humongous_allow_expand

HeapRegion* HeapRegionManager::allocate_humongous_allow_expand(uint num_regions) {
    expand_exact(candidate, num_regions, G1CollectedHeap::heap()->workers());
    return allocate_free_regions_starting_at(candidate, num_regions);
}

allocate_humongous_from_free_list

HeapRegion* HeapRegionManager::allocate_humongous_from_free_list(uint num_regions) {
    return allocate_free_regions_starting_at(candidate, num_regions);
}

remove_region

inline HeapRegion* FreeRegionList::remove_region(bool from_head) {
    remove(hr);
}
HeapRegion* HeapRegionManager::allocate_free_region(HeapRegionType type, uint requested_node_index) {
    HeapRegion* hr = NULL;
    if (requested_node_index != G1NUMA::AnyNodeIndex && numa->is_enabled()) {
        hr = _free_list.remove_region_with_node_index(from_head, requested_node_index);
    }
    if (hr == NULL) {
        hr = _free_list.remove_region(from_head);
    }
}

remove_region_with_node_index

inline HeapRegion* FreeRegionList::remove_region_with_node_index(bool from_head,
                                                                 uint requested_node_index) {
    HeapRegion* cur;
    remove(cur);
}
HeapRegion* HeapRegionManager::allocate_free_region(HeapRegionType type, uint requested_node_index) {
    HeapRegion* hr = NULL;
    if (requested_node_index != G1NUMA::AnyNodeIndex && numa->is_enabled()) {
        hr = _free_list.remove_region_with_node_index(from_head, requested_node_index);
    }
}

region->set_free()

class HeapRegionType {
    void set_free() { set(FreeTag); }
};
void HeapRegion::set_free() {
    _type.set_free();
}
void HeapRegion::hr_clear(bool clear_space) {
    set_free();
}
void G1CollectedHeap::free_region(HeapRegion* hr, FreeRegionList* free_list) {
    hr->hr_clear(true /* clear_space */);
}
class FreeCSetClosure : public HeapRegionClosure {
    void handle_evacuated_region(HeapRegion* r) {
        _g1h->free_region(r, nullptr);
    }
};
class FreeCSetClosure : public HeapRegionClosure {
    virtual bool do_heap_region(HeapRegion* r) {
        if (_g1h->evacuation_failed(r->hrm_index())) {
        } else {
            handle_evacuated_region(r);
        }
    }
};
void G1PostEvacuateCollectionSetCleanupTask2::FreeCollectionSetTask::do_work(uint worker_id) {
    FreeCSetClosure cl(_surviving_young_words, worker_id, worker_stats(worker_id));
    _g1h->collection_set_par_iterate_all(&cl, &_claimer, worker_id);
}
void G1CollectedHeap::post_evacuate_cleanup_2(PreservedMarksSet* preserved_marks,
                                              G1RedirtyCardsQueueSet* rdcqs,
                                              G1EvacuationInfo* evacuation_info,
                                              const size_t* surviving_young_words) {
    G1PostEvacuateCollectionSetCleanupTask2 cl(preserved_marks, rdcqs, evacuation_info, surviving_young_words);
    run_batch_task(&cl);
}
void G1CollectedHeap::post_evacuate_collection_set(G1EvacuationInfo& evacuation_info,
                                                   G1RedirtyCardsQueueSet* rdcqs,
                                                   G1ParScanThreadStateSet* per_thread_states) {
    post_evacuate_cleanup_2(&_preserved_marks_set, rdcqs, &evacuation_info, per_thread_states->surviving_young_words());
    rebuild_free_region_list();
}
void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_pause_time_ms) {
    post_evacuate_collection_set(evacuation_info, &rdcqs, &per_thread_states);
    policy()->record_collection_pause_end(pause_time_ms, concurrent_operation_is_full_mark);
}

Clone this wiki locally