Path: blob/master/src/hotspot/share/gc/g1/g1CommittedRegionMap.cpp
40961 views
/*1* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "gc/g1/g1CommittedRegionMap.inline.hpp"26#include "logging/log.hpp"27#include "memory/universe.hpp"28#include "runtime/mutexLocker.hpp"29#include "runtime/safepoint.hpp"30#include "utilities/debug.hpp"3132HeapRegionRange::HeapRegionRange(uint start, uint end) :33_start(start),34_end(end) {35assert(start <= end, "Invariant");36}3738G1CommittedRegionMap::G1CommittedRegionMap() :39_active(mtGC),40_inactive(mtGC),41_num_active(0),42_num_inactive(0) { }4344void G1CommittedRegionMap::initialize(uint num_regions) {45_active.initialize(num_regions);46_inactive.initialize(num_regions);47}4849uint G1CommittedRegionMap::num_active() const {50return _num_active;51}5253uint G1CommittedRegionMap::num_inactive() const {54return _num_inactive;55}5657uint G1CommittedRegionMap::max_length() const {58return (uint) _active.size();59}6061void G1CommittedRegionMap::activate(uint start, uint end) {62verify_active_count(start, end, 0);63verify_inactive_count(start, end, 0);6465log_debug(gc, heap, region)("Activate regions [%u, %u)", start, end);6667active_set_range(start, end);68}6970void G1CommittedRegionMap::reactivate(uint start, uint end) {71verify_active_count(start, end, 0);72verify_inactive_count(start, end, (end - start));7374log_debug(gc, heap, region)("Reactivate regions [%u, %u)", start, end);7576active_set_range(start, end);77inactive_clear_range(start, end);78}7980void G1CommittedRegionMap::deactivate(uint start, uint end) {81verify_active_count(start, end, (end - start));82verify_inactive_count(start, end, 0);8384log_debug(gc, heap, region)("Deactivate regions [%u, %u)", start, end);8586active_clear_range(start, end);87inactive_set_range(start, end);88}8990void G1CommittedRegionMap::uncommit(uint start, uint end) {91verify_active_count(start, end, 0);92verify_inactive_count(start, end, (end-start));9394log_debug(gc, heap, region)("Uncommit regions [%u, %u)", start, end);9596inactive_clear_range(start, end);97}9899HeapRegionRange G1CommittedRegionMap::next_active_range(uint offset) const {100// Find first active index from offset.101uint start = (uint) _active.get_next_one_offset(offset);102if (start == max_length()) {103// Early out when no active regions are found.104return HeapRegionRange(max_length(), max_length());105}106107uint end = (uint) _active.get_next_zero_offset(start);108verify_active_range(start, end);109110return HeapRegionRange(start, end);111}112113HeapRegionRange G1CommittedRegionMap::next_committable_range(uint offset) const {114// We should only call this function when there are no inactive regions.115verify_no_inactive_regons();116117// Find first free region from offset.118uint start = (uint) _active.get_next_zero_offset(offset);119if (start == max_length()) {120// Early out when no free regions are found.121return HeapRegionRange(max_length(), max_length());122}123124uint end = (uint) _active.get_next_one_offset(start);125verify_free_range(start, end);126127return HeapRegionRange(start, end);128}129130HeapRegionRange G1CommittedRegionMap::next_inactive_range(uint offset) const {131// Find first inactive region from offset.132uint start = (uint) _inactive.get_next_one_offset(offset);133134if (start == max_length()) {135// Early when no inactive regions are found.136return HeapRegionRange(max_length(), max_length());137}138139uint end = (uint) _inactive.get_next_zero_offset(start);140verify_inactive_range(start, end);141142return HeapRegionRange(start, end);143}144145void G1CommittedRegionMap::active_set_range(uint start, uint end) {146guarantee_mt_safety_active();147148_active.par_set_range(start, end, BitMap::unknown_range);149_num_active += (end - start);150}151152void G1CommittedRegionMap::active_clear_range(uint start, uint end) {153guarantee_mt_safety_active();154155_active.par_clear_range(start, end, BitMap::unknown_range);156_num_active -= (end - start);157}158159void G1CommittedRegionMap::inactive_set_range(uint start, uint end) {160guarantee_mt_safety_inactive();161162_inactive.par_set_range(start, end, BitMap::unknown_range);163_num_inactive += (end - start);164}165166void G1CommittedRegionMap::inactive_clear_range(uint start, uint end) {167guarantee_mt_safety_inactive();168169_inactive.par_clear_range(start, end, BitMap::unknown_range);170_num_inactive -= (end - start);171}172173void G1CommittedRegionMap::guarantee_mt_safety_active() const {174// G1CommittedRegionMap _active-map MT safety protocol:175// (a) If we're at a safepoint, the caller must either be the VM thread or176// hold the FreeList_lock.177// (b) If we're not at a safepoint, the caller must hold the Heap_lock.178// Protocol only applies after initialization is complete.179180if (!Universe::is_fully_initialized()) {181return;182}183184if (SafepointSynchronize::is_at_safepoint()) {185guarantee(Thread::current()->is_VM_thread() ||186FreeList_lock->owned_by_self(),187"G1CommittedRegionMap _active-map MT safety protocol at a safepoint");188} else {189guarantee(Heap_lock->owned_by_self(),190"G1CommittedRegionMap _active-map MT safety protocol outside a safepoint");191}192}193194void G1CommittedRegionMap::guarantee_mt_safety_inactive() const {195// G1CommittedRegionMap _inactive-map MT safety protocol:196// (a) If we're at a safepoint, the caller must either be the VM thread or197// hold the FreeList_lock.198// (b) If we're not at a safepoint, the caller must hold the Uncommit_lock.199// Protocol only applies after initialization is complete.200201if (!Universe::is_fully_initialized()) {202return;203}204205if (SafepointSynchronize::is_at_safepoint()) {206guarantee(Thread::current()->is_VM_thread() ||207FreeList_lock->owned_by_self(),208"G1CommittedRegionMap MT safety protocol at a safepoint");209} else {210guarantee(Uncommit_lock->owned_by_self(),211"G1CommittedRegionMap MT safety protocol outside a safepoint");212}213}214215#ifdef ASSERT216void G1CommittedRegionMap::verify_active_range(uint start, uint end) const {217assert(active(start), "First region (%u) is not active", start);218assert(active(end - 1), "Last region (%u) is not active", end - 1);219assert(end == _active.size() || !active(end), "Region (%u) is active but not included in range", end);220}221222void G1CommittedRegionMap::verify_inactive_range(uint start, uint end) const {223assert(inactive(start), "First region (%u) is not inactive", start);224assert(inactive(end - 1), "Last region (%u) in range is not inactive", end - 1);225assert(end == _inactive.size() || !inactive(end), "Region (%u) is inactive but not included in range", end);226}227228void G1CommittedRegionMap::verify_free_range(uint start, uint end) const {229assert(!active(start), "First region (%u) is active", start);230assert(!active(end - 1), "Last region (%u) in range is active", end - 1);231}232233void G1CommittedRegionMap::verify_no_inactive_regons() const {234BitMap::idx_t first_inactive = _inactive.get_next_one_offset(0);235assert(first_inactive == _inactive.size(), "Should be no inactive regions, but was at index: " SIZE_FORMAT, first_inactive);236}237238void G1CommittedRegionMap::verify_active_count(uint start, uint end, uint expected) const {239uint found = (uint) _active.count_one_bits(start, end);240assert(found == expected, "Unexpected number of active regions, found: %u, expected: %u", found, expected);241}242243void G1CommittedRegionMap::verify_inactive_count(uint start, uint end, uint expected) const {244uint found = (uint) _inactive.count_one_bits(start, end);245assert(found == expected, "Unexpected number of inactive regions, found: %u, expected: %u", found, expected);246}247248#endif //ASSERT249250251