1 /*
2 * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
26 #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
27
28 #include "gc/shared/gc_globals.hpp"
29 #include "gc/shared/spaceDecorator.hpp"
30 #include "gc/shenandoah/shenandoahAllocRequest.hpp"
31 #include "gc/shenandoah/shenandoahAsserts.hpp"
32 #include "gc/shenandoah/shenandoahHeap.hpp"
33 #include "gc/shenandoah/shenandoahPadding.hpp"
34 #include "utilities/sizes.hpp"
35
36 class VMStructs;
37 class ShenandoahHeapRegionStateConstant;
38
39 class ShenandoahHeapRegion {
40 friend class VMStructs;
41 friend class ShenandoahHeapRegionStateConstant;
42 private:
43 /*
44 Region state is described by a state machine. Transitions are guarded by
45 heap lock, which allows changing the state of several regions atomically.
46 Region states can be logically aggregated in groups.
47
48 "Empty":
49 .................................................................
150 case _humongous_cont: return 4;
151 case _cset: return 5;
152 case _pinned: return 6;
153 case _trash: return 7;
154 case _pinned_cset: return 8;
155 case _pinned_humongous_start: return 9;
156 default:
157 ShouldNotReachHere();
158 return -1;
159 }
160 }
161
162 void report_illegal_transition(const char* method);
163
164 public:
165 static int region_states_num() {
166 return _REGION_STATES_NUM;
167 }
168
169 // Allowed transitions from the outside code:
170 void make_regular_allocation();
171 void make_regular_bypass();
172 void make_humongous_start();
173 void make_humongous_cont();
174 void make_humongous_start_bypass();
175 void make_humongous_cont_bypass();
176 void make_pinned();
177 void make_unpinned();
178 void make_cset();
179 void make_trash();
180 void make_trash_immediate();
181 void make_empty();
182 void make_uncommitted();
183 void make_committed_bypass();
184
185 // Individual states:
186 bool is_empty_uncommitted() const { return _state == _empty_uncommitted; }
187 bool is_empty_committed() const { return _state == _empty_committed; }
188 bool is_regular() const { return _state == _regular; }
189 bool is_humongous_continuation() const { return _state == _humongous_cont; }
190
191 // Participation in logical groups:
192 bool is_empty() const { return is_empty_committed() || is_empty_uncommitted(); }
193 bool is_active() const { return !is_empty() && !is_trash(); }
194 bool is_trash() const { return _state == _trash; }
195 bool is_humongous_start() const { return _state == _humongous_start || _state == _pinned_humongous_start; }
196 bool is_humongous() const { return is_humongous_start() || is_humongous_continuation(); }
197 bool is_committed() const { return !is_empty_uncommitted(); }
198 bool is_cset() const { return _state == _cset || _state == _pinned_cset; }
199 bool is_pinned() const { return _state == _pinned || _state == _pinned_cset || _state == _pinned_humongous_start; }
200
201 // Macro-properties:
202 bool is_alloc_allowed() const { return is_empty() || is_regular() || _state == _pinned; }
203 bool is_stw_move_allowed() const { return is_regular() || _state == _cset || (ShenandoahHumongousMoves && _state == _humongous_start); }
204
205 RegionState state() const { return _state; }
206 int state_ordinal() const { return region_state_to_ordinal(_state); }
207
208 void record_pin();
209 void record_unpin();
210 size_t pin_count() const;
211
212 private:
213 static size_t RegionCount;
214 static size_t RegionSizeBytes;
215 static size_t RegionSizeWords;
216 static size_t RegionSizeBytesShift;
217 static size_t RegionSizeWordsShift;
218 static size_t RegionSizeBytesMask;
219 static size_t RegionSizeWordsMask;
220 static size_t HumongousThresholdBytes;
221 static size_t HumongousThresholdWords;
222 static size_t MaxTLABSizeBytes;
223 static size_t MaxTLABSizeWords;
224
225 // Never updated fields
226 size_t const _index;
227 HeapWord* const _bottom;
228 HeapWord* const _end;
229
230 // Rarely updated fields
231 HeapWord* _new_top;
232 double _empty_time;
233
234 // Seldom updated fields
235 RegionState _state;
236
237 // Frequently updated fields
238 HeapWord* _top;
239
240 size_t _tlab_allocs;
241 size_t _gclab_allocs;
242
243 volatile size_t _live_data;
244 volatile size_t _critical_pins;
245
246 HeapWord* volatile _update_watermark;
247
248 public:
249 ShenandoahHeapRegion(HeapWord* start, size_t index, bool committed);
250
251 static const size_t MIN_NUM_REGIONS = 10;
252
253 // Return adjusted max heap size
254 static size_t setup_sizes(size_t max_heap_size);
255
256 double empty_time() {
257 return _empty_time;
258 }
259
260 inline static size_t required_regions(size_t bytes) {
261 return (bytes + ShenandoahHeapRegion::region_size_bytes() - 1) >> ShenandoahHeapRegion::region_size_bytes_shift();
262 }
263
264 inline static size_t region_count() {
265 return ShenandoahHeapRegion::RegionCount;
266 }
267
316 inline static size_t humongous_threshold_bytes() {
317 return ShenandoahHeapRegion::HumongousThresholdBytes;
318 }
319
320 inline static size_t humongous_threshold_words() {
321 return ShenandoahHeapRegion::HumongousThresholdWords;
322 }
323
324 inline static size_t max_tlab_size_bytes() {
325 return ShenandoahHeapRegion::MaxTLABSizeBytes;
326 }
327
328 inline static size_t max_tlab_size_words() {
329 return ShenandoahHeapRegion::MaxTLABSizeWords;
330 }
331
332 inline size_t index() const {
333 return _index;
334 }
335
336 // Allocation (return null if full)
337 inline HeapWord* allocate(size_t word_size, ShenandoahAllocRequest::Type type);
338
339 inline void clear_live_data();
340 void set_live_data(size_t s);
341
342 // Increase live data for newly allocated region
343 inline void increase_live_data_alloc_words(size_t s);
344
345 // Increase live data for region scanned with GC
346 inline void increase_live_data_gc_words(size_t s);
347
348 inline bool has_live() const;
349 inline size_t get_live_data_bytes() const;
350 inline size_t get_live_data_words() const;
351
352 inline size_t garbage() const;
353
354 void print_on(outputStream* st) const;
355
356 void recycle();
357
358 void oop_iterate(OopIterateClosure* cl);
359
360 HeapWord* block_start(const void* p) const;
361 size_t block_size(const HeapWord* p) const;
362 bool block_is_obj(const HeapWord* p) const { return p < top(); }
363
364 // Find humongous start region that this region belongs to
365 ShenandoahHeapRegion* humongous_start_region() const;
366
367 HeapWord* top() const { return _top; }
368 void set_top(HeapWord* v) { _top = v; }
369
370 HeapWord* new_top() const { return _new_top; }
371 void set_new_top(HeapWord* v) { _new_top = v; }
372
373 HeapWord* bottom() const { return _bottom; }
374 HeapWord* end() const { return _end; }
375
376 size_t capacity() const { return byte_size(bottom(), end()); }
377 size_t used() const { return byte_size(bottom(), top()); }
378 size_t free() const { return byte_size(top(), end()); }
379
380 inline void adjust_alloc_metadata(ShenandoahAllocRequest::Type type, size_t);
381 void reset_alloc_metadata();
382 size_t get_shared_allocs() const;
383 size_t get_tlab_allocs() const;
384 size_t get_gclab_allocs() const;
385
386 inline HeapWord* get_update_watermark() const;
387 inline void set_update_watermark(HeapWord* w);
388 inline void set_update_watermark_at_safepoint(HeapWord* w);
389
390 private:
391 void do_commit();
392 void do_uncommit();
393
394 void oop_iterate_objects(OopIterateClosure* cl);
395 void oop_iterate_humongous(OopIterateClosure* cl);
396
397 inline void internal_increase_live_data(size_t s);
398
399 void set_state(RegionState to);
400 };
401
402 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
|
1 /*
2 * Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
27 #define SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
28
29 #include "gc/shared/gc_globals.hpp"
30 #include "gc/shared/spaceDecorator.hpp"
31 #include "gc/shenandoah/shenandoahAffiliation.hpp"
32 #include "gc/shenandoah/shenandoahAllocRequest.hpp"
33 #include "gc/shenandoah/shenandoahAsserts.hpp"
34 #include "gc/shenandoah/shenandoahHeap.hpp"
35 #include "gc/shenandoah/shenandoahPadding.hpp"
36 #include "utilities/sizes.hpp"
37
38 class VMStructs;
39 class ShenandoahHeapRegionStateConstant;
40
41 class ShenandoahHeapRegion {
42 friend class VMStructs;
43 friend class ShenandoahHeapRegionStateConstant;
44 private:
45 /*
46 Region state is described by a state machine. Transitions are guarded by
47 heap lock, which allows changing the state of several regions atomically.
48 Region states can be logically aggregated in groups.
49
50 "Empty":
51 .................................................................
152 case _humongous_cont: return 4;
153 case _cset: return 5;
154 case _pinned: return 6;
155 case _trash: return 7;
156 case _pinned_cset: return 8;
157 case _pinned_humongous_start: return 9;
158 default:
159 ShouldNotReachHere();
160 return -1;
161 }
162 }
163
164 void report_illegal_transition(const char* method);
165
166 public:
167 static int region_states_num() {
168 return _REGION_STATES_NUM;
169 }
170
171 // Allowed transitions from the outside code:
172 void make_regular_allocation(ShenandoahAffiliation affiliation);
173 void make_young_maybe();
174 void make_regular_bypass();
175 void make_humongous_start();
176 void make_humongous_cont();
177 void make_humongous_start_bypass(ShenandoahAffiliation affiliation);
178 void make_humongous_cont_bypass(ShenandoahAffiliation affiliation);
179 void make_pinned();
180 void make_unpinned();
181 void make_cset();
182 void make_trash();
183 void make_trash_immediate();
184 void make_empty();
185 void make_uncommitted();
186 void make_committed_bypass();
187
188 // Individual states:
189 bool is_empty_uncommitted() const { return _state == _empty_uncommitted; }
190 bool is_empty_committed() const { return _state == _empty_committed; }
191 bool is_regular() const { return _state == _regular; }
192 bool is_humongous_continuation() const { return _state == _humongous_cont; }
193
194 // Participation in logical groups:
195 bool is_empty() const { return is_empty_committed() || is_empty_uncommitted(); }
196 bool is_active() const { return !is_empty() && !is_trash(); }
197 bool is_trash() const { return _state == _trash; }
198 bool is_humongous_start() const { return _state == _humongous_start || _state == _pinned_humongous_start; }
199 bool is_humongous() const { return is_humongous_start() || is_humongous_continuation(); }
200 bool is_committed() const { return !is_empty_uncommitted(); }
201 bool is_cset() const { return _state == _cset || _state == _pinned_cset; }
202 bool is_pinned() const { return _state == _pinned || _state == _pinned_cset || _state == _pinned_humongous_start; }
203 inline bool is_young() const;
204 inline bool is_old() const;
205 inline bool is_affiliated() const;
206
207 // Macro-properties:
208 bool is_alloc_allowed() const { return is_empty() || is_regular() || _state == _pinned; }
209 bool is_stw_move_allowed() const { return is_regular() || _state == _cset || (ShenandoahHumongousMoves && _state == _humongous_start); }
210
211 RegionState state() const { return _state; }
212 int state_ordinal() const { return region_state_to_ordinal(_state); }
213
214 void record_pin();
215 void record_unpin();
216 size_t pin_count() const;
217
218 private:
219 static size_t RegionCount;
220 static size_t RegionSizeBytes;
221 static size_t RegionSizeWords;
222 static size_t RegionSizeBytesShift;
223 static size_t RegionSizeWordsShift;
224 static size_t RegionSizeBytesMask;
225 static size_t RegionSizeWordsMask;
226 static size_t HumongousThresholdBytes;
227 static size_t HumongousThresholdWords;
228 static size_t MaxTLABSizeBytes;
229 static size_t MaxTLABSizeWords;
230
231 // Never updated fields
232 size_t const _index;
233 HeapWord* const _bottom;
234 HeapWord* const _end;
235
236 // Rarely updated fields
237 HeapWord* _new_top;
238 double _empty_time;
239
240 HeapWord* _top_before_promoted;
241
242 // Seldom updated fields
243 RegionState _state;
244 HeapWord* _coalesce_and_fill_boundary; // for old regions not selected as collection set candidates.
245
246 // Frequently updated fields
247 HeapWord* _top;
248
249 size_t _tlab_allocs;
250 size_t _gclab_allocs;
251 size_t _plab_allocs;
252
253 volatile size_t _live_data;
254 volatile size_t _critical_pins;
255
256 HeapWord* volatile _update_watermark;
257
258 uint _age;
259 CENSUS_NOISE(uint _youth;) // tracks epochs of retrograde ageing (rejuvenation)
260
261 public:
262 ShenandoahHeapRegion(HeapWord* start, size_t index, bool committed);
263
264 static const size_t MIN_NUM_REGIONS = 10;
265
266 // Return adjusted max heap size
267 static size_t setup_sizes(size_t max_heap_size);
268
269 double empty_time() {
270 return _empty_time;
271 }
272
273 inline static size_t required_regions(size_t bytes) {
274 return (bytes + ShenandoahHeapRegion::region_size_bytes() - 1) >> ShenandoahHeapRegion::region_size_bytes_shift();
275 }
276
277 inline static size_t region_count() {
278 return ShenandoahHeapRegion::RegionCount;
279 }
280
329 inline static size_t humongous_threshold_bytes() {
330 return ShenandoahHeapRegion::HumongousThresholdBytes;
331 }
332
333 inline static size_t humongous_threshold_words() {
334 return ShenandoahHeapRegion::HumongousThresholdWords;
335 }
336
337 inline static size_t max_tlab_size_bytes() {
338 return ShenandoahHeapRegion::MaxTLABSizeBytes;
339 }
340
341 inline static size_t max_tlab_size_words() {
342 return ShenandoahHeapRegion::MaxTLABSizeWords;
343 }
344
345 inline size_t index() const {
346 return _index;
347 }
348
349 inline void save_top_before_promote();
350 inline HeapWord* get_top_before_promote() const { return _top_before_promoted; }
351 inline void restore_top_before_promote();
352 inline size_t garbage_before_padded_for_promote() const;
353
354 // If next available memory is not aligned on address that is multiple of alignment, fill the empty space
355 // so that returned object is aligned on an address that is a multiple of alignment_in_bytes. Requested
356 // size is in words. It is assumed that this->is_old(). A pad object is allocated, filled, and registered
357 // if necessary to assure the new allocation is properly aligned. Return nullptr if memory is not available.
358 inline HeapWord* allocate_aligned(size_t word_size, ShenandoahAllocRequest &req, size_t alignment_in_bytes);
359
360 // Allocation (return nullptr if full)
361 inline HeapWord* allocate(size_t word_size, ShenandoahAllocRequest req);
362
363 inline void clear_live_data();
364 void set_live_data(size_t s);
365
366 // Increase live data for newly allocated region
367 inline void increase_live_data_alloc_words(size_t s);
368
369 // Increase live data for region scanned with GC
370 inline void increase_live_data_gc_words(size_t s);
371
372 inline bool has_live() const;
373 inline size_t get_live_data_bytes() const;
374 inline size_t get_live_data_words() const;
375
376 inline size_t garbage() const;
377
378 void print_on(outputStream* st) const;
379
380 void recycle();
381
382 inline void begin_preemptible_coalesce_and_fill() {
383 _coalesce_and_fill_boundary = _bottom;
384 }
385
386 inline void end_preemptible_coalesce_and_fill() {
387 _coalesce_and_fill_boundary = _end;
388 }
389
390 inline void suspend_coalesce_and_fill(HeapWord* next_focus) {
391 _coalesce_and_fill_boundary = next_focus;
392 }
393
394 inline HeapWord* resume_coalesce_and_fill() {
395 return _coalesce_and_fill_boundary;
396 }
397
398 // Coalesce contiguous spans of garbage objects by filling header and reregistering start locations with remembered set.
399 // This is used by old-gen GC following concurrent marking to make old-gen HeapRegions parsable. Return true iff
400 // region is completely coalesced and filled. Returns false if cancelled before task is complete.
401 bool oop_fill_and_coalesce();
402
403 // Like oop_fill_and_coalesce(), but without honoring cancellation requests.
404 bool oop_fill_and_coalesce_without_cancel();
405
406 // During global collections, this service iterates through an old-gen heap region that is not part of collection
407 // set to fill and register ranges of dead memory. Note that live objects were previously registered. Some dead objects
408 // that are subsumed into coalesced ranges of dead memory need to be "unregistered".
409 void global_oop_iterate_and_fill_dead(OopIterateClosure* cl);
410 void oop_iterate_humongous(OopIterateClosure* cl);
411 void oop_iterate_humongous(OopIterateClosure* cl, HeapWord* start, size_t words);
412
413 // Invoke closure on every reference contained within the humongous object that spans this humongous
414 // region if the reference is contained within a DIRTY card and the reference is no more than words following
415 // start within the humongous object.
416 void oop_iterate_humongous_slice(OopIterateClosure* cl, bool dirty_only, HeapWord* start, size_t words, bool write_table);
417
418 HeapWord* block_start(const void* p) const;
419 size_t block_size(const HeapWord* p) const;
420 bool block_is_obj(const HeapWord* p) const { return p < top(); }
421
422 // Find humongous start region that this region belongs to
423 ShenandoahHeapRegion* humongous_start_region() const;
424
425 HeapWord* top() const { return _top; }
426 void set_top(HeapWord* v) { _top = v; }
427
428 HeapWord* new_top() const { return _new_top; }
429 void set_new_top(HeapWord* v) { _new_top = v; }
430
431 HeapWord* bottom() const { return _bottom; }
432 HeapWord* end() const { return _end; }
433
434 size_t capacity() const { return byte_size(bottom(), end()); }
435 size_t used() const { return byte_size(bottom(), top()); }
436 size_t used_before_promote() const { return byte_size(bottom(), get_top_before_promote()); }
437 size_t free() const { return byte_size(top(), end()); }
438
439 // Does this region contain this address?
440 bool contains(HeapWord* p) const {
441 return (bottom() <= p) && (p < top());
442 }
443
444 inline void adjust_alloc_metadata(ShenandoahAllocRequest::Type type, size_t);
445 void reset_alloc_metadata();
446 size_t get_shared_allocs() const;
447 size_t get_tlab_allocs() const;
448 size_t get_gclab_allocs() const;
449 size_t get_plab_allocs() const;
450
451 inline HeapWord* get_update_watermark() const;
452 inline void set_update_watermark(HeapWord* w);
453 inline void set_update_watermark_at_safepoint(HeapWord* w);
454
455 inline ShenandoahAffiliation affiliation() const;
456 inline const char* affiliation_name() const;
457
458 void set_affiliation(ShenandoahAffiliation new_affiliation);
459
460 // Region ageing and rejuvenation
461 uint age() { return _age; }
462 CENSUS_NOISE(uint youth() { return _youth; })
463
464 void increment_age() {
465 const uint max_age = markWord::max_age;
466 assert(_age <= max_age, "Error");
467 if (_age++ >= max_age) {
468 _age = max_age; // clamp
469 }
470 }
471
472 void reset_age() {
473 CENSUS_NOISE(_youth += _age;)
474 _age = 0;
475 }
476
477 CENSUS_NOISE(void clear_youth() { _youth = 0; })
478
479 // Register all objects. Set all remembered set cards to dirty.
480 void promote_humongous();
481 void promote_in_place();
482
483 private:
484 void decrement_humongous_waste() const;
485 void do_commit();
486 void do_uncommit();
487
488 // This is an old-region that was not part of the collection set during a GLOBAL collection. We coalesce the dead
489 // objects, but do not need to register the live objects as they are already registered.
490 void global_oop_iterate_objects_and_fill_dead(OopIterateClosure* cl);
491
492 inline void internal_increase_live_data(size_t s);
493
494 void set_state(RegionState to);
495 };
496
497 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP
|