Mercurial > hg > graal-compiler
comparison src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp @ 17753:191174b49bec
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: mgerdin, brutisso
author | tschatzl |
---|---|
date | Mon, 24 Mar 2014 15:30:14 +0100 |
parents | 55fb97c4c58d |
children | d7070f371770 |
comparison
equal
deleted
inserted
replaced
17750:f53edbc2b728 | 17753:191174b49bec |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
23 */ | 23 */ |
24 | 24 |
25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP | 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP |
26 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP | 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONREMSET_HPP |
27 | 27 |
28 #include "gc_implementation/g1/g1CodeCacheRemSet.hpp" | |
28 #include "gc_implementation/g1/sparsePRT.hpp" | 29 #include "gc_implementation/g1/sparsePRT.hpp" |
29 | 30 |
30 // Remembered set for a heap region. Represent a set of "cards" that | 31 // Remembered set for a heap region. Represent a set of "cards" that |
31 // contain pointers into the owner heap region. Cards are defined somewhat | 32 // contain pointers into the owner heap region. Cards are defined somewhat |
32 // abstractly, in terms of what the "BlockOffsetTable" in use can parse. | 33 // abstractly, in terms of what the "BlockOffsetTable" in use can parse. |
70 | 71 |
71 class OtherRegionsTable VALUE_OBJ_CLASS_SPEC { | 72 class OtherRegionsTable VALUE_OBJ_CLASS_SPEC { |
72 friend class HeapRegionRemSetIterator; | 73 friend class HeapRegionRemSetIterator; |
73 | 74 |
74 G1CollectedHeap* _g1h; | 75 G1CollectedHeap* _g1h; |
75 Mutex _m; | 76 Mutex* _m; |
76 HeapRegion* _hr; | 77 HeapRegion* _hr; |
77 | 78 |
78 // These are protected by "_m". | 79 // These are protected by "_m". |
79 BitMap _coarse_map; | 80 BitMap _coarse_map; |
80 size_t _n_coarse_entries; | 81 size_t _n_coarse_entries; |
127 void link_to_all(PerRegionTable * prt); | 128 void link_to_all(PerRegionTable * prt); |
128 // unlink/remove the given fine grain remembered set into the "all" list | 129 // unlink/remove the given fine grain remembered set into the "all" list |
129 void unlink_from_all(PerRegionTable * prt); | 130 void unlink_from_all(PerRegionTable * prt); |
130 | 131 |
131 public: | 132 public: |
132 OtherRegionsTable(HeapRegion* hr); | 133 OtherRegionsTable(HeapRegion* hr, Mutex* m); |
133 | 134 |
134 HeapRegion* hr() const { return _hr; } | 135 HeapRegion* hr() const { return _hr; } |
135 | 136 |
136 // For now. Could "expand" some tables in the future, so that this made | 137 // For now. Could "expand" some tables in the future, so that this made |
137 // sense. | 138 // sense. |
139 | 140 |
140 // Removes any entries shown by the given bitmaps to contain only dead | 141 // Removes any entries shown by the given bitmaps to contain only dead |
141 // objects. | 142 // objects. |
142 void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); | 143 void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); |
143 | 144 |
144 // Not const because it takes a lock. | |
145 size_t occupied() const; | 145 size_t occupied() const; |
146 size_t occ_fine() const; | 146 size_t occ_fine() const; |
147 size_t occ_coarse() const; | 147 size_t occ_coarse() const; |
148 size_t occ_sparse() const; | 148 size_t occ_sparse() const; |
149 | 149 |
190 | 190 |
191 private: | 191 private: |
192 G1BlockOffsetSharedArray* _bosa; | 192 G1BlockOffsetSharedArray* _bosa; |
193 G1BlockOffsetSharedArray* bosa() const { return _bosa; } | 193 G1BlockOffsetSharedArray* bosa() const { return _bosa; } |
194 | 194 |
195 // A list of code blobs (nmethods) whose code contains pointers into | 195 // A set of code blobs (nmethods) whose code contains pointers into |
196 // the region that owns this RSet. | 196 // the region that owns this RSet. |
197 GrowableArray<nmethod*>* _strong_code_roots_list; | 197 G1CodeRootSet _code_roots; |
198 | |
199 Mutex _m; | |
198 | 200 |
199 OtherRegionsTable _other_regions; | 201 OtherRegionsTable _other_regions; |
200 | 202 |
201 enum ParIterState { Unclaimed, Claimed, Complete }; | 203 enum ParIterState { Unclaimed, Claimed, Complete }; |
202 volatile ParIterState _iter_state; | 204 volatile ParIterState _iter_state; |
216 static int _n_recorded_events; | 218 static int _n_recorded_events; |
217 | 219 |
218 static void print_event(outputStream* str, Event evnt); | 220 static void print_event(outputStream* str, Event evnt); |
219 | 221 |
220 public: | 222 public: |
221 HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, | 223 HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr); |
222 HeapRegion* hr); | |
223 | 224 |
224 static int num_par_rem_sets(); | 225 static int num_par_rem_sets(); |
225 static void setup_remset_size(); | 226 static void setup_remset_size(); |
226 | 227 |
227 HeapRegion* hr() const { | 228 HeapRegion* hr() const { |
228 return _other_regions.hr(); | 229 return _other_regions.hr(); |
229 } | 230 } |
230 | 231 |
231 size_t occupied() const { | 232 size_t occupied() { |
233 MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); | |
234 return occupied_locked(); | |
235 } | |
236 size_t occupied_locked() { | |
232 return _other_regions.occupied(); | 237 return _other_regions.occupied(); |
233 } | 238 } |
234 size_t occ_fine() const { | 239 size_t occ_fine() const { |
235 return _other_regions.occ_fine(); | 240 return _other_regions.occ_fine(); |
236 } | 241 } |
258 void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); | 263 void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); |
259 | 264 |
260 // The region is being reclaimed; clear its remset, and any mention of | 265 // The region is being reclaimed; clear its remset, and any mention of |
261 // entries for this region in other remsets. | 266 // entries for this region in other remsets. |
262 void clear(); | 267 void clear(); |
268 void clear_locked(); | |
263 | 269 |
264 // Attempt to claim the region. Returns true iff this call caused an | 270 // Attempt to claim the region. Returns true iff this call caused an |
265 // atomic transition from Unclaimed to Claimed. | 271 // atomic transition from Unclaimed to Claimed. |
266 bool claim_iter(); | 272 bool claim_iter(); |
267 // Sets the iteration state to "complete". | 273 // Sets the iteration state to "complete". |
287 } | 293 } |
288 | 294 |
289 // The actual # of bytes this hr_remset takes up. | 295 // The actual # of bytes this hr_remset takes up. |
290 // Note also includes the strong code root set. | 296 // Note also includes the strong code root set. |
291 size_t mem_size() { | 297 size_t mem_size() { |
298 MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag); | |
292 return _other_regions.mem_size() | 299 return _other_regions.mem_size() |
293 // This correction is necessary because the above includes the second | 300 // This correction is necessary because the above includes the second |
294 // part. | 301 // part. |
295 + (sizeof(this) - sizeof(OtherRegionsTable)) | 302 + (sizeof(this) - sizeof(OtherRegionsTable)) |
296 + strong_code_roots_mem_size(); | 303 + strong_code_roots_mem_size(); |
297 } | 304 } |
298 | 305 |
299 // Returns the memory occupancy of all static data structures associated | 306 // Returns the memory occupancy of all static data structures associated |
300 // with remembered sets. | 307 // with remembered sets. |
301 static size_t static_mem_size() { | 308 static size_t static_mem_size() { |
302 return OtherRegionsTable::static_mem_size(); | 309 return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size(); |
303 } | 310 } |
304 | 311 |
305 // Returns the memory occupancy of all free_list data structures associated | 312 // Returns the memory occupancy of all free_list data structures associated |
306 // with remembered sets. | 313 // with remembered sets. |
307 static size_t fl_mem_size() { | 314 static size_t fl_mem_size() { |
308 return OtherRegionsTable::fl_mem_size(); | 315 return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::fl_mem_size(); |
309 } | 316 } |
310 | 317 |
311 bool contains_reference(OopOrNarrowOopStar from) const { | 318 bool contains_reference(OopOrNarrowOopStar from) const { |
312 return _other_regions.contains_reference(from); | 319 return _other_regions.contains_reference(from); |
313 } | 320 } |
326 // Applies blk->do_code_blob() to each of the entries in | 333 // Applies blk->do_code_blob() to each of the entries in |
327 // the strong code roots list | 334 // the strong code roots list |
328 void strong_code_roots_do(CodeBlobClosure* blk) const; | 335 void strong_code_roots_do(CodeBlobClosure* blk) const; |
329 | 336 |
330 // Returns the number of elements in the strong code roots list | 337 // Returns the number of elements in the strong code roots list |
331 int strong_code_roots_list_length() { | 338 size_t strong_code_roots_list_length() { |
332 return _strong_code_roots_list->length(); | 339 return _code_roots.length(); |
333 } | 340 } |
334 | 341 |
335 // Returns true if the strong code roots contains the given | 342 // Returns true if the strong code roots contains the given |
336 // nmethod. | 343 // nmethod. |
337 bool strong_code_roots_list_contains(nmethod* nm) { | 344 bool strong_code_roots_list_contains(nmethod* nm) { |
338 return _strong_code_roots_list->contains(nm); | 345 return _code_roots.contains(nm); |
339 } | 346 } |
340 | 347 |
341 // Returns the amount of memory, in bytes, currently | 348 // Returns the amount of memory, in bytes, currently |
342 // consumed by the strong code roots. | 349 // consumed by the strong code roots. |
343 size_t strong_code_roots_mem_size(); | 350 size_t strong_code_roots_mem_size(); |
344 | 351 |
345 void print() const; | 352 void print() PRODUCT_RETURN; |
346 | 353 |
347 // Called during a stop-world phase to perform any deferred cleanups. | 354 // Called during a stop-world phase to perform any deferred cleanups. |
348 static void cleanup(); | 355 static void cleanup(); |
349 | 356 |
350 // Declare the heap size (in # of regions) to the HeapRegionRemSet(s). | 357 // Declare the heap size (in # of regions) to the HeapRegionRemSet(s). |
351 // (Uses it to initialize from_card_cache). | 358 // (Uses it to initialize from_card_cache). |
352 static void init_heap(uint max_regions) { | 359 static void init_heap(uint max_regions) { |
360 G1CodeRootSet::initialize(); | |
353 OtherRegionsTable::init_from_card_cache((size_t) max_regions); | 361 OtherRegionsTable::init_from_card_cache((size_t) max_regions); |
354 } | 362 } |
355 | 363 |
356 // Declares that only regions i s.t. 0 <= i < new_n_regs are in use. | 364 // Declares that only regions i s.t. 0 <= i < new_n_regs are in use. |
357 static void shrink_heap(uint new_n_regs) { | 365 static void shrink_heap(uint new_n_regs) { |
382 }; | 390 }; |
383 | 391 |
384 class HeapRegionRemSetIterator : public StackObj { | 392 class HeapRegionRemSetIterator : public StackObj { |
385 | 393 |
386 // The region RSet over which we're iterating. | 394 // The region RSet over which we're iterating. |
387 const HeapRegionRemSet* _hrrs; | 395 HeapRegionRemSet* _hrrs; |
388 | 396 |
389 // Local caching of HRRS fields. | 397 // Local caching of HRRS fields. |
390 const BitMap* _coarse_map; | 398 const BitMap* _coarse_map; |
391 PerRegionTable** _fine_grain_regions; | 399 PerRegionTable** _fine_grain_regions; |
392 | 400 |
439 bool fine_has_next(size_t& card_index); | 447 bool fine_has_next(size_t& card_index); |
440 | 448 |
441 public: | 449 public: |
442 // We require an iterator to be initialized before use, so the | 450 // We require an iterator to be initialized before use, so the |
443 // constructor does little. | 451 // constructor does little. |
444 HeapRegionRemSetIterator(const HeapRegionRemSet* hrrs); | 452 HeapRegionRemSetIterator(HeapRegionRemSet* hrrs); |
445 | 453 |
446 // If there remains one or more cards to be yielded, returns true and | 454 // If there remains one or more cards to be yielded, returns true and |
447 // sets "card_index" to one of those cards (which is then considered | 455 // sets "card_index" to one of those cards (which is then considered |
448 // yielded.) Otherwise, returns false (and leaves "card_index" | 456 // yielded.) Otherwise, returns false (and leaves "card_index" |
449 // undefined.) | 457 // undefined.) |