--- a/src/hotspot/share/gc/z/zRelocate.cpp Mon Mar 18 11:50:38 2019 +0100
+++ b/src/hotspot/share/gc/z/zRelocate.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -30,9 +30,13 @@
#include "gc/z/zRelocate.hpp"
#include "gc/z/zRelocationSet.inline.hpp"
#include "gc/z/zRootsIterator.hpp"
+#include "gc/z/zStat.hpp"
#include "gc/z/zTask.hpp"
#include "gc/z/zThreadLocalAllocBuffer.hpp"
#include "gc/z/zWorkers.hpp"
+#include "logging/log.hpp"
+
+static const ZStatCounter ZCounterRelocationContention("Contention", "Relocation Contention", ZStatUnitOpsPerSecond);
ZRelocate::ZRelocate(ZWorkers* workers) :
_workers(workers) {}
@@ -78,16 +82,93 @@
_workers->run_parallel(&task);
}
+uintptr_t ZRelocate::relocate_object_inner(ZPage* page, uintptr_t from_index, uintptr_t from_offset) const {
+ ZForwardingTableCursor cursor;
+
+ // Lookup address in forwarding table
+ const ZForwardingTableEntry entry = page->find_forwarding(from_index, &cursor);
+ if (entry.from_index() == from_index) {
+ // Already relocated, return new address
+ return entry.to_offset();
+ }
+
+ assert(ZHeap::heap()->is_object_live(ZAddress::good(from_offset)), "Should be live");
+
+ if (page->is_pinned()) {
+ // In-place forward
+ return page->insert_forwarding(from_index, from_offset, &cursor);
+ }
+
+ // Allocate object
+ const uintptr_t from_good = ZAddress::good(from_offset);
+ const size_t size = ZUtils::object_size(from_good);
+ const uintptr_t to_good = ZHeap::heap()->alloc_object_for_relocation(size);
+ if (to_good == 0) {
+ // Failed, in-place forward
+ return page->insert_forwarding(from_index, from_offset, &cursor);
+ }
+
+ // Copy object
+ ZUtils::object_copy(from_good, to_good, size);
+
+ // Update forwarding table
+ const uintptr_t to_offset = ZAddress::offset(to_good);
+ const uintptr_t to_offset_final = page->insert_forwarding(from_index, to_offset, &cursor);
+ if (to_offset_final == to_offset) {
+ // Relocation succeeded
+ return to_offset;
+ }
+
+ // Relocation contention
+ ZStatInc(ZCounterRelocationContention);
+ log_trace(gc)("Relocation contention, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT
+ ", entry: " SIZE_FORMAT ", oop: " PTR_FORMAT ", size: " SIZE_FORMAT,
+ ZThread::id(), ZThread::name(), p2i(this), cursor, from_good, size);
+
+ // Try undo allocation
+ ZHeap::heap()->undo_alloc_object_for_relocation(to_good, size);
+
+ return to_offset_final;
+}
+
+uintptr_t ZRelocate::relocate_object(ZPage* page, uintptr_t from_addr) const {
+ assert(ZHeap::heap()->is_relocating(from_addr), "Should be relocating");
+
+ const uintptr_t from_offset = ZAddress::offset(from_addr);
+ const uintptr_t from_index = (from_offset - page->start()) >> page->object_alignment_shift();
+ const uintptr_t to_offset = relocate_object_inner(page, from_index, from_offset);
+ if (from_offset == to_offset) {
+ // In-place forwarding, pin page
+ page->set_pinned();
+ }
+
+ return ZAddress::good(to_offset);
+}
+
+uintptr_t ZRelocate::forward_object(ZPage* page, uintptr_t from_addr) const {
+ assert(ZHeap::heap()->is_relocating(from_addr), "Should be relocated");
+
+ // Lookup address in forwarding table
+ const uintptr_t from_offset = ZAddress::offset(from_addr);
+ const uintptr_t from_index = (from_offset - page->start()) >> page->object_alignment_shift();
+ const ZForwardingTableEntry entry = page->find_forwarding(from_index);
+ assert(entry.from_index() == from_index, "Should be forwarded");
+
+ return ZAddress::good(entry.to_offset());
+}
+
class ZRelocateObjectClosure : public ObjectClosure {
private:
- ZPage* const _page;
+ ZRelocate* const _relocate;
+ ZPage* const _page;
public:
- ZRelocateObjectClosure(ZPage* page) :
+ ZRelocateObjectClosure(ZRelocate* relocate, ZPage* page) :
+ _relocate(relocate),
_page(page) {}
virtual void do_object(oop o) {
- _page->relocate_object(ZOop::to_address(o));
+ _relocate->relocate_object(_page, ZOop::to_address(o));
}
};
@@ -97,7 +178,7 @@
// Relocate pages in the relocation set
for (ZPage* page; iter->next(&page);) {
// Relocate objects in page
- ZRelocateObjectClosure cl(page);
+ ZRelocateObjectClosure cl(this, page);
page->object_iterate(&cl);
if (ZVerifyForwarding) {