src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp

Print this page
rev 5920 : 8035406: Improve data structure for Code Cache remembered sets
Summary: Change the code cache remembered sets data structure from a GrowableArray to a chunked list of nmethods. This makes the data structure more amenable to parallelization, and decreases freeing time.
Reviewed-by:

*** 1,7 **** /* ! * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 257,270 **** size_t OtherRegionsTable::_max_fine_entries = 0; size_t OtherRegionsTable::_mod_max_fine_entries_mask = 0; size_t OtherRegionsTable::_fine_eviction_stride = 0; size_t OtherRegionsTable::_fine_eviction_sample_size = 0; ! OtherRegionsTable::OtherRegionsTable(HeapRegion* hr) : _g1h(G1CollectedHeap::heap()), ! _m(Mutex::leaf, "An OtherRegionsTable lock", true), ! _hr(hr), _coarse_map(G1CollectedHeap::heap()->max_regions(), false /* in-resource-area */), _fine_grain_regions(NULL), _first_all_fine_prts(NULL), _last_all_fine_prts(NULL), _n_fine_entries(0), _n_coarse_entries(0), --- 257,269 ---- size_t OtherRegionsTable::_max_fine_entries = 0; size_t OtherRegionsTable::_mod_max_fine_entries_mask = 0; size_t OtherRegionsTable::_fine_eviction_stride = 0; size_t OtherRegionsTable::_fine_eviction_sample_size = 0; ! OtherRegionsTable::OtherRegionsTable(HeapRegion* hr, Mutex* m) : _g1h(G1CollectedHeap::heap()), ! _hr(hr), _m(m), _coarse_map(G1CollectedHeap::heap()->max_regions(), false /* in-resource-area */), _fine_grain_regions(NULL), _first_all_fine_prts(NULL), _last_all_fine_prts(NULL), _n_fine_entries(0), _n_coarse_entries(0),
*** 440,450 **** // Otherwise find a per-region table to add it to. size_t ind = from_hrs_ind & _mod_max_fine_entries_mask; PerRegionTable* prt = find_region_table(ind, from_hr); if (prt == NULL) { ! MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); // Confirm that it's really not there... prt = find_region_table(ind, from_hr); if (prt == NULL) { uintptr_t from_hr_bot_card_index = --- 439,449 ---- // Otherwise find a per-region table to add it to. size_t ind = from_hrs_ind & _mod_max_fine_entries_mask; PerRegionTable* prt = find_region_table(ind, from_hr); if (prt == NULL) { ! MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); // Confirm that it's really not there... prt = find_region_table(ind, from_hr); if (prt == NULL) { uintptr_t from_hr_bot_card_index =
*** 542,552 **** } jint OtherRegionsTable::_n_coarsenings = 0; PerRegionTable* OtherRegionsTable::delete_region_table() { ! assert(_m.owned_by_self(), "Precondition"); assert(_n_fine_entries == _max_fine_entries, "Precondition"); PerRegionTable* max = NULL; jint max_occ = 0; PerRegionTable** max_prev; size_t max_ind; --- 541,551 ---- } jint OtherRegionsTable::_n_coarsenings = 0; PerRegionTable* OtherRegionsTable::delete_region_table() { ! assert(_m->owned_by_self(), "Precondition"); assert(_n_fine_entries == _max_fine_entries, "Precondition"); PerRegionTable* max = NULL; jint max_occ = 0; PerRegionTable** max_prev; size_t max_ind;
*** 674,685 **** clear_fcc(); } size_t OtherRegionsTable::occupied() const { - // Cast away const in this case. - MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag); size_t sum = occ_fine(); sum += occ_sparse(); sum += occ_coarse(); return sum; } --- 673,682 ----
*** 705,716 **** size_t OtherRegionsTable::occ_sparse() const { return _sparse_table.occupied(); } size_t OtherRegionsTable::mem_size() const { - // Cast away const in this case. - MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag); size_t sum = 0; // all PRTs are of the same size so it is sufficient to query only one of them. if (_first_all_fine_prts != NULL) { assert(_last_all_fine_prts != NULL && _first_all_fine_prts->mem_size() == _last_all_fine_prts->mem_size(), "check that mem_size() is constant"); --- 702,711 ----
*** 737,747 **** _from_card_cache[i][hrs_idx] = -1; } } void OtherRegionsTable::clear() { - MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); // if there are no entries, skip this step if (_first_all_fine_prts != NULL) { guarantee(_first_all_fine_prts != NULL && _last_all_fine_prts != NULL, "just checking"); PerRegionTable::bulk_free(_first_all_fine_prts, _last_all_fine_prts); memset(_fine_grain_regions, 0, _max_fine_entries * sizeof(_fine_grain_regions[0])); --- 732,741 ----
*** 757,767 **** clear_fcc(); } void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) { ! MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); size_t hrs_ind = (size_t) from_hr->hrs_index(); size_t ind = hrs_ind & _mod_max_fine_entries_mask; if (del_single_region_table(ind, from_hr)) { assert(!_coarse_map.at(hrs_ind), "Inv"); } else { --- 751,761 ---- clear_fcc(); } void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) { ! MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag); size_t hrs_ind = (size_t) from_hr->hrs_index(); size_t ind = hrs_ind & _mod_max_fine_entries_mask; if (del_single_region_table(ind, from_hr)) { assert(!_coarse_map.at(hrs_ind), "Inv"); } else {
*** 803,813 **** } } bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const { // Cast away const in this case. ! MutexLockerEx x((Mutex*)&_m, Mutex::_no_safepoint_check_flag); return contains_reference_locked(from); } bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const { HeapRegion* hr = _g1h->heap_region_containing_raw(from); --- 797,807 ---- } } bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const { // Cast away const in this case. ! MutexLockerEx x((Mutex*)_m, Mutex::_no_safepoint_check_flag); return contains_reference_locked(from); } bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const { HeapRegion* hr = _g1h->heap_region_containing_raw(from);
*** 848,858 **** return (int)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); } HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr) ! : _bosa(bosa), _strong_code_roots_list(NULL), _other_regions(hr) { reset_for_par_iteration(); } void HeapRegionRemSet::setup_remset_size() { // Setup sparse and fine-grain tables sizes. --- 842,853 ---- return (int)MAX2(DirtyCardQueueSet::num_par_ids() + ConcurrentG1Refine::thread_num(), ParallelGCThreads); } HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr) ! : _bosa(bosa), _m(Mutex::leaf, "An OtherRegionsTable lock", true), ! _code_roots(), _other_regions(hr, &_m) { reset_for_par_iteration(); } void HeapRegionRemSet::setup_remset_size() { // Setup sparse and fine-grain tables sizes.
*** 881,891 **** bool HeapRegionRemSet::iter_is_complete() { return _iter_state == Complete; } #ifndef PRODUCT ! void HeapRegionRemSet::print() const { HeapRegionRemSetIterator iter(this); size_t card_index; while (iter.has_next(card_index)) { HeapWord* card_start = G1CollectedHeap::heap()->bot_shared()->address_for_index(card_index); --- 876,886 ---- bool HeapRegionRemSet::iter_is_complete() { return _iter_state == Complete; } #ifndef PRODUCT ! void HeapRegionRemSet::print() { HeapRegionRemSetIterator iter(this); size_t card_index; while (iter.has_next(card_index)) { HeapWord* card_start = G1CollectedHeap::heap()->bot_shared()->address_for_index(card_index);
*** 907,924 **** void HeapRegionRemSet::cleanup() { SparsePRT::cleanup_all(); } void HeapRegionRemSet::clear() { ! if (_strong_code_roots_list != NULL) { ! delete _strong_code_roots_list; ! } ! _strong_code_roots_list = new (ResourceObj::C_HEAP, mtGC) ! GrowableArray<nmethod*>(10, 0, NULL, true); _other_regions.clear(); ! assert(occupied() == 0, "Should be clear."); reset_for_par_iteration(); } void HeapRegionRemSet::reset_for_par_iteration() { _iter_state = Unclaimed; --- 902,919 ---- void HeapRegionRemSet::cleanup() { SparsePRT::cleanup_all(); } void HeapRegionRemSet::clear() { ! MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); ! clear_locked(); ! } + void HeapRegionRemSet::clear_locked() { + _code_roots.clear(); _other_regions.clear(); ! assert(occupied_locked() == 0, "Should be clear."); reset_for_par_iteration(); } void HeapRegionRemSet::reset_for_par_iteration() { _iter_state = Unclaimed;
*** 935,960 **** // Code roots support void HeapRegionRemSet::add_strong_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); ! // Search for the code blob from the RHS to avoid ! // duplicate entries as much as possible ! if (_strong_code_roots_list->find_from_end(nm) < 0) { ! // Code blob isn't already in the list ! _strong_code_roots_list->push(nm); ! } } void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); ! int idx = _strong_code_roots_list->find(nm); ! if (idx >= 0) { ! _strong_code_roots_list->remove_at(idx); ! } // Check that there were no duplicates ! guarantee(_strong_code_roots_list->find(nm) < 0, "duplicate entry found"); } class NMethodMigrationOopClosure : public OopClosure { G1CollectedHeap* _g1h; HeapRegion* _from; --- 930,947 ---- // Code roots support void HeapRegionRemSet::add_strong_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); ! _code_roots.add(nm); } void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) { assert(nm != NULL, "sanity"); ! _code_roots.remove(nm); // Check that there were no duplicates ! guarantee(!_code_roots.contains(nm), "duplicate entry found"); } class NMethodMigrationOopClosure : public OopClosure { G1CollectedHeap* _g1h; HeapRegion* _from;
*** 1012,1023 **** // List of code blobs to retain for this region GrowableArray<nmethod*> to_be_retained(10); G1CollectedHeap* g1h = G1CollectedHeap::heap(); ! while (_strong_code_roots_list->is_nonempty()) { ! nmethod *nm = _strong_code_roots_list->pop(); if (nm != NULL) { NMethodMigrationOopClosure oop_cl(g1h, hr(), nm); nm->oops_do(&oop_cl); if (oop_cl.retain()) { to_be_retained.push(nm); --- 999,1010 ---- // List of code blobs to retain for this region GrowableArray<nmethod*> to_be_retained(10); G1CollectedHeap* g1h = G1CollectedHeap::heap(); ! while (!_code_roots.is_empty()) { ! nmethod *nm = _code_roots.pop(); if (nm != NULL) { NMethodMigrationOopClosure oop_cl(g1h, hr(), nm); nm->oops_do(&oop_cl); if (oop_cl.retain()) { to_be_retained.push(nm);
*** 1036,1059 **** add_strong_code_root(nm); } } void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const { ! for (int i = 0; i < _strong_code_roots_list->length(); i += 1) { ! nmethod* nm = _strong_code_roots_list->at(i); ! blk->do_code_blob(nm); ! } } size_t HeapRegionRemSet::strong_code_roots_mem_size() { ! return sizeof(GrowableArray<nmethod*>) + ! _strong_code_roots_list->max_length() * sizeof(nmethod*); } //-------------------- Iteration -------------------- ! HeapRegionRemSetIterator:: HeapRegionRemSetIterator(const HeapRegionRemSet* hrrs) : _hrrs(hrrs), _g1h(G1CollectedHeap::heap()), _coarse_map(&hrrs->_other_regions._coarse_map), _fine_grain_regions(hrrs->_other_regions._fine_grain_regions), _bosa(hrrs->bosa()), --- 1023,1042 ---- add_strong_code_root(nm); } } void HeapRegionRemSet::strong_code_roots_do(CodeBlobClosure* blk) const { ! _code_roots.nmethods_do(blk); } size_t HeapRegionRemSet::strong_code_roots_mem_size() { ! return _code_roots.mem_size(); } //-------------------- Iteration -------------------- ! HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) : _hrrs(hrrs), _g1h(G1CollectedHeap::heap()), _coarse_map(&hrrs->_other_regions._coarse_map), _fine_grain_regions(hrrs->_other_regions._fine_grain_regions), _bosa(hrrs->bosa()),