8295658: G1: Refactor G1SegmentedArray to indicate that it is an allocator
Reviewed-by: tschatzl, sjohanss
This commit is contained in:
parent
cf656056a3
commit
dd5d4df5b6
@ -26,17 +26,17 @@
|
||||
|
||||
#include "gc/g1/g1CardSetContainers.inline.hpp"
|
||||
#include "gc/g1/g1CardSetMemory.inline.hpp"
|
||||
#include "gc/g1/g1SegmentedArray.inline.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
G1CardSetAllocator::G1CardSetAllocator(const char* name,
|
||||
const G1CardSetAllocOptions* alloc_options,
|
||||
G1CardSetFreeList* free_segment_list) :
|
||||
_segmented_array(alloc_options, free_segment_list),
|
||||
_free_slots_list(name, &_segmented_array)
|
||||
SegmentFreeList* segment_free_list) :
|
||||
_arena(alloc_options, segment_free_list),
|
||||
_free_slots_list(name, &_arena)
|
||||
{
|
||||
uint slot_size = _segmented_array.slot_size();
|
||||
uint slot_size = _arena.slot_size();
|
||||
assert(slot_size >= sizeof(G1CardSetContainer), "Slot instance size %u for allocator %s too small", slot_size, name);
|
||||
}
|
||||
|
||||
@ -51,23 +51,23 @@ void G1CardSetAllocator::free(void* slot) {
|
||||
|
||||
void G1CardSetAllocator::drop_all() {
|
||||
_free_slots_list.reset();
|
||||
_segmented_array.drop_all();
|
||||
_arena.drop_all();
|
||||
}
|
||||
|
||||
size_t G1CardSetAllocator::mem_size() const {
|
||||
return sizeof(*this) +
|
||||
num_segments() * sizeof(G1CardSetSegment) +
|
||||
_segmented_array.num_total_slots() * _segmented_array.slot_size();
|
||||
num_segments() * sizeof(Segment) +
|
||||
_arena.num_total_slots() * _arena.slot_size();
|
||||
}
|
||||
|
||||
size_t G1CardSetAllocator::unused_mem_size() const {
|
||||
uint num_unused_slots = (_segmented_array.num_total_slots() - _segmented_array.num_allocated_slots()) +
|
||||
uint num_unused_slots = (_arena.num_total_slots() - _arena.num_allocated_slots()) +
|
||||
(uint)_free_slots_list.free_count();
|
||||
return num_unused_slots * _segmented_array.slot_size();
|
||||
return num_unused_slots * _arena.slot_size();
|
||||
}
|
||||
|
||||
uint G1CardSetAllocator::num_segments() const {
|
||||
return _segmented_array.num_segments();
|
||||
return _arena.num_segments();
|
||||
}
|
||||
|
||||
G1CardSetMemoryManager::G1CardSetMemoryManager(G1CardSetConfiguration* config,
|
||||
@ -123,8 +123,8 @@ size_t G1CardSetMemoryManager::unused_mem_size() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
G1SegmentedArrayMemoryStats G1CardSetMemoryManager::memory_stats() const {
|
||||
G1SegmentedArrayMemoryStats result;
|
||||
G1MonotonicArenaMemoryStats G1CardSetMemoryManager::memory_stats() const {
|
||||
G1MonotonicArenaMemoryStats result;
|
||||
for (uint i = 0; i < num_mem_object_types(); i++) {
|
||||
result._num_mem_sizes[i] += _allocators[i].mem_size();
|
||||
result._num_segments[i] += _allocators[i].num_segments();
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
#include "gc/g1/g1CardSet.hpp"
|
||||
#include "gc/g1/g1CardSetContainers.hpp"
|
||||
#include "gc/g1/g1SegmentedArray.hpp"
|
||||
#include "gc/g1/g1SegmentedArrayFreePool.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreePool.hpp"
|
||||
#include "gc/shared/freeListAllocator.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
@ -37,8 +37,8 @@ class G1CardSetConfiguration;
|
||||
class outputStream;
|
||||
|
||||
// Collects G1CardSetAllocator options/heuristics. Called by G1CardSetAllocator
|
||||
// to determine the next size of the allocated G1CardSetSegment.
|
||||
class G1CardSetAllocOptions : public G1SegmentedArrayAllocOptions {
|
||||
// to determine the next size of the allocated memory Segment.
|
||||
class G1CardSetAllocOptions : public G1MonotonicArena::AllocOptions {
|
||||
static const uint MinimumNumSlots = 8;
|
||||
static const uint MaximumNumSlots = UINT_MAX / 2;
|
||||
|
||||
@ -50,7 +50,7 @@ public:
|
||||
static const uint SlotAlignment = 8;
|
||||
|
||||
G1CardSetAllocOptions(uint slot_size, uint initial_num_slots = MinimumNumSlots, uint max_num_slots = MaximumNumSlots) :
|
||||
G1SegmentedArrayAllocOptions(mtGCCardSet, slot_size, initial_num_slots, max_num_slots, SlotAlignment) {
|
||||
G1MonotonicArena::AllocOptions(mtGCCardSet, slot_size, initial_num_slots, max_num_slots, SlotAlignment) {
|
||||
}
|
||||
|
||||
virtual uint next_num_slots(uint prev_num_slots) const override {
|
||||
@ -58,22 +58,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
using G1CardSetSegment = G1SegmentedArraySegment;
|
||||
|
||||
using G1CardSetFreeList = G1SegmentedArrayFreeList;
|
||||
|
||||
// Arena-like allocator for (card set) heap memory objects.
|
||||
//
|
||||
// Allocation occurs from an internal free list of objects first. If the free list is
|
||||
// empty then tries to allocate from the G1SegmentedArray.
|
||||
// empty then tries to allocate from the G1MonotonicArena.
|
||||
class G1CardSetAllocator {
|
||||
G1SegmentedArray _segmented_array;
|
||||
using Segment = G1MonotonicArena::Segment;
|
||||
using SegmentFreeList = G1MonotonicArena::SegmentFreeList;
|
||||
G1MonotonicArena _arena;
|
||||
FreeListAllocator _free_slots_list;
|
||||
|
||||
public:
|
||||
G1CardSetAllocator(const char* name,
|
||||
const G1CardSetAllocOptions* alloc_options,
|
||||
G1CardSetFreeList* free_segment_list);
|
||||
SegmentFreeList* segment_free_list);
|
||||
~G1CardSetAllocator();
|
||||
|
||||
void* allocate();
|
||||
@ -91,7 +89,7 @@ public:
|
||||
uint num_segments() const;
|
||||
};
|
||||
|
||||
using G1CardSetFreePool = G1SegmentedArrayFreePool;
|
||||
using G1CardSetFreePool = G1MonotonicArenaFreePool;
|
||||
|
||||
class G1CardSetMemoryManager : public CHeapObj<mtGCCardSet> {
|
||||
G1CardSetConfiguration* _config;
|
||||
@ -118,7 +116,7 @@ public:
|
||||
size_t mem_size() const;
|
||||
size_t unused_mem_size() const;
|
||||
|
||||
G1SegmentedArrayMemoryStats memory_stats() const;
|
||||
G1MonotonicArenaMemoryStats memory_stats() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1CARDSETMEMORY_HPP
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "gc/g1/g1CardSetMemory.hpp"
|
||||
#include "gc/g1/g1CardSetContainers.inline.hpp"
|
||||
#include "gc/g1/g1SegmentedArray.inline.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.inline.hpp"
|
||||
#include "utilities/globalCounter.inline.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "gc/g1/g1HotCardCache.hpp"
|
||||
#include "gc/g1/g1InitLogger.hpp"
|
||||
#include "gc/g1/g1MemoryPool.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1OopClosures.inline.hpp"
|
||||
#include "gc/g1/g1ParallelCleaning.hpp"
|
||||
#include "gc/g1/g1ParScanThreadState.inline.hpp"
|
||||
@ -64,7 +65,6 @@
|
||||
#include "gc/g1/g1RootClosures.hpp"
|
||||
#include "gc/g1/g1RootProcessor.hpp"
|
||||
#include "gc/g1/g1SATBMarkQueueSet.hpp"
|
||||
#include "gc/g1/g1SegmentedArrayFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1ServiceThread.hpp"
|
||||
#include "gc/g1/g1ThreadLocalData.hpp"
|
||||
#include "gc/g1/g1Trace.hpp"
|
||||
@ -1429,7 +1429,7 @@ G1CollectedHeap::G1CollectedHeap() :
|
||||
CollectedHeap(),
|
||||
_service_thread(NULL),
|
||||
_periodic_gc_task(NULL),
|
||||
_free_segmented_array_memory_task(NULL),
|
||||
_free_arena_memory_task(NULL),
|
||||
_workers(NULL),
|
||||
_card_table(NULL),
|
||||
_collection_pause_end(Ticks::now()),
|
||||
@ -1717,8 +1717,8 @@ jint G1CollectedHeap::initialize() {
|
||||
_periodic_gc_task = new G1PeriodicGCTask("Periodic GC Task");
|
||||
_service_thread->register_task(_periodic_gc_task);
|
||||
|
||||
_free_segmented_array_memory_task = new G1SegmentedArrayFreeMemoryTask("Card Set Free Memory Task");
|
||||
_service_thread->register_task(_free_segmented_array_memory_task);
|
||||
_free_arena_memory_task = new G1MonotonicArenaFreeMemoryTask("Card Set Free Memory Task");
|
||||
_service_thread->register_task(_free_arena_memory_task);
|
||||
|
||||
// Here we allocate the dummy HeapRegion that is required by the
|
||||
// G1AllocRegion class.
|
||||
@ -2612,8 +2612,8 @@ void G1CollectedHeap::gc_epilogue(bool full) {
|
||||
|
||||
_collection_pause_end = Ticks::now();
|
||||
|
||||
_free_segmented_array_memory_task->notify_new_stats(&_young_gen_card_set_stats,
|
||||
&_collection_set_candidates_card_set_stats);
|
||||
_free_arena_memory_task->notify_new_stats(&_young_gen_card_set_stats,
|
||||
&_collection_set_candidates_card_set_stats);
|
||||
}
|
||||
|
||||
uint G1CollectedHeap::uncommit_regions(uint region_limit) {
|
||||
@ -2922,11 +2922,11 @@ bool G1CollectedHeap::should_sample_collection_set_candidates() const {
|
||||
return candidates != NULL && candidates->num_remaining() > 0;
|
||||
}
|
||||
|
||||
void G1CollectedHeap::set_collection_set_candidates_stats(G1SegmentedArrayMemoryStats& stats) {
|
||||
void G1CollectedHeap::set_collection_set_candidates_stats(G1MonotonicArenaMemoryStats& stats) {
|
||||
_collection_set_candidates_card_set_stats = stats;
|
||||
}
|
||||
|
||||
void G1CollectedHeap::set_young_gen_card_set_stats(const G1SegmentedArrayMemoryStats& stats) {
|
||||
void G1CollectedHeap::set_young_gen_card_set_stats(const G1MonotonicArenaMemoryStats& stats) {
|
||||
_young_gen_card_set_stats = stats;
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,8 @@
|
||||
#include "gc/g1/g1HeapVerifier.hpp"
|
||||
#include "gc/g1/g1HRPrinter.hpp"
|
||||
#include "gc/g1/g1MonitoringSupport.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1NUMA.hpp"
|
||||
#include "gc/g1/g1SegmentedArrayFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1SurvivorRegions.hpp"
|
||||
#include "gc/g1/g1YoungGCEvacFailureInjector.hpp"
|
||||
#include "gc/g1/heapRegionManager.hpp"
|
||||
@ -145,7 +145,7 @@ class G1CollectedHeap : public CollectedHeap {
|
||||
private:
|
||||
G1ServiceThread* _service_thread;
|
||||
G1ServiceTask* _periodic_gc_task;
|
||||
G1SegmentedArrayFreeMemoryTask* _free_segmented_array_memory_task;
|
||||
G1MonotonicArenaFreeMemoryTask* _free_arena_memory_task;
|
||||
|
||||
WorkerThreads* _workers;
|
||||
G1CardTable* _card_table;
|
||||
@ -162,9 +162,9 @@ private:
|
||||
HeapRegionSet _humongous_set;
|
||||
|
||||
// Young gen memory statistics before GC.
|
||||
G1SegmentedArrayMemoryStats _young_gen_card_set_stats;
|
||||
G1MonotonicArenaMemoryStats _young_gen_card_set_stats;
|
||||
// Collection set candidates memory statistics after GC.
|
||||
G1SegmentedArrayMemoryStats _collection_set_candidates_card_set_stats;
|
||||
G1MonotonicArenaMemoryStats _collection_set_candidates_card_set_stats;
|
||||
|
||||
// The block offset table for the G1 heap.
|
||||
G1BlockOffsetTable* _bot;
|
||||
@ -239,8 +239,8 @@ public:
|
||||
void set_humongous_stats(uint num_humongous_total, uint num_humongous_candidates);
|
||||
|
||||
bool should_sample_collection_set_candidates() const;
|
||||
void set_collection_set_candidates_stats(G1SegmentedArrayMemoryStats& stats);
|
||||
void set_young_gen_card_set_stats(const G1SegmentedArrayMemoryStats& stats);
|
||||
void set_collection_set_candidates_stats(G1MonotonicArenaMemoryStats& stats);
|
||||
void set_young_gen_card_set_stats(const G1MonotonicArenaMemoryStats& stats);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -24,13 +24,13 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1SegmentedArray.inline.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.inline.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/vmOperations.hpp"
|
||||
#include "utilities/globalCounter.inline.hpp"
|
||||
|
||||
G1SegmentedArraySegment::G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next, MEMFLAGS flag) :
|
||||
G1MonotonicArena::Segment::Segment(uint slot_size, uint num_slots, Segment* next, MEMFLAGS flag) :
|
||||
_slot_size(slot_size),
|
||||
_num_slots(num_slots),
|
||||
_next(next),
|
||||
@ -39,44 +39,44 @@ G1SegmentedArraySegment::G1SegmentedArraySegment(uint slot_size, uint num_slots,
|
||||
_bottom = ((char*) this) + header_size();
|
||||
}
|
||||
|
||||
G1SegmentedArraySegment* G1SegmentedArraySegment::create_segment(uint slot_size,
|
||||
uint num_slots,
|
||||
G1SegmentedArraySegment* next,
|
||||
MEMFLAGS mem_flag) {
|
||||
G1MonotonicArena::Segment* G1MonotonicArena::Segment::create_segment(uint slot_size,
|
||||
uint num_slots,
|
||||
Segment* next,
|
||||
MEMFLAGS mem_flag) {
|
||||
size_t block_size = size_in_bytes(slot_size, num_slots);
|
||||
char* alloc_block = NEW_C_HEAP_ARRAY(char, block_size, mem_flag);
|
||||
return new (alloc_block) G1SegmentedArraySegment(slot_size, num_slots, next, mem_flag);
|
||||
return new (alloc_block) Segment(slot_size, num_slots, next, mem_flag);
|
||||
}
|
||||
|
||||
void G1SegmentedArraySegment::delete_segment(G1SegmentedArraySegment* segment) {
|
||||
void G1MonotonicArena::Segment::delete_segment(Segment* segment) {
|
||||
// Wait for concurrent readers of the segment to exit before freeing; but only if the VM
|
||||
// isn't exiting.
|
||||
if (!VM_Exit::vm_exited()) {
|
||||
GlobalCounter::write_synchronize();
|
||||
}
|
||||
segment->~G1SegmentedArraySegment();
|
||||
segment->~Segment();
|
||||
FREE_C_HEAP_ARRAY(_mem_flag, segment);
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreeList::bulk_add(G1SegmentedArraySegment& first,
|
||||
G1SegmentedArraySegment& last,
|
||||
size_t num,
|
||||
size_t mem_size) {
|
||||
void G1MonotonicArena::SegmentFreeList::bulk_add(Segment& first,
|
||||
Segment& last,
|
||||
size_t num,
|
||||
size_t mem_size) {
|
||||
_list.prepend(first, last);
|
||||
Atomic::add(&_num_segments, num, memory_order_relaxed);
|
||||
Atomic::add(&_mem_size, mem_size, memory_order_relaxed);
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreeList::print_on(outputStream* out, const char* prefix) {
|
||||
void G1MonotonicArena::SegmentFreeList::print_on(outputStream* out, const char* prefix) {
|
||||
out->print_cr("%s: segments %zu size %zu",
|
||||
prefix, Atomic::load(&_num_segments), Atomic::load(&_mem_size));
|
||||
}
|
||||
|
||||
G1SegmentedArraySegment* G1SegmentedArrayFreeList::get_all(size_t& num_segments,
|
||||
size_t& mem_size) {
|
||||
G1MonotonicArena::Segment* G1MonotonicArena::SegmentFreeList::get_all(size_t& num_segments,
|
||||
size_t& mem_size) {
|
||||
GlobalCounter::CriticalSection cs(Thread::current());
|
||||
|
||||
G1SegmentedArraySegment* result = _list.pop_all();
|
||||
Segment* result = _list.pop_all();
|
||||
num_segments = Atomic::load(&_num_segments);
|
||||
mem_size = Atomic::load(&_mem_size);
|
||||
|
||||
@ -87,29 +87,29 @@ G1SegmentedArraySegment* G1SegmentedArrayFreeList::get_all(size_t& num_segments,
|
||||
return result;
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreeList::free_all() {
|
||||
void G1MonotonicArena::SegmentFreeList::free_all() {
|
||||
size_t num_freed = 0;
|
||||
size_t mem_size_freed = 0;
|
||||
G1SegmentedArraySegment* cur;
|
||||
Segment* cur;
|
||||
|
||||
while ((cur = _list.pop()) != nullptr) {
|
||||
mem_size_freed += cur->mem_size();
|
||||
num_freed++;
|
||||
G1SegmentedArraySegment::delete_segment(cur);
|
||||
Segment::delete_segment(cur);
|
||||
}
|
||||
|
||||
Atomic::sub(&_num_segments, num_freed, memory_order_relaxed);
|
||||
Atomic::sub(&_mem_size, mem_size_freed, memory_order_relaxed);
|
||||
}
|
||||
|
||||
G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySegment* const prev) {
|
||||
G1MonotonicArena::Segment* G1MonotonicArena::new_segment(Segment* const prev) {
|
||||
// Take an existing segment if available.
|
||||
G1SegmentedArraySegment* next = _free_segment_list->get();
|
||||
Segment* next = _segment_free_list->get();
|
||||
if (next == nullptr) {
|
||||
uint prev_num_slots = (prev != nullptr) ? prev->num_slots() : 0;
|
||||
uint num_slots = _alloc_options->next_num_slots(prev_num_slots);
|
||||
|
||||
next = G1SegmentedArraySegment::create_segment(slot_size(), num_slots, prev, _alloc_options->mem_flag());
|
||||
next = Segment::create_segment(slot_size(), num_slots, prev, _alloc_options->mem_flag());
|
||||
} else {
|
||||
assert(slot_size() == next->slot_size() ,
|
||||
"Mismatch %d != %d", slot_size(), next->slot_size());
|
||||
@ -117,10 +117,10 @@ G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySe
|
||||
}
|
||||
|
||||
// Install it as current allocation segment.
|
||||
G1SegmentedArraySegment* old = Atomic::cmpxchg(&_first, prev, next);
|
||||
Segment* old = Atomic::cmpxchg(&_first, prev, next);
|
||||
if (old != prev) {
|
||||
// Somebody else installed the segment, use that one.
|
||||
G1SegmentedArraySegment::delete_segment(next);
|
||||
Segment::delete_segment(next);
|
||||
return old;
|
||||
} else {
|
||||
// Did we install the first segment in the list? If so, this is also the last.
|
||||
@ -135,44 +135,44 @@ G1SegmentedArraySegment* G1SegmentedArray::create_new_segment(G1SegmentedArraySe
|
||||
}
|
||||
}
|
||||
|
||||
G1SegmentedArray::G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options,
|
||||
G1SegmentedArrayFreeList* free_segment_list) :
|
||||
G1MonotonicArena::G1MonotonicArena(const AllocOptions* alloc_options,
|
||||
SegmentFreeList* segment_free_list) :
|
||||
_alloc_options(alloc_options),
|
||||
_first(nullptr),
|
||||
_last(nullptr),
|
||||
_num_segments(0),
|
||||
_mem_size(0),
|
||||
_free_segment_list(free_segment_list),
|
||||
_segment_free_list(segment_free_list),
|
||||
_num_total_slots(0),
|
||||
_num_allocated_slots(0) {
|
||||
assert(_free_segment_list != nullptr, "precondition!");
|
||||
assert(_segment_free_list != nullptr, "precondition!");
|
||||
}
|
||||
|
||||
G1SegmentedArray::~G1SegmentedArray() {
|
||||
G1MonotonicArena::~G1MonotonicArena() {
|
||||
drop_all();
|
||||
}
|
||||
|
||||
uint G1SegmentedArray::slot_size() const {
|
||||
uint G1MonotonicArena::slot_size() const {
|
||||
return _alloc_options->slot_size();
|
||||
}
|
||||
|
||||
void G1SegmentedArray::drop_all() {
|
||||
G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first);
|
||||
void G1MonotonicArena::drop_all() {
|
||||
Segment* cur = Atomic::load_acquire(&_first);
|
||||
|
||||
if (cur != nullptr) {
|
||||
assert(_last != nullptr, "If there is at least one segment, there must be a last one.");
|
||||
|
||||
G1SegmentedArraySegment* first = cur;
|
||||
Segment* first = cur;
|
||||
#ifdef ASSERT
|
||||
// Check list consistency.
|
||||
G1SegmentedArraySegment* last = cur;
|
||||
Segment* last = cur;
|
||||
uint num_segments = 0;
|
||||
size_t mem_size = 0;
|
||||
while (cur != nullptr) {
|
||||
mem_size += cur->mem_size();
|
||||
num_segments++;
|
||||
|
||||
G1SegmentedArraySegment* next = cur->next();
|
||||
Segment* next = cur->next();
|
||||
last = cur;
|
||||
cur = next;
|
||||
}
|
||||
@ -181,7 +181,7 @@ void G1SegmentedArray::drop_all() {
|
||||
assert(mem_size == _mem_size, "Memory size inconsistent");
|
||||
assert(last == _last, "Inconsistent last segment");
|
||||
|
||||
_free_segment_list->bulk_add(*first, *_last, _num_segments, _mem_size);
|
||||
_segment_free_list->bulk_add(*first, *_last, _num_segments, _mem_size);
|
||||
}
|
||||
|
||||
_first = nullptr;
|
||||
@ -192,16 +192,16 @@ void G1SegmentedArray::drop_all() {
|
||||
_num_allocated_slots = 0;
|
||||
}
|
||||
|
||||
void* G1SegmentedArray::allocate() {
|
||||
void* G1MonotonicArena::allocate() {
|
||||
assert(slot_size() > 0, "instance size not set.");
|
||||
|
||||
G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first);
|
||||
Segment* cur = Atomic::load_acquire(&_first);
|
||||
if (cur == nullptr) {
|
||||
cur = create_new_segment(cur);
|
||||
cur = new_segment(cur);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
void* slot = cur->get_new_slot();
|
||||
void* slot = cur->allocate_slot();
|
||||
if (slot != nullptr) {
|
||||
Atomic::inc(&_num_allocated_slots, memory_order_relaxed);
|
||||
guarantee(is_aligned(slot, _alloc_options->slot_alignment()),
|
||||
@ -210,11 +210,11 @@ void* G1SegmentedArray::allocate() {
|
||||
}
|
||||
// The segment is full. Next round.
|
||||
assert(cur->is_full(), "must be");
|
||||
cur = create_new_segment(cur);
|
||||
cur = new_segment(cur);
|
||||
}
|
||||
}
|
||||
|
||||
uint G1SegmentedArray::num_segments() const {
|
||||
uint G1MonotonicArena::num_segments() const {
|
||||
return Atomic::load(&_num_segments);
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ class LengthClosure {
|
||||
uint _total;
|
||||
public:
|
||||
LengthClosure() : _total(0) {}
|
||||
void do_segment(G1SegmentedArraySegment* segment, uint limit) {
|
||||
void do_segment(G1MonotonicArena::Segment* segment, uint limit) {
|
||||
_total += limit;
|
||||
}
|
||||
uint length() const {
|
||||
@ -231,7 +231,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
uint G1SegmentedArray::calculate_length() const {
|
||||
uint G1MonotonicArena::calculate_length() const {
|
||||
LengthClosure closure;
|
||||
iterate_segments(closure);
|
||||
return closure.length();
|
||||
@ -239,8 +239,8 @@ uint G1SegmentedArray::calculate_length() const {
|
||||
#endif
|
||||
|
||||
template <typename SegmentClosure>
|
||||
void G1SegmentedArray::iterate_segments(SegmentClosure& closure) const {
|
||||
G1SegmentedArraySegment* cur = Atomic::load_acquire(&_first);
|
||||
void G1MonotonicArena::iterate_segments(SegmentClosure& closure) const {
|
||||
Segment* cur = Atomic::load_acquire(&_first);
|
||||
|
||||
assert((cur != nullptr) == (_last != nullptr),
|
||||
"If there is at least one segment, there must be a last one");
|
@ -23,20 +23,99 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1SEGMENTEDARRAY_HPP
|
||||
#define SHARE_GC_G1_G1SEGMENTEDARRAY_HPP
|
||||
#ifndef SHARE_GC_G1_G1MONOTONICARENA_HPP
|
||||
#define SHARE_GC_G1_G1MONOTONICARENA_HPP
|
||||
|
||||
#include "gc/shared/freeListAllocator.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/lockFreeStack.hpp"
|
||||
|
||||
// A G1MonotonicArena extends the FreeListConfig, memory
|
||||
// blocks allocated from the OS are managed as a linked-list of Segments.
|
||||
//
|
||||
// Implementation details as below:
|
||||
//
|
||||
// Allocation arena for (card set, or ...) heap memory objects (Slot slots).
|
||||
//
|
||||
// Actual allocation from the C heap occurs as memory blocks called Segments.
|
||||
// The allocation pattern for these Segments is assumed to be strictly two-phased:
|
||||
//
|
||||
// - in the first phase, Segments are allocated from the C heap (or a free
|
||||
// list given at initialization time). This allocation may occur in parallel. This
|
||||
// typically corresponds to a single mutator phase, but may extend over multiple.
|
||||
//
|
||||
// - in the second phase, Segments are added in bulk to the free list.
|
||||
// This is typically done during a GC pause.
|
||||
//
|
||||
// Some third party is responsible for giving back memory from the free list to
|
||||
// the operating system.
|
||||
//
|
||||
// Allocation and deallocation in the first phase basis may occur by multiple threads concurrently.
|
||||
//
|
||||
// The class also manages a few counters for statistics using atomic operations.
|
||||
// Their values are only consistent within each other with extra global
|
||||
// synchronization.
|
||||
class G1MonotonicArena : public FreeListConfig {
|
||||
public:
|
||||
class AllocOptions;
|
||||
class Segment;
|
||||
class SegmentFreeList;
|
||||
private:
|
||||
// AllocOptions provides parameters for Segment sizing and expansion.
|
||||
const AllocOptions* _alloc_options;
|
||||
|
||||
Segment* volatile _first; // The (start of the) list of all segments.
|
||||
Segment* _last; // The last segment of the list of all segments.
|
||||
volatile uint _num_segments; // Number of assigned segments to this allocator.
|
||||
volatile size_t _mem_size; // Memory used by all segments.
|
||||
|
||||
SegmentFreeList* _segment_free_list; // The global free segment list to preferentially
|
||||
// get new segments from.
|
||||
|
||||
volatile uint _num_total_slots; // Number of slots available in all segments (allocated + not yet used).
|
||||
volatile uint _num_allocated_slots; // Number of total slots allocated ever (including free and pending).
|
||||
|
||||
inline Segment* new_segment(Segment* const prev);
|
||||
|
||||
DEBUG_ONLY(uint calculate_length() const;)
|
||||
|
||||
public:
|
||||
const Segment* first_segment() const { return Atomic::load(&_first); }
|
||||
|
||||
uint num_total_slots() const { return Atomic::load(&_num_total_slots); }
|
||||
uint num_allocated_slots() const {
|
||||
uint allocated = Atomic::load(&_num_allocated_slots);
|
||||
assert(calculate_length() == allocated, "Must be");
|
||||
return allocated;
|
||||
}
|
||||
|
||||
uint slot_size() const;
|
||||
|
||||
G1MonotonicArena(const AllocOptions* alloc_options,
|
||||
SegmentFreeList* segment_free_list);
|
||||
~G1MonotonicArena();
|
||||
|
||||
// Deallocate all segments to the free segment list and reset this allocator. Must
|
||||
// be called in a globally synchronized area.
|
||||
void drop_all();
|
||||
|
||||
uint num_segments() const;
|
||||
|
||||
template<typename SegmentClosure>
|
||||
void iterate_segments(SegmentClosure& closure) const;
|
||||
protected:
|
||||
void* allocate() override;
|
||||
// We do not deallocate individual slots
|
||||
void deallocate(void* slot) override { ShouldNotReachHere(); }
|
||||
};
|
||||
|
||||
// A single segment/arena containing _num_slots blocks of memory of _slot_size.
|
||||
// G1SegmentedArraySegments can be linked together using a singly linked list.
|
||||
class G1SegmentedArraySegment {
|
||||
// Segments can be linked together using a singly linked list.
|
||||
class G1MonotonicArena::Segment {
|
||||
const uint _slot_size;
|
||||
const uint _num_slots;
|
||||
G1SegmentedArraySegment* volatile _next;
|
||||
Segment* volatile _next;
|
||||
// Index into the next free slot to allocate into. Full if equal (or larger)
|
||||
// to _num_slots (can be larger because we atomically increment this value and
|
||||
// check only afterwards if the allocation has been successful).
|
||||
@ -46,7 +125,7 @@ class G1SegmentedArraySegment {
|
||||
char* _bottom; // Actual data.
|
||||
// Do not add class member variables beyond this point
|
||||
|
||||
static size_t header_size() { return align_up(sizeof(G1SegmentedArraySegment), DEFAULT_CACHE_LINE_SIZE); }
|
||||
static size_t header_size() { return align_up(sizeof(Segment), DEFAULT_CACHE_LINE_SIZE); }
|
||||
|
||||
static size_t payload_size(uint slot_size, uint num_slots) {
|
||||
// The cast (size_t) is required to guard against overflow wrap around.
|
||||
@ -55,25 +134,25 @@ class G1SegmentedArraySegment {
|
||||
|
||||
size_t payload_size() const { return payload_size(_slot_size, _num_slots); }
|
||||
|
||||
NONCOPYABLE(G1SegmentedArraySegment);
|
||||
NONCOPYABLE(Segment);
|
||||
|
||||
G1SegmentedArraySegment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next, MEMFLAGS flag);
|
||||
~G1SegmentedArraySegment() = default;
|
||||
Segment(uint slot_size, uint num_slots, Segment* next, MEMFLAGS flag);
|
||||
~Segment() = default;
|
||||
public:
|
||||
G1SegmentedArraySegment* volatile* next_addr() { return &_next; }
|
||||
Segment* volatile* next_addr() { return &_next; }
|
||||
|
||||
void* get_new_slot();
|
||||
void* allocate_slot();
|
||||
|
||||
uint num_slots() const { return _num_slots; }
|
||||
|
||||
G1SegmentedArraySegment* next() const { return _next; }
|
||||
Segment* next() const { return _next; }
|
||||
|
||||
void set_next(G1SegmentedArraySegment* next) {
|
||||
void set_next(Segment* next) {
|
||||
assert(next != this, " loop condition");
|
||||
_next = next;
|
||||
}
|
||||
|
||||
void reset(G1SegmentedArraySegment* next) {
|
||||
void reset(Segment* next) {
|
||||
_next_allocate = 0;
|
||||
assert(next != this, " loop condition");
|
||||
set_next(next);
|
||||
@ -94,10 +173,10 @@ public:
|
||||
return header_size() + payload_size(slot_size, num_slots);
|
||||
}
|
||||
|
||||
static G1SegmentedArraySegment* create_segment(uint slot_size, uint num_slots, G1SegmentedArraySegment* next, MEMFLAGS mem_flag);
|
||||
static void delete_segment(G1SegmentedArraySegment* segment);
|
||||
static Segment* create_segment(uint slot_size, uint num_slots, Segment* next, MEMFLAGS mem_flag);
|
||||
static void delete_segment(Segment* segment);
|
||||
|
||||
// Copies the (valid) contents of this segment into the destination.
|
||||
// Copies the contents of this segment into the destination.
|
||||
void copy_to(void* dest) const {
|
||||
::memcpy(dest, _bottom, length() * _slot_size);
|
||||
}
|
||||
@ -105,15 +184,16 @@ public:
|
||||
bool is_full() const { return _next_allocate >= _num_slots; }
|
||||
};
|
||||
|
||||
// Set of (free) G1SegmentedArraySegments. The assumed usage is that allocation
|
||||
|
||||
// Set of (free) Segments. The assumed usage is that allocation
|
||||
// to it and removal of segments is strictly separate, but every action may be
|
||||
// performed by multiple threads at the same time.
|
||||
// performed by multiple threads concurrently.
|
||||
// Counts and memory usage are current on a best-effort basis if accessed concurrently.
|
||||
class G1SegmentedArrayFreeList {
|
||||
static G1SegmentedArraySegment* volatile* next_ptr(G1SegmentedArraySegment& segment) {
|
||||
class G1MonotonicArena::SegmentFreeList {
|
||||
static Segment* volatile* next_ptr(Segment& segment) {
|
||||
return segment.next_addr();
|
||||
}
|
||||
using SegmentStack = LockFreeStack<G1SegmentedArraySegment, &G1SegmentedArrayFreeList::next_ptr>;
|
||||
using SegmentStack = LockFreeStack<Segment, &SegmentFreeList::next_ptr>;
|
||||
|
||||
SegmentStack _list;
|
||||
|
||||
@ -121,13 +201,13 @@ class G1SegmentedArrayFreeList {
|
||||
volatile size_t _mem_size;
|
||||
|
||||
public:
|
||||
G1SegmentedArrayFreeList() : _list(), _num_segments(0), _mem_size(0) { }
|
||||
~G1SegmentedArrayFreeList() { free_all(); }
|
||||
SegmentFreeList() : _list(), _num_segments(0), _mem_size(0) { }
|
||||
~SegmentFreeList() { free_all(); }
|
||||
|
||||
void bulk_add(G1SegmentedArraySegment& first, G1SegmentedArraySegment& last, size_t num, size_t mem_size);
|
||||
void bulk_add(Segment& first, Segment& last, size_t num, size_t mem_size);
|
||||
|
||||
G1SegmentedArraySegment* get();
|
||||
G1SegmentedArraySegment* get_all(size_t& num_segments, size_t& mem_size);
|
||||
Segment* get();
|
||||
Segment* get_all(size_t& num_segments, size_t& mem_size);
|
||||
|
||||
// Give back all memory to the OS.
|
||||
void free_all();
|
||||
@ -138,8 +218,8 @@ public:
|
||||
size_t mem_size() const { return Atomic::load(&_mem_size); }
|
||||
};
|
||||
|
||||
// Configuration for G1SegmentedArray, e.g slot size, slot number of next G1SegmentedArraySegment.
|
||||
class G1SegmentedArrayAllocOptions {
|
||||
// Configuration for G1MonotonicArena, e.g slot size, slot number of next Segment.
|
||||
class G1MonotonicArena::AllocOptions {
|
||||
|
||||
protected:
|
||||
const MEMFLAGS _mem_flag;
|
||||
@ -150,7 +230,7 @@ protected:
|
||||
const uint _slot_alignment;
|
||||
|
||||
public:
|
||||
G1SegmentedArrayAllocOptions(MEMFLAGS mem_flag, uint slot_size, uint initial_num_slots, uint max_num_slots, uint alignment) :
|
||||
AllocOptions(MEMFLAGS mem_flag, uint slot_size, uint initial_num_slots, uint max_num_slots, uint alignment) :
|
||||
_mem_flag(mem_flag),
|
||||
_slot_size(align_up(slot_size, alignment)),
|
||||
_initial_num_slots(initial_num_slots),
|
||||
@ -173,85 +253,4 @@ public:
|
||||
MEMFLAGS mem_flag() const {return _mem_flag; }
|
||||
};
|
||||
|
||||
// A segmented array where G1SegmentedArraySegment is the segment, and
|
||||
// G1SegmentedArrayFreeList is the free list to cache G1SegmentedArraySegments,
|
||||
// and G1SegmentedArrayAllocOptions is the configuration for G1SegmentedArray
|
||||
// attributes.
|
||||
//
|
||||
// Implementation details as below:
|
||||
//
|
||||
// Arena-like allocator for (card set, or ...) heap memory objects (Slot slots).
|
||||
//
|
||||
// Actual allocation from the C heap occurs on G1SegmentedArraySegment basis, i.e. segments
|
||||
// of slots. The assumed allocation pattern for these G1SegmentedArraySegment slots
|
||||
// is assumed to be strictly two-phased:
|
||||
//
|
||||
// - in the first phase, G1SegmentedArraySegments are allocated from the C heap (or a free
|
||||
// list given at initialization time). This allocation may occur in parallel. This
|
||||
// typically corresponds to a single mutator phase, but may extend over multiple.
|
||||
//
|
||||
// - in the second phase, G1SegmentedArraySegments are given back in bulk to the free list.
|
||||
// This is typically done during a GC pause.
|
||||
//
|
||||
// Some third party is responsible for giving back memory from the free list to
|
||||
// the operating system.
|
||||
//
|
||||
// Allocation and deallocation in the first phase basis may occur by multiple threads at once.
|
||||
//
|
||||
// The class also manages a few counters for statistics using atomic operations.
|
||||
// Their values are only consistent within each other with extra global
|
||||
// synchronization.
|
||||
|
||||
class G1SegmentedArray : public FreeListConfig {
|
||||
// G1SegmentedArrayAllocOptions provides parameters for allocation segment
|
||||
// sizing and expansion.
|
||||
const G1SegmentedArrayAllocOptions* _alloc_options;
|
||||
|
||||
G1SegmentedArraySegment* volatile _first; // The (start of the) list of all segments.
|
||||
G1SegmentedArraySegment* _last; // The last segment of the list of all segments.
|
||||
volatile uint _num_segments; // Number of assigned segments to this allocator.
|
||||
volatile size_t _mem_size; // Memory used by all segments.
|
||||
|
||||
G1SegmentedArrayFreeList* _free_segment_list; // The global free segment list to preferentially
|
||||
// get new segments from.
|
||||
|
||||
volatile uint _num_total_slots; // Number of slots available in all segments (allocated + not yet used).
|
||||
volatile uint _num_allocated_slots; // Number of total slots allocated ever (including free and pending).
|
||||
|
||||
private:
|
||||
inline G1SegmentedArraySegment* create_new_segment(G1SegmentedArraySegment* const prev);
|
||||
|
||||
DEBUG_ONLY(uint calculate_length() const;)
|
||||
|
||||
public:
|
||||
const G1SegmentedArraySegment* first_array_segment() const { return Atomic::load(&_first); }
|
||||
|
||||
uint num_total_slots() const { return Atomic::load(&_num_total_slots); }
|
||||
uint num_allocated_slots() const {
|
||||
uint allocated = Atomic::load(&_num_allocated_slots);
|
||||
assert(calculate_length() == allocated, "Must be");
|
||||
return allocated;
|
||||
}
|
||||
|
||||
uint slot_size() const;
|
||||
|
||||
G1SegmentedArray(const G1SegmentedArrayAllocOptions* alloc_options,
|
||||
G1SegmentedArrayFreeList* free_segment_list);
|
||||
~G1SegmentedArray();
|
||||
|
||||
// Deallocate all segments to the free segment list and reset this allocator. Must
|
||||
// be called in a globally synchronized area.
|
||||
void drop_all();
|
||||
|
||||
inline void* allocate() override;
|
||||
|
||||
// We do not deallocate individual slots
|
||||
inline void deallocate(void* node) override { ShouldNotReachHere(); }
|
||||
|
||||
uint num_segments() const;
|
||||
|
||||
template<typename SegmentClosure>
|
||||
void iterate_segments(SegmentClosure& closure) const;
|
||||
};
|
||||
|
||||
#endif //SHARE_GC_G1_G1SEGMENTEDARRAY_HPP
|
||||
#endif //SHARE_GC_G1_MONOTONICARENA_HPP
|
@ -23,14 +23,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1SEGMENTEDARRAY_INLINE_HPP
|
||||
#define SHARE_GC_G1_G1SEGMENTEDARRAY_INLINE_HPP
|
||||
#ifndef SHARE_GC_G1_G1MONOTONICARENA_INLINE_HPP
|
||||
#define SHARE_GC_G1_G1MONOTONICARENA_INLINE_HPP
|
||||
|
||||
#include "gc/g1/g1SegmentedArray.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/globalCounter.inline.hpp"
|
||||
|
||||
inline void* G1SegmentedArraySegment::get_new_slot() {
|
||||
inline void* G1MonotonicArena::Segment::allocate_slot() {
|
||||
if (_next_allocate >= _num_slots) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -42,10 +42,10 @@ inline void* G1SegmentedArraySegment::get_new_slot() {
|
||||
return r;
|
||||
}
|
||||
|
||||
inline G1SegmentedArraySegment* G1SegmentedArrayFreeList::get() {
|
||||
inline G1MonotonicArena::Segment* G1MonotonicArena::SegmentFreeList::get() {
|
||||
GlobalCounter::CriticalSection cs(Thread::current());
|
||||
|
||||
G1SegmentedArraySegment* result = _list.pop();
|
||||
Segment* result = _list.pop();
|
||||
if (result != nullptr) {
|
||||
Atomic::dec(&_num_segments, memory_order_relaxed);
|
||||
Atomic::sub(&_mem_size, result->mem_size(), memory_order_relaxed);
|
||||
@ -53,4 +53,4 @@ inline G1SegmentedArraySegment* G1SegmentedArrayFreeList::get() {
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif //SHARE_GC_G1_G1SEGMENTEDARRAY_INLINE_HPP
|
||||
#endif //SHARE_GC_G1_G1MONOTONICARENA_INLINE_HPP
|
@ -26,7 +26,7 @@
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "gc/g1/g1CardSetMemory.inline.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.hpp"
|
||||
#include "gc/g1/g1SegmentedArrayFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1_globals.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
@ -34,13 +34,13 @@
|
||||
#include "gc/shared/suspendibleThreadSet.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
constexpr const char* G1SegmentedArrayFreeMemoryTask::_state_names[];
|
||||
constexpr const char* G1MonotonicArenaFreeMemoryTask::_state_names[];
|
||||
|
||||
const char* G1SegmentedArrayFreeMemoryTask::get_state_name(State value) const {
|
||||
const char* G1MonotonicArenaFreeMemoryTask::get_state_name(State value) const {
|
||||
return _state_names[static_cast<std::underlying_type_t<State>>(value)];
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::deadline_exceeded(jlong deadline) {
|
||||
bool G1MonotonicArenaFreeMemoryTask::deadline_exceeded(jlong deadline) {
|
||||
return os::elapsed_counter() >= deadline;
|
||||
}
|
||||
|
||||
@ -49,18 +49,18 @@ static size_t keep_size(size_t free, size_t used, double percent) {
|
||||
return MIN2(free, to_keep);
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::calculate_return_infos(jlong deadline) {
|
||||
bool G1MonotonicArenaFreeMemoryTask::calculate_return_infos(jlong deadline) {
|
||||
// Ignore the deadline in this step as it is very short.
|
||||
|
||||
G1SegmentedArrayMemoryStats used = _total_used;
|
||||
G1SegmentedArrayMemoryStats free = G1SegmentedArrayFreePool::free_list_sizes();
|
||||
G1MonotonicArenaMemoryStats used = _total_used;
|
||||
G1MonotonicArenaMemoryStats free = G1MonotonicArenaFreePool::free_list_sizes();
|
||||
|
||||
_return_info = new G1ReturnMemoryProcessorSet(used.num_pools());
|
||||
for (uint i = 0; i < used.num_pools(); i++) {
|
||||
size_t return_to_vm_size = keep_size(free._num_mem_sizes[i],
|
||||
used._num_mem_sizes[i],
|
||||
G1RemSetFreeMemoryKeepExcessRatio);
|
||||
log_trace(gc, task)("Segmented Array Free Memory: Type %s: Free: %zu (%zu) "
|
||||
log_trace(gc, task)("Monotonic Arena Free Memory: Type %s: Free: %zu (%zu) "
|
||||
"Used: %zu Keep: %zu",
|
||||
G1CardSetConfiguration::mem_object_type_name_str(i),
|
||||
free._num_mem_sizes[i], free._num_segments[i],
|
||||
@ -69,11 +69,11 @@ bool G1SegmentedArrayFreeMemoryTask::calculate_return_infos(jlong deadline) {
|
||||
_return_info->append(new G1ReturnMemoryProcessor(return_to_vm_size));
|
||||
}
|
||||
|
||||
G1SegmentedArrayFreePool::update_unlink_processors(_return_info);
|
||||
G1MonotonicArenaFreePool::update_unlink_processors(_return_info);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::return_memory_to_vm(jlong deadline) {
|
||||
bool G1MonotonicArenaFreeMemoryTask::return_memory_to_vm(jlong deadline) {
|
||||
for (int i = 0; i < _return_info->length(); i++) {
|
||||
G1ReturnMemoryProcessor* info = _return_info->at(i);
|
||||
if (!info->finished_return_to_vm()) {
|
||||
@ -85,7 +85,7 @@ bool G1SegmentedArrayFreeMemoryTask::return_memory_to_vm(jlong deadline) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::return_memory_to_os(jlong deadline) {
|
||||
bool G1MonotonicArenaFreeMemoryTask::return_memory_to_os(jlong deadline) {
|
||||
for (int i = 0; i < _return_info->length(); i++) {
|
||||
G1ReturnMemoryProcessor* info = _return_info->at(i);
|
||||
if (!info->finished_return_to_os()) {
|
||||
@ -97,7 +97,7 @@ bool G1SegmentedArrayFreeMemoryTask::return_memory_to_os(jlong deadline) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::cleanup_return_infos() {
|
||||
bool G1MonotonicArenaFreeMemoryTask::cleanup_return_infos() {
|
||||
for (int i = 0; i < _return_info->length(); i++) {
|
||||
G1ReturnMemoryProcessor* info = _return_info->at(i);
|
||||
delete info;
|
||||
@ -108,12 +108,12 @@ bool G1SegmentedArrayFreeMemoryTask::cleanup_return_infos() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::free_excess_segmented_array_memory() {
|
||||
bool G1MonotonicArenaFreeMemoryTask::free_excess_arena_memory() {
|
||||
jlong start = os::elapsed_counter();
|
||||
jlong end = start +
|
||||
(os::elapsed_frequency() / 1000) * G1RemSetFreeMemoryStepDurationMillis;
|
||||
|
||||
log_trace(gc, task)("Segmented Array Free Memory: Step start %1.3f end %1.3f",
|
||||
log_trace(gc, task)("Monotonic Arena Free Memory: Step start %1.3f end %1.3f",
|
||||
TimeHelper::counter_to_millis(start), TimeHelper::counter_to_millis(end));
|
||||
|
||||
State next_state;
|
||||
@ -150,7 +150,7 @@ bool G1SegmentedArrayFreeMemoryTask::free_excess_segmented_array_memory() {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
log_error(gc, task)("Should not try to free excess segmented array memory in %s state", get_state_name(_state));
|
||||
log_error(gc, task)("Should not try to free excess monotonic area memory in %s state", get_state_name(_state));
|
||||
ShouldNotReachHere();
|
||||
break;
|
||||
}
|
||||
@ -158,41 +158,41 @@ bool G1SegmentedArrayFreeMemoryTask::free_excess_segmented_array_memory() {
|
||||
set_state(next_state);
|
||||
} while (_state != State::Inactive && !deadline_exceeded(end));
|
||||
|
||||
log_trace(gc, task)("Segmented Array Free Memory: Step took %1.3fms, done %s",
|
||||
log_trace(gc, task)("Monotonic Arena Free Memory: Step took %1.3fms, done %s",
|
||||
TimeHelper::counter_to_millis(os::elapsed_counter() - start),
|
||||
bool_to_str(_state == State::CalculateUsed));
|
||||
|
||||
return is_active();
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreeMemoryTask::set_state(State new_state) {
|
||||
log_trace(gc, task)("Segmented Array Free Memory: State change from %s to %s",
|
||||
void G1MonotonicArenaFreeMemoryTask::set_state(State new_state) {
|
||||
log_trace(gc, task)("Monotonic Arena Free Memory: State change from %s to %s",
|
||||
get_state_name(_state),
|
||||
get_state_name(new_state));
|
||||
_state = new_state;
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreeMemoryTask::is_active() const {
|
||||
bool G1MonotonicArenaFreeMemoryTask::is_active() const {
|
||||
return _state != State::Inactive;
|
||||
}
|
||||
|
||||
jlong G1SegmentedArrayFreeMemoryTask::reschedule_delay_ms() const {
|
||||
jlong G1MonotonicArenaFreeMemoryTask::reschedule_delay_ms() const {
|
||||
return G1RemSetFreeMemoryRescheduleDelayMillis;
|
||||
}
|
||||
|
||||
G1SegmentedArrayFreeMemoryTask::G1SegmentedArrayFreeMemoryTask(const char* name) :
|
||||
G1MonotonicArenaFreeMemoryTask::G1MonotonicArenaFreeMemoryTask(const char* name) :
|
||||
G1ServiceTask(name), _state(State::CalculateUsed), _return_info(nullptr) { }
|
||||
|
||||
void G1SegmentedArrayFreeMemoryTask::execute() {
|
||||
void G1MonotonicArenaFreeMemoryTask::execute() {
|
||||
SuspendibleThreadSetJoiner sts;
|
||||
|
||||
if (free_excess_segmented_array_memory()) {
|
||||
if (free_excess_arena_memory()) {
|
||||
schedule(reschedule_delay_ms());
|
||||
}
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreeMemoryTask::notify_new_stats(G1SegmentedArrayMemoryStats* young_gen_stats,
|
||||
G1SegmentedArrayMemoryStats* collection_set_candidate_stats) {
|
||||
void G1MonotonicArenaFreeMemoryTask::notify_new_stats(G1MonotonicArenaMemoryStats* young_gen_stats,
|
||||
G1MonotonicArenaMemoryStats* collection_set_candidate_stats) {
|
||||
assert_at_safepoint_on_vm_thread();
|
||||
|
||||
_total_used = *young_gen_stats;
|
@ -22,18 +22,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1SEGMENTEDARRAYFREEMEMORYTASK_HPP
|
||||
#define SHARE_GC_G1_G1SEGMENTEDARRAYFREEMEMORYTASK_HPP
|
||||
#ifndef SHARE_GC_G1_G1MONOTONICARENAFREEMEMORYTASK_HPP
|
||||
#define SHARE_GC_G1_G1MONOTONICARENAFREEMEMORYTASK_HPP
|
||||
|
||||
#include "gc/g1/g1CardSetMemory.hpp"
|
||||
#include "gc/g1/g1SegmentedArrayFreePool.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreePool.hpp"
|
||||
#include "gc/g1/g1ServiceThread.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
// Task handling deallocation of free segmented array memory.
|
||||
class G1SegmentedArrayFreeMemoryTask : public G1ServiceTask {
|
||||
// Task handling deallocation of free G1MonotonicArena memory.
|
||||
class G1MonotonicArenaFreeMemoryTask : public G1ServiceTask {
|
||||
|
||||
enum class State : uint {
|
||||
Inactive,
|
||||
@ -53,11 +53,11 @@ class G1SegmentedArrayFreeMemoryTask : public G1ServiceTask {
|
||||
|
||||
State _state;
|
||||
|
||||
// Current total segmented array memory usage.
|
||||
G1SegmentedArrayMemoryStats _total_used;
|
||||
// Current total monotonic arena memory usage.
|
||||
G1MonotonicArenaMemoryStats _total_used;
|
||||
|
||||
using G1ReturnMemoryProcessor = G1SegmentedArrayFreePool::G1ReturnMemoryProcessor;
|
||||
using G1ReturnMemoryProcessorSet = G1SegmentedArrayFreePool::G1ReturnMemoryProcessorSet;
|
||||
using G1ReturnMemoryProcessor = G1MonotonicArenaFreePool::G1ReturnMemoryProcessor;
|
||||
using G1ReturnMemoryProcessorSet = G1MonotonicArenaFreePool::G1ReturnMemoryProcessorSet;
|
||||
|
||||
G1ReturnMemoryProcessorSet* _return_info;
|
||||
|
||||
@ -71,9 +71,9 @@ class G1SegmentedArrayFreeMemoryTask : public G1ServiceTask {
|
||||
bool return_memory_to_os(jlong deadline);
|
||||
bool cleanup_return_infos();
|
||||
|
||||
// Free excess segmented array memory, main method. Returns true if there is more work
|
||||
// Free excess monotonic arena memory, main method. Returns true if there is more work
|
||||
// to do.
|
||||
bool free_excess_segmented_array_memory();
|
||||
bool free_excess_arena_memory();
|
||||
|
||||
void set_state(State new_state);
|
||||
// Returns whether we are currently processing a recent request.
|
||||
@ -83,14 +83,14 @@ class G1SegmentedArrayFreeMemoryTask : public G1ServiceTask {
|
||||
jlong reschedule_delay_ms() const;
|
||||
|
||||
public:
|
||||
explicit G1SegmentedArrayFreeMemoryTask(const char* name);
|
||||
explicit G1MonotonicArenaFreeMemoryTask(const char* name);
|
||||
|
||||
void execute() override;
|
||||
|
||||
// Notify the task of new used remembered set memory statistics for the young
|
||||
// generation and the collection set candidate sets.
|
||||
void notify_new_stats(G1SegmentedArrayMemoryStats* young_gen_stats,
|
||||
G1SegmentedArrayMemoryStats* collection_set_candidate_stats);
|
||||
void notify_new_stats(G1MonotonicArenaMemoryStats* young_gen_stats,
|
||||
G1MonotonicArenaMemoryStats* collection_set_candidate_stats);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1SEGMENTEDARRAYFREEMEMORYTASK_HPP
|
||||
#endif // SHARE_GC_G1_G1MONOTONICARENAFREEMEMORYTASK_HPP
|
@ -24,26 +24,26 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1SegmentedArrayFreePool.hpp"
|
||||
#include "gc/g1/g1SegmentedArray.inline.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.inline.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreePool.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "utilities/formatBuffer.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
G1SegmentedArrayMemoryStats::G1SegmentedArrayMemoryStats() {
|
||||
G1MonotonicArenaMemoryStats::G1MonotonicArenaMemoryStats() {
|
||||
clear();
|
||||
}
|
||||
|
||||
void G1SegmentedArrayMemoryStats::clear() {
|
||||
void G1MonotonicArenaMemoryStats::clear() {
|
||||
for (uint i = 0; i < num_pools(); i++) {
|
||||
_num_mem_sizes[i] = 0;
|
||||
_num_segments[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) {
|
||||
void G1MonotonicArenaFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) {
|
||||
uint num_free_lists = _freelist_pool.num_free_lists();
|
||||
|
||||
for (uint i = 0; i < num_free_lists; i++) {
|
||||
@ -51,7 +51,7 @@ void G1SegmentedArrayFreePool::update_unlink_processors(G1ReturnMemoryProcessorS
|
||||
}
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::visit_free_list(G1SegmentedArrayFreeList* source) {
|
||||
void G1MonotonicArenaFreePool::G1ReturnMemoryProcessor::visit_free_list(G1MonotonicArena::SegmentFreeList* source) {
|
||||
assert(_source == nullptr, "already visited");
|
||||
if (_return_to_vm_size > 0) {
|
||||
_source = source;
|
||||
@ -73,15 +73,15 @@ void G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::visit_free_list(G1Segmen
|
||||
}
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) {
|
||||
bool G1MonotonicArenaFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadline) {
|
||||
assert(!finished_return_to_vm(), "already returned everything to the VM");
|
||||
assert(_first != nullptr, "must have segment to return");
|
||||
|
||||
size_t keep_size = 0;
|
||||
size_t keep_num = 0;
|
||||
|
||||
G1SegmentedArraySegment* cur = _first;
|
||||
G1SegmentedArraySegment* last = nullptr;
|
||||
Segment* cur = _first;
|
||||
Segment* last = nullptr;
|
||||
|
||||
while (cur != nullptr && _return_to_vm_size > 0) {
|
||||
size_t cur_size = cur->mem_size();
|
||||
@ -108,7 +108,7 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadl
|
||||
_source->bulk_add(*_first, *last, keep_num, keep_size);
|
||||
_first = cur;
|
||||
|
||||
log_trace(gc, task)("Segmented Array Free Memory: Returned to VM %zu segments size %zu", keep_num, keep_size);
|
||||
log_trace(gc, task)("Monotonic Arena Free Memory: Returned to VM %zu segments size %zu", keep_num, keep_size);
|
||||
|
||||
// _return_to_vm_size may be larger than what is available in the list at the
|
||||
// time we actually get the list. I.e. the list and _return_to_vm_size may be
|
||||
@ -122,7 +122,7 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_vm(jlong deadl
|
||||
return _source != nullptr;
|
||||
}
|
||||
|
||||
bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) {
|
||||
bool G1MonotonicArenaFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadline) {
|
||||
assert(finished_return_to_vm(), "not finished returning to VM");
|
||||
assert(!finished_return_to_os(), "already returned everything to the OS");
|
||||
|
||||
@ -131,10 +131,10 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadl
|
||||
size_t mem_size_deleted = 0;
|
||||
|
||||
while (_first != nullptr) {
|
||||
G1SegmentedArraySegment* next = _first->next();
|
||||
Segment* next = _first->next();
|
||||
num_delete++;
|
||||
mem_size_deleted += _first->mem_size();
|
||||
G1SegmentedArraySegment::delete_segment(_first);
|
||||
Segment::delete_segment(_first);
|
||||
_first = next;
|
||||
|
||||
// To ensure progress, perform the deadline check here.
|
||||
@ -143,31 +143,31 @@ bool G1SegmentedArrayFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadl
|
||||
}
|
||||
}
|
||||
|
||||
log_trace(gc, task)("Segmented Array Free Memory: Return to OS %zu segments size %zu", num_delete, mem_size_deleted);
|
||||
log_trace(gc, task)("Monotonic Arena Free Memory: Return to OS %zu segments size %zu", num_delete, mem_size_deleted);
|
||||
|
||||
return _first != nullptr;
|
||||
}
|
||||
|
||||
G1SegmentedArrayFreePool G1SegmentedArrayFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types());
|
||||
G1MonotonicArenaFreePool G1MonotonicArenaFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types());
|
||||
|
||||
G1SegmentedArrayFreePool::G1SegmentedArrayFreePool(uint num_free_lists) :
|
||||
G1MonotonicArenaFreePool::G1MonotonicArenaFreePool(uint num_free_lists) :
|
||||
_num_free_lists(num_free_lists) {
|
||||
|
||||
_free_lists = NEW_C_HEAP_ARRAY(G1SegmentedArrayFreeList, _num_free_lists, mtGC);
|
||||
_free_lists = NEW_C_HEAP_ARRAY(SegmentFreeList, _num_free_lists, mtGC);
|
||||
for (uint i = 0; i < _num_free_lists; i++) {
|
||||
new (&_free_lists[i]) G1SegmentedArrayFreeList();
|
||||
new (&_free_lists[i]) SegmentFreeList();
|
||||
}
|
||||
}
|
||||
|
||||
G1SegmentedArrayFreePool::~G1SegmentedArrayFreePool() {
|
||||
G1MonotonicArenaFreePool::~G1MonotonicArenaFreePool() {
|
||||
for (uint i = 0; i < _num_free_lists; i++) {
|
||||
_free_lists[i].~G1SegmentedArrayFreeList();
|
||||
_free_lists[i].~SegmentFreeList();
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(mtGC, _free_lists);
|
||||
}
|
||||
|
||||
G1SegmentedArrayMemoryStats G1SegmentedArrayFreePool::memory_sizes() const {
|
||||
G1SegmentedArrayMemoryStats free_list_stats;
|
||||
G1MonotonicArenaMemoryStats G1MonotonicArenaFreePool::memory_sizes() const {
|
||||
G1MonotonicArenaMemoryStats free_list_stats;
|
||||
assert(free_list_stats.num_pools() == num_free_lists(), "must be");
|
||||
for (uint i = 0; i < num_free_lists(); i++) {
|
||||
free_list_stats._num_mem_sizes[i] = _free_lists[i].mem_size();
|
||||
@ -176,7 +176,7 @@ G1SegmentedArrayMemoryStats G1SegmentedArrayFreePool::memory_sizes() const {
|
||||
return free_list_stats;
|
||||
}
|
||||
|
||||
size_t G1SegmentedArrayFreePool::mem_size() const {
|
||||
size_t G1MonotonicArenaFreePool::mem_size() const {
|
||||
size_t result = 0;
|
||||
for (uint i = 0; i < _num_free_lists; i++) {
|
||||
result += _free_lists[i].mem_size();
|
||||
@ -184,7 +184,7 @@ size_t G1SegmentedArrayFreePool::mem_size() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
void G1SegmentedArrayFreePool::print_on(outputStream* out) {
|
||||
void G1MonotonicArenaFreePool::print_on(outputStream* out) {
|
||||
out->print_cr(" Free Pool: size %zu", free_list_pool()->mem_size());
|
||||
for (uint i = 0; i < _num_free_lists; i++) {
|
||||
FormatBuffer<> fmt(" %s", G1CardSetConfiguration::mem_object_type_name_str(i));
|
@ -22,26 +22,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1SEGMENTEDARRAYFREEPOOL_HPP
|
||||
#define SHARE_GC_G1_G1SEGMENTEDARRAYFREEPOOL_HPP
|
||||
#ifndef SHARE_GC_G1_G1MONOTONICARENAFREEPOOL_HPP
|
||||
#define SHARE_GC_G1_G1MONOTONICARENAFREEPOOL_HPP
|
||||
|
||||
#include "gc/g1/g1CardSet.hpp"
|
||||
#include "gc/g1/g1SegmentedArray.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
||||
// Statistics for a segmented array. Contains the number of segments and memory
|
||||
// Statistics for a monotonic arena. Contains the number of segments and memory
|
||||
// used for each. Note that statistics are typically not taken atomically so there
|
||||
// can be inconsistencies. The user must be prepared for them.
|
||||
class G1SegmentedArrayMemoryStats {
|
||||
class G1MonotonicArenaMemoryStats {
|
||||
public:
|
||||
|
||||
size_t _num_mem_sizes[G1CardSetConfiguration::num_mem_object_types()];
|
||||
size_t _num_segments[G1CardSetConfiguration::num_mem_object_types()];
|
||||
|
||||
// Returns all-zero statistics.
|
||||
G1SegmentedArrayMemoryStats();
|
||||
G1MonotonicArenaMemoryStats();
|
||||
|
||||
void add(G1SegmentedArrayMemoryStats const other) {
|
||||
void add(G1MonotonicArenaMemoryStats const other) {
|
||||
STATIC_ASSERT(ARRAY_SIZE(_num_segments) == ARRAY_SIZE(_num_mem_sizes));
|
||||
for (uint i = 0; i < ARRAY_SIZE(_num_mem_sizes); i++) {
|
||||
_num_mem_sizes[i] += other._num_mem_sizes[i];
|
||||
@ -54,47 +54,50 @@ public:
|
||||
uint num_pools() const { return G1CardSetConfiguration::num_mem_object_types(); }
|
||||
};
|
||||
|
||||
// A set of free lists holding freed segments for use by G1SegmentedArray,
|
||||
// e.g. G1CardSetAllocators::SegmentedArray
|
||||
class G1SegmentedArrayFreePool {
|
||||
// A set of free lists holding freed segments for use by G1MonotonicArena,
|
||||
// e.g. G1CardSetAllocators::_arena
|
||||
class G1MonotonicArenaFreePool {
|
||||
using SegmentFreeList = G1MonotonicArena::SegmentFreeList;
|
||||
// The global free pool.
|
||||
static G1SegmentedArrayFreePool _freelist_pool;
|
||||
static G1MonotonicArenaFreePool _freelist_pool;
|
||||
|
||||
const uint _num_free_lists;
|
||||
G1SegmentedArrayFreeList* _free_lists;
|
||||
SegmentFreeList* _free_lists;
|
||||
|
||||
public:
|
||||
static G1SegmentedArrayFreePool* free_list_pool() { return &_freelist_pool; }
|
||||
static G1SegmentedArrayMemoryStats free_list_sizes() { return _freelist_pool.memory_sizes(); }
|
||||
static G1MonotonicArenaFreePool* free_list_pool() { return &_freelist_pool; }
|
||||
static G1MonotonicArenaMemoryStats free_list_sizes() { return _freelist_pool.memory_sizes(); }
|
||||
|
||||
class G1ReturnMemoryProcessor;
|
||||
typedef GrowableArrayCHeap<G1ReturnMemoryProcessor*, mtGC> G1ReturnMemoryProcessorSet;
|
||||
|
||||
static void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors);
|
||||
|
||||
explicit G1SegmentedArrayFreePool(uint num_free_lists);
|
||||
~G1SegmentedArrayFreePool();
|
||||
explicit G1MonotonicArenaFreePool(uint num_free_lists);
|
||||
~G1MonotonicArenaFreePool();
|
||||
|
||||
G1SegmentedArrayFreeList* free_list(uint i) {
|
||||
SegmentFreeList* free_list(uint i) {
|
||||
assert(i < _num_free_lists, "must be");
|
||||
return &_free_lists[i];
|
||||
}
|
||||
|
||||
uint num_free_lists() const { return _num_free_lists; }
|
||||
|
||||
G1SegmentedArrayMemoryStats memory_sizes() const;
|
||||
G1MonotonicArenaMemoryStats memory_sizes() const;
|
||||
size_t mem_size() const;
|
||||
|
||||
void print_on(outputStream* out);
|
||||
};
|
||||
|
||||
// Data structure containing current in-progress state for returning memory to the
|
||||
// operating system for a single G1SegmentedArrayFreeList.
|
||||
class G1SegmentedArrayFreePool::G1ReturnMemoryProcessor : public CHeapObj<mtGC> {
|
||||
G1SegmentedArrayFreeList* _source;
|
||||
// operating system for a single G1SegmentFreeList.
|
||||
class G1MonotonicArenaFreePool::G1ReturnMemoryProcessor : public CHeapObj<mtGC> {
|
||||
using SegmentFreeList = G1MonotonicArena::SegmentFreeList;
|
||||
using Segment = G1MonotonicArena::Segment;
|
||||
SegmentFreeList* _source;
|
||||
size_t _return_to_vm_size;
|
||||
|
||||
G1SegmentedArraySegment* _first;
|
||||
Segment* _first;
|
||||
size_t _unlinked_bytes;
|
||||
size_t _num_unlinked;
|
||||
|
||||
@ -106,7 +109,7 @@ public:
|
||||
// Updates the instance members about the given free list for
|
||||
// the purpose of giving back memory. Only necessary members are updated,
|
||||
// e.g. if there is nothing to return to the VM, do not set the source list.
|
||||
void visit_free_list(G1SegmentedArrayFreeList* source);
|
||||
void visit_free_list(SegmentFreeList* source);
|
||||
|
||||
bool finished_return_to_vm() const { return _return_to_vm_size == 0; }
|
||||
bool finished_return_to_os() const { return _first == nullptr; }
|
||||
@ -123,4 +126,4 @@ public:
|
||||
bool return_to_os(jlong deadline);
|
||||
};
|
||||
|
||||
#endif //SHARE_GC_G1_G1SEGMENTEDARRAYFREEPOOL_HPP
|
||||
#endif //SHARE_GC_G1_G1MONOTONICARENAFREEPOOL_HPP
|
@ -290,7 +290,7 @@ class G1PrepareEvacuationTask : public WorkerTask {
|
||||
uint _worker_humongous_total;
|
||||
uint _worker_humongous_candidates;
|
||||
|
||||
G1SegmentedArrayMemoryStats _card_set_stats;
|
||||
G1MonotonicArenaMemoryStats _card_set_stats;
|
||||
|
||||
void sample_card_set_size(HeapRegion* hr) {
|
||||
// Sample card set sizes for young gen and humongous before GC: this makes
|
||||
@ -404,7 +404,7 @@ class G1PrepareEvacuationTask : public WorkerTask {
|
||||
return false;
|
||||
}
|
||||
|
||||
G1SegmentedArrayMemoryStats card_set_stats() const {
|
||||
G1MonotonicArenaMemoryStats card_set_stats() const {
|
||||
return _card_set_stats;
|
||||
}
|
||||
};
|
||||
@ -414,7 +414,7 @@ class G1PrepareEvacuationTask : public WorkerTask {
|
||||
volatile uint _humongous_total;
|
||||
volatile uint _humongous_candidates;
|
||||
|
||||
G1SegmentedArrayMemoryStats _all_card_set_stats;
|
||||
G1MonotonicArenaMemoryStats _all_card_set_stats;
|
||||
|
||||
public:
|
||||
G1PrepareEvacuationTask(G1CollectedHeap* g1h) :
|
||||
@ -448,7 +448,7 @@ public:
|
||||
return _humongous_total;
|
||||
}
|
||||
|
||||
const G1SegmentedArrayMemoryStats all_card_set_stats() const {
|
||||
const G1MonotonicArenaMemoryStats all_card_set_stats() const {
|
||||
return _all_card_set_stats;
|
||||
}
|
||||
};
|
||||
|
@ -43,12 +43,12 @@ class G1GCPhaseTimes;
|
||||
class G1HotCardCache;
|
||||
class G1HRPrinter;
|
||||
class G1MonitoringSupport;
|
||||
class G1MonotonicArenaMemoryStats;
|
||||
class G1NewTracer;
|
||||
class G1ParScanThreadStateSet;
|
||||
class G1Policy;
|
||||
class G1RedirtyCardsQueueSet;
|
||||
class G1RemSet;
|
||||
class G1SegmentedArrayMemoryStats;
|
||||
class G1SurvivorRegions;
|
||||
class G1YoungGCEvacFailureInjector;
|
||||
class STWGCTimer;
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
|
||||
class G1SampleCollectionSetCandidatesClosure : public HeapRegionClosure {
|
||||
public:
|
||||
G1SegmentedArrayMemoryStats _total;
|
||||
G1MonotonicArenaMemoryStats _total;
|
||||
|
||||
bool do_heap_region(HeapRegion* r) override {
|
||||
_total.add(r->rem_set()->card_set_memory_stats());
|
||||
|
@ -31,8 +31,8 @@
|
||||
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp"
|
||||
#include "gc/g1/g1MonotonicArena.inline.hpp"
|
||||
#include "gc/g1/g1Predictions.hpp"
|
||||
#include "gc/g1/g1SegmentedArray.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/init.hpp"
|
||||
|
@ -59,7 +59,7 @@ HeapRegionRemSet::HeapRegionRemSet(HeapRegion* hr,
|
||||
G1CardSetConfiguration* config) :
|
||||
_m(Mutex::service - 1, FormatBuffer<128>("HeapRegionRemSet#%u_lock", hr->hrm_index())),
|
||||
_code_roots(),
|
||||
_card_set_mm(config, G1SegmentedArrayFreePool::free_list_pool()),
|
||||
_card_set_mm(config, G1MonotonicArenaFreePool::free_list_pool()),
|
||||
_card_set(config, &_card_set_mm),
|
||||
_hr(hr),
|
||||
_state(Untracked) { }
|
||||
@ -83,7 +83,7 @@ void HeapRegionRemSet::clear_locked(bool only_cardset) {
|
||||
assert(occupied() == 0, "Should be clear.");
|
||||
}
|
||||
|
||||
G1SegmentedArrayMemoryStats HeapRegionRemSet::card_set_memory_stats() const {
|
||||
G1MonotonicArenaMemoryStats HeapRegionRemSet::card_set_memory_stats() const {
|
||||
return _card_set_mm.memory_stats();
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
void clear(bool only_cardset = false);
|
||||
void clear_locked(bool only_cardset = false);
|
||||
|
||||
G1SegmentedArrayMemoryStats card_set_memory_stats() const;
|
||||
G1MonotonicArenaMemoryStats card_set_memory_stats() const;
|
||||
|
||||
// The actual # of bytes this hr_remset takes up. Also includes the code
|
||||
// root set.
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "gc/g1/g1CardSet.inline.hpp"
|
||||
#include "gc/g1/g1CardSetContainers.hpp"
|
||||
#include "gc/g1/g1CardSetMemory.hpp"
|
||||
#include "gc/g1/g1SegmentedArrayFreePool.hpp"
|
||||
#include "gc/g1/g1MonotonicArenaFreePool.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.hpp"
|
||||
#include "gc/shared/gcTraceTime.inline.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
|
Loading…
Reference in New Issue
Block a user