8220588: ZGC: Convert ZRelocationSet to hold ZForwardings instead of ZPages
Reviewed-by: stefank, eosterlund
This commit is contained in:
parent
5a079bf515
commit
0ce7c21d33
@ -45,7 +45,6 @@ static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Co
|
||||
static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
|
||||
static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages");
|
||||
static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set");
|
||||
static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set");
|
||||
static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start");
|
||||
static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");
|
||||
static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
|
||||
@ -317,11 +316,6 @@ void ZDriver::concurrent_select_relocation_set() {
|
||||
ZHeap::heap()->select_relocation_set();
|
||||
}
|
||||
|
||||
void ZDriver::concurrent_prepare_relocation_set() {
|
||||
ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet);
|
||||
ZHeap::heap()->prepare_relocation_set();
|
||||
}
|
||||
|
||||
void ZDriver::pause_relocate_start() {
|
||||
pause<VM_ZRelocateStart>();
|
||||
}
|
||||
@ -393,13 +387,10 @@ void ZDriver::gc(GCCause::Cause cause) {
|
||||
// Phase 8: Concurrent Select Relocation Set
|
||||
concurrent_select_relocation_set();
|
||||
|
||||
// Phase 9: Concurrent Prepare Relocation Set
|
||||
concurrent_prepare_relocation_set();
|
||||
|
||||
// Phase 10: Pause Relocate Start
|
||||
// Phase 9: Pause Relocate Start
|
||||
pause_relocate_start();
|
||||
|
||||
// Phase 11: Concurrent Relocate
|
||||
// Phase 10: Concurrent Relocate
|
||||
concurrent_relocate();
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ private:
|
||||
void concurrent_destroy_detached_pages();
|
||||
void pause_verify();
|
||||
void concurrent_select_relocation_set();
|
||||
void concurrent_prepare_relocation_set();
|
||||
void pause_relocate_start();
|
||||
void concurrent_relocate();
|
||||
|
||||
|
@ -23,30 +23,32 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zForwarding.inline.hpp"
|
||||
#include "gc/z/zPage.inline.hpp"
|
||||
#include "gc/z/zUtils.inline.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
ZForwarding::ZForwarding(uintptr_t start, size_t object_alignment_shift, uint32_t nentries) :
|
||||
_start(start),
|
||||
_object_alignment_shift(object_alignment_shift),
|
||||
ZForwarding::ZForwarding(ZPage* page, uint32_t nentries) :
|
||||
_virtual(page->virtual_memory()),
|
||||
_object_alignment_shift(page->object_alignment_shift()),
|
||||
_nentries(nentries),
|
||||
_page(page),
|
||||
_refcount(1),
|
||||
_pinned(false) {}
|
||||
|
||||
ZForwarding* ZForwarding::create(uintptr_t start, size_t object_alignment_shift, uint32_t live_objects) {
|
||||
assert(live_objects > 0, "Invalid value");
|
||||
ZForwarding* ZForwarding::create(ZPage* page) {
|
||||
assert(page->live_objects() > 0, "Invalid value");
|
||||
|
||||
// Allocate table for linear probing. The size of the table must be
|
||||
// a power of two to allow for quick and inexpensive indexing/masking.
|
||||
// The table is sized to have a load factor of 50%, i.e. sized to have
|
||||
// double the number of entries actually inserted.
|
||||
const uint32_t nentries = ZUtils::round_up_power_of_2(live_objects * 2);
|
||||
|
||||
const uint32_t nentries = ZUtils::round_up_power_of_2(page->live_objects() * 2);
|
||||
const size_t size = sizeof(ZForwarding) + (sizeof(ZForwardingEntry) * nentries);
|
||||
uint8_t* const addr = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
|
||||
ZForwardingEntry* const entries = ::new (addr + sizeof(ZForwarding)) ZForwardingEntry[nentries];
|
||||
ZForwarding* const forwarding = ::new (addr) ZForwarding(start, object_alignment_shift, nentries);
|
||||
ZForwarding* const forwarding = ::new (addr) ZForwarding(page, nentries);
|
||||
|
||||
return forwarding;
|
||||
}
|
||||
|
||||
@ -54,8 +56,11 @@ void ZForwarding::destroy(ZForwarding* forwarding) {
|
||||
FREE_C_HEAP_ARRAY(uint8_t, forwarding);
|
||||
}
|
||||
|
||||
void ZForwarding::verify(uint32_t object_max_count, uint32_t live_objects) const {
|
||||
uint32_t count = 0;
|
||||
void ZForwarding::verify() const {
|
||||
guarantee(_refcount > 0, "Invalid refcount");
|
||||
guarantee(_page != NULL, "Invalid page");
|
||||
|
||||
uint32_t live_objects = 0;
|
||||
|
||||
for (ZForwardingCursor i = 0; i < _nentries; i++) {
|
||||
const ZForwardingEntry entry = at(&i);
|
||||
@ -65,7 +70,7 @@ void ZForwarding::verify(uint32_t object_max_count, uint32_t live_objects) const
|
||||
}
|
||||
|
||||
// Check from index
|
||||
guarantee(entry.from_index() < object_max_count, "Invalid from index");
|
||||
guarantee(entry.from_index() < _page->object_max_count(), "Invalid from index");
|
||||
|
||||
// Check for duplicates
|
||||
for (ZForwardingCursor j = i + 1; j < _nentries; j++) {
|
||||
@ -74,9 +79,9 @@ void ZForwarding::verify(uint32_t object_max_count, uint32_t live_objects) const
|
||||
guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
|
||||
}
|
||||
|
||||
count++;
|
||||
live_objects++;
|
||||
}
|
||||
|
||||
// Check number of non-null entries
|
||||
guarantee(live_objects == count, "Count mismatch");
|
||||
// Check number of non-empty entries
|
||||
guarantee(live_objects == _page->live_objects(), "Invalid number of entries");
|
||||
}
|
||||
|
@ -25,6 +25,9 @@
|
||||
#define SHARE_GC_Z_ZFORWARDING_HPP
|
||||
|
||||
#include "gc/z/zForwardingEntry.hpp"
|
||||
#include "gc/z/zVirtualMemory.hpp"
|
||||
|
||||
class ZPage;
|
||||
|
||||
typedef uint32_t ZForwardingCursor;
|
||||
|
||||
@ -33,37 +36,43 @@ class ZForwarding {
|
||||
friend class ZForwardingTest;
|
||||
|
||||
private:
|
||||
const uintptr_t _start;
|
||||
const size_t _object_alignment_shift;
|
||||
const uint32_t _nentries;
|
||||
volatile uint32_t _refcount;
|
||||
volatile bool _pinned;
|
||||
const ZVirtualMemory _virtual;
|
||||
const size_t _object_alignment_shift;
|
||||
const uint32_t _nentries;
|
||||
ZPage* _page;
|
||||
volatile uint32_t _refcount;
|
||||
volatile bool _pinned;
|
||||
|
||||
bool inc_refcount();
|
||||
bool dec_refcount();
|
||||
|
||||
ZForwardingEntry* entries() const;
|
||||
ZForwardingEntry at(ZForwardingCursor* cursor) const;
|
||||
ZForwardingEntry first(uintptr_t from_index, ZForwardingCursor* cursor) const;
|
||||
ZForwardingEntry next(ZForwardingCursor* cursor) const;
|
||||
|
||||
ZForwarding(uintptr_t start, size_t object_alignment_shift, uint32_t nentries);
|
||||
ZForwarding(ZPage* page, uint32_t nentries);
|
||||
|
||||
public:
|
||||
static ZForwarding* create(uintptr_t start, size_t object_alignment_shift, uint32_t live_objects);
|
||||
static ZForwarding* create(ZPage* page);
|
||||
static void destroy(ZForwarding* forwarding);
|
||||
|
||||
uintptr_t start() const;
|
||||
size_t size() const;
|
||||
size_t object_alignment_shift() const;
|
||||
|
||||
bool inc_refcount();
|
||||
bool dec_refcount();
|
||||
ZPage* page() const;
|
||||
|
||||
bool is_pinned() const;
|
||||
void set_pinned();
|
||||
|
||||
bool retain_page();
|
||||
void release_page();
|
||||
|
||||
ZForwardingEntry find(uintptr_t from_index) const;
|
||||
ZForwardingEntry find(uintptr_t from_index, ZForwardingCursor* cursor) const;
|
||||
uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor);
|
||||
|
||||
void verify(uint32_t object_max_count, uint32_t live_objects) const;
|
||||
void verify() const;
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_Z_ZFORWARDING_HPP
|
||||
|
@ -27,17 +27,35 @@
|
||||
#include "gc/z/zForwarding.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zHash.inline.hpp"
|
||||
#include "gc/z/zHeap.hpp"
|
||||
#include "gc/z/zVirtualMemory.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
inline uintptr_t ZForwarding::start() const {
|
||||
return _start;
|
||||
return _virtual.start();
|
||||
}
|
||||
|
||||
inline size_t ZForwarding::size() const {
|
||||
return _virtual.size();
|
||||
}
|
||||
|
||||
inline size_t ZForwarding::object_alignment_shift() const {
|
||||
return _object_alignment_shift;
|
||||
}
|
||||
|
||||
inline ZPage* ZForwarding::page() const {
|
||||
return _page;
|
||||
}
|
||||
|
||||
inline bool ZForwarding::is_pinned() const {
|
||||
return Atomic::load(&_pinned);
|
||||
}
|
||||
|
||||
inline void ZForwarding::set_pinned() {
|
||||
Atomic::store(true, &_pinned);
|
||||
}
|
||||
|
||||
inline bool ZForwarding::inc_refcount() {
|
||||
uint32_t refcount = Atomic::load(&_refcount);
|
||||
|
||||
@ -60,12 +78,15 @@ inline bool ZForwarding::dec_refcount() {
|
||||
return Atomic::sub(1u, &_refcount) == 0u;
|
||||
}
|
||||
|
||||
inline bool ZForwarding::is_pinned() const {
|
||||
return Atomic::load(&_pinned);
|
||||
inline bool ZForwarding::retain_page() {
|
||||
return inc_refcount();
|
||||
}
|
||||
|
||||
inline void ZForwarding::set_pinned() {
|
||||
Atomic::store(true, &_pinned);
|
||||
inline void ZForwarding::release_page() {
|
||||
if (dec_refcount()) {
|
||||
ZHeap::heap()->free_page(_page, true /* reclaimed */);
|
||||
_page = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
inline ZForwardingEntry* ZForwarding::entries() const {
|
||||
|
@ -22,7 +22,8 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zForwarding.hpp"
|
||||
#include "gc/z/zAddress.inline.hpp"
|
||||
#include "gc/z/zForwarding.inline.hpp"
|
||||
#include "gc/z/zForwardingTable.inline.hpp"
|
||||
#include "gc/z/zGranuleMap.inline.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
@ -30,41 +31,18 @@
|
||||
ZForwardingTable::ZForwardingTable() :
|
||||
_map() {}
|
||||
|
||||
void ZForwardingTable::insert(uintptr_t start,
|
||||
size_t size,
|
||||
size_t object_alignment_shift,
|
||||
uint32_t live_objects) {
|
||||
// Allocate forwarding
|
||||
ZForwarding* const forwarding = ZForwarding::create(start,
|
||||
object_alignment_shift,
|
||||
live_objects);
|
||||
void ZForwardingTable::insert(ZForwarding* forwarding) {
|
||||
const uintptr_t addr = ZAddress::good(forwarding->start());
|
||||
const size_t size = forwarding->size();
|
||||
|
||||
// Insert into forwarding table
|
||||
const uintptr_t addr = ZAddress::good(start);
|
||||
assert(get(addr) == NULL, "Invalid entry");
|
||||
_map.put(addr, size, forwarding);
|
||||
}
|
||||
|
||||
void ZForwardingTable::clear() {
|
||||
ZForwarding* prev_forwarding = NULL;
|
||||
void ZForwardingTable::remove(ZForwarding* forwarding) {
|
||||
const uintptr_t addr = ZAddress::good(forwarding->start());
|
||||
const size_t size = forwarding->size();
|
||||
|
||||
// Clear and destroy all non-NULL entries
|
||||
ZGranuleMapIterator<ZForwarding*> iter(&_map);
|
||||
for (ZForwarding** entry; iter.next(&entry);) {
|
||||
ZForwarding* const forwarding = *entry;
|
||||
if (forwarding == NULL) {
|
||||
// Skip entry
|
||||
continue;
|
||||
}
|
||||
|
||||
// Clear entry
|
||||
*entry = NULL;
|
||||
|
||||
// More than one entry can point to the same
|
||||
// forwarding. Make sure we only destroy it once.
|
||||
if (forwarding != prev_forwarding) {
|
||||
ZForwarding::destroy(forwarding);
|
||||
prev_forwarding = forwarding;
|
||||
}
|
||||
}
|
||||
assert(get(addr) == forwarding, "Invalid entry");
|
||||
_map.put(addr, size, NULL);
|
||||
}
|
||||
|
@ -37,11 +37,8 @@ public:
|
||||
|
||||
ZForwarding* get(uintptr_t addr) const;
|
||||
|
||||
void insert(uintptr_t start,
|
||||
size_t size,
|
||||
size_t object_alignment_shift,
|
||||
uint32_t live_objects);
|
||||
void clear();
|
||||
void insert(ZForwarding* forwarding);
|
||||
void remove(ZForwarding* forwarding);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_Z_ZFORWARDINGTABLE_HPP
|
||||
|
@ -417,8 +417,8 @@ void ZHeap::destroy_detached_pages() {
|
||||
void ZHeap::select_relocation_set() {
|
||||
// Register relocatable pages with selector
|
||||
ZRelocationSetSelector selector;
|
||||
ZPageTableIterator iter(&_pagetable);
|
||||
for (ZPage* page; iter.next(&page);) {
|
||||
ZPageTableIterator pt_iter(&_pagetable);
|
||||
for (ZPage* page; pt_iter.next(&page);) {
|
||||
if (!page->is_relocatable()) {
|
||||
// Not relocatable, don't register
|
||||
continue;
|
||||
@ -439,6 +439,12 @@ void ZHeap::select_relocation_set() {
|
||||
// Select pages to relocate
|
||||
selector.select(&_relocation_set);
|
||||
|
||||
// Setup forwarding table
|
||||
ZRelocationSetIterator rs_iter(&_relocation_set);
|
||||
for (ZForwarding* forwarding; rs_iter.next(&forwarding);) {
|
||||
_forwarding_table.insert(forwarding);
|
||||
}
|
||||
|
||||
// Update statistics
|
||||
ZStatRelocation::set_at_select_relocation_set(selector.relocating());
|
||||
ZStatHeap::set_at_select_relocation_set(selector.live(),
|
||||
@ -446,20 +452,15 @@ void ZHeap::select_relocation_set() {
|
||||
reclaimed());
|
||||
}
|
||||
|
||||
void ZHeap::prepare_relocation_set() {
|
||||
ZRelocationSetIterator iter(&_relocation_set);
|
||||
for (ZPage* page; iter.next(&page);) {
|
||||
// Setup forwarding for page
|
||||
_forwarding_table.insert(page->start(),
|
||||
page->size(),
|
||||
page->object_alignment_shift(),
|
||||
page->live_objects());
|
||||
}
|
||||
}
|
||||
|
||||
void ZHeap::reset_relocation_set() {
|
||||
// Clear forwarding table
|
||||
_forwarding_table.clear();
|
||||
// Reset forwarding table
|
||||
ZRelocationSetIterator iter(&_relocation_set);
|
||||
for (ZForwarding* forwarding; iter.next(&forwarding);) {
|
||||
_forwarding_table.remove(forwarding);
|
||||
}
|
||||
|
||||
// Reset relocation set
|
||||
_relocation_set.reset();
|
||||
}
|
||||
|
||||
void ZHeap::relocate_start() {
|
||||
|
@ -149,11 +149,9 @@ public:
|
||||
|
||||
// Relocation set
|
||||
void select_relocation_set();
|
||||
void prepare_relocation_set();
|
||||
void reset_relocation_set();
|
||||
|
||||
// Relocation
|
||||
ZForwarding* forwarding(uintptr_t addr);
|
||||
void relocate_start();
|
||||
uintptr_t relocate_object(uintptr_t addr);
|
||||
uintptr_t remap_object(uintptr_t addr);
|
||||
|
@ -44,10 +44,6 @@ inline ReferenceDiscoverer* ZHeap::reference_discoverer() {
|
||||
return &_reference_processor;
|
||||
}
|
||||
|
||||
inline ZForwarding* ZHeap::forwarding(uintptr_t addr) {
|
||||
return _forwarding_table.get(addr);
|
||||
}
|
||||
|
||||
inline bool ZHeap::is_object_live(uintptr_t addr) const {
|
||||
ZPage* page = _pagetable.get(addr);
|
||||
return page->is_object_live(addr);
|
||||
@ -101,11 +97,10 @@ inline uintptr_t ZHeap::relocate_object(uintptr_t addr) {
|
||||
}
|
||||
|
||||
// Relocate object
|
||||
const bool retained = forwarding->inc_refcount();
|
||||
const bool retained = forwarding->retain_page();
|
||||
const uintptr_t new_addr = _relocate.relocate_object(forwarding, addr);
|
||||
if (retained && forwarding->dec_refcount()) {
|
||||
ZPage* const page = _pagetable.get(addr);
|
||||
free_page(page, true /* reclaimed */);
|
||||
if (retained) {
|
||||
forwarding->release_page();
|
||||
}
|
||||
|
||||
return new_addr;
|
||||
|
@ -83,11 +83,6 @@ void ZRelocate::start() {
|
||||
_workers->run_parallel(&task);
|
||||
}
|
||||
|
||||
ZForwarding* ZRelocate::forwarding_for_page(ZPage* page) const {
|
||||
const uintptr_t addr = ZAddress::good(page->start());
|
||||
return ZHeap::heap()->forwarding(addr);
|
||||
}
|
||||
|
||||
uintptr_t ZRelocate::relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const {
|
||||
ZForwardingCursor cursor;
|
||||
|
||||
@ -178,14 +173,13 @@ bool ZRelocate::work(ZRelocationSetParallelIterator* iter) {
|
||||
bool success = true;
|
||||
|
||||
// Relocate pages in the relocation set
|
||||
for (ZPage* page; iter->next(&page);) {
|
||||
for (ZForwarding* forwarding; iter->next(&forwarding);) {
|
||||
// Relocate objects in page
|
||||
ZForwarding* const forwarding = forwarding_for_page(page);
|
||||
ZRelocateObjectClosure cl(this, forwarding);
|
||||
page->object_iterate(&cl);
|
||||
forwarding->page()->object_iterate(&cl);
|
||||
|
||||
if (ZVerifyForwarding) {
|
||||
forwarding->verify(page->object_max_count(), page->live_objects());
|
||||
forwarding->verify();
|
||||
}
|
||||
|
||||
if (forwarding->is_pinned()) {
|
||||
@ -193,9 +187,7 @@ bool ZRelocate::work(ZRelocationSetParallelIterator* iter) {
|
||||
success = false;
|
||||
} else {
|
||||
// Relocation succeeded, release page
|
||||
if (forwarding->dec_refcount()) {
|
||||
ZHeap::heap()->free_page(page, true /* reclaimed */);
|
||||
}
|
||||
forwarding->release_page();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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
|
||||
@ -22,24 +22,35 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zForwarding.hpp"
|
||||
#include "gc/z/zRelocationSet.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
ZRelocationSet::ZRelocationSet() :
|
||||
_pages(NULL),
|
||||
_npages(0) {}
|
||||
_forwardings(NULL),
|
||||
_nforwardings(0) {}
|
||||
|
||||
void ZRelocationSet::populate(const ZPage* const* group0, size_t ngroup0,
|
||||
const ZPage* const* group1, size_t ngroup1) {
|
||||
_npages = ngroup0 + ngroup1;
|
||||
_pages = REALLOC_C_HEAP_ARRAY(ZPage*, _pages, _npages, mtGC);
|
||||
void ZRelocationSet::populate(ZPage* const* group0, size_t ngroup0,
|
||||
ZPage* const* group1, size_t ngroup1) {
|
||||
_nforwardings = ngroup0 + ngroup1;
|
||||
_forwardings = REALLOC_C_HEAP_ARRAY(ZForwarding*, _forwardings, _nforwardings, mtGC);
|
||||
|
||||
if (_pages != NULL) {
|
||||
if (group0 != NULL) {
|
||||
memcpy(_pages, group0, ngroup0 * sizeof(ZPage*));
|
||||
}
|
||||
if (group1 != NULL) {
|
||||
memcpy(_pages + ngroup0, group1, ngroup1 * sizeof(ZPage*));
|
||||
}
|
||||
size_t j = 0;
|
||||
|
||||
// Populate group 0
|
||||
for (size_t i = 0; i < ngroup0; i++) {
|
||||
_forwardings[j++] = ZForwarding::create(group0[i]);
|
||||
}
|
||||
|
||||
// Populate group 1
|
||||
for (size_t i = 0; i < ngroup1; i++) {
|
||||
_forwardings[j++] = ZForwarding::create(group1[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void ZRelocationSet::reset() {
|
||||
for (size_t i = 0; i < _nforwardings; i++) {
|
||||
ZForwarding::destroy(_forwardings[i]);
|
||||
_forwardings[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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
|
||||
@ -26,20 +26,22 @@
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class ZForwarding;
|
||||
class ZPage;
|
||||
|
||||
class ZRelocationSet {
|
||||
template <bool> friend class ZRelocationSetIteratorImpl;
|
||||
|
||||
private:
|
||||
ZPage** _pages;
|
||||
size_t _npages;
|
||||
ZForwarding** _forwardings;
|
||||
size_t _nforwardings;
|
||||
|
||||
public:
|
||||
ZRelocationSet();
|
||||
|
||||
void populate(const ZPage* const* group0, size_t ngroup0,
|
||||
const ZPage* const* group1, size_t ngroup1);
|
||||
void populate(ZPage* const* group0, size_t ngroup0,
|
||||
ZPage* const* group1, size_t ngroup1);
|
||||
void reset();
|
||||
};
|
||||
|
||||
template <bool parallel>
|
||||
@ -51,7 +53,7 @@ private:
|
||||
public:
|
||||
ZRelocationSetIteratorImpl(ZRelocationSet* relocation_set);
|
||||
|
||||
bool next(ZPage** page);
|
||||
bool next(ZForwarding** forwarding);
|
||||
};
|
||||
|
||||
// Iterator types
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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
|
||||
@ -33,20 +33,20 @@ inline ZRelocationSetIteratorImpl<parallel>::ZRelocationSetIteratorImpl(ZRelocat
|
||||
_next(0) {}
|
||||
|
||||
template <bool parallel>
|
||||
inline bool ZRelocationSetIteratorImpl<parallel>::next(ZPage** page) {
|
||||
const size_t npages = _relocation_set->_npages;
|
||||
inline bool ZRelocationSetIteratorImpl<parallel>::next(ZForwarding** forwarding) {
|
||||
const size_t nforwardings = _relocation_set->_nforwardings;
|
||||
|
||||
if (parallel) {
|
||||
if (_next < npages) {
|
||||
if (_next < nforwardings) {
|
||||
const size_t next = Atomic::add(1u, &_next) - 1u;
|
||||
if (next < npages) {
|
||||
*page = _relocation_set->_pages[next];
|
||||
if (next < nforwardings) {
|
||||
*forwarding = _relocation_set->_forwardings[next];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_next < npages) {
|
||||
*page = _relocation_set->_pages[_next++];
|
||||
if (_next < nforwardings) {
|
||||
*forwarding = _relocation_set->_forwardings[_next++];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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
|
||||
@ -44,10 +44,10 @@ ZRelocationSetSelectorGroup::ZRelocationSetSelectorGroup(const char* name,
|
||||
_fragmentation(0) {}
|
||||
|
||||
ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() {
|
||||
FREE_C_HEAP_ARRAY(const ZPage*, _sorted_pages);
|
||||
FREE_C_HEAP_ARRAY(ZPage*, _sorted_pages);
|
||||
}
|
||||
|
||||
void ZRelocationSetSelectorGroup::register_live_page(const ZPage* page, size_t garbage) {
|
||||
void ZRelocationSetSelectorGroup::register_live_page(ZPage* page, size_t garbage) {
|
||||
if (garbage > _fragmentation_limit) {
|
||||
_registered_pages.add(page);
|
||||
} else {
|
||||
@ -67,13 +67,13 @@ void ZRelocationSetSelectorGroup::semi_sort() {
|
||||
size_t partitions[npartitions];
|
||||
|
||||
// Allocate destination array
|
||||
_sorted_pages = REALLOC_C_HEAP_ARRAY(const ZPage*, _sorted_pages, npages, mtGC);
|
||||
_sorted_pages = REALLOC_C_HEAP_ARRAY(ZPage*, _sorted_pages, npages, mtGC);
|
||||
debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*)));
|
||||
|
||||
// Calculate partition slots
|
||||
memset(partitions, 0, sizeof(partitions));
|
||||
ZArrayIterator<const ZPage*> iter1(&_registered_pages);
|
||||
for (const ZPage* page; iter1.next(&page);) {
|
||||
ZArrayIterator<ZPage*> iter1(&_registered_pages);
|
||||
for (ZPage* page; iter1.next(&page);) {
|
||||
const size_t index = page->live_bytes() >> partition_size_shift;
|
||||
partitions[index]++;
|
||||
}
|
||||
@ -87,8 +87,8 @@ void ZRelocationSetSelectorGroup::semi_sort() {
|
||||
}
|
||||
|
||||
// Sort pages into partitions
|
||||
ZArrayIterator<const ZPage*> iter2(&_registered_pages);
|
||||
for (const ZPage* page; iter2.next(&page);) {
|
||||
ZArrayIterator<ZPage*> iter2(&_registered_pages);
|
||||
for (ZPage* page; iter2.next(&page);) {
|
||||
const size_t index = page->live_bytes() >> partition_size_shift;
|
||||
const size_t finger = partitions[index]++;
|
||||
assert(_sorted_pages[finger] == NULL, "Invalid finger");
|
||||
@ -140,7 +140,7 @@ void ZRelocationSetSelectorGroup::select() {
|
||||
// Update statistics
|
||||
_relocating = from_size;
|
||||
for (size_t i = _nselected; i < npages; i++) {
|
||||
const ZPage* const page = _sorted_pages[i];
|
||||
ZPage* const page = _sorted_pages[i];
|
||||
_fragmentation += page->size() - page->live_bytes();
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ void ZRelocationSetSelectorGroup::select() {
|
||||
_name, selected_from, selected_to, npages - _nselected);
|
||||
}
|
||||
|
||||
const ZPage* const* ZRelocationSetSelectorGroup::selected() const {
|
||||
ZPage* const* ZRelocationSetSelectorGroup::selected() const {
|
||||
return _sorted_pages;
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ ZRelocationSetSelector::ZRelocationSetSelector() :
|
||||
_garbage(0),
|
||||
_fragmentation(0) {}
|
||||
|
||||
void ZRelocationSetSelector::register_live_page(const ZPage* page) {
|
||||
void ZRelocationSetSelector::register_live_page(ZPage* page) {
|
||||
const uint8_t type = page->type();
|
||||
const size_t live = page->live_bytes();
|
||||
const size_t garbage = page->size() - live;
|
||||
@ -188,7 +188,7 @@ void ZRelocationSetSelector::register_live_page(const ZPage* page) {
|
||||
_garbage += garbage;
|
||||
}
|
||||
|
||||
void ZRelocationSetSelector::register_garbage_page(const ZPage* page) {
|
||||
void ZRelocationSetSelector::register_garbage_page(ZPage* page) {
|
||||
_garbage += page->size();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2019, 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
|
||||
@ -32,16 +32,16 @@ class ZRelocationSet;
|
||||
|
||||
class ZRelocationSetSelectorGroup {
|
||||
private:
|
||||
const char* const _name;
|
||||
const size_t _page_size;
|
||||
const size_t _object_size_limit;
|
||||
const size_t _fragmentation_limit;
|
||||
const char* const _name;
|
||||
const size_t _page_size;
|
||||
const size_t _object_size_limit;
|
||||
const size_t _fragmentation_limit;
|
||||
|
||||
ZArray<const ZPage*> _registered_pages;
|
||||
const ZPage** _sorted_pages;
|
||||
size_t _nselected;
|
||||
size_t _relocating;
|
||||
size_t _fragmentation;
|
||||
ZArray<ZPage*> _registered_pages;
|
||||
ZPage** _sorted_pages;
|
||||
size_t _nselected;
|
||||
size_t _relocating;
|
||||
size_t _fragmentation;
|
||||
|
||||
void semi_sort();
|
||||
|
||||
@ -51,10 +51,10 @@ public:
|
||||
size_t object_size_limit);
|
||||
~ZRelocationSetSelectorGroup();
|
||||
|
||||
void register_live_page(const ZPage* page, size_t garbage);
|
||||
void register_live_page(ZPage* page, size_t garbage);
|
||||
void select();
|
||||
|
||||
const ZPage* const* selected() const;
|
||||
ZPage* const* selected() const;
|
||||
size_t nselected() const;
|
||||
size_t relocating() const;
|
||||
size_t fragmentation() const;
|
||||
@ -71,8 +71,8 @@ private:
|
||||
public:
|
||||
ZRelocationSetSelector();
|
||||
|
||||
void register_live_page(const ZPage* page);
|
||||
void register_garbage_page(const ZPage* page);
|
||||
void register_live_page(ZPage* page);
|
||||
void register_garbage_page(ZPage* page);
|
||||
void select(ZRelocationSet* relocation_set);
|
||||
|
||||
size_t live() const;
|
||||
|
@ -22,7 +22,10 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/z/zAddress.inline.hpp"
|
||||
#include "gc/z/zForwarding.inline.hpp"
|
||||
#include "gc/z/zGlobals.hpp"
|
||||
#include "gc/z/zPage.inline.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
using namespace testing;
|
||||
@ -141,16 +144,37 @@ public:
|
||||
}
|
||||
|
||||
static void test(void (*function)(ZForwarding*), uint32_t size) {
|
||||
// Setup
|
||||
ZForwarding* forwarding = ZForwarding::create(0 /* start */,
|
||||
0 /* object_alignment_shift */,
|
||||
size);
|
||||
// Create page
|
||||
const ZVirtualMemory vmem(0, ZPageSizeSmall);
|
||||
const ZPhysicalMemory pmem(ZPhysicalMemorySegment(0, ZPageSizeSmall));
|
||||
ZPage page(ZPageTypeSmall, vmem, pmem);
|
||||
|
||||
page.reset();
|
||||
|
||||
const size_t object_size = 16;
|
||||
const uintptr_t object = page.alloc_object(object_size);
|
||||
|
||||
ZGlobalSeqNum++;
|
||||
|
||||
bool dummy = false;
|
||||
page.mark_object(ZAddress::marked(object), dummy, dummy);
|
||||
|
||||
const uint32_t live_objects = size;
|
||||
const uint32_t live_bytes = live_objects * object_size;
|
||||
page.inc_live_atomic(live_objects, live_bytes);
|
||||
|
||||
// Setup forwarding
|
||||
ZForwarding* const forwarding = ZForwarding::create(&page);
|
||||
|
||||
// Actual test function
|
||||
(*function)(forwarding);
|
||||
|
||||
// Teardown
|
||||
// Teardown forwarding
|
||||
ZForwarding::destroy(forwarding);
|
||||
|
||||
// Teardown page
|
||||
page.physical_memory().clear();
|
||||
page.set_inactive();
|
||||
}
|
||||
|
||||
// Run the given function with a few different input values.
|
||||
|
Loading…
x
Reference in New Issue
Block a user