2008-06-05 15:57:56 -07:00
/*
2019-01-10 15:13:51 -05:00
* Copyright ( c ) 2001 , 2019 , Oracle and / or its affiliates . All rights reserved .
2008-06-05 15:57:56 -07:00
* 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 .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
2010-05-27 19:08:38 -07:00
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
2008-06-05 15:57:56 -07:00
*
*/
2019-01-10 15:13:51 -05:00
# ifndef SHARE_GC_G1_HEAPREGIONREMSET_HPP
# define SHARE_GC_G1_HEAPREGIONREMSET_HPP
2010-11-23 13:22:55 -08:00
2015-05-13 15:16:06 +02:00
# include "gc/g1/g1CodeCacheRemSet.hpp"
2015-12-21 12:02:08 +01:00
# include "gc/g1/g1FromCardCache.hpp"
2015-05-13 15:16:06 +02:00
# include "gc/g1/sparsePRT.hpp"
2010-11-23 13:22:55 -08:00
2008-06-05 15:57:56 -07:00
// Remembered set for a heap region. Represent a set of "cards" that
// contain pointers into the owner heap region. Cards are defined somewhat
// abstractly, in terms of what the "BlockOffsetTable" in use can parse.
class G1CollectedHeap ;
2016-01-07 16:25:53 +01:00
class G1BlockOffsetTable ;
2016-04-06 13:41:59 +02:00
class G1CardLiveData ;
2008-06-05 15:57:56 -07:00
class HeapRegion ;
class HeapRegionRemSetIterator ;
2012-06-25 16:00:55 -07:00
class PerRegionTable ;
2008-06-05 15:57:56 -07:00
class SparsePRT ;
2013-08-15 10:52:18 +02:00
class nmethod ;
2008-06-05 15:57:56 -07:00
// The "_coarse_map" is a bitmap with one bit for each region, where set
// bits indicate that the corresponding region may contain some pointer
// into the owning region.
// The "_fine_grain_entries" array is an open hash table of PerRegionTables
// (PRTs), indicating regions for which we're keeping the RS as a set of
// cards. The strategy is to cap the size of the fine-grain table,
// deleting an entry and setting the corresponding coarse-grained bit when
// we would overflow this cap.
// We use a mixture of locking and lock-free techniques here. We allow
// threads to locate PRTs without locking, but threads attempting to alter
// a bucket list obtain a lock. This means that any failing attempt to
// find a PRT must be retried with the lock. It might seem dangerous that
// a read can find a PRT that is concurrently deleted. This is all right,
// because:
//
// 1) We only actually free PRT's at safe points (though we reuse them at
// other times).
// 2) We find PRT's in an attempt to add entries. If a PRT is deleted,
// it's _coarse_map bit is set, so the that we were attempting to add
// is represented. If a deleted PRT is re-used, a thread adding a bit,
// thinking the PRT is for a different region, does no harm.
2018-03-14 07:27:19 -04:00
class OtherRegionsTable {
2008-06-05 15:57:56 -07:00
friend class HeapRegionRemSetIterator ;
G1CollectedHeap * _g1h ;
2014-03-17 10:12:21 +01:00
Mutex * _m ;
2008-06-05 15:57:56 -07:00
// These are protected by "_m".
2016-05-03 22:45:27 +02:00
CHeapBitMap _coarse_map ;
2008-06-05 15:57:56 -07:00
size_t _n_coarse_entries ;
static jint _n_coarsenings ;
2012-06-25 16:00:55 -07:00
PerRegionTable * * _fine_grain_regions ;
size_t _n_fine_entries ;
2008-06-05 15:57:56 -07:00
2012-07-17 12:24:05 -07:00
// The fine grain remembered sets are doubly linked together using
// their 'next' and 'prev' fields.
// This allows fast bulk freeing of all the fine grain remembered
// set entries, and fast finding of all of them without iterating
// over the _fine_grain_regions table.
PerRegionTable * _first_all_fine_prts ;
PerRegionTable * _last_all_fine_prts ;
2012-06-25 16:00:55 -07:00
// Used to sample a subset of the fine grain PRTs to determine which
// PRT to evict and coarsen.
2008-06-05 15:57:56 -07:00
size_t _fine_eviction_start ;
static size_t _fine_eviction_stride ;
static size_t _fine_eviction_sample_size ;
SparsePRT _sparse_table ;
// These are static after init.
static size_t _max_fine_entries ;
static size_t _mod_max_fine_entries_mask ;
// Requires "prt" to be the first element of the bucket list appropriate
// for "hr". If this list contains an entry for "hr", return it,
// otherwise return "NULL".
2012-06-25 16:00:55 -07:00
PerRegionTable * find_region_table ( size_t ind , HeapRegion * hr ) const ;
2008-06-05 15:57:56 -07:00
2012-06-25 16:00:55 -07:00
// Find, delete, and return a candidate PerRegionTable, if any exists,
2008-06-05 15:57:56 -07:00
// adding the deleted region to the coarse bitmap. Requires the caller
// to hold _m, and the fine-grain table to be full.
2012-06-25 16:00:55 -07:00
PerRegionTable * delete_region_table ( ) ;
2008-06-05 15:57:56 -07:00
2012-07-17 12:24:05 -07:00
// link/add the given fine grain remembered set into the "all" list
void link_to_all ( PerRegionTable * prt ) ;
// unlink/remove the given fine grain remembered set into the "all" list
void unlink_from_all ( PerRegionTable * prt ) ;
2014-12-09 12:47:19 +01:00
bool contains_reference_locked ( OopOrNarrowOopStar from ) const ;
2018-11-28 11:06:58 +01:00
size_t occ_fine ( ) const ;
size_t occ_coarse ( ) const ;
size_t occ_sparse ( ) const ;
2018-03-26 16:51:43 +02:00
public :
2018-10-31 13:43:57 +01:00
// Create a new remembered set. The given mutex is used to ensure consistency.
OtherRegionsTable ( Mutex * m ) ;
2008-06-05 15:57:56 -07:00
2018-03-26 16:51:43 +02:00
// Returns the card index of the given within_region pointer relative to the bottom
// of the given heap region.
static CardIdx_t card_within_region ( OopOrNarrowOopStar within_region , HeapRegion * hr ) ;
2018-03-26 16:51:43 +02:00
// Adds the reference from "from to this remembered set.
2014-09-24 11:00:12 +02:00
void add_reference ( OopOrNarrowOopStar from , uint tid ) ;
2008-06-05 15:57:56 -07:00
2014-12-09 12:47:19 +01:00
// Returns whether the remembered set contains the given reference.
bool contains_reference ( OopOrNarrowOopStar from ) const ;
2015-01-07 15:15:37 +01:00
// Returns whether this remembered set (and all sub-sets) have an occupancy
// that is less or equal than the given occupancy.
bool occupancy_less_or_equal_than ( size_t limit ) const ;
2014-12-09 12:47:19 +01:00
// Returns whether this remembered set (and all sub-sets) does not contain any entry.
2014-07-23 09:03:32 +02:00
bool is_empty ( ) const ;
2014-12-09 12:47:19 +01:00
// Returns the number of cards contained in this remembered set.
2008-06-05 15:57:56 -07:00
size_t occupied ( ) const ;
static jint n_coarsenings ( ) { return _n_coarsenings ; }
2014-12-09 12:47:19 +01:00
// Returns size of the actual remembered set containers in bytes.
2008-06-05 15:57:56 -07:00
size_t mem_size ( ) const ;
2014-12-09 12:47:19 +01:00
// Returns the size of static data in bytes.
2008-06-05 15:57:56 -07:00
static size_t static_mem_size ( ) ;
2014-12-09 12:47:19 +01:00
// Returns the size of the free list content in bytes.
2008-06-05 15:57:56 -07:00
static size_t fl_mem_size ( ) ;
2014-12-09 12:47:19 +01:00
// Clear the entire contents of this remembered set.
2008-06-05 15:57:56 -07:00
void clear ( ) ;
} ;
2012-06-28 17:03:16 -04:00
class HeapRegionRemSet : public CHeapObj < mtGC > {
2008-06-05 15:57:56 -07:00
friend class VMStructs ;
friend class HeapRegionRemSetIterator ;
private :
2016-01-07 16:25:53 +01:00
G1BlockOffsetTable * _bot ;
2008-06-05 15:57:56 -07:00
2014-03-17 10:12:21 +01:00
// A set of code blobs (nmethods) whose code contains pointers into
2013-08-15 10:52:18 +02:00
// the region that owns this RSet.
2014-03-17 10:12:21 +01:00
G1CodeRootSet _code_roots ;
Mutex _m ;
2013-08-15 10:52:18 +02:00
2008-06-05 15:57:56 -07:00
OtherRegionsTable _other_regions ;
2018-10-31 13:43:57 +01:00
HeapRegion * _hr ;
void clear_fcc ( ) ;
2008-06-05 15:57:56 -07:00
public :
2016-01-07 16:25:53 +01:00
HeapRegionRemSet ( G1BlockOffsetTable * bot , HeapRegion * hr ) ;
2008-06-05 15:57:56 -07:00
2010-02-11 15:52:19 -08:00
static void setup_remset_size ( ) ;
2008-06-05 15:57:56 -07:00
2018-10-31 13:43:57 +01:00
bool cardset_is_empty ( ) const {
return _other_regions . is_empty ( ) ;
}
2014-07-23 09:03:32 +02:00
bool is_empty ( ) const {
2018-10-31 13:43:57 +01:00
return ( strong_code_roots_list_length ( ) = = 0 ) & & cardset_is_empty ( ) ;
2014-07-23 09:03:32 +02:00
}
2015-01-07 15:15:37 +01:00
bool occupancy_less_or_equal_than ( size_t occ ) const {
return ( strong_code_roots_list_length ( ) = = 0 ) & & _other_regions . occupancy_less_or_equal_than ( occ ) ;
}
2014-03-17 10:12:21 +01:00
size_t occupied ( ) {
MutexLockerEx x ( & _m , Mutex : : _no_safepoint_check_flag ) ;
return occupied_locked ( ) ;
}
size_t occupied_locked ( ) {
2008-06-05 15:57:56 -07:00
return _other_regions . occupied ( ) ;
}
static jint n_coarsenings ( ) { return OtherRegionsTable : : n_coarsenings ( ) ; }
2018-03-26 16:51:43 +02:00
private :
enum RemSetState {
Untracked ,
Updating ,
Complete
} ;
RemSetState _state ;
static const char * _state_strings [ ] ;
2018-04-04 14:51:26 +02:00
static const char * _short_state_strings [ ] ;
2018-03-26 16:51:43 +02:00
public :
const char * get_state_str ( ) const { return _state_strings [ _state ] ; }
2018-04-04 14:51:26 +02:00
const char * get_short_state_str ( ) const { return _short_state_strings [ _state ] ; }
2018-03-26 16:51:43 +02:00
bool is_tracked ( ) { return _state ! = Untracked ; }
bool is_updating ( ) { return _state = = Updating ; }
bool is_complete ( ) { return _state = = Complete ; }
void set_state_empty ( ) {
guarantee ( SafepointSynchronize : : is_at_safepoint ( ) | | ! is_tracked ( ) , " Should only set to Untracked during safepoint but is %s. " , get_state_str ( ) ) ;
if ( _state = = Untracked ) {
return ;
}
2018-10-31 13:43:57 +01:00
clear_fcc ( ) ;
2018-03-26 16:51:43 +02:00
_state = Untracked ;
}
void set_state_updating ( ) {
guarantee ( SafepointSynchronize : : is_at_safepoint ( ) & & ! is_tracked ( ) , " Should only set to Updating from Untracked during safepoint but is %s " , get_state_str ( ) ) ;
2018-10-31 13:43:57 +01:00
clear_fcc ( ) ;
2018-03-26 16:51:43 +02:00
_state = Updating ;
}
void set_state_complete ( ) {
2018-10-31 13:43:57 +01:00
clear_fcc ( ) ;
2018-03-26 16:51:43 +02:00
_state = Complete ;
}
2012-06-25 16:00:55 -07:00
// Used in the sequential case.
2009-07-14 15:40:39 -07:00
void add_reference ( OopOrNarrowOopStar from ) {
2018-03-26 16:51:43 +02:00
add_reference ( from , 0 ) ;
2008-06-05 15:57:56 -07:00
}
2012-06-25 16:00:55 -07:00
// Used in the parallel case.
2014-09-24 11:00:12 +02:00
void add_reference ( OopOrNarrowOopStar from , uint tid ) {
2018-03-26 16:51:43 +02:00
RemSetState state = _state ;
if ( state = = Untracked ) {
return ;
}
2018-10-31 13:43:57 +01:00
uint cur_idx = _hr - > hrm_index ( ) ;
uintptr_t from_card = uintptr_t ( from ) > > CardTable : : card_shift ;
if ( G1FromCardCache : : contains_or_replace ( tid , cur_idx , from_card ) ) {
assert ( contains_reference ( from ) , " We just found " PTR_FORMAT " in the FromCardCache " , p2i ( from ) ) ;
return ;
}
2008-06-05 15:57:56 -07:00
_other_regions . add_reference ( from , tid ) ;
}
// The region is being reclaimed; clear its remset, and any mention of
// entries for this region in other remsets.
2018-03-26 16:51:43 +02:00
void clear ( bool only_cardset = false ) ;
void clear_locked ( bool only_cardset = false ) ;
2008-06-05 15:57:56 -07:00
// The actual # of bytes this hr_remset takes up.
2013-08-15 10:52:18 +02:00
// Note also includes the strong code root set.
2008-06-05 15:57:56 -07:00
size_t mem_size ( ) {
2014-03-17 10:12:21 +01:00
MutexLockerEx x ( & _m , Mutex : : _no_safepoint_check_flag ) ;
2008-06-05 15:57:56 -07:00
return _other_regions . mem_size ( )
// This correction is necessary because the above includes the second
// part.
2014-04-22 11:10:12 +02:00
+ ( sizeof ( HeapRegionRemSet ) - sizeof ( OtherRegionsTable ) )
2013-08-15 10:52:18 +02:00
+ strong_code_roots_mem_size ( ) ;
2008-06-05 15:57:56 -07:00
}
// Returns the memory occupancy of all static data structures associated
// with remembered sets.
static size_t static_mem_size ( ) {
2014-08-29 13:12:21 +02:00
return OtherRegionsTable : : static_mem_size ( ) + G1CodeRootSet : : static_mem_size ( ) ;
2008-06-05 15:57:56 -07:00
}
// Returns the memory occupancy of all free_list data structures associated
// with remembered sets.
static size_t fl_mem_size ( ) {
2014-08-29 13:12:21 +02:00
return OtherRegionsTable : : fl_mem_size ( ) ;
2008-06-05 15:57:56 -07:00
}
2009-07-14 15:40:39 -07:00
bool contains_reference ( OopOrNarrowOopStar from ) const {
2008-06-05 15:57:56 -07:00
return _other_regions . contains_reference ( from ) ;
}
2013-08-15 10:52:18 +02:00
// Routines for managing the list of code roots that point into
// the heap region that owns this RSet.
void add_strong_code_root ( nmethod * nm ) ;
2014-08-29 13:12:21 +02:00
void add_strong_code_root_locked ( nmethod * nm ) ;
2013-08-15 10:52:18 +02:00
void remove_strong_code_root ( nmethod * nm ) ;
// Applies blk->do_code_blob() to each of the entries in
// the strong code roots list
void strong_code_roots_do ( CodeBlobClosure * blk ) const ;
2014-08-29 13:12:21 +02:00
void clean_strong_code_roots ( HeapRegion * hr ) ;
2013-08-15 10:52:18 +02:00
// Returns the number of elements in the strong code roots list
2014-07-23 09:03:32 +02:00
size_t strong_code_roots_list_length ( ) const {
2014-03-17 10:12:21 +01:00
return _code_roots . length ( ) ;
2013-08-15 10:52:18 +02:00
}
// Returns true if the strong code roots contains the given
// nmethod.
bool strong_code_roots_list_contains ( nmethod * nm ) {
2014-03-17 10:12:21 +01:00
return _code_roots . contains ( nm ) ;
2013-08-15 10:52:18 +02:00
}
// Returns the amount of memory, in bytes, currently
// consumed by the strong code roots.
size_t strong_code_roots_mem_size ( ) ;
2014-12-09 12:47:19 +01:00
static void invalidate_from_card_cache ( uint start_idx , size_t num_regions ) {
2015-12-21 12:04:32 +01:00
G1FromCardCache : : invalidate ( start_idx , num_regions ) ;
2008-06-05 15:57:56 -07:00
}
# ifndef PRODUCT
static void print_from_card_cache ( ) {
2015-12-21 12:04:32 +01:00
G1FromCardCache : : print ( ) ;
2008-06-05 15:57:56 -07:00
}
static void test ( ) ;
# endif
} ;
2013-04-18 10:09:23 -07:00
class HeapRegionRemSetIterator : public StackObj {
2018-10-31 13:43:57 +01:00
private :
2014-04-16 10:55:58 +02:00
// The region RSet over which we are iterating.
2014-03-17 10:12:21 +01:00
HeapRegionRemSet * _hrrs ;
2008-06-05 15:57:56 -07:00
// Local caching of HRRS fields.
const BitMap * _coarse_map ;
2016-01-07 16:25:53 +01:00
G1BlockOffsetTable * _bot ;
2008-06-05 15:57:56 -07:00
G1CollectedHeap * _g1h ;
2014-04-16 10:55:58 +02:00
// The number of cards yielded since initialization.
2008-06-05 15:57:56 -07:00
size_t _n_yielded_fine ;
size_t _n_yielded_coarse ;
size_t _n_yielded_sparse ;
2014-04-16 10:55:58 +02:00
// Indicates what granularity of table that we are currently iterating over.
2013-04-18 10:09:23 -07:00
// We start iterating over the sparse table, progress to the fine grain
// table, and then finish with the coarse table.
2008-06-05 15:57:56 -07:00
enum IterState {
Sparse ,
Fine ,
Coarse
} ;
IterState _is ;
2014-04-16 10:55:58 +02:00
// For both Coarse and Fine remembered set iteration this contains the
// first card number of the heap region we currently iterate over.
2008-06-05 15:57:56 -07:00
size_t _cur_region_card_offset ;
2014-04-16 10:55:58 +02:00
// Current region index for the Coarse remembered set iteration.
2011-10-05 08:44:10 -07:00
int _coarse_cur_region_index ;
size_t _coarse_cur_region_cur_card ;
2008-06-05 15:57:56 -07:00
bool coarse_has_next ( size_t & card_index ) ;
2014-04-16 10:55:58 +02:00
// The PRT we are currently iterating over.
2012-06-25 16:00:55 -07:00
PerRegionTable * _fine_cur_prt ;
2014-04-16 10:55:58 +02:00
// Card offset within the current PRT.
size_t _cur_card_in_prt ;
2008-06-05 15:57:56 -07:00
2014-04-16 10:55:58 +02:00
// Update internal variables when switching to the given PRT.
void switch_to_prt ( PerRegionTable * prt ) ;
2008-06-05 15:57:56 -07:00
bool fine_has_next ( ) ;
bool fine_has_next ( size_t & card_index ) ;
2014-04-16 10:55:58 +02:00
// The Sparse remembered set iterator.
SparsePRTIter _sparse_iter ;
2018-10-31 13:43:57 +01:00
public :
2014-03-17 10:12:21 +01:00
HeapRegionRemSetIterator ( HeapRegionRemSet * hrrs ) ;
2008-06-05 15:57:56 -07:00
// If there remains one or more cards to be yielded, returns true and
// sets "card_index" to one of those cards (which is then considered
// yielded.) Otherwise, returns false (and leaves "card_index"
// undefined.)
bool has_next ( size_t & card_index ) ;
size_t n_yielded_fine ( ) { return _n_yielded_fine ; }
size_t n_yielded_coarse ( ) { return _n_yielded_coarse ; }
size_t n_yielded_sparse ( ) { return _n_yielded_sparse ; }
size_t n_yielded ( ) {
return n_yielded_fine ( ) + n_yielded_coarse ( ) + n_yielded_sparse ( ) ;
}
} ;
2019-01-10 15:13:51 -05:00
# endif // SHARE_GC_G1_HEAPREGIONREMSET_HPP