Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.hpp
38920 views
/*1* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation.6*7* This code is distributed in the hope that it will be useful, but WITHOUT8* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or9* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License10* version 2 for more details (a copy is included in the LICENSE file that11* accompanied this code).12*13* You should have received a copy of the GNU General Public License version14* 2 along with this work; if not, write to the Free Software Foundation,15* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.16*17* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA18* or visit www.oracle.com if you need additional information or have any19* questions.20*21*/2223#ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP24#define SHARE_VM_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP2526#include "gc_implementation/shenandoah/shenandoahAllocRequest.hpp"27#include "gc_implementation/shenandoah/shenandoahAsserts.hpp"28#include "gc_implementation/shenandoah/shenandoahHeap.hpp"29#include "gc_implementation/shenandoah/shenandoahPacer.hpp"30#include "gc_implementation/shenandoah/shenandoahPadding.hpp"3132class VMStructs;33class ShenandoahHeapRegionStateConstant;3435class ShenandoahHeapRegion {36friend class VMStructs;37friend class ShenandoahHeapRegionStateConstant;38private:39/*40Region state is described by a state machine. Transitions are guarded by41heap lock, which allows changing the state of several regions atomically.42Region states can be logically aggregated in groups.4344"Empty":45.................................................................46. .47. .48. Uncommitted <------- Committed <------------------------\49. | | . |50. \---------v-----------/ . |51. | . |52.........................|....................................... |53| |54"Active": | |55.........................|....................................... |56. | . |57. /-----------------^-------------------\ . |58. | | . |59. v v "Humongous": . |60. Regular ---\-----\ ..................O................ . |61. | ^ | | . | . . |62. | | | | . *---------\ . . |63. v | | | . v v . . |64. Pinned Cset | . HStart <--> H/Start H/Cont . . |65. ^ / | | . Pinned v | . . |66. | / | | . *<--------/ . . |67. | v | | . | . . |68. CsetPinned | | ..................O................ . |69. | | | . |70. \-----\---v-------------------/ . |71. | . |72.........................|....................................... |73| |74"Trash": | |75.........................|....................................... |76. | . |77. v . |78. Trash ---------------------------------------/79. .80. .81.................................................................8283Transition from "Empty" to "Active" is first allocation. It can go from {Uncommitted, Committed}84to {Regular, "Humongous"}. The allocation may happen in Regular regions too, but not in Humongous.8586Transition from "Active" to "Trash" is reclamation. It can go from CSet during the normal cycle,87and from {Regular, "Humongous"} for immediate reclamation. The existence of Trash state allows88quick reclamation without actual cleaning up.8990Transition from "Trash" to "Empty" is recycling. It cleans up the regions and corresponding metadata.91Can be done asynchronously and in bulk.9293Note how internal transitions disallow logic bugs:94a) No region can go Empty, unless properly reclaimed/recycled;95b) No region can go Uncommitted, unless reclaimed/recycled first;96c) Only Regular regions can go to CSet;97d) Pinned cannot go Trash, thus it could never be reclaimed until unpinned;98e) Pinned cannot go CSet, thus it never moves;99f) Humongous cannot be used for regular allocations;100g) Humongous cannot go CSet, thus it never moves;101h) Humongous start can go pinned, and thus can be protected from moves (humongous continuations should102follow associated humongous starts, not pinnable/movable by themselves);103i) Empty cannot go Trash, avoiding useless work;104j) ...105*/106107enum RegionState {108_empty_uncommitted, // region is empty and has memory uncommitted109_empty_committed, // region is empty and has memory committed110_regular, // region is for regular allocations111_humongous_start, // region is the humongous start112_humongous_cont, // region is the humongous continuation113_pinned_humongous_start, // region is both humongous start and pinned114_cset, // region is in collection set115_pinned, // region is pinned116_pinned_cset, // region is pinned and in cset (evac failure path)117_trash, // region contains only trash118_REGION_STATES_NUM // last119};120121static const char* region_state_to_string(RegionState s) {122switch (s) {123case _empty_uncommitted: return "Empty Uncommitted";124case _empty_committed: return "Empty Committed";125case _regular: return "Regular";126case _humongous_start: return "Humongous Start";127case _humongous_cont: return "Humongous Continuation";128case _pinned_humongous_start: return "Humongous Start, Pinned";129case _cset: return "Collection Set";130case _pinned: return "Pinned";131case _pinned_cset: return "Collection Set, Pinned";132case _trash: return "Trash";133default:134ShouldNotReachHere();135return "";136}137}138139// This method protects from accidental changes in enum order:140int region_state_to_ordinal(RegionState s) const {141switch (s) {142case _empty_uncommitted: return 0;143case _empty_committed: return 1;144case _regular: return 2;145case _humongous_start: return 3;146case _humongous_cont: return 4;147case _cset: return 5;148case _pinned: return 6;149case _trash: return 7;150case _pinned_cset: return 8;151case _pinned_humongous_start: return 9;152default:153ShouldNotReachHere();154return -1;155}156}157158void report_illegal_transition(const char* method);159160public:161static const int region_states_num() {162return _REGION_STATES_NUM;163}164165// Allowed transitions from the outside code:166void make_regular_allocation();167void make_regular_bypass();168void make_humongous_start();169void make_humongous_cont();170void make_humongous_start_bypass();171void make_humongous_cont_bypass();172void make_pinned();173void make_unpinned();174void make_cset();175void make_trash();176void make_trash_immediate();177void make_empty();178void make_uncommitted();179void make_committed_bypass();180181// Individual states:182bool is_empty_uncommitted() const { return _state == _empty_uncommitted; }183bool is_empty_committed() const { return _state == _empty_committed; }184bool is_regular() const { return _state == _regular; }185bool is_humongous_continuation() const { return _state == _humongous_cont; }186187// Participation in logical groups:188bool is_empty() const { return is_empty_committed() || is_empty_uncommitted(); }189bool is_active() const { return !is_empty() && !is_trash(); }190bool is_trash() const { return _state == _trash; }191bool is_humongous_start() const { return _state == _humongous_start || _state == _pinned_humongous_start; }192bool is_humongous() const { return is_humongous_start() || is_humongous_continuation(); }193bool is_committed() const { return !is_empty_uncommitted(); }194bool is_cset() const { return _state == _cset || _state == _pinned_cset; }195bool is_pinned() const { return _state == _pinned || _state == _pinned_cset || _state == _pinned_humongous_start; }196197// Macro-properties:198bool is_alloc_allowed() const { return is_empty() || is_regular() || _state == _pinned; }199bool is_stw_move_allowed() const { return is_regular() || _state == _cset || (ShenandoahHumongousMoves && _state == _humongous_start); }200201RegionState state() const { return _state; }202int state_ordinal() const { return region_state_to_ordinal(_state); }203204void record_pin();205void record_unpin();206size_t pin_count() const;207208private:209static size_t RegionCount;210static size_t RegionSizeBytes;211static size_t RegionSizeWords;212static size_t RegionSizeBytesShift;213static size_t RegionSizeWordsShift;214static size_t RegionSizeBytesMask;215static size_t RegionSizeWordsMask;216static size_t HumongousThresholdBytes;217static size_t HumongousThresholdWords;218static size_t MaxTLABSizeBytes;219static size_t MaxTLABSizeWords;220221// Never updated fields222size_t const _index;223HeapWord* const _bottom;224HeapWord* const _end;225226// Rarely updated fields227HeapWord* _new_top;228double _empty_time;229230// Seldom updated fields231RegionState _state;232233// Frequently updated fields234HeapWord* _top;235236size_t _tlab_allocs;237size_t _gclab_allocs;238239volatile jint _live_data;240volatile jint _critical_pins;241242HeapWord* volatile _update_watermark;243244public:245ShenandoahHeapRegion(HeapWord* start, size_t index, bool committed);246247static const size_t MIN_NUM_REGIONS = 10;248249static void setup_sizes(size_t max_heap_size);250251double empty_time() {252return _empty_time;253}254255inline static size_t required_regions(size_t bytes) {256return (bytes + ShenandoahHeapRegion::region_size_bytes() - 1) >> ShenandoahHeapRegion::region_size_bytes_shift();257}258259inline static size_t region_count() {260return ShenandoahHeapRegion::RegionCount;261}262263inline static size_t region_size_bytes() {264return ShenandoahHeapRegion::RegionSizeBytes;265}266267inline static size_t region_size_words() {268return ShenandoahHeapRegion::RegionSizeWords;269}270271inline static size_t region_size_bytes_shift() {272return ShenandoahHeapRegion::RegionSizeBytesShift;273}274275inline static size_t region_size_words_shift() {276return ShenandoahHeapRegion::RegionSizeWordsShift;277}278279inline static size_t region_size_bytes_mask() {280return ShenandoahHeapRegion::RegionSizeBytesMask;281}282283inline static size_t region_size_words_mask() {284return ShenandoahHeapRegion::RegionSizeWordsMask;285}286287// Convert to jint with sanity checking288inline static jint region_size_bytes_jint() {289assert (ShenandoahHeapRegion::RegionSizeBytes <= (size_t)max_jint, "sanity");290return (jint)ShenandoahHeapRegion::RegionSizeBytes;291}292293// Convert to jint with sanity checking294inline static jint region_size_words_jint() {295assert (ShenandoahHeapRegion::RegionSizeWords <= (size_t)max_jint, "sanity");296return (jint)ShenandoahHeapRegion::RegionSizeWords;297}298299// Convert to jint with sanity checking300inline static jint region_size_bytes_shift_jint() {301assert (ShenandoahHeapRegion::RegionSizeBytesShift <= (size_t)max_jint, "sanity");302return (jint)ShenandoahHeapRegion::RegionSizeBytesShift;303}304305// Convert to jint with sanity checking306inline static jint region_size_words_shift_jint() {307assert (ShenandoahHeapRegion::RegionSizeWordsShift <= (size_t)max_jint, "sanity");308return (jint)ShenandoahHeapRegion::RegionSizeWordsShift;309}310311inline static size_t humongous_threshold_bytes() {312return ShenandoahHeapRegion::HumongousThresholdBytes;313}314315inline static size_t humongous_threshold_words() {316return ShenandoahHeapRegion::HumongousThresholdWords;317}318319inline static size_t max_tlab_size_bytes() {320return ShenandoahHeapRegion::MaxTLABSizeBytes;321}322323inline static size_t max_tlab_size_words() {324return ShenandoahHeapRegion::MaxTLABSizeWords;325}326327inline size_t index() const {328return _index;329}330331// Allocation (return NULL if full)332inline HeapWord* allocate(size_t word_size, ShenandoahAllocRequest::Type type);333334inline void clear_live_data();335void set_live_data(size_t s);336337// Increase live data for newly allocated region338inline void increase_live_data_alloc_words(size_t s);339340// Increase live data for region scanned with GC341inline void increase_live_data_gc_words(size_t s);342343inline bool has_live() const;344inline size_t get_live_data_bytes() const;345inline size_t get_live_data_words() const;346347inline size_t garbage() const;348349void print_on(outputStream* st) const;350351void recycle();352353HeapWord* block_start(const void* p) const;354size_t block_size(const HeapWord* p) const;355bool block_is_obj(const HeapWord* p) const { return p < top(); }356357// Find humongous start region that this region belongs to358ShenandoahHeapRegion* humongous_start_region() const;359360HeapWord* top() const { return _top; }361void set_top(HeapWord* v) { _top = v; }362363HeapWord* new_top() const { return _new_top; }364void set_new_top(HeapWord* v) { _new_top = v; }365366HeapWord* bottom() const { return _bottom; }367HeapWord* end() const { return _end; }368369size_t capacity() const { return byte_size(bottom(), end()); }370size_t used() const { return byte_size(bottom(), top()); }371size_t free() const { return byte_size(top(), end()); }372373inline void adjust_alloc_metadata(ShenandoahAllocRequest::Type type, size_t);374void reset_alloc_metadata();375size_t get_shared_allocs() const;376size_t get_tlab_allocs() const;377size_t get_gclab_allocs() const;378379inline HeapWord* get_update_watermark() const;380inline void set_update_watermark(HeapWord* w);381inline void set_update_watermark_at_safepoint(HeapWord* w);382383private:384void do_commit();385void do_uncommit();386387inline void internal_increase_live_data(size_t s);388389void set_state(RegionState to);390};391392#endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHHEAPREGION_HPP393394395