提交 c8128861 编写于 作者: T tschatzl

7163191: G1: introduce a "heap spanning table" abstraction

Summary: Add G1BiasedArray<T> that is an array where each element represents a fixed-sized subdivision of the heap. Use this abstraction to refactor the HeapRegionSeq class.
Reviewed-by: brutisso
上级 4a607c5a
...@@ -88,7 +88,7 @@ ifeq ($(INCLUDE_ALL_GCS), false) ...@@ -88,7 +88,7 @@ ifeq ($(INCLUDE_ALL_GCS), false)
g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \ g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \
g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp \ g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp \
g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \ g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \
heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \ g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \
ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp \ ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp \
adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \ adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \
cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \ cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \
......
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "gc_implementation/g1/g1BiasedArray.hpp"
#ifndef PRODUCT
void G1BiasedMappedArrayBase::verify_index(idx_t index) const {
guarantee(_base != NULL, "Array not initialized");
guarantee(index < length(), err_msg("Index out of bounds index: "SIZE_FORMAT" length: "SIZE_FORMAT, index, length()));
}
void G1BiasedMappedArrayBase::verify_biased_index(idx_t biased_index) const {
guarantee(_biased_base != NULL, "Array not initialized");
guarantee(biased_index >= bias() && biased_index < (bias() + length()),
err_msg("Biased index out of bounds, index: "SIZE_FORMAT" bias: "SIZE_FORMAT" length: "SIZE_FORMAT, biased_index, bias(), length()));
}
void G1BiasedMappedArrayBase::verify_biased_index_inclusive_end(idx_t biased_index) const {
guarantee(_biased_base != NULL, "Array not initialized");
guarantee(biased_index >= bias() && biased_index <= (bias() + length()),
err_msg("Biased index out of inclusive bounds, index: "SIZE_FORMAT" bias: "SIZE_FORMAT" length: "SIZE_FORMAT, biased_index, bias(), length()));
}
class TestMappedArray : public G1BiasedMappedArray<int> {
protected:
virtual int default_value() const { return 0xBAADBABE; }
public:
static void test_biasedarray() {
const size_t REGION_SIZE_IN_WORDS = 512;
const size_t NUM_REGIONS = 20;
HeapWord* fake_heap = (HeapWord*)LP64_ONLY(0xBAAA00000) NOT_LP64(0xBA000000); // Any value that is non-zero
TestMappedArray array;
array.initialize(fake_heap, fake_heap + REGION_SIZE_IN_WORDS * NUM_REGIONS,
REGION_SIZE_IN_WORDS * HeapWordSize);
// Check address calculation (bounds)
assert(array.bottom_address_mapped() == fake_heap,
err_msg("bottom mapped address should be "PTR_FORMAT", but is "PTR_FORMAT, fake_heap, array.bottom_address_mapped()));
assert(array.end_address_mapped() == (fake_heap + REGION_SIZE_IN_WORDS * NUM_REGIONS), "must be");
int* bottom = array.address_mapped_to(fake_heap);
assert((void*)bottom == (void*) array.base(), "must be");
int* end = array.address_mapped_to(fake_heap + REGION_SIZE_IN_WORDS * NUM_REGIONS);
assert((void*)end == (void*)(array.base() + array.length()), "must be");
// The entire array should contain default value elements
for (int* current = bottom; current < end; current++) {
assert(*current == array.default_value(), "must be");
}
// Test setting values in the table
HeapWord* region_start_address = fake_heap + REGION_SIZE_IN_WORDS * (NUM_REGIONS / 2);
HeapWord* region_end_address = fake_heap + (REGION_SIZE_IN_WORDS * (NUM_REGIONS / 2) + REGION_SIZE_IN_WORDS - 1);
// Set/get by address tests: invert some value; first retrieve one
int actual_value = array.get_by_index(NUM_REGIONS / 2);
array.set_by_index(NUM_REGIONS / 2, ~actual_value);
// Get the same value by address, should correspond to the start of the "region"
int value = array.get_by_address(region_start_address);
assert(value == ~actual_value, "must be");
// Get the same value by address, at one HeapWord before the start
value = array.get_by_address(region_start_address - 1);
assert(value == array.default_value(), "must be");
// Get the same value by address, at the end of the "region"
value = array.get_by_address(region_end_address);
assert(value == ~actual_value, "must be");
// Make sure the next value maps to another index
value = array.get_by_address(region_end_address + 1);
assert(value == array.default_value(), "must be");
// Reset the value in the array
array.set_by_address(region_start_address + (region_end_address - region_start_address) / 2, actual_value);
// The entire array should have the default value again
for (int* current = bottom; current < end; current++) {
assert(*current == array.default_value(), "must be");
}
// Set/get by index tests: invert some value
idx_t index = NUM_REGIONS / 2;
actual_value = array.get_by_index(index);
array.set_by_index(index, ~actual_value);
value = array.get_by_index(index);
assert(value == ~actual_value, "must be");
value = array.get_by_index(index - 1);
assert(value == array.default_value(), "must be");
value = array.get_by_index(index + 1);
assert(value == array.default_value(), "must be");
array.set_by_index(0, 0);
value = array.get_by_index(0);
assert(value == 0, "must be");
array.set_by_index(array.length() - 1, 0);
value = array.get_by_index(array.length() - 1);
assert(value == 0, "must be");
array.set_by_index(index, 0);
// The array should have three zeros, and default values otherwise
size_t num_zeros = 0;
for (int* current = bottom; current < end; current++) {
assert(*current == array.default_value() || *current == 0, "must be");
if (*current == 0) {
num_zeros++;
}
}
assert(num_zeros == 3, "must be");
}
};
void TestG1BiasedArray_test() {
TestMappedArray::test_biasedarray();
}
#endif
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP
#include "utilities/debug.hpp"
#include "memory/allocation.inline.hpp"
// Implements the common base functionality for arrays that contain provisions
// for accessing its elements using a biased index.
// The element type is defined by the instantiating the template.
class G1BiasedMappedArrayBase VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
public:
typedef size_t idx_t;
protected:
address _base; // the real base address
size_t _length; // the length of the array
address _biased_base; // base address biased by "bias" elements
size_t _bias; // the bias, i.e. the offset biased_base is located to the right in elements
uint _shift_by; // the amount of bits to shift right when mapping to an index of the array.
protected:
G1BiasedMappedArrayBase() : _base(NULL), _length(0), _biased_base(NULL),
_bias(0), _shift_by(0) { }
// Allocate a new array, generic version.
static address create_new_base_array(size_t length, size_t elem_size) {
assert(length > 0, "just checking");
assert(elem_size > 0, "just checking");
return NEW_C_HEAP_ARRAY(u_char, length * elem_size, mtGC);
}
// Initialize the members of this class. The biased start address of this array
// is the bias (in elements) multiplied by the element size.
void initialize_base(address base, size_t length, size_t bias, size_t elem_size, uint shift_by) {
assert(base != NULL, "just checking");
assert(length > 0, "just checking");
assert(shift_by < sizeof(uintptr_t) * 8, err_msg("Shifting by %zd, larger than word size?", shift_by));
_base = base;
_length = length;
_biased_base = base - (bias * elem_size);
_bias = bias;
_shift_by = shift_by;
}
// Allocate and initialize this array to cover the heap addresses in the range
// of [bottom, end).
void initialize(HeapWord* bottom, HeapWord* end, size_t target_elem_size_in_bytes, size_t mapping_granularity_in_bytes) {
assert(mapping_granularity_in_bytes > 0, "just checking");
assert(is_power_of_2(mapping_granularity_in_bytes),
err_msg("mapping granularity must be power of 2, is %zd", mapping_granularity_in_bytes));
assert((uintptr_t)bottom % mapping_granularity_in_bytes == 0,
err_msg("bottom mapping area address must be a multiple of mapping granularity %zd, is "PTR_FORMAT,
mapping_granularity_in_bytes, bottom));
assert((uintptr_t)end % mapping_granularity_in_bytes == 0,
err_msg("end mapping area address must be a multiple of mapping granularity %zd, is "PTR_FORMAT,
mapping_granularity_in_bytes, end));
size_t num_target_elems = (end - bottom) / (mapping_granularity_in_bytes / HeapWordSize);
idx_t bias = (uintptr_t)bottom / mapping_granularity_in_bytes;
address base = create_new_base_array(num_target_elems, target_elem_size_in_bytes);
initialize_base(base, num_target_elems, bias, target_elem_size_in_bytes, log2_intptr(mapping_granularity_in_bytes));
}
size_t bias() const { return _bias; }
uint shift_by() const { return _shift_by; }
void verify_index(idx_t index) const PRODUCT_RETURN;
void verify_biased_index(idx_t biased_index) const PRODUCT_RETURN;
void verify_biased_index_inclusive_end(idx_t biased_index) const PRODUCT_RETURN;
public:
// Return the length of the array in elements.
size_t length() const { return _length; }
};
// Array that provides biased access and mapping from (valid) addresses in the
// heap into this array.
template<class T>
class G1BiasedMappedArray : public G1BiasedMappedArrayBase {
public:
typedef G1BiasedMappedArrayBase::idx_t idx_t;
T* base() const { return (T*)G1BiasedMappedArrayBase::_base; }
// Return the element of the given array at the given index. Assume
// the index is valid. This is a convenience method that does sanity
// checking on the index.
T get_by_index(idx_t index) const {
verify_index(index);
return this->base()[index];
}
// Set the element of the given array at the given index to the
// given value. Assume the index is valid. This is a convenience
// method that does sanity checking on the index.
void set_by_index(idx_t index, T value) {
verify_index(index);
this->base()[index] = value;
}
// The raw biased base pointer.
T* biased_base() const { return (T*)G1BiasedMappedArrayBase::_biased_base; }
// Return the element of the given array that covers the given word in the
// heap. Assumes the index is valid.
T get_by_address(HeapWord* value) const {
idx_t biased_index = ((uintptr_t)value) >> this->shift_by();
this->verify_biased_index(biased_index);
return biased_base()[biased_index];
}
// Set the value of the array entry that corresponds to the given array.
void set_by_address(HeapWord * address, T value) {
idx_t biased_index = ((uintptr_t)address) >> this->shift_by();
this->verify_biased_index(biased_index);
biased_base()[biased_index] = value;
}
protected:
// Returns the address of the element the given address maps to
T* address_mapped_to(HeapWord* address) {
idx_t biased_index = ((uintptr_t)address) >> this->shift_by();
this->verify_biased_index_inclusive_end(biased_index);
return biased_base() + biased_index;
}
public:
// Return the smallest address (inclusive) in the heap that this array covers.
HeapWord* bottom_address_mapped() const {
return (HeapWord*) ((uintptr_t)this->bias() << this->shift_by());
}
// Return the highest address (exclusive) in the heap that this array covers.
HeapWord* end_address_mapped() const {
return (HeapWord*) ((uintptr_t)(this->bias() + this->length()) << this->shift_by());
}
protected:
virtual T default_value() const = 0;
// Set all elements of the given array to the given value.
void clear() {
T value = default_value();
for (idx_t i = 0; i < length(); i++) {
set_by_index(i, value);
}
}
public:
G1BiasedMappedArray() {}
// Allocate and initialize this array to cover the heap addresses in the range
// of [bottom, end).
void initialize(HeapWord* bottom, HeapWord* end, size_t mapping_granularity) {
G1BiasedMappedArrayBase::initialize(bottom, end, sizeof(T), mapping_granularity);
this->clear();
}
};
#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP
...@@ -2069,8 +2069,10 @@ jint G1CollectedHeap::initialize() { ...@@ -2069,8 +2069,10 @@ jint G1CollectedHeap::initialize() {
_g1_storage.initialize(g1_rs, 0); _g1_storage.initialize(g1_rs, 0);
_g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0); _g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0);
_hrs.initialize((HeapWord*) _g1_reserved.start(), _hrs.initialize((HeapWord*) _g1_reserved.start(),
(HeapWord*) _g1_reserved.end(), (HeapWord*) _g1_reserved.end());
_expansion_regions); assert(_hrs.max_length() == _expansion_regions,
err_msg("max length: %u expansion regions: %u",
_hrs.max_length(), _expansion_regions));
// Do later initialization work for concurrent refinement. // Do later initialization work for concurrent refinement.
_cg1r->init(); _cg1r->init();
......
...@@ -71,27 +71,16 @@ uint HeapRegionSeq::find_contiguous_from(uint from, uint num) { ...@@ -71,27 +71,16 @@ uint HeapRegionSeq::find_contiguous_from(uint from, uint num) {
// Public // Public
void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end, void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end) {
uint max_length) {
assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0, assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0,
"bottom should be heap region aligned"); "bottom should be heap region aligned");
assert((uintptr_t) end % HeapRegion::GrainBytes == 0, assert((uintptr_t) end % HeapRegion::GrainBytes == 0,
"end should be heap region aligned"); "end should be heap region aligned");
_length = 0;
_heap_bottom = bottom;
_heap_end = end;
_region_shift = HeapRegion::LogOfHRGrainBytes;
_next_search_index = 0; _next_search_index = 0;
_allocated_length = 0; _allocated_length = 0;
_max_length = max_length;
_regions = NEW_C_HEAP_ARRAY(HeapRegion*, max_length, mtGC); _regions.initialize(bottom, end, HeapRegion::GrainBytes);
memset(_regions, 0, (size_t) max_length * sizeof(HeapRegion*));
_regions_biased = _regions - ((uintx) bottom >> _region_shift);
assert(&_regions[0] == &_regions_biased[addr_to_index_biased(bottom)],
"bottom should be included in the region with index 0");
} }
MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, MemRegion HeapRegionSeq::expand_by(HeapWord* old_end,
...@@ -101,15 +90,15 @@ MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, ...@@ -101,15 +90,15 @@ MemRegion HeapRegionSeq::expand_by(HeapWord* old_end,
G1CollectedHeap* g1h = G1CollectedHeap::heap(); G1CollectedHeap* g1h = G1CollectedHeap::heap();
HeapWord* next_bottom = old_end; HeapWord* next_bottom = old_end;
assert(_heap_bottom <= next_bottom, "invariant"); assert(heap_bottom() <= next_bottom, "invariant");
while (next_bottom < new_end) { while (next_bottom < new_end) {
assert(next_bottom < _heap_end, "invariant"); assert(next_bottom < heap_end(), "invariant");
uint index = length(); uint index = length();
assert(index < _max_length, "otherwise we cannot expand further"); assert(index < max_length(), "otherwise we cannot expand further");
if (index == 0) { if (index == 0) {
// We have not allocated any regions so far // We have not allocated any regions so far
assert(next_bottom == _heap_bottom, "invariant"); assert(next_bottom == heap_bottom(), "invariant");
} else { } else {
// next_bottom should match the end of the last/previous region // next_bottom should match the end of the last/previous region
assert(next_bottom == at(index - 1)->end(), "invariant"); assert(next_bottom == at(index - 1)->end(), "invariant");
...@@ -122,8 +111,8 @@ MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, ...@@ -122,8 +111,8 @@ MemRegion HeapRegionSeq::expand_by(HeapWord* old_end,
// allocation failed, we bail out and return what we have done so far // allocation failed, we bail out and return what we have done so far
return MemRegion(old_end, next_bottom); return MemRegion(old_end, next_bottom);
} }
assert(_regions[index] == NULL, "invariant"); assert(_regions.get_by_index(index) == NULL, "invariant");
_regions[index] = new_hr; _regions.set_by_index(index, new_hr);
increment_allocated_length(); increment_allocated_length();
} }
// Have to increment the length first, otherwise we will get an // Have to increment the length first, otherwise we will get an
...@@ -228,26 +217,26 @@ uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) { ...@@ -228,26 +217,26 @@ uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) {
#ifndef PRODUCT #ifndef PRODUCT
void HeapRegionSeq::verify_optional() { void HeapRegionSeq::verify_optional() {
guarantee(_length <= _allocated_length, guarantee(length() <= _allocated_length,
err_msg("invariant: _length: %u _allocated_length: %u", err_msg("invariant: _length: %u _allocated_length: %u",
_length, _allocated_length)); length(), _allocated_length));
guarantee(_allocated_length <= _max_length, guarantee(_allocated_length <= max_length(),
err_msg("invariant: _allocated_length: %u _max_length: %u", err_msg("invariant: _allocated_length: %u _max_length: %u",
_allocated_length, _max_length)); _allocated_length, max_length()));
guarantee(_next_search_index <= _length, guarantee(_next_search_index <= length(),
err_msg("invariant: _next_search_index: %u _length: %u", err_msg("invariant: _next_search_index: %u _length: %u",
_next_search_index, _length)); _next_search_index, length()));
HeapWord* prev_end = _heap_bottom; HeapWord* prev_end = heap_bottom();
for (uint i = 0; i < _allocated_length; i += 1) { for (uint i = 0; i < _allocated_length; i += 1) {
HeapRegion* hr = _regions[i]; HeapRegion* hr = _regions.get_by_index(i);
guarantee(hr != NULL, err_msg("invariant: i: %u", i)); guarantee(hr != NULL, err_msg("invariant: i: %u", i));
guarantee(hr->bottom() == prev_end, guarantee(hr->bottom() == prev_end,
err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT, err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT,
i, HR_FORMAT_PARAMS(hr), prev_end)); i, HR_FORMAT_PARAMS(hr), prev_end));
guarantee(hr->hrs_index() == i, guarantee(hr->hrs_index() == i,
err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index())); err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index()));
if (i < _length) { if (i < length()) {
// Asserts will fire if i is >= _length // Asserts will fire if i is >= _length
HeapWord* addr = hr->bottom(); HeapWord* addr = hr->bottom();
guarantee(addr_to_region(addr) == hr, "sanity"); guarantee(addr_to_region(addr) == hr, "sanity");
...@@ -265,8 +254,8 @@ void HeapRegionSeq::verify_optional() { ...@@ -265,8 +254,8 @@ void HeapRegionSeq::verify_optional() {
prev_end = hr->end(); prev_end = hr->end();
} }
} }
for (uint i = _allocated_length; i < _max_length; i += 1) { for (uint i = _allocated_length; i < max_length(); i += 1) {
guarantee(_regions[i] == NULL, err_msg("invariant i: %u", i)); guarantee(_regions.get_by_index(i) == NULL, err_msg("invariant i: %u", i));
} }
} }
#endif // PRODUCT #endif // PRODUCT
...@@ -25,10 +25,17 @@ ...@@ -25,10 +25,17 @@
#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP
#define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP
#include "gc_implementation/g1/g1BiasedArray.hpp"
class HeapRegion; class HeapRegion;
class HeapRegionClosure; class HeapRegionClosure;
class FreeRegionList; class FreeRegionList;
class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
protected:
virtual HeapRegion* default_value() const { return NULL; }
};
// This class keeps track of the region metadata (i.e., HeapRegion // This class keeps track of the region metadata (i.e., HeapRegion
// instances). They are kept in the _regions array in address // instances). They are kept in the _regions array in address
// order. A region's index in the array corresponds to its index in // order. A region's index in the array corresponds to its index in
...@@ -44,35 +51,21 @@ class FreeRegionList; ...@@ -44,35 +51,21 @@ class FreeRegionList;
// //
// We keep track of three lengths: // We keep track of three lengths:
// //
// * _length (returned by length()) is the number of currently // * _committed_length (returned by length()) is the number of currently
// committed regions. // committed regions.
// * _allocated_length (not exposed outside this class) is the // * _allocated_length (not exposed outside this class) is the
// number of regions for which we have HeapRegions. // number of regions for which we have HeapRegions.
// * _max_length (returned by max_length()) is the maximum number of // * max_length() returns the maximum number of regions the heap can have.
// regions the heap can have.
// //
// and maintain that: _length <= _allocated_length <= _max_length // and maintain that: _committed_length <= _allocated_length <= max_length()
class HeapRegionSeq: public CHeapObj<mtGC> { class HeapRegionSeq: public CHeapObj<mtGC> {
friend class VMStructs; friend class VMStructs;
// The array that holds the HeapRegions. G1HeapRegionTable _regions;
HeapRegion** _regions;
// Version of _regions biased to address 0
HeapRegion** _regions_biased;
// The number of regions committed in the heap. // The number of regions committed in the heap.
uint _length; uint _committed_length;
// The address of the first reserved word in the heap.
HeapWord* _heap_bottom;
// The address of the last reserved word in the heap - 1.
HeapWord* _heap_end;
// The log of the region byte size.
uint _region_shift;
// A hint for which index to start searching from for humongous // A hint for which index to start searching from for humongous
// allocations. // allocations.
...@@ -81,37 +74,33 @@ class HeapRegionSeq: public CHeapObj<mtGC> { ...@@ -81,37 +74,33 @@ class HeapRegionSeq: public CHeapObj<mtGC> {
// The number of regions for which we have allocated HeapRegions for. // The number of regions for which we have allocated HeapRegions for.
uint _allocated_length; uint _allocated_length;
// The maximum number of regions in the heap.
uint _max_length;
// Find a contiguous set of empty regions of length num, starting // Find a contiguous set of empty regions of length num, starting
// from the given index. // from the given index.
uint find_contiguous_from(uint from, uint num); uint find_contiguous_from(uint from, uint num);
// Map a heap address to a biased region index. Assume that the
// address is valid.
inline uintx addr_to_index_biased(HeapWord* addr) const;
void increment_allocated_length() { void increment_allocated_length() {
assert(_allocated_length < _max_length, "pre-condition"); assert(_allocated_length < max_length(), "pre-condition");
_allocated_length++; _allocated_length++;
} }
void increment_length() { void increment_length() {
assert(_length < _max_length, "pre-condition"); assert(length() < max_length(), "pre-condition");
_length++; _committed_length++;
} }
void decrement_length() { void decrement_length() {
assert(_length > 0, "pre-condition"); assert(length() > 0, "pre-condition");
_length--; _committed_length--;
} }
HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); }
HeapWord* heap_end() const {return _regions.end_address_mapped(); }
public: public:
// Empty contructor, we'll initialize it with the initialize() method. // Empty contructor, we'll initialize it with the initialize() method.
HeapRegionSeq() { } HeapRegionSeq() : _regions(), _committed_length(0), _next_search_index(0), _allocated_length(0) { }
void initialize(HeapWord* bottom, HeapWord* end, uint max_length); void initialize(HeapWord* bottom, HeapWord* end);
// Return the HeapRegion at the given index. Assume that the index // Return the HeapRegion at the given index. Assume that the index
// is valid. // is valid.
...@@ -126,10 +115,10 @@ class HeapRegionSeq: public CHeapObj<mtGC> { ...@@ -126,10 +115,10 @@ class HeapRegionSeq: public CHeapObj<mtGC> {
inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const; inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const;
// Return the number of regions that have been committed in the heap. // Return the number of regions that have been committed in the heap.
uint length() const { return _length; } uint length() const { return _committed_length; }
// Return the maximum number of regions in the heap. // Return the maximum number of regions in the heap.
uint max_length() const { return _max_length; } uint max_length() const { return (uint)_regions.length(); }
// Expand the sequence to reflect that the heap has grown from // Expand the sequence to reflect that the heap has grown from
// old_end to new_end. Either create new HeapRegions, or re-use // old_end to new_end. Either create new HeapRegions, or re-use
......
...@@ -28,28 +28,16 @@ ...@@ -28,28 +28,16 @@
#include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegion.hpp"
#include "gc_implementation/g1/heapRegionSeq.hpp" #include "gc_implementation/g1/heapRegionSeq.hpp"
inline uintx HeapRegionSeq::addr_to_index_biased(HeapWord* addr) const {
assert(_heap_bottom <= addr && addr < _heap_end,
err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT,
addr, _heap_bottom, _heap_end));
uintx index = (uintx) addr >> _region_shift;
return index;
}
inline HeapRegion* HeapRegionSeq::addr_to_region_unsafe(HeapWord* addr) const { inline HeapRegion* HeapRegionSeq::addr_to_region_unsafe(HeapWord* addr) const {
assert(_heap_bottom <= addr && addr < _heap_end, HeapRegion* hr = _regions.get_by_address(addr);
err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT,
addr, _heap_bottom, _heap_end));
uintx index_biased = addr_to_index_biased(addr);
HeapRegion* hr = _regions_biased[index_biased];
assert(hr != NULL, "invariant"); assert(hr != NULL, "invariant");
return hr; return hr;
} }
inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const {
if (addr != NULL && addr < _heap_end) { if (addr != NULL && addr < heap_end()) {
assert(addr >= _heap_bottom, assert(addr >= heap_bottom(),
err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, _heap_bottom)); err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, heap_bottom()));
return addr_to_region_unsafe(addr); return addr_to_region_unsafe(addr);
} }
return NULL; return NULL;
...@@ -57,7 +45,7 @@ inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { ...@@ -57,7 +45,7 @@ inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const {
inline HeapRegion* HeapRegionSeq::at(uint index) const { inline HeapRegion* HeapRegionSeq::at(uint index) const {
assert(index < length(), "pre-condition"); assert(index < length(), "pre-condition");
HeapRegion* hr = _regions[index]; HeapRegion* hr = _regions.get_by_index(index);
assert(hr != NULL, "sanity"); assert(hr != NULL, "sanity");
assert(hr->hrs_index() == index, "sanity"); assert(hr->hrs_index() == index, "sanity");
return hr; return hr;
......
...@@ -34,8 +34,14 @@ ...@@ -34,8 +34,14 @@
static_field(HeapRegion, GrainBytes, size_t) \ static_field(HeapRegion, GrainBytes, size_t) \
static_field(HeapRegion, LogOfHRGrainBytes, int) \ static_field(HeapRegion, LogOfHRGrainBytes, int) \
\ \
nonstatic_field(HeapRegionSeq, _regions, HeapRegion**) \ nonstatic_field(G1HeapRegionTable, _base, address) \
nonstatic_field(HeapRegionSeq, _length, uint) \ nonstatic_field(G1HeapRegionTable, _length, size_t) \
nonstatic_field(G1HeapRegionTable, _biased_base, address) \
nonstatic_field(G1HeapRegionTable, _bias, size_t) \
nonstatic_field(G1HeapRegionTable, _shift_by, uint) \
\
nonstatic_field(HeapRegionSeq, _regions, G1HeapRegionTable) \
nonstatic_field(HeapRegionSeq, _committed_length, uint) \
\ \
nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \ nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \
nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \
...@@ -58,6 +64,8 @@ ...@@ -58,6 +64,8 @@
#define VM_TYPES_G1(declare_type, declare_toplevel_type) \ #define VM_TYPES_G1(declare_type, declare_toplevel_type) \
\ \
declare_toplevel_type(G1HeapRegionTable) \
\
declare_type(G1CollectedHeap, SharedHeap) \ declare_type(G1CollectedHeap, SharedHeap) \
\ \
declare_type(HeapRegion, ContiguousSpace) \ declare_type(HeapRegion, ContiguousSpace) \
......
...@@ -5047,6 +5047,9 @@ void TestReservedSpace_test(); ...@@ -5047,6 +5047,9 @@ void TestReservedSpace_test();
void TestReserveMemorySpecial_test(); void TestReserveMemorySpecial_test();
void TestVirtualSpace_test(); void TestVirtualSpace_test();
void MetaspaceAux_test(); void MetaspaceAux_test();
#if INCLUDE_ALL_GCS
void TestG1BiasedArray_test();
#endif
void execute_internal_vm_tests() { void execute_internal_vm_tests() {
if (ExecuteInternalVMTests) { if (ExecuteInternalVMTests) {
...@@ -5066,6 +5069,7 @@ void execute_internal_vm_tests() { ...@@ -5066,6 +5069,7 @@ void execute_internal_vm_tests() {
run_unit_test(VMStructs::test()); run_unit_test(VMStructs::test());
#endif #endif
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
run_unit_test(TestG1BiasedArray_test());
run_unit_test(HeapRegionRemSet::test_prt()); run_unit_test(HeapRegionRemSet::test_prt());
#endif #endif
tty->print_cr("All internal VM tests passed"); tty->print_cr("All internal VM tests passed");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册