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

Mon, 02 Aug 2010 12:51:43 -0700

author
johnc
date
Mon, 02 Aug 2010 12:51:43 -0700
changeset 2060
2d160770d2e5
parent 1907
c18cbe5936b8
child 2314
f95d63e2154a
permissions
-rw-r--r--

6814437: G1: remove the _new_refs array
Summary: The per-worker _new_refs array is used to hold references that point into the collection set. It is populated during RSet updating and subsequently processed. In the event of an evacuation failure it processed again to recreate the RSets of regions in the collection set. Remove the per-worker _new_refs array by processing the references directly. Use a DirtyCardQueue to hold the cards containing the references so that the RSets of regions in the collection set can be recreated when handling an evacuation failure.
Reviewed-by: iveresov, jmasa, tonyp

ysr@777 1 /*
trims@1907 2 * Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
ysr@777 25 // Remembered set for a heap region. Represent a set of "cards" that
ysr@777 26 // contain pointers into the owner heap region. Cards are defined somewhat
ysr@777 27 // abstractly, in terms of what the "BlockOffsetTable" in use can parse.
ysr@777 28
ysr@777 29 class G1CollectedHeap;
ysr@777 30 class G1BlockOffsetSharedArray;
ysr@777 31 class HeapRegion;
ysr@777 32 class HeapRegionRemSetIterator;
ysr@777 33 class PosParPRT;
ysr@777 34 class SparsePRT;
ysr@777 35
ysr@777 36
ysr@777 37 // The "_coarse_map" is a bitmap with one bit for each region, where set
ysr@777 38 // bits indicate that the corresponding region may contain some pointer
ysr@777 39 // into the owning region.
ysr@777 40
ysr@777 41 // The "_fine_grain_entries" array is an open hash table of PerRegionTables
ysr@777 42 // (PRTs), indicating regions for which we're keeping the RS as a set of
ysr@777 43 // cards. The strategy is to cap the size of the fine-grain table,
ysr@777 44 // deleting an entry and setting the corresponding coarse-grained bit when
ysr@777 45 // we would overflow this cap.
ysr@777 46
ysr@777 47 // We use a mixture of locking and lock-free techniques here. We allow
ysr@777 48 // threads to locate PRTs without locking, but threads attempting to alter
ysr@777 49 // a bucket list obtain a lock. This means that any failing attempt to
ysr@777 50 // find a PRT must be retried with the lock. It might seem dangerous that
ysr@777 51 // a read can find a PRT that is concurrently deleted. This is all right,
ysr@777 52 // because:
ysr@777 53 //
ysr@777 54 // 1) We only actually free PRT's at safe points (though we reuse them at
ysr@777 55 // other times).
ysr@777 56 // 2) We find PRT's in an attempt to add entries. If a PRT is deleted,
ysr@777 57 // it's _coarse_map bit is set, so the that we were attempting to add
ysr@777 58 // is represented. If a deleted PRT is re-used, a thread adding a bit,
ysr@777 59 // thinking the PRT is for a different region, does no harm.
ysr@777 60
apetrusenko@984 61 class OtherRegionsTable VALUE_OBJ_CLASS_SPEC {
ysr@777 62 friend class HeapRegionRemSetIterator;
ysr@777 63
ysr@777 64 G1CollectedHeap* _g1h;
ysr@777 65 Mutex _m;
ysr@777 66 HeapRegion* _hr;
ysr@777 67
ysr@777 68 // These are protected by "_m".
ysr@777 69 BitMap _coarse_map;
ysr@777 70 size_t _n_coarse_entries;
ysr@777 71 static jint _n_coarsenings;
ysr@777 72
ysr@777 73 PosParPRT** _fine_grain_regions;
ysr@777 74 size_t _n_fine_entries;
ysr@777 75
ysr@777 76 #define SAMPLE_FOR_EVICTION 1
ysr@777 77 #if SAMPLE_FOR_EVICTION
ysr@777 78 size_t _fine_eviction_start;
ysr@777 79 static size_t _fine_eviction_stride;
ysr@777 80 static size_t _fine_eviction_sample_size;
ysr@777 81 #endif
ysr@777 82
ysr@777 83 SparsePRT _sparse_table;
ysr@777 84
ysr@777 85 // These are static after init.
ysr@777 86 static size_t _max_fine_entries;
ysr@777 87 static size_t _mod_max_fine_entries_mask;
ysr@777 88
ysr@777 89 // Requires "prt" to be the first element of the bucket list appropriate
ysr@777 90 // for "hr". If this list contains an entry for "hr", return it,
ysr@777 91 // otherwise return "NULL".
ysr@777 92 PosParPRT* find_region_table(size_t ind, HeapRegion* hr) const;
ysr@777 93
ysr@777 94 // Find, delete, and return a candidate PosParPRT, if any exists,
ysr@777 95 // adding the deleted region to the coarse bitmap. Requires the caller
ysr@777 96 // to hold _m, and the fine-grain table to be full.
ysr@777 97 PosParPRT* delete_region_table();
ysr@777 98
ysr@777 99 // If a PRT for "hr" is in the bucket list indicated by "ind" (which must
ysr@777 100 // be the correct index for "hr"), delete it and return true; else return
ysr@777 101 // false.
ysr@777 102 bool del_single_region_table(size_t ind, HeapRegion* hr);
ysr@777 103
ysr@777 104 static jint _cache_probes;
ysr@777 105 static jint _cache_hits;
ysr@777 106
ysr@777 107 // Indexed by thread X heap region, to minimize thread contention.
ysr@777 108 static int** _from_card_cache;
ysr@777 109 static size_t _from_card_cache_max_regions;
ysr@777 110 static size_t _from_card_cache_mem_size;
ysr@777 111
ysr@777 112 public:
ysr@777 113 OtherRegionsTable(HeapRegion* hr);
ysr@777 114
ysr@777 115 HeapRegion* hr() const { return _hr; }
ysr@777 116
ysr@777 117 // For now. Could "expand" some tables in the future, so that this made
ysr@777 118 // sense.
ysr@1280 119 void add_reference(OopOrNarrowOopStar from, int tid);
ysr@777 120
ysr@1280 121 void add_reference(OopOrNarrowOopStar from) {
ysr@777 122 return add_reference(from, 0);
ysr@777 123 }
ysr@777 124
ysr@777 125 // Removes any entries shown by the given bitmaps to contain only dead
ysr@777 126 // objects.
ysr@777 127 void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
ysr@777 128
ysr@777 129 // Not const because it takes a lock.
ysr@777 130 size_t occupied() const;
ysr@777 131 size_t occ_fine() const;
ysr@777 132 size_t occ_coarse() const;
ysr@777 133 size_t occ_sparse() const;
ysr@777 134
ysr@777 135 static jint n_coarsenings() { return _n_coarsenings; }
ysr@777 136
ysr@777 137 // Returns size in bytes.
ysr@777 138 // Not const because it takes a lock.
ysr@777 139 size_t mem_size() const;
ysr@777 140 static size_t static_mem_size();
ysr@777 141 static size_t fl_mem_size();
ysr@777 142
ysr@1280 143 bool contains_reference(OopOrNarrowOopStar from) const;
ysr@1280 144 bool contains_reference_locked(OopOrNarrowOopStar from) const;
ysr@777 145
ysr@777 146 void clear();
ysr@777 147
ysr@777 148 // Specifically clear the from_card_cache.
ysr@777 149 void clear_fcc();
ysr@777 150
ysr@777 151 // "from_hr" is being cleared; remove any entries from it.
ysr@777 152 void clear_incoming_entry(HeapRegion* from_hr);
ysr@777 153
ysr@777 154 // Declare the heap size (in # of regions) to the OtherRegionsTable.
ysr@777 155 // (Uses it to initialize from_card_cache).
ysr@777 156 static void init_from_card_cache(size_t max_regions);
ysr@777 157
ysr@777 158 // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
ysr@777 159 // Make sure any entries for higher regions are invalid.
ysr@777 160 static void shrink_from_card_cache(size_t new_n_regs);
ysr@777 161
ysr@777 162 static void print_from_card_cache();
ysr@777 163
ysr@777 164 };
ysr@777 165
ysr@777 166
ysr@777 167 class HeapRegionRemSet : public CHeapObj {
ysr@777 168 friend class VMStructs;
ysr@777 169 friend class HeapRegionRemSetIterator;
ysr@777 170
ysr@777 171 public:
ysr@777 172 enum Event {
ysr@777 173 Event_EvacStart, Event_EvacEnd, Event_RSUpdateEnd
ysr@777 174 };
ysr@777 175
ysr@777 176 private:
ysr@777 177 G1BlockOffsetSharedArray* _bosa;
ysr@777 178 G1BlockOffsetSharedArray* bosa() const { return _bosa; }
ysr@777 179
ysr@777 180 OtherRegionsTable _other_regions;
ysr@777 181
ysr@777 182 enum ParIterState { Unclaimed, Claimed, Complete };
iveresov@1696 183 volatile ParIterState _iter_state;
iveresov@1696 184 volatile jlong _iter_claimed;
ysr@777 185
ysr@777 186 // Unused unless G1RecordHRRSOops is true.
ysr@777 187
ysr@777 188 static const int MaxRecorded = 1000000;
ysr@1280 189 static OopOrNarrowOopStar* _recorded_oops;
ysr@1280 190 static HeapWord** _recorded_cards;
ysr@1280 191 static HeapRegion** _recorded_regions;
ysr@1280 192 static int _n_recorded;
ysr@777 193
ysr@777 194 static const int MaxRecordedEvents = 1000;
ysr@777 195 static Event* _recorded_events;
ysr@777 196 static int* _recorded_event_index;
ysr@777 197 static int _n_recorded_events;
ysr@777 198
ysr@777 199 static void print_event(outputStream* str, Event evnt);
ysr@777 200
ysr@777 201 public:
ysr@777 202 HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
ysr@777 203 HeapRegion* hr);
ysr@777 204
ysr@777 205 static int num_par_rem_sets();
iveresov@1696 206 static void setup_remset_size();
ysr@777 207
ysr@777 208 HeapRegion* hr() const {
ysr@777 209 return _other_regions.hr();
ysr@777 210 }
ysr@777 211
ysr@777 212 size_t occupied() const {
ysr@777 213 return _other_regions.occupied();
ysr@777 214 }
ysr@777 215 size_t occ_fine() const {
ysr@777 216 return _other_regions.occ_fine();
ysr@777 217 }
ysr@777 218 size_t occ_coarse() const {
ysr@777 219 return _other_regions.occ_coarse();
ysr@777 220 }
ysr@777 221 size_t occ_sparse() const {
ysr@777 222 return _other_regions.occ_sparse();
ysr@777 223 }
ysr@777 224
ysr@777 225 static jint n_coarsenings() { return OtherRegionsTable::n_coarsenings(); }
ysr@777 226
ysr@777 227 /* Used in the sequential case. Returns "true" iff this addition causes
ysr@777 228 the size limit to be reached. */
ysr@1280 229 void add_reference(OopOrNarrowOopStar from) {
ysr@777 230 _other_regions.add_reference(from);
ysr@777 231 }
ysr@777 232
ysr@777 233 /* Used in the parallel case. Returns "true" iff this addition causes
ysr@777 234 the size limit to be reached. */
ysr@1280 235 void add_reference(OopOrNarrowOopStar from, int tid) {
ysr@777 236 _other_regions.add_reference(from, tid);
ysr@777 237 }
ysr@777 238
ysr@777 239 // Removes any entries shown by the given bitmaps to contain only dead
ysr@777 240 // objects.
ysr@777 241 void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
ysr@777 242
ysr@777 243 // The region is being reclaimed; clear its remset, and any mention of
ysr@777 244 // entries for this region in other remsets.
ysr@777 245 void clear();
ysr@777 246
ysr@777 247 // Forget any entries due to pointers from "from_hr".
ysr@777 248 void clear_incoming_entry(HeapRegion* from_hr) {
ysr@777 249 _other_regions.clear_incoming_entry(from_hr);
ysr@777 250 }
ysr@777 251
ysr@777 252 #if 0
ysr@777 253 virtual void cleanup() = 0;
ysr@777 254 #endif
ysr@777 255
ysr@777 256 // Should be called from single-threaded code.
ysr@777 257 void init_for_par_iteration();
ysr@777 258 // Attempt to claim the region. Returns true iff this call caused an
ysr@777 259 // atomic transition from Unclaimed to Claimed.
ysr@777 260 bool claim_iter();
ysr@777 261 // Sets the iteration state to "complete".
ysr@777 262 void set_iter_complete();
ysr@777 263 // Returns "true" iff the region's iteration is complete.
ysr@777 264 bool iter_is_complete();
ysr@777 265
iveresov@1696 266 // Support for claiming blocks of cards during iteration
iveresov@1696 267 void set_iter_claimed(size_t x) { _iter_claimed = (jlong)x; }
iveresov@1696 268 size_t iter_claimed() const { return (size_t)_iter_claimed; }
iveresov@1696 269 // Claim the next block of cards
iveresov@1696 270 size_t iter_claimed_next(size_t step) {
iveresov@1696 271 size_t current, next;
iveresov@1696 272 do {
iveresov@1696 273 current = iter_claimed();
iveresov@1696 274 next = current + step;
iveresov@1696 275 } while (Atomic::cmpxchg((jlong)next, &_iter_claimed, (jlong)current) != (jlong)current);
iveresov@1696 276 return current;
iveresov@1696 277 }
iveresov@1696 278
ysr@777 279 // Initialize the given iterator to iterate over this rem set.
ysr@777 280 void init_iterator(HeapRegionRemSetIterator* iter) const;
ysr@777 281
ysr@777 282 #if 0
ysr@777 283 // Apply the "do_card" method to the start address of every card in the
ysr@777 284 // rem set. Returns false if some application of the closure aborted.
ysr@777 285 virtual bool card_iterate(CardClosure* iter) = 0;
ysr@777 286 #endif
ysr@777 287
ysr@777 288 // The actual # of bytes this hr_remset takes up.
ysr@777 289 size_t mem_size() {
ysr@777 290 return _other_regions.mem_size()
ysr@777 291 // This correction is necessary because the above includes the second
ysr@777 292 // part.
ysr@777 293 + sizeof(this) - sizeof(OtherRegionsTable);
ysr@777 294 }
ysr@777 295
ysr@777 296 // Returns the memory occupancy of all static data structures associated
ysr@777 297 // with remembered sets.
ysr@777 298 static size_t static_mem_size() {
ysr@777 299 return OtherRegionsTable::static_mem_size();
ysr@777 300 }
ysr@777 301
ysr@777 302 // Returns the memory occupancy of all free_list data structures associated
ysr@777 303 // with remembered sets.
ysr@777 304 static size_t fl_mem_size() {
ysr@777 305 return OtherRegionsTable::fl_mem_size();
ysr@777 306 }
ysr@777 307
ysr@1280 308 bool contains_reference(OopOrNarrowOopStar from) const {
ysr@777 309 return _other_regions.contains_reference(from);
ysr@777 310 }
ysr@777 311 void print() const;
ysr@777 312
ysr@777 313 // Called during a stop-world phase to perform any deferred cleanups.
ysr@777 314 // The second version may be called by parallel threads after then finish
ysr@777 315 // collection work.
ysr@777 316 static void cleanup();
ysr@777 317 static void par_cleanup();
ysr@777 318
ysr@777 319 // Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
ysr@777 320 // (Uses it to initialize from_card_cache).
ysr@777 321 static void init_heap(size_t max_regions) {
ysr@777 322 OtherRegionsTable::init_from_card_cache(max_regions);
ysr@777 323 }
ysr@777 324
ysr@777 325 // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
ysr@777 326 static void shrink_heap(size_t new_n_regs) {
ysr@777 327 OtherRegionsTable::shrink_from_card_cache(new_n_regs);
ysr@777 328 }
ysr@777 329
ysr@777 330 #ifndef PRODUCT
ysr@777 331 static void print_from_card_cache() {
ysr@777 332 OtherRegionsTable::print_from_card_cache();
ysr@777 333 }
ysr@777 334 #endif
ysr@777 335
ysr@1280 336 static void record(HeapRegion* hr, OopOrNarrowOopStar f);
ysr@777 337 static void print_recorded();
ysr@777 338 static void record_event(Event evnt);
ysr@777 339
ysr@777 340 // Run unit tests.
ysr@777 341 #ifndef PRODUCT
ysr@777 342 static void test();
ysr@777 343 #endif
ysr@777 344
ysr@777 345 };
ysr@777 346
ysr@777 347 class HeapRegionRemSetIterator : public CHeapObj {
ysr@777 348
ysr@777 349 // The region over which we're iterating.
ysr@777 350 const HeapRegionRemSet* _hrrs;
ysr@777 351
ysr@777 352 // Local caching of HRRS fields.
ysr@777 353 const BitMap* _coarse_map;
ysr@777 354 PosParPRT** _fine_grain_regions;
ysr@777 355
ysr@777 356 G1BlockOffsetSharedArray* _bosa;
ysr@777 357 G1CollectedHeap* _g1h;
ysr@777 358
ysr@777 359 // The number yielded since initialization.
ysr@777 360 size_t _n_yielded_fine;
ysr@777 361 size_t _n_yielded_coarse;
ysr@777 362 size_t _n_yielded_sparse;
ysr@777 363
ysr@777 364 // If true we're iterating over the coarse table; if false the fine
ysr@777 365 // table.
ysr@777 366 enum IterState {
ysr@777 367 Sparse,
ysr@777 368 Fine,
ysr@777 369 Coarse
ysr@777 370 };
ysr@777 371 IterState _is;
ysr@777 372
ysr@777 373 // In both kinds of iteration, heap offset of first card of current
ysr@777 374 // region.
ysr@777 375 size_t _cur_region_card_offset;
ysr@777 376 // Card offset within cur region.
ysr@777 377 size_t _cur_region_cur_card;
ysr@777 378
ysr@777 379 // Coarse table iteration fields:
ysr@777 380
ysr@777 381 // Current region index;
ysr@777 382 int _coarse_cur_region_index;
ysr@777 383 int _coarse_cur_region_cur_card;
ysr@777 384
ysr@777 385 bool coarse_has_next(size_t& card_index);
ysr@777 386
ysr@777 387 // Fine table iteration fields:
ysr@777 388
ysr@777 389 // Index of bucket-list we're working on.
ysr@777 390 int _fine_array_index;
ysr@777 391 // Per Region Table we're doing within current bucket list.
ysr@777 392 PosParPRT* _fine_cur_prt;
ysr@777 393
ysr@777 394 /* SparsePRT::*/ SparsePRTIter _sparse_iter;
ysr@777 395
ysr@777 396 void fine_find_next_non_null_prt();
ysr@777 397
ysr@777 398 bool fine_has_next();
ysr@777 399 bool fine_has_next(size_t& card_index);
ysr@777 400
ysr@777 401 public:
ysr@777 402 // We require an iterator to be initialized before use, so the
ysr@777 403 // constructor does little.
ysr@777 404 HeapRegionRemSetIterator();
ysr@777 405
ysr@777 406 void initialize(const HeapRegionRemSet* hrrs);
ysr@777 407
ysr@777 408 // If there remains one or more cards to be yielded, returns true and
ysr@777 409 // sets "card_index" to one of those cards (which is then considered
ysr@777 410 // yielded.) Otherwise, returns false (and leaves "card_index"
ysr@777 411 // undefined.)
ysr@777 412 bool has_next(size_t& card_index);
ysr@777 413
ysr@777 414 size_t n_yielded_fine() { return _n_yielded_fine; }
ysr@777 415 size_t n_yielded_coarse() { return _n_yielded_coarse; }
ysr@777 416 size_t n_yielded_sparse() { return _n_yielded_sparse; }
ysr@777 417 size_t n_yielded() {
ysr@777 418 return n_yielded_fine() + n_yielded_coarse() + n_yielded_sparse();
ysr@777 419 }
ysr@777 420 };
ysr@777 421
ysr@777 422 #if 0
ysr@777 423 class CardClosure: public Closure {
ysr@777 424 public:
ysr@777 425 virtual void do_card(HeapWord* card_start) = 0;
ysr@777 426 };
ysr@777 427
ysr@777 428 #endif

mercurial