8220588: ZGC: Convert ZRelocationSet to hold ZForwardings instead of ZPages

Reviewed-by: stefank, eosterlund
This commit is contained in:
Per Lidén 2019-03-18 11:50:39 +01:00
parent 5a079bf515
commit 0ce7c21d33
17 changed files with 199 additions and 176 deletions

View File

@ -45,7 +45,6 @@ static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Co
static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set");
static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages"); static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages");
static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set"); 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 ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start");
static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate"); static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate");
static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */); static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */);
@ -317,11 +316,6 @@ void ZDriver::concurrent_select_relocation_set() {
ZHeap::heap()->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() { void ZDriver::pause_relocate_start() {
pause<VM_ZRelocateStart>(); pause<VM_ZRelocateStart>();
} }
@ -393,13 +387,10 @@ void ZDriver::gc(GCCause::Cause cause) {
// Phase 8: Concurrent Select Relocation Set // Phase 8: Concurrent Select Relocation Set
concurrent_select_relocation_set(); concurrent_select_relocation_set();
// Phase 9: Concurrent Prepare Relocation Set // Phase 9: Pause Relocate Start
concurrent_prepare_relocation_set();
// Phase 10: Pause Relocate Start
pause_relocate_start(); pause_relocate_start();
// Phase 11: Concurrent Relocate // Phase 10: Concurrent Relocate
concurrent_relocate(); concurrent_relocate();
} }

View File

@ -46,7 +46,6 @@ private:
void concurrent_destroy_detached_pages(); void concurrent_destroy_detached_pages();
void pause_verify(); void pause_verify();
void concurrent_select_relocation_set(); void concurrent_select_relocation_set();
void concurrent_prepare_relocation_set();
void pause_relocate_start(); void pause_relocate_start();
void concurrent_relocate(); void concurrent_relocate();

View File

@ -23,30 +23,32 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc/z/zForwarding.inline.hpp" #include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zPage.inline.hpp"
#include "gc/z/zUtils.inline.hpp" #include "gc/z/zUtils.inline.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
ZForwarding::ZForwarding(uintptr_t start, size_t object_alignment_shift, uint32_t nentries) : ZForwarding::ZForwarding(ZPage* page, uint32_t nentries) :
_start(start), _virtual(page->virtual_memory()),
_object_alignment_shift(object_alignment_shift), _object_alignment_shift(page->object_alignment_shift()),
_nentries(nentries), _nentries(nentries),
_page(page),
_refcount(1), _refcount(1),
_pinned(false) {} _pinned(false) {}
ZForwarding* ZForwarding::create(uintptr_t start, size_t object_alignment_shift, uint32_t live_objects) { ZForwarding* ZForwarding::create(ZPage* page) {
assert(live_objects > 0, "Invalid value"); assert(page->live_objects() > 0, "Invalid value");
// Allocate table for linear probing. The size of the table must be // Allocate table for linear probing. The size of the table must be
// a power of two to allow for quick and inexpensive indexing/masking. // 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 // The table is sized to have a load factor of 50%, i.e. sized to have
// double the number of entries actually inserted. // 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); const size_t size = sizeof(ZForwarding) + (sizeof(ZForwardingEntry) * nentries);
uint8_t* const addr = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC); uint8_t* const addr = NEW_C_HEAP_ARRAY(uint8_t, size, mtGC);
ZForwardingEntry* const entries = ::new (addr + sizeof(ZForwarding)) ZForwardingEntry[nentries]; 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; return forwarding;
} }
@ -54,8 +56,11 @@ void ZForwarding::destroy(ZForwarding* forwarding) {
FREE_C_HEAP_ARRAY(uint8_t, forwarding); FREE_C_HEAP_ARRAY(uint8_t, forwarding);
} }
void ZForwarding::verify(uint32_t object_max_count, uint32_t live_objects) const { void ZForwarding::verify() const {
uint32_t count = 0; guarantee(_refcount > 0, "Invalid refcount");
guarantee(_page != NULL, "Invalid page");
uint32_t live_objects = 0;
for (ZForwardingCursor i = 0; i < _nentries; i++) { for (ZForwardingCursor i = 0; i < _nentries; i++) {
const ZForwardingEntry entry = at(&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 // 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 // Check for duplicates
for (ZForwardingCursor j = i + 1; j < _nentries; j++) { 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"); guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
} }
count++; live_objects++;
} }
// Check number of non-null entries // Check number of non-empty entries
guarantee(live_objects == count, "Count mismatch"); guarantee(live_objects == _page->live_objects(), "Invalid number of entries");
} }

View File

@ -25,6 +25,9 @@
#define SHARE_GC_Z_ZFORWARDING_HPP #define SHARE_GC_Z_ZFORWARDING_HPP
#include "gc/z/zForwardingEntry.hpp" #include "gc/z/zForwardingEntry.hpp"
#include "gc/z/zVirtualMemory.hpp"
class ZPage;
typedef uint32_t ZForwardingCursor; typedef uint32_t ZForwardingCursor;
@ -33,37 +36,43 @@ class ZForwarding {
friend class ZForwardingTest; friend class ZForwardingTest;
private: private:
const uintptr_t _start; const ZVirtualMemory _virtual;
const size_t _object_alignment_shift; const size_t _object_alignment_shift;
const uint32_t _nentries; const uint32_t _nentries;
volatile uint32_t _refcount; ZPage* _page;
volatile bool _pinned; volatile uint32_t _refcount;
volatile bool _pinned;
bool inc_refcount();
bool dec_refcount();
ZForwardingEntry* entries() const; ZForwardingEntry* entries() const;
ZForwardingEntry at(ZForwardingCursor* cursor) const; ZForwardingEntry at(ZForwardingCursor* cursor) const;
ZForwardingEntry first(uintptr_t from_index, ZForwardingCursor* cursor) const; ZForwardingEntry first(uintptr_t from_index, ZForwardingCursor* cursor) const;
ZForwardingEntry next(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: 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); static void destroy(ZForwarding* forwarding);
uintptr_t start() const; uintptr_t start() const;
size_t size() const;
size_t object_alignment_shift() const; size_t object_alignment_shift() const;
ZPage* page() const;
bool inc_refcount();
bool dec_refcount();
bool is_pinned() const; bool is_pinned() const;
void set_pinned(); void set_pinned();
bool retain_page();
void release_page();
ZForwardingEntry find(uintptr_t from_index) const; ZForwardingEntry find(uintptr_t from_index) const;
ZForwardingEntry find(uintptr_t from_index, ZForwardingCursor* cursor) const; ZForwardingEntry find(uintptr_t from_index, ZForwardingCursor* cursor) const;
uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor); 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 #endif // SHARE_GC_Z_ZFORWARDING_HPP

View File

@ -27,17 +27,35 @@
#include "gc/z/zForwarding.hpp" #include "gc/z/zForwarding.hpp"
#include "gc/z/zGlobals.hpp" #include "gc/z/zGlobals.hpp"
#include "gc/z/zHash.inline.hpp" #include "gc/z/zHash.inline.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zVirtualMemory.inline.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
inline uintptr_t ZForwarding::start() const { 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 { inline size_t ZForwarding::object_alignment_shift() const {
return _object_alignment_shift; 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() { inline bool ZForwarding::inc_refcount() {
uint32_t refcount = Atomic::load(&_refcount); uint32_t refcount = Atomic::load(&_refcount);
@ -60,12 +78,15 @@ inline bool ZForwarding::dec_refcount() {
return Atomic::sub(1u, &_refcount) == 0u; return Atomic::sub(1u, &_refcount) == 0u;
} }
inline bool ZForwarding::is_pinned() const { inline bool ZForwarding::retain_page() {
return Atomic::load(&_pinned); return inc_refcount();
} }
inline void ZForwarding::set_pinned() { inline void ZForwarding::release_page() {
Atomic::store(true, &_pinned); if (dec_refcount()) {
ZHeap::heap()->free_page(_page, true /* reclaimed */);
_page = NULL;
}
} }
inline ZForwardingEntry* ZForwarding::entries() const { inline ZForwardingEntry* ZForwarding::entries() const {

View File

@ -22,7 +22,8 @@
*/ */
#include "precompiled.hpp" #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/zForwardingTable.inline.hpp"
#include "gc/z/zGranuleMap.inline.hpp" #include "gc/z/zGranuleMap.inline.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
@ -30,41 +31,18 @@
ZForwardingTable::ZForwardingTable() : ZForwardingTable::ZForwardingTable() :
_map() {} _map() {}
void ZForwardingTable::insert(uintptr_t start, void ZForwardingTable::insert(ZForwarding* forwarding) {
size_t size, const uintptr_t addr = ZAddress::good(forwarding->start());
size_t object_alignment_shift, const size_t size = forwarding->size();
uint32_t live_objects) {
// Allocate forwarding
ZForwarding* const forwarding = ZForwarding::create(start,
object_alignment_shift,
live_objects);
// Insert into forwarding table
const uintptr_t addr = ZAddress::good(start);
assert(get(addr) == NULL, "Invalid entry"); assert(get(addr) == NULL, "Invalid entry");
_map.put(addr, size, forwarding); _map.put(addr, size, forwarding);
} }
void ZForwardingTable::clear() { void ZForwardingTable::remove(ZForwarding* forwarding) {
ZForwarding* prev_forwarding = NULL; const uintptr_t addr = ZAddress::good(forwarding->start());
const size_t size = forwarding->size();
// Clear and destroy all non-NULL entries assert(get(addr) == forwarding, "Invalid entry");
ZGranuleMapIterator<ZForwarding*> iter(&_map); _map.put(addr, size, NULL);
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;
}
}
} }

View File

@ -37,11 +37,8 @@ public:
ZForwarding* get(uintptr_t addr) const; ZForwarding* get(uintptr_t addr) const;
void insert(uintptr_t start, void insert(ZForwarding* forwarding);
size_t size, void remove(ZForwarding* forwarding);
size_t object_alignment_shift,
uint32_t live_objects);
void clear();
}; };
#endif // SHARE_GC_Z_ZFORWARDINGTABLE_HPP #endif // SHARE_GC_Z_ZFORWARDINGTABLE_HPP

View File

@ -417,8 +417,8 @@ void ZHeap::destroy_detached_pages() {
void ZHeap::select_relocation_set() { void ZHeap::select_relocation_set() {
// Register relocatable pages with selector // Register relocatable pages with selector
ZRelocationSetSelector selector; ZRelocationSetSelector selector;
ZPageTableIterator iter(&_pagetable); ZPageTableIterator pt_iter(&_pagetable);
for (ZPage* page; iter.next(&page);) { for (ZPage* page; pt_iter.next(&page);) {
if (!page->is_relocatable()) { if (!page->is_relocatable()) {
// Not relocatable, don't register // Not relocatable, don't register
continue; continue;
@ -439,6 +439,12 @@ void ZHeap::select_relocation_set() {
// Select pages to relocate // Select pages to relocate
selector.select(&_relocation_set); 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 // Update statistics
ZStatRelocation::set_at_select_relocation_set(selector.relocating()); ZStatRelocation::set_at_select_relocation_set(selector.relocating());
ZStatHeap::set_at_select_relocation_set(selector.live(), ZStatHeap::set_at_select_relocation_set(selector.live(),
@ -446,20 +452,15 @@ void ZHeap::select_relocation_set() {
reclaimed()); 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() { void ZHeap::reset_relocation_set() {
// Clear forwarding table // Reset forwarding table
_forwarding_table.clear(); ZRelocationSetIterator iter(&_relocation_set);
for (ZForwarding* forwarding; iter.next(&forwarding);) {
_forwarding_table.remove(forwarding);
}
// Reset relocation set
_relocation_set.reset();
} }
void ZHeap::relocate_start() { void ZHeap::relocate_start() {

View File

@ -149,11 +149,9 @@ public:
// Relocation set // Relocation set
void select_relocation_set(); void select_relocation_set();
void prepare_relocation_set();
void reset_relocation_set(); void reset_relocation_set();
// Relocation // Relocation
ZForwarding* forwarding(uintptr_t addr);
void relocate_start(); void relocate_start();
uintptr_t relocate_object(uintptr_t addr); uintptr_t relocate_object(uintptr_t addr);
uintptr_t remap_object(uintptr_t addr); uintptr_t remap_object(uintptr_t addr);

View File

@ -44,10 +44,6 @@ inline ReferenceDiscoverer* ZHeap::reference_discoverer() {
return &_reference_processor; 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 { inline bool ZHeap::is_object_live(uintptr_t addr) const {
ZPage* page = _pagetable.get(addr); ZPage* page = _pagetable.get(addr);
return page->is_object_live(addr); return page->is_object_live(addr);
@ -101,11 +97,10 @@ inline uintptr_t ZHeap::relocate_object(uintptr_t addr) {
} }
// Relocate object // Relocate object
const bool retained = forwarding->inc_refcount(); const bool retained = forwarding->retain_page();
const uintptr_t new_addr = _relocate.relocate_object(forwarding, addr); const uintptr_t new_addr = _relocate.relocate_object(forwarding, addr);
if (retained && forwarding->dec_refcount()) { if (retained) {
ZPage* const page = _pagetable.get(addr); forwarding->release_page();
free_page(page, true /* reclaimed */);
} }
return new_addr; return new_addr;

View File

@ -83,11 +83,6 @@ void ZRelocate::start() {
_workers->run_parallel(&task); _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 { uintptr_t ZRelocate::relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const {
ZForwardingCursor cursor; ZForwardingCursor cursor;
@ -178,14 +173,13 @@ bool ZRelocate::work(ZRelocationSetParallelIterator* iter) {
bool success = true; bool success = true;
// Relocate pages in the relocation set // Relocate pages in the relocation set
for (ZPage* page; iter->next(&page);) { for (ZForwarding* forwarding; iter->next(&forwarding);) {
// Relocate objects in page // Relocate objects in page
ZForwarding* const forwarding = forwarding_for_page(page);
ZRelocateObjectClosure cl(this, forwarding); ZRelocateObjectClosure cl(this, forwarding);
page->object_iterate(&cl); forwarding->page()->object_iterate(&cl);
if (ZVerifyForwarding) { if (ZVerifyForwarding) {
forwarding->verify(page->object_max_count(), page->live_objects()); forwarding->verify();
} }
if (forwarding->is_pinned()) { if (forwarding->is_pinned()) {
@ -193,9 +187,7 @@ bool ZRelocate::work(ZRelocationSetParallelIterator* iter) {
success = false; success = false;
} else { } else {
// Relocation succeeded, release page // Relocation succeeded, release page
if (forwarding->dec_refcount()) { forwarding->release_page();
ZHeap::heap()->free_page(page, true /* reclaimed */);
}
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,24 +22,35 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc/z/zForwarding.hpp"
#include "gc/z/zRelocationSet.hpp" #include "gc/z/zRelocationSet.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.hpp"
ZRelocationSet::ZRelocationSet() : ZRelocationSet::ZRelocationSet() :
_pages(NULL), _forwardings(NULL),
_npages(0) {} _nforwardings(0) {}
void ZRelocationSet::populate(const ZPage* const* group0, size_t ngroup0, void ZRelocationSet::populate(ZPage* const* group0, size_t ngroup0,
const ZPage* const* group1, size_t ngroup1) { ZPage* const* group1, size_t ngroup1) {
_npages = ngroup0 + ngroup1; _nforwardings = ngroup0 + ngroup1;
_pages = REALLOC_C_HEAP_ARRAY(ZPage*, _pages, _npages, mtGC); _forwardings = REALLOC_C_HEAP_ARRAY(ZForwarding*, _forwardings, _nforwardings, mtGC);
if (_pages != NULL) { size_t j = 0;
if (group0 != NULL) {
memcpy(_pages, group0, ngroup0 * sizeof(ZPage*)); // Populate group 0
} for (size_t i = 0; i < ngroup0; i++) {
if (group1 != NULL) { _forwardings[j++] = ZForwarding::create(group0[i]);
memcpy(_pages + ngroup0, group1, ngroup1 * sizeof(ZPage*)); }
}
// 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;
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,20 +26,22 @@
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
class ZForwarding;
class ZPage; class ZPage;
class ZRelocationSet { class ZRelocationSet {
template <bool> friend class ZRelocationSetIteratorImpl; template <bool> friend class ZRelocationSetIteratorImpl;
private: private:
ZPage** _pages; ZForwarding** _forwardings;
size_t _npages; size_t _nforwardings;
public: public:
ZRelocationSet(); ZRelocationSet();
void populate(const ZPage* const* group0, size_t ngroup0, void populate(ZPage* const* group0, size_t ngroup0,
const ZPage* const* group1, size_t ngroup1); ZPage* const* group1, size_t ngroup1);
void reset();
}; };
template <bool parallel> template <bool parallel>
@ -51,7 +53,7 @@ private:
public: public:
ZRelocationSetIteratorImpl(ZRelocationSet* relocation_set); ZRelocationSetIteratorImpl(ZRelocationSet* relocation_set);
bool next(ZPage** page); bool next(ZForwarding** forwarding);
}; };
// Iterator types // Iterator types

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -33,20 +33,20 @@ inline ZRelocationSetIteratorImpl<parallel>::ZRelocationSetIteratorImpl(ZRelocat
_next(0) {} _next(0) {}
template <bool parallel> template <bool parallel>
inline bool ZRelocationSetIteratorImpl<parallel>::next(ZPage** page) { inline bool ZRelocationSetIteratorImpl<parallel>::next(ZForwarding** forwarding) {
const size_t npages = _relocation_set->_npages; const size_t nforwardings = _relocation_set->_nforwardings;
if (parallel) { if (parallel) {
if (_next < npages) { if (_next < nforwardings) {
const size_t next = Atomic::add(1u, &_next) - 1u; const size_t next = Atomic::add(1u, &_next) - 1u;
if (next < npages) { if (next < nforwardings) {
*page = _relocation_set->_pages[next]; *forwarding = _relocation_set->_forwardings[next];
return true; return true;
} }
} }
} else { } else {
if (_next < npages) { if (_next < nforwardings) {
*page = _relocation_set->_pages[_next++]; *forwarding = _relocation_set->_forwardings[_next++];
return true; return true;
} }
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -44,10 +44,10 @@ ZRelocationSetSelectorGroup::ZRelocationSetSelectorGroup(const char* name,
_fragmentation(0) {} _fragmentation(0) {}
ZRelocationSetSelectorGroup::~ZRelocationSetSelectorGroup() { 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) { if (garbage > _fragmentation_limit) {
_registered_pages.add(page); _registered_pages.add(page);
} else { } else {
@ -67,13 +67,13 @@ void ZRelocationSetSelectorGroup::semi_sort() {
size_t partitions[npartitions]; size_t partitions[npartitions];
// Allocate destination array // 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*))); debug_only(memset(_sorted_pages, 0, npages * sizeof(ZPage*)));
// Calculate partition slots // Calculate partition slots
memset(partitions, 0, sizeof(partitions)); memset(partitions, 0, sizeof(partitions));
ZArrayIterator<const ZPage*> iter1(&_registered_pages); ZArrayIterator<ZPage*> iter1(&_registered_pages);
for (const ZPage* page; iter1.next(&page);) { for (ZPage* page; iter1.next(&page);) {
const size_t index = page->live_bytes() >> partition_size_shift; const size_t index = page->live_bytes() >> partition_size_shift;
partitions[index]++; partitions[index]++;
} }
@ -87,8 +87,8 @@ void ZRelocationSetSelectorGroup::semi_sort() {
} }
// Sort pages into partitions // Sort pages into partitions
ZArrayIterator<const ZPage*> iter2(&_registered_pages); ZArrayIterator<ZPage*> iter2(&_registered_pages);
for (const ZPage* page; iter2.next(&page);) { for (ZPage* page; iter2.next(&page);) {
const size_t index = page->live_bytes() >> partition_size_shift; const size_t index = page->live_bytes() >> partition_size_shift;
const size_t finger = partitions[index]++; const size_t finger = partitions[index]++;
assert(_sorted_pages[finger] == NULL, "Invalid finger"); assert(_sorted_pages[finger] == NULL, "Invalid finger");
@ -140,7 +140,7 @@ void ZRelocationSetSelectorGroup::select() {
// Update statistics // Update statistics
_relocating = from_size; _relocating = from_size;
for (size_t i = _nselected; i < npages; i++) { 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(); _fragmentation += page->size() - page->live_bytes();
} }
@ -148,7 +148,7 @@ void ZRelocationSetSelectorGroup::select() {
_name, selected_from, selected_to, npages - _nselected); _name, selected_from, selected_to, npages - _nselected);
} }
const ZPage* const* ZRelocationSetSelectorGroup::selected() const { ZPage* const* ZRelocationSetSelectorGroup::selected() const {
return _sorted_pages; return _sorted_pages;
} }
@ -171,7 +171,7 @@ ZRelocationSetSelector::ZRelocationSetSelector() :
_garbage(0), _garbage(0),
_fragmentation(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 uint8_t type = page->type();
const size_t live = page->live_bytes(); const size_t live = page->live_bytes();
const size_t garbage = page->size() - live; const size_t garbage = page->size() - live;
@ -188,7 +188,7 @@ void ZRelocationSetSelector::register_live_page(const ZPage* page) {
_garbage += garbage; _garbage += garbage;
} }
void ZRelocationSetSelector::register_garbage_page(const ZPage* page) { void ZRelocationSetSelector::register_garbage_page(ZPage* page) {
_garbage += page->size(); _garbage += page->size();
} }

View File

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -32,16 +32,16 @@ class ZRelocationSet;
class ZRelocationSetSelectorGroup { class ZRelocationSetSelectorGroup {
private: private:
const char* const _name; const char* const _name;
const size_t _page_size; const size_t _page_size;
const size_t _object_size_limit; const size_t _object_size_limit;
const size_t _fragmentation_limit; const size_t _fragmentation_limit;
ZArray<const ZPage*> _registered_pages; ZArray<ZPage*> _registered_pages;
const ZPage** _sorted_pages; ZPage** _sorted_pages;
size_t _nselected; size_t _nselected;
size_t _relocating; size_t _relocating;
size_t _fragmentation; size_t _fragmentation;
void semi_sort(); void semi_sort();
@ -51,10 +51,10 @@ public:
size_t object_size_limit); size_t object_size_limit);
~ZRelocationSetSelectorGroup(); ~ZRelocationSetSelectorGroup();
void register_live_page(const ZPage* page, size_t garbage); void register_live_page(ZPage* page, size_t garbage);
void select(); void select();
const ZPage* const* selected() const; ZPage* const* selected() const;
size_t nselected() const; size_t nselected() const;
size_t relocating() const; size_t relocating() const;
size_t fragmentation() const; size_t fragmentation() const;
@ -71,8 +71,8 @@ private:
public: public:
ZRelocationSetSelector(); ZRelocationSetSelector();
void register_live_page(const ZPage* page); void register_live_page(ZPage* page);
void register_garbage_page(const ZPage* page); void register_garbage_page(ZPage* page);
void select(ZRelocationSet* relocation_set); void select(ZRelocationSet* relocation_set);
size_t live() const; size_t live() const;

View File

@ -22,7 +22,10 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zForwarding.inline.hpp" #include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zPage.inline.hpp"
#include "unittest.hpp" #include "unittest.hpp"
using namespace testing; using namespace testing;
@ -141,16 +144,37 @@ public:
} }
static void test(void (*function)(ZForwarding*), uint32_t size) { static void test(void (*function)(ZForwarding*), uint32_t size) {
// Setup // Create page
ZForwarding* forwarding = ZForwarding::create(0 /* start */, const ZVirtualMemory vmem(0, ZPageSizeSmall);
0 /* object_alignment_shift */, const ZPhysicalMemory pmem(ZPhysicalMemorySegment(0, ZPageSizeSmall));
size); 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 // Actual test function
(*function)(forwarding); (*function)(forwarding);
// Teardown // Teardown forwarding
ZForwarding::destroy(forwarding); ZForwarding::destroy(forwarding);
// Teardown page
page.physical_memory().clear();
page.set_inactive();
} }
// Run the given function with a few different input values. // Run the given function with a few different input values.