Repository navigation
g1 region Free_Region
wangkaiwu edited this page Feb 5, 2022
·
1 revision
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; }
};void FreeRegionList::add_list_common_end(FreeRegionList* from_list) {
_length += from_list->length();
}void FreeRegionList::clear() {
_length = 0;
}inline void HeapRegionSetBase::add(HeapRegion* hr) {
_length++;
}inline void HeapRegionSetBase::remove(HeapRegion* hr) {
_length--;
}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();
}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();
}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);
}
}void FreeRegionList::remove_all() {
clear();
}class HeapRegionManager: public CHeapObj<mtGC> {
FreeRegionList _free_list;
void remove_all_free_regions() {
_free_list.remove_all();
}
};void G1FullCollector::prepare_collection() {
_heap->prepare_heap_for_full_collection();
}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);
}
}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();
}void G1ConcurrentMark::remark() {
_g1h->resize_heap_if_necessary();
}inline void FreeRegionList::add_ordered(HeapRegion* hr) {
add(hr);
}void G1CollectedHeap::free_region(HeapRegion* hr, FreeRegionList* free_list) {
if (free_list != NULL) {
free_list->add_ordered(hr);
}
}void G1CollectedHeap::free_humongous_region(HeapRegion* hr,
FreeRegionList* free_list) {
free_region(hr, free_list);
}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();
}inline void HeapRegionManager::insert_into_free_list(HeapRegion* hr) {
_free_list.add_ordered(hr);
}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);
}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();
}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);
}
}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);
}
}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;
}
}
}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);
}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);
}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;
}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);
}
}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);
}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);
}HeapRegion* HeapRegionManager::allocate_humongous_from_free_list(uint num_regions) {
return allocate_free_regions_starting_at(candidate, num_regions);
}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);
}
}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);
}
}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);
}