src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp
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.
*** 23,32 ****
--- 23,33 ----
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP
+ #include "gc_implementation/g1/g1CodeCacheRemSet.hpp"
#include "gc_implementation/g1/sparsePRT.hpp"
// 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.
*** 70,80 ****
class OtherRegionsTable VALUE_OBJ_CLASS_SPEC {
friend class HeapRegionRemSetIterator;
G1CollectedHeap* _g1h;
! Mutex _m;
HeapRegion* _hr;
// These are protected by "_m".
BitMap _coarse_map;
size_t _n_coarse_entries;
--- 71,81 ----
class OtherRegionsTable VALUE_OBJ_CLASS_SPEC {
friend class HeapRegionRemSetIterator;
G1CollectedHeap* _g1h;
! Mutex* _m;
HeapRegion* _hr;
// These are protected by "_m".
BitMap _coarse_map;
size_t _n_coarse_entries;
*** 129,149 ****
void unlink_from_all(PerRegionTable * prt);
public:
OtherRegionsTable(HeapRegion* hr);
HeapRegion* hr() const { return _hr; }
// For now. Could "expand" some tables in the future, so that this made
// sense.
void add_reference(OopOrNarrowOopStar from, int tid);
// Removes any entries shown by the given bitmaps to contain only dead
// objects.
void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
- // Not const because it takes a lock.
size_t occupied() const;
size_t occ_fine() const;
size_t occ_coarse() const;
size_t occ_sparse() const;
--- 130,151 ----
void unlink_from_all(PerRegionTable * prt);
public:
OtherRegionsTable(HeapRegion* hr);
+ void set_mutex(Mutex* m) { _m = m; }
+
HeapRegion* hr() const { return _hr; }
// For now. Could "expand" some tables in the future, so that this made
// sense.
void add_reference(OopOrNarrowOopStar from, int tid);
// Removes any entries shown by the given bitmaps to contain only dead
// objects.
void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
size_t occupied() const;
size_t occ_fine() const;
size_t occ_coarse() const;
size_t occ_sparse() const;
*** 190,202 ****
private:
G1BlockOffsetSharedArray* _bosa;
G1BlockOffsetSharedArray* bosa() const { return _bosa; }
! // A list of code blobs (nmethods) whose code contains pointers into
// the region that owns this RSet.
! GrowableArray<nmethod*>* _strong_code_roots_list;
OtherRegionsTable _other_regions;
enum ParIterState { Unclaimed, Claimed, Complete };
volatile ParIterState _iter_state;
--- 192,206 ----
private:
G1BlockOffsetSharedArray* _bosa;
G1BlockOffsetSharedArray* bosa() const { return _bosa; }
! // A set of code blobs (nmethods) whose code contains pointers into
// the region that owns this RSet.
! G1CodeRootSet _code_roots;
!
! Mutex* _m;
OtherRegionsTable _other_regions;
enum ParIterState { Unclaimed, Claimed, Complete };
volatile ParIterState _iter_state;
*** 216,236 ****
static int _n_recorded_events;
static void print_event(outputStream* str, Event evnt);
public:
! HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
! HeapRegion* hr);
static int num_par_rem_sets();
static void setup_remset_size();
HeapRegion* hr() const {
return _other_regions.hr();
}
! size_t occupied() const {
return _other_regions.occupied();
}
size_t occ_fine() const {
return _other_regions.occ_fine();
}
--- 220,244 ----
static int _n_recorded_events;
static void print_event(outputStream* str, Event evnt);
public:
! HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr);
! ~HeapRegionRemSet();
static int num_par_rem_sets();
static void setup_remset_size();
HeapRegion* hr() const {
return _other_regions.hr();
}
! size_t occupied() {
! MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
! return occupied_locked();
! }
! size_t occupied_locked() {
return _other_regions.occupied();
}
size_t occ_fine() const {
return _other_regions.occ_fine();
}
*** 258,267 ****
--- 266,276 ----
void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
// The region is being reclaimed; clear its remset, and any mention of
// entries for this region in other remsets.
void clear();
+ void clear_locked();
// Attempt to claim the region. Returns true iff this call caused an
// atomic transition from Unclaimed to Claimed.
bool claim_iter();
// Sets the iteration state to "complete".
*** 287,313 ****
}
// The actual # of bytes this hr_remset takes up.
// Note also includes the strong code root set.
size_t mem_size() {
return _other_regions.mem_size()
// This correction is necessary because the above includes the second
// part.
+ (sizeof(this) - sizeof(OtherRegionsTable))
+ strong_code_roots_mem_size();
}
// Returns the memory occupancy of all static data structures associated
// with remembered sets.
static size_t static_mem_size() {
! return OtherRegionsTable::static_mem_size();
}
// Returns the memory occupancy of all free_list data structures associated
// with remembered sets.
static size_t fl_mem_size() {
! return OtherRegionsTable::fl_mem_size();
}
bool contains_reference(OopOrNarrowOopStar from) const {
return _other_regions.contains_reference(from);
}
--- 296,323 ----
}
// The actual # of bytes this hr_remset takes up.
// Note also includes the strong code root set.
size_t mem_size() {
+ MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
return _other_regions.mem_size()
// This correction is necessary because the above includes the second
// part.
+ (sizeof(this) - sizeof(OtherRegionsTable))
+ strong_code_roots_mem_size();
}
// Returns the memory occupancy of all static data structures associated
// with remembered sets.
static size_t static_mem_size() {
! return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size();
}
// Returns the memory occupancy of all free_list data structures associated
// with remembered sets.
static size_t fl_mem_size() {
! return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::fl_mem_size();
}
bool contains_reference(OopOrNarrowOopStar from) const {
return _other_regions.contains_reference(from);
}
*** 326,357 ****
// Applies blk->do_code_blob() to each of the entries in
// the strong code roots list
void strong_code_roots_do(CodeBlobClosure* blk) const;
// Returns the number of elements in the strong code roots list
! int strong_code_roots_list_length() {
! return _strong_code_roots_list->length();
}
// Returns true if the strong code roots contains the given
// nmethod.
bool strong_code_roots_list_contains(nmethod* nm) {
! return _strong_code_roots_list->contains(nm);
}
// Returns the amount of memory, in bytes, currently
// consumed by the strong code roots.
size_t strong_code_roots_mem_size();
! void print() const;
// Called during a stop-world phase to perform any deferred cleanups.
static void cleanup();
// Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
// (Uses it to initialize from_card_cache).
static void init_heap(uint max_regions) {
OtherRegionsTable::init_from_card_cache((size_t) max_regions);
}
// Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
static void shrink_heap(uint new_n_regs) {
--- 336,368 ----
// Applies blk->do_code_blob() to each of the entries in
// the strong code roots list
void strong_code_roots_do(CodeBlobClosure* blk) const;
// Returns the number of elements in the strong code roots list
! size_t strong_code_roots_list_length() {
! return _code_roots.length();
}
// Returns true if the strong code roots contains the given
// nmethod.
bool strong_code_roots_list_contains(nmethod* nm) {
! return _code_roots.contains(nm);
}
// Returns the amount of memory, in bytes, currently
// consumed by the strong code roots.
size_t strong_code_roots_mem_size();
! void print() PRODUCT_RETURN;
// Called during a stop-world phase to perform any deferred cleanups.
static void cleanup();
// Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
// (Uses it to initialize from_card_cache).
static void init_heap(uint max_regions) {
+ G1CodeRootSet::initialize();
OtherRegionsTable::init_from_card_cache((size_t) max_regions);
}
// Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
static void shrink_heap(uint new_n_regs) {
*** 382,392 ****
};
class HeapRegionRemSetIterator : public StackObj {
// The region RSet over which we're iterating.
! const HeapRegionRemSet* _hrrs;
// Local caching of HRRS fields.
const BitMap* _coarse_map;
PerRegionTable** _fine_grain_regions;
--- 393,403 ----
};
class HeapRegionRemSetIterator : public StackObj {
// The region RSet over which we're iterating.
! HeapRegionRemSet* _hrrs;
// Local caching of HRRS fields.
const BitMap* _coarse_map;
PerRegionTable** _fine_grain_regions;
*** 439,449 ****
bool fine_has_next(size_t& card_index);
public:
// We require an iterator to be initialized before use, so the
// constructor does little.
! HeapRegionRemSetIterator(const HeapRegionRemSet* hrrs);
// 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.)
--- 450,460 ----
bool fine_has_next(size_t& card_index);
public:
// We require an iterator to be initialized before use, so the
// constructor does little.
! HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
// 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.)