Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.cpp
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#include "precompiled.hpp"2425#include "memory/allocation.hpp"26#include "gc_implementation/shared/spaceDecorator.hpp"27#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"28#include "gc_implementation/shenandoah/shenandoahHeapRegion.hpp"29#include "gc_implementation/shenandoah/shenandoahMarkingContext.inline.hpp"30#include "jfr/jfrEvents.hpp"31#include "memory/space.inline.hpp"32#include "memory/resourceArea.hpp"33#include "memory/universe.hpp"34#include "oops/oop.inline.hpp"35#include "runtime/java.hpp"36#include "runtime/mutexLocker.hpp"37#include "runtime/os.hpp"38#include "runtime/safepoint.hpp"3940size_t ShenandoahHeapRegion::RegionCount = 0;41size_t ShenandoahHeapRegion::RegionSizeBytes = 0;42size_t ShenandoahHeapRegion::RegionSizeWords = 0;43size_t ShenandoahHeapRegion::RegionSizeBytesShift = 0;44size_t ShenandoahHeapRegion::RegionSizeWordsShift = 0;45size_t ShenandoahHeapRegion::RegionSizeBytesMask = 0;46size_t ShenandoahHeapRegion::RegionSizeWordsMask = 0;47size_t ShenandoahHeapRegion::HumongousThresholdBytes = 0;48size_t ShenandoahHeapRegion::HumongousThresholdWords = 0;49size_t ShenandoahHeapRegion::MaxTLABSizeBytes = 0;50size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0;5152ShenandoahHeapRegion::ShenandoahHeapRegion(HeapWord* start, size_t index, bool committed) :53_index(index),54_bottom(start),55_end(start + RegionSizeWords),56_new_top(NULL),57_empty_time(os::elapsedTime()),58_state(committed ? _empty_committed : _empty_uncommitted),59_top(start),60_tlab_allocs(0),61_gclab_allocs(0),62_live_data(0),63_critical_pins(0),64_update_watermark(start) {6566assert(Universe::on_page_boundary(_bottom) && Universe::on_page_boundary(_end),67"invalid space boundaries");68if (ZapUnusedHeapArea && committed) {69SpaceMangler::mangle_region(MemRegion(_bottom, _end));70}71}7273void ShenandoahHeapRegion::report_illegal_transition(const char *method) {74ResourceMark rm;75stringStream ss;76ss.print("Illegal region state transition from \"%s\", at %s\n ", region_state_to_string(_state), method);77print_on(&ss);78fatal(ss.as_string());79}8081void ShenandoahHeapRegion::make_regular_allocation() {82shenandoah_assert_heaplocked();83switch (_state) {84case _empty_uncommitted:85do_commit();86case _empty_committed:87set_state(_regular);88case _regular:89case _pinned:90return;91default:92report_illegal_transition("regular allocation");93}94}9596void ShenandoahHeapRegion::make_regular_bypass() {97shenandoah_assert_heaplocked();98assert (ShenandoahHeap::heap()->is_full_gc_in_progress() || ShenandoahHeap::heap()->is_degenerated_gc_in_progress(),99"only for full or degen GC");100101switch (_state) {102case _empty_uncommitted:103do_commit();104case _empty_committed:105case _cset:106case _humongous_start:107case _humongous_cont:108set_state(_regular);109return;110case _pinned_cset:111set_state(_pinned);112return;113case _regular:114case _pinned:115return;116default:117report_illegal_transition("regular bypass");118}119}120121void ShenandoahHeapRegion::make_humongous_start() {122shenandoah_assert_heaplocked();123switch (_state) {124case _empty_uncommitted:125do_commit();126case _empty_committed:127set_state(_humongous_start);128return;129default:130report_illegal_transition("humongous start allocation");131}132}133134void ShenandoahHeapRegion::make_humongous_start_bypass() {135shenandoah_assert_heaplocked();136assert (ShenandoahHeap::heap()->is_full_gc_in_progress(), "only for full GC");137138switch (_state) {139case _empty_committed:140case _regular:141case _humongous_start:142case _humongous_cont:143set_state(_humongous_start);144return;145default:146report_illegal_transition("humongous start bypass");147}148}149150void ShenandoahHeapRegion::make_humongous_cont() {151shenandoah_assert_heaplocked();152switch (_state) {153case _empty_uncommitted:154do_commit();155case _empty_committed:156set_state(_humongous_cont);157return;158default:159report_illegal_transition("humongous continuation allocation");160}161}162163void ShenandoahHeapRegion::make_humongous_cont_bypass() {164shenandoah_assert_heaplocked();165assert (ShenandoahHeap::heap()->is_full_gc_in_progress(), "only for full GC");166167switch (_state) {168case _empty_committed:169case _regular:170case _humongous_start:171case _humongous_cont:172set_state(_humongous_cont);173return;174default:175report_illegal_transition("humongous continuation bypass");176}177}178179void ShenandoahHeapRegion::make_pinned() {180shenandoah_assert_heaplocked();181assert(pin_count() > 0, err_msg("Should have pins: " SIZE_FORMAT, pin_count()));182183switch (_state) {184case _regular:185set_state(_pinned);186case _pinned_cset:187case _pinned:188return;189case _humongous_start:190set_state(_pinned_humongous_start);191case _pinned_humongous_start:192return;193case _cset:194set_state(_pinned_cset);195return;196default:197report_illegal_transition("pinning");198}199}200201void ShenandoahHeapRegion::make_unpinned() {202shenandoah_assert_heaplocked();203assert(pin_count() == 0, err_msg("Should not have pins: " SIZE_FORMAT, pin_count()));204205switch (_state) {206case _pinned:207set_state(_regular);208return;209case _regular:210case _humongous_start:211return;212case _pinned_cset:213set_state(_cset);214return;215case _pinned_humongous_start:216set_state(_humongous_start);217return;218default:219report_illegal_transition("unpinning");220}221}222223void ShenandoahHeapRegion::make_cset() {224shenandoah_assert_heaplocked();225switch (_state) {226case _regular:227set_state(_cset);228case _cset:229return;230default:231report_illegal_transition("cset");232}233}234235void ShenandoahHeapRegion::make_trash() {236shenandoah_assert_heaplocked();237switch (_state) {238case _cset:239// Reclaiming cset regions240case _humongous_start:241case _humongous_cont:242// Reclaiming humongous regions243case _regular:244// Immediate region reclaim245set_state(_trash);246return;247default:248report_illegal_transition("trashing");249}250}251252void ShenandoahHeapRegion::make_trash_immediate() {253make_trash();254255// On this path, we know there are no marked objects in the region,256// tell marking context about it to bypass bitmap resets.257ShenandoahHeap::heap()->complete_marking_context()->reset_top_bitmap(this);258}259260void ShenandoahHeapRegion::make_empty() {261shenandoah_assert_heaplocked();262switch (_state) {263case _trash:264set_state(_empty_committed);265_empty_time = os::elapsedTime();266return;267default:268report_illegal_transition("emptying");269}270}271272void ShenandoahHeapRegion::make_uncommitted() {273shenandoah_assert_heaplocked();274switch (_state) {275case _empty_committed:276do_uncommit();277set_state(_empty_uncommitted);278return;279default:280report_illegal_transition("uncommiting");281}282}283284void ShenandoahHeapRegion::make_committed_bypass() {285shenandoah_assert_heaplocked();286assert (ShenandoahHeap::heap()->is_full_gc_in_progress(), "only for full GC");287288switch (_state) {289case _empty_uncommitted:290do_commit();291set_state(_empty_committed);292return;293default:294report_illegal_transition("commit bypass");295}296}297298void ShenandoahHeapRegion::reset_alloc_metadata() {299_tlab_allocs = 0;300_gclab_allocs = 0;301}302303size_t ShenandoahHeapRegion::get_shared_allocs() const {304return used() - (_tlab_allocs + _gclab_allocs) * HeapWordSize;305}306307size_t ShenandoahHeapRegion::get_tlab_allocs() const {308return _tlab_allocs * HeapWordSize;309}310311size_t ShenandoahHeapRegion::get_gclab_allocs() const {312return _gclab_allocs * HeapWordSize;313}314315void ShenandoahHeapRegion::set_live_data(size_t s) {316assert(Thread::current()->is_VM_thread(), "by VM thread");317size_t v = s >> LogHeapWordSize;318assert(v < (size_t)max_jint, "sanity");319_live_data = (jint)v;320}321322void ShenandoahHeapRegion::print_on(outputStream* st) const {323st->print("|");324st->print(SIZE_FORMAT_W(5), this->_index);325326switch (_state) {327case _empty_uncommitted:328st->print("|EU ");329break;330case _empty_committed:331st->print("|EC ");332break;333case _regular:334st->print("|R ");335break;336case _humongous_start:337st->print("|H ");338break;339case _pinned_humongous_start:340st->print("|HP ");341break;342case _humongous_cont:343st->print("|HC ");344break;345case _cset:346st->print("|CS ");347break;348case _trash:349st->print("|T ");350break;351case _pinned:352st->print("|P ");353break;354case _pinned_cset:355st->print("|CSP");356break;357default:358ShouldNotReachHere();359}360st->print("|BTE " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12),361p2i(bottom()), p2i(top()), p2i(end()));362st->print("|TAMS " INTPTR_FORMAT_W(12),363p2i(ShenandoahHeap::heap()->marking_context()->top_at_mark_start(const_cast<ShenandoahHeapRegion*>(this))));364st->print("|UWM " INTPTR_FORMAT_W(12),365p2i(_update_watermark));366st->print("|U " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(used()), proper_unit_for_byte_size(used()));367st->print("|T " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_tlab_allocs()), proper_unit_for_byte_size(get_tlab_allocs()));368st->print("|G " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_gclab_allocs()), proper_unit_for_byte_size(get_gclab_allocs()));369st->print("|S " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_shared_allocs()), proper_unit_for_byte_size(get_shared_allocs()));370st->print("|L " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_live_data_bytes()), proper_unit_for_byte_size(get_live_data_bytes()));371st->print("|CP " SIZE_FORMAT_W(3), pin_count());372st->cr();373}374375ShenandoahHeapRegion* ShenandoahHeapRegion::humongous_start_region() const {376ShenandoahHeap* heap = ShenandoahHeap::heap();377assert(is_humongous(), "Must be a part of the humongous region");378size_t i = index();379ShenandoahHeapRegion* r = const_cast<ShenandoahHeapRegion*>(this);380while (!r->is_humongous_start()) {381assert(i > 0, "Sanity");382i--;383r = heap->get_region(i);384assert(r->is_humongous(), "Must be a part of the humongous region");385}386assert(r->is_humongous_start(), "Must be");387return r;388}389390void ShenandoahHeapRegion::recycle() {391set_top(bottom());392clear_live_data();393reset_alloc_metadata();394395ShenandoahHeap::heap()->marking_context()->reset_top_at_mark_start(this);396set_update_watermark(bottom());397398make_empty();399400if (ZapUnusedHeapArea) {401SpaceMangler::mangle_region(MemRegion(bottom(), end()));402}403}404405HeapWord* ShenandoahHeapRegion::block_start(const void* p) const {406assert(MemRegion(bottom(), end()).contains(p),407err_msg("p (" PTR_FORMAT ") not in space [" PTR_FORMAT ", " PTR_FORMAT ")",408p2i(p), p2i(bottom()), p2i(end())));409if (p >= top()) {410return top();411} else {412HeapWord* last = bottom();413HeapWord* cur = last;414while (cur <= p) {415last = cur;416cur += oop(cur)->size();417}418shenandoah_assert_correct(NULL, oop(last));419return last;420}421}422423size_t ShenandoahHeapRegion::block_size(const HeapWord* p) const {424assert(MemRegion(bottom(), end()).contains(p),425err_msg("p (" PTR_FORMAT ") not in space [" PTR_FORMAT ", " PTR_FORMAT ")",426p2i(p), p2i(bottom()), p2i(end())));427if (p < top()) {428return oop(p)->size();429} else {430assert(p == top(), "just checking");431return pointer_delta(end(), (HeapWord*) p);432}433}434435void ShenandoahHeapRegion::setup_sizes(size_t max_heap_size) {436// Absolute minimums we should not ever break:437static const size_t MIN_REGION_SIZE = 256*K;438439size_t region_size;440if (FLAG_IS_DEFAULT(ShenandoahRegionSize)) {441if (ShenandoahMinRegionSize > max_heap_size / MIN_NUM_REGIONS) {442err_msg message("Max heap size (" SIZE_FORMAT "%s) is too low to afford the minimum number "443"of regions (" SIZE_FORMAT ") of minimum region size (" SIZE_FORMAT "%s).",444byte_size_in_proper_unit(max_heap_size), proper_unit_for_byte_size(max_heap_size),445MIN_NUM_REGIONS,446byte_size_in_proper_unit<size_t>(ShenandoahMinRegionSize),447proper_unit_for_byte_size(ShenandoahMinRegionSize));448vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize option", message);449}450if (ShenandoahMinRegionSize < MIN_REGION_SIZE) {451err_msg message("" SIZE_FORMAT "%s should not be lower than minimum region size (" SIZE_FORMAT "%s).",452byte_size_in_proper_unit<size_t>(ShenandoahMinRegionSize),453proper_unit_for_byte_size(ShenandoahMinRegionSize),454byte_size_in_proper_unit(MIN_REGION_SIZE), proper_unit_for_byte_size(MIN_REGION_SIZE));455vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize option", message);456}457if (ShenandoahMinRegionSize < MinTLABSize) {458err_msg message("" SIZE_FORMAT "%s should not be lower than TLAB size size (" SIZE_FORMAT "%s).",459byte_size_in_proper_unit<size_t>(ShenandoahMinRegionSize),460proper_unit_for_byte_size(ShenandoahMinRegionSize),461byte_size_in_proper_unit<size_t>(MinTLABSize), proper_unit_for_byte_size(MinTLABSize));462vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize option", message);463}464if (ShenandoahMaxRegionSize < MIN_REGION_SIZE) {465err_msg message("" SIZE_FORMAT "%s should not be lower than min region size (" SIZE_FORMAT "%s).",466byte_size_in_proper_unit<size_t>(ShenandoahMaxRegionSize),467proper_unit_for_byte_size(ShenandoahMaxRegionSize),468byte_size_in_proper_unit(MIN_REGION_SIZE), proper_unit_for_byte_size(MIN_REGION_SIZE));469vm_exit_during_initialization("Invalid -XX:ShenandoahMaxRegionSize option", message);470}471if (ShenandoahMinRegionSize > ShenandoahMaxRegionSize) {472err_msg message("Minimum (" SIZE_FORMAT "%s) should be larger than maximum (" SIZE_FORMAT "%s).",473byte_size_in_proper_unit<size_t>(ShenandoahMinRegionSize),474proper_unit_for_byte_size(ShenandoahMinRegionSize),475byte_size_in_proper_unit<size_t>(ShenandoahMaxRegionSize),476proper_unit_for_byte_size(ShenandoahMaxRegionSize));477vm_exit_during_initialization("Invalid -XX:ShenandoahMinRegionSize or -XX:ShenandoahMaxRegionSize", message);478}479480// We rapidly expand to max_heap_size in most scenarios, so that is the measure481// for usual heap sizes. Do not depend on initial_heap_size here.482region_size = max_heap_size / ShenandoahTargetNumRegions;483484// Now make sure that we don't go over or under our limits.485region_size = MAX2<size_t>(ShenandoahMinRegionSize, region_size);486region_size = MIN2<size_t>(ShenandoahMaxRegionSize, region_size);487488} else {489if (ShenandoahRegionSize > max_heap_size / MIN_NUM_REGIONS) {490err_msg message("Max heap size (" SIZE_FORMAT "%s) is too low to afford the minimum number "491"of regions (" SIZE_FORMAT ") of requested size (" SIZE_FORMAT "%s).",492byte_size_in_proper_unit(max_heap_size), proper_unit_for_byte_size(max_heap_size),493MIN_NUM_REGIONS,494byte_size_in_proper_unit<size_t>(ShenandoahRegionSize),495proper_unit_for_byte_size(ShenandoahRegionSize));496vm_exit_during_initialization("Invalid -XX:ShenandoahRegionSize option", message);497}498if (ShenandoahRegionSize < ShenandoahMinRegionSize) {499err_msg message("Heap region size (" SIZE_FORMAT "%s) should be larger than min region size (" SIZE_FORMAT "%s).",500byte_size_in_proper_unit<size_t>(ShenandoahRegionSize),501proper_unit_for_byte_size(ShenandoahRegionSize),502byte_size_in_proper_unit<size_t>(ShenandoahMinRegionSize),503proper_unit_for_byte_size(ShenandoahMinRegionSize));504vm_exit_during_initialization("Invalid -XX:ShenandoahRegionSize option", message);505}506if (ShenandoahRegionSize > ShenandoahMaxRegionSize) {507err_msg message("Heap region size (" SIZE_FORMAT "%s) should be lower than max region size (" SIZE_FORMAT "%s).",508byte_size_in_proper_unit<size_t>(ShenandoahRegionSize),509proper_unit_for_byte_size(ShenandoahRegionSize),510byte_size_in_proper_unit<size_t>(ShenandoahMaxRegionSize),511proper_unit_for_byte_size(ShenandoahMaxRegionSize));512vm_exit_during_initialization("Invalid -XX:ShenandoahRegionSize option", message);513}514region_size = ShenandoahRegionSize;515}516517if (1 > ShenandoahHumongousThreshold || ShenandoahHumongousThreshold > 100) {518vm_exit_during_initialization("Invalid -XX:ShenandoahHumongousThreshold option, should be within [1..100]");519}520521// Make sure region size is at least one large page, if enabled.522// Otherwise, uncommitting one region may falsely uncommit the adjacent523// regions too.524// Also see shenandoahArguments.cpp, where it handles UseLargePages.525if (UseLargePages && ShenandoahUncommit) {526region_size = MAX2(region_size, os::large_page_size());527}528529int region_size_log = log2_long((jlong) region_size);530// Recalculate the region size to make sure it's a power of531// 2. This means that region_size is the largest power of 2 that's532// <= what we've calculated so far.533region_size = size_t(1) << region_size_log;534535// Now, set up the globals.536guarantee(RegionSizeBytesShift == 0, "we should only set it once");537RegionSizeBytesShift = (size_t)region_size_log;538539guarantee(RegionSizeWordsShift == 0, "we should only set it once");540RegionSizeWordsShift = RegionSizeBytesShift - LogHeapWordSize;541542guarantee(RegionSizeBytes == 0, "we should only set it once");543RegionSizeBytes = region_size;544RegionSizeWords = RegionSizeBytes >> LogHeapWordSize;545assert (RegionSizeWords*HeapWordSize == RegionSizeBytes, "sanity");546547guarantee(RegionSizeWordsMask == 0, "we should only set it once");548RegionSizeWordsMask = RegionSizeWords - 1;549550guarantee(RegionSizeBytesMask == 0, "we should only set it once");551RegionSizeBytesMask = RegionSizeBytes - 1;552553guarantee(RegionCount == 0, "we should only set it once");554RegionCount = max_heap_size / RegionSizeBytes;555556guarantee(HumongousThresholdWords == 0, "we should only set it once");557HumongousThresholdWords = RegionSizeWords * ShenandoahHumongousThreshold / 100;558HumongousThresholdWords = (size_t)align_size_down(HumongousThresholdWords, MinObjAlignment);559assert (HumongousThresholdWords <= RegionSizeWords, "sanity");560561guarantee(HumongousThresholdBytes == 0, "we should only set it once");562HumongousThresholdBytes = HumongousThresholdWords * HeapWordSize;563assert (HumongousThresholdBytes <= RegionSizeBytes, "sanity");564565// The rationale for trimming the TLAB sizes has to do with the raciness in566// TLAB allocation machinery. It may happen that TLAB sizing policy polls Shenandoah567// about next free size, gets the answer for region #N, goes away for a while, then568// tries to allocate in region #N, and fail because some other thread have claimed part569// of the region #N, and then the freeset allocation code has to retire the region #N,570// before moving the allocation to region #N+1.571//572// The worst case realizes when "answer" is "region size", which means it could573// prematurely retire an entire region. Having smaller TLABs does not fix that574// completely, but reduces the probability of too wasteful region retirement.575// With current divisor, we will waste no more than 1/8 of region size in the worst576// case. This also has a secondary effect on collection set selection: even under577// the race, the regions would be at least 7/8 used, which allows relying on578// "used" - "live" for cset selection. Otherwise, we can get the fragmented region579// below the garbage threshold that would never be considered for collection.580//581// The whole thing would be mitigated if Elastic TLABs were enabled, but there582// is no support in this JDK.583//584guarantee(MaxTLABSizeWords == 0, "we should only set it once");585MaxTLABSizeWords = MIN2(RegionSizeWords / 8, HumongousThresholdWords);586MaxTLABSizeWords = (size_t)align_size_down(MaxTLABSizeWords, MinObjAlignment);587588guarantee(MaxTLABSizeBytes == 0, "we should only set it once");589MaxTLABSizeBytes = MaxTLABSizeWords * HeapWordSize;590assert (MaxTLABSizeBytes > MinTLABSize, "should be larger");591592log_info(gc, init)("Regions: " SIZE_FORMAT " x " SIZE_FORMAT "%s",593RegionCount, byte_size_in_proper_unit(RegionSizeBytes), proper_unit_for_byte_size(RegionSizeBytes));594log_info(gc, init)("Humongous object threshold: " SIZE_FORMAT "%s",595byte_size_in_proper_unit(HumongousThresholdBytes), proper_unit_for_byte_size(HumongousThresholdBytes));596log_info(gc, init)("Max TLAB size: " SIZE_FORMAT "%s",597byte_size_in_proper_unit(MaxTLABSizeBytes), proper_unit_for_byte_size(MaxTLABSizeBytes));598}599600void ShenandoahHeapRegion::do_commit() {601ShenandoahHeap* heap = ShenandoahHeap::heap();602if (!heap->is_heap_region_special() && !os::commit_memory((char *) bottom(), RegionSizeBytes, false)) {603report_java_out_of_memory("Unable to commit region");604}605if (!heap->commit_bitmap_slice(this)) {606report_java_out_of_memory("Unable to commit bitmaps for region");607}608if (AlwaysPreTouch) {609os::pretouch_memory((char*)bottom(), (char*)end());610}611heap->increase_committed(ShenandoahHeapRegion::region_size_bytes());612}613614void ShenandoahHeapRegion::do_uncommit() {615ShenandoahHeap* heap = ShenandoahHeap::heap();616if (!heap->is_heap_region_special() && !os::uncommit_memory((char *) bottom(), RegionSizeBytes)) {617report_java_out_of_memory("Unable to uncommit region");618}619if (!heap->uncommit_bitmap_slice(this)) {620report_java_out_of_memory("Unable to uncommit bitmaps for region");621}622heap->decrease_committed(ShenandoahHeapRegion::region_size_bytes());623}624625void ShenandoahHeapRegion::record_pin() {626Atomic::add(1, &_critical_pins);627}628629void ShenandoahHeapRegion::record_unpin() {630assert(pin_count() > 0, err_msg("Region " SIZE_FORMAT " should have non-zero pins", index()));631Atomic::add(-1, &_critical_pins);632}633634size_t ShenandoahHeapRegion::pin_count() const {635jint v = OrderAccess::load_acquire((volatile jint*)&_critical_pins);636assert(v >= 0, "sanity");637return (size_t)v;638}639640void ShenandoahHeapRegion::set_state(RegionState to) {641EventShenandoahHeapRegionStateChange evt;642if (evt.should_commit()){643evt.set_index((unsigned)index());644evt.set_start((uintptr_t)bottom());645evt.set_used(used());646evt.set_from(_state);647evt.set_to(to);648evt.commit();649}650_state = to;651}652653654