8220587: ZGC: Break out forwarding information from ZPage
Reviewed-by: stefank, eosterlund
--- a/src/hotspot/share/gc/z/vmStructs_z.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/vmStructs_z.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -25,6 +25,7 @@
#define SHARE_GC_Z_VMSTRUCTS_Z_HPP
#include "gc/z/zCollectedHeap.hpp"
+#include "gc/z/zForwarding.hpp"
#include "gc/z/zGranuleMap.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zPageAllocator.hpp"
@@ -73,8 +74,6 @@
nonstatic_field(ZPage, _seqnum, uint32_t) \
nonstatic_field(ZPage, _virtual, const ZVirtualMemory) \
volatile_nonstatic_field(ZPage, _top, uintptr_t) \
- volatile_nonstatic_field(ZPage, _refcount, uint32_t) \
- nonstatic_field(ZPage, _forwarding, ZForwardingTable) \
\
nonstatic_field(ZPageAllocator, _physical, ZPhysicalMemoryManager) \
nonstatic_field(ZPageAllocator, _used, size_t) \
@@ -86,8 +85,7 @@
nonstatic_field(ZVirtualMemory, _start, uintptr_t) \
nonstatic_field(ZVirtualMemory, _end, uintptr_t) \
\
- nonstatic_field(ZForwardingTable, _table, ZForwardingTableEntry*) \
- nonstatic_field(ZForwardingTable, _size, size_t) \
+ nonstatic_field(ZForwarding, _nentries, const uint32_t) \
\
nonstatic_field(ZPhysicalMemoryManager, _max_capacity, const size_t) \
nonstatic_field(ZPhysicalMemoryManager, _capacity, size_t)
@@ -121,7 +119,8 @@
declare_toplevel_type(ZGranuleMapForPageTable) \
declare_toplevel_type(ZVirtualMemory) \
declare_toplevel_type(ZForwardingTable) \
- declare_toplevel_type(ZForwardingTableEntry) \
+ declare_toplevel_type(ZForwarding) \
+ declare_toplevel_type(ZForwardingEntry) \
declare_toplevel_type(ZPhysicalMemoryManager)
#endif // SHARE_GC_Z_VMSTRUCTS_Z_HPP
--- a/src/hotspot/share/gc/z/zBarrier.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zBarrier.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -98,27 +98,13 @@
uintptr_t ZBarrier::remap(uintptr_t addr) {
assert(!ZAddress::is_good(addr), "Should not be good");
assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
-
- if (ZHeap::heap()->is_relocating(addr)) {
- // Forward
- return ZHeap::heap()->forward_object(addr);
- }
-
- // Remap
- return ZAddress::good(addr);
+ return ZHeap::heap()->remap_object(addr);
}
uintptr_t ZBarrier::relocate(uintptr_t addr) {
assert(!ZAddress::is_good(addr), "Should not be good");
assert(!ZAddress::is_weak_good(addr), "Should not be weak good");
-
- if (ZHeap::heap()->is_relocating(addr)) {
- // Relocate
- return ZHeap::heap()->relocate_object(addr);
- }
-
- // Remap
- return ZAddress::good(addr);
+ return ZHeap::heap()->relocate_object(addr);
}
uintptr_t ZBarrier::relocate_or_mark(uintptr_t addr) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zForwarding.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),
+ _nentries(nentries),
+ _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");
+
+ // 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 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);
+ return forwarding;
+}
+
+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;
+
+ for (ZForwardingCursor i = 0; i < _nentries; i++) {
+ const ZForwardingEntry entry = at(&i);
+ if (entry.is_empty()) {
+ // Skip empty entries
+ continue;
+ }
+
+ // Check from index
+ guarantee(entry.from_index() < object_max_count, "Invalid from index");
+
+ // Check for duplicates
+ for (ZForwardingCursor j = i + 1; j < _nentries; j++) {
+ const ZForwardingEntry other = at(&j);
+ guarantee(entry.from_index() != other.from_index(), "Duplicate from");
+ guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
+ }
+
+ count++;
+ }
+
+ // Check number of non-null entries
+ guarantee(live_objects == count, "Count mismatch");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDING_HPP
+#define SHARE_GC_Z_ZFORWARDING_HPP
+
+#include "gc/z/zForwardingEntry.hpp"
+
+typedef uint32_t ZForwardingCursor;
+
+class ZForwarding {
+ friend class VMStructs;
+ 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;
+
+ 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);
+
+public:
+ static ZForwarding* create(uintptr_t start, size_t object_alignment_shift, uint32_t live_objects);
+ static void destroy(ZForwarding* forwarding);
+
+ uintptr_t start() const;
+ size_t object_alignment_shift() const;
+
+ bool inc_refcount();
+ bool dec_refcount();
+
+ bool is_pinned() const;
+ void set_pinned();
+
+ 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;
+};
+
+#endif // SHARE_GC_Z_ZFORWARDING_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwarding.inline.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDING_INLINE_HPP
+#define SHARE_GC_Z_ZFORWARDING_INLINE_HPP
+
+#include "gc/z/zForwarding.hpp"
+#include "gc/z/zGlobals.hpp"
+#include "gc/z/zHash.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "utilities/debug.hpp"
+
+inline uintptr_t ZForwarding::start() const {
+ return _start;
+}
+
+inline size_t ZForwarding::object_alignment_shift() const {
+ return _object_alignment_shift;
+}
+
+inline bool ZForwarding::inc_refcount() {
+ uint32_t refcount = Atomic::load(&_refcount);
+
+ while (refcount > 0) {
+ const uint32_t old_refcount = refcount;
+ const uint32_t new_refcount = old_refcount + 1;
+ const uint32_t prev_refcount = Atomic::cmpxchg(new_refcount, &_refcount, old_refcount);
+ if (prev_refcount == old_refcount) {
+ return true;
+ }
+
+ refcount = prev_refcount;
+ }
+
+ return false;
+}
+
+inline bool ZForwarding::dec_refcount() {
+ assert(_refcount > 0, "Invalid state");
+ return Atomic::sub(1u, &_refcount) == 0u;
+}
+
+inline bool ZForwarding::is_pinned() const {
+ return Atomic::load(&_pinned);
+}
+
+inline void ZForwarding::set_pinned() {
+ Atomic::store(true, &_pinned);
+}
+
+inline ZForwardingEntry* ZForwarding::entries() const {
+ return reinterpret_cast<ZForwardingEntry*>(reinterpret_cast<uintptr_t>(this) + sizeof(*this));
+}
+
+inline ZForwardingEntry ZForwarding::at(ZForwardingCursor* cursor) const {
+ return Atomic::load(entries() + *cursor);
+}
+
+inline ZForwardingEntry ZForwarding::first(uintptr_t from_index, ZForwardingCursor* cursor) const {
+ const uint32_t mask = _nentries - 1;
+ const uint32_t hash = ZHash::uint32_to_uint32((uint32_t)from_index);
+ *cursor = hash & mask;
+ return at(cursor);
+}
+
+inline ZForwardingEntry ZForwarding::next(ZForwardingCursor* cursor) const {
+ const uint32_t mask = _nentries - 1;
+ *cursor = (*cursor + 1) & mask;
+ return at(cursor);
+}
+
+inline ZForwardingEntry ZForwarding::find(uintptr_t from_index) const {
+ ZForwardingCursor dummy;
+ return find(from_index, &dummy);
+}
+
+inline ZForwardingEntry ZForwarding::find(uintptr_t from_index, ZForwardingCursor* cursor) const {
+ // Reading entries in the table races with the atomic CAS done for
+ // insertion into the table. This is safe because each entry is at
+ // most updated once (from -1 to something else).
+ ZForwardingEntry entry = first(from_index, cursor);
+ while (!entry.is_empty()) {
+ if (entry.from_index() == from_index) {
+ // Match found, return matching entry
+ return entry;
+ }
+
+ entry = next(cursor);
+ }
+
+ // Match not found, return empty entry
+ return entry;
+}
+
+inline uintptr_t ZForwarding::insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingCursor* cursor) {
+ const ZForwardingEntry new_entry(from_index, to_offset);
+ const ZForwardingEntry old_entry; // empty
+
+ for (;;) {
+ const ZForwardingEntry prev_entry = Atomic::cmpxchg(new_entry, entries() + *cursor, old_entry);
+ if (prev_entry.is_empty()) {
+ // Success
+ return to_offset;
+ }
+
+ // Find next empty or matching entry
+ ZForwardingEntry entry = at(cursor);
+ while (!entry.is_empty()) {
+ if (entry.from_index() == from_index) {
+ // Match found, return already inserted address
+ return entry.to_offset();
+ }
+
+ entry = next(cursor);
+ }
+ }
+}
+
+#endif // SHARE_GC_Z_ZFORWARDING_INLINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/z/zForwardingEntry.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -0,0 +1,97 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_Z_ZFORWARDINGENTRY_HPP
+#define SHARE_GC_Z_ZFORWARDINGENTRY_HPP
+
+#include "gc/z/zBitField.hpp"
+#include "memory/allocation.hpp"
+#include "metaprogramming/primitiveConversions.hpp"
+
+//
+// Forwarding entry layout
+// -----------------------
+//
+// 6 4 4 0
+// 3 2 1 0
+// +------------------------+-----------------------------------------------+
+// |11111111 11111111 111111|11 11111111 11111111 11111111 11111111 11111111|
+// +------------------------+-----------------------------------------------+
+// | |
+// | * 41-0 To Object Offset (42-bits)
+// |
+// * 63-42 From Object Index (22-bits)
+//
+
+class ZForwardingEntry {
+ friend struct PrimitiveConversions;
+
+private:
+ typedef ZBitField<uint64_t, size_t, 0, 42> field_to_offset;
+ typedef ZBitField<uint64_t, size_t, 42, 22> field_from_index;
+
+ uint64_t _entry;
+
+ static uintptr_t empty() {
+ return (uintptr_t)-1;
+ }
+
+public:
+ ZForwardingEntry() :
+ _entry(empty()) {}
+
+ ZForwardingEntry(size_t from_index, size_t to_offset) :
+ _entry(field_from_index::encode(from_index) |
+ field_to_offset::encode(to_offset)) {}
+
+ bool is_empty() const {
+ return _entry == empty();
+ }
+
+ size_t to_offset() const {
+ return field_to_offset::decode(_entry);
+ }
+
+ size_t from_index() const {
+ return field_from_index::decode(_entry);
+ }
+};
+
+// Needed to allow atomic operations on ZForwardingEntry
+template <>
+struct PrimitiveConversions::Translate<ZForwardingEntry> : public TrueType {
+ typedef ZForwardingEntry Value;
+ typedef uint64_t Decayed;
+
+ static Decayed decay(Value v) {
+ return v._entry;
+ }
+
+ static Value recover(Decayed d) {
+ ZForwardingEntry entry;
+ entry._entry = d;
+ return entry;
+ }
+};
+
+#endif // SHARE_GC_Z_ZFORWARDINGENTRY_HPP
--- a/src/hotspot/share/gc/z/zForwardingTable.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zForwardingTable.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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,63 +22,49 @@
*/
#include "precompiled.hpp"
+#include "gc/z/zForwarding.hpp"
#include "gc/z/zForwardingTable.inline.hpp"
-#include "gc/z/zUtils.inline.hpp"
-#include "memory/allocation.inline.hpp"
+#include "gc/z/zGranuleMap.inline.hpp"
#include "utilities/debug.hpp"
-void ZForwardingTable::setup(size_t live_objects) {
- assert(is_null(), "Should be empty");
- assert(live_objects > 0, "Invalid size");
+ZForwardingTable::ZForwardingTable() :
+ _map() {}
- // 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.
- _size = ZUtils::round_up_power_of_2(live_objects * 2);
- _table = MallocArrayAllocator<ZForwardingTableEntry>::allocate(_size, mtGC);
+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);
- // Construct table entries
- for (size_t i = 0; i < _size; i++) {
- ::new (_table + i) ZForwardingTableEntry();
- }
+ // Insert into forwarding table
+ const uintptr_t addr = ZAddress::good(start);
+ assert(get(addr) == NULL, "Invalid entry");
+ _map.put(addr, size, forwarding);
}
-void ZForwardingTable::reset() {
- // Destruct table entries
- for (size_t i = 0; i < _size; i++) {
- (_table + i)->~ZForwardingTableEntry();
- }
+void ZForwardingTable::clear() {
+ ZForwarding* prev_forwarding = NULL;
- // Free table
- MallocArrayAllocator<ZForwardingTableEntry>::free(_table);
- _table = NULL;
- _size = 0;
-}
-
-void ZForwardingTable::verify(size_t object_max_count, size_t live_objects) const {
- size_t count = 0;
-
- for (size_t i = 0; i < _size; i++) {
- const ZForwardingTableEntry entry = _table[i];
- if (entry.is_empty()) {
- // Skip empty entries
+ // 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;
}
- // Check from index
- guarantee(entry.from_index() < object_max_count, "Invalid from index");
+ // Clear entry
+ *entry = NULL;
- // Check for duplicates
- for (size_t j = i + 1; j < _size; j++) {
- const ZForwardingTableEntry other = _table[j];
- guarantee(entry.from_index() != other.from_index(), "Duplicate from");
- guarantee(entry.to_offset() != other.to_offset(), "Duplicate to");
+ // 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;
}
-
- count++;
}
-
- // Check number of non-null entries
- guarantee(live_objects == count, "Count mismatch");
}
--- a/src/hotspot/share/gc/z/zForwardingTable.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zForwardingTable.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -24,36 +24,24 @@
#ifndef SHARE_GC_Z_ZFORWARDINGTABLE_HPP
#define SHARE_GC_Z_ZFORWARDINGTABLE_HPP
-#include "gc/z/zForwardingTableEntry.hpp"
-#include "memory/allocation.hpp"
+#include "gc/z/zGranuleMap.hpp"
-typedef size_t ZForwardingTableCursor;
+class ZForwarding;
class ZForwardingTable {
- friend class VMStructs;
- friend class ZForwardingTableTest;
-
private:
- ZForwardingTableEntry* _table;
- size_t _size;
-
- ZForwardingTableEntry at(ZForwardingTableCursor* cursor) const;
- ZForwardingTableEntry first(uintptr_t from_index, ZForwardingTableCursor* cursor) const;
- ZForwardingTableEntry next(ZForwardingTableCursor* cursor) const;
+ ZGranuleMap<ZForwarding*> _map;
public:
ZForwardingTable();
- ~ZForwardingTable();
- bool is_null() const;
- void setup(size_t live_objects);
- void reset();
+ ZForwarding* get(uintptr_t addr) const;
- ZForwardingTableEntry find(uintptr_t from_index) const;
- ZForwardingTableEntry find(uintptr_t from_index, ZForwardingTableCursor* cursor) const;
- uintptr_t insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor);
-
- void verify(size_t object_max_count, size_t live_objects) const;
+ void insert(uintptr_t start,
+ size_t size,
+ size_t object_alignment_shift,
+ uint32_t live_objects);
+ void clear();
};
#endif // SHARE_GC_Z_ZFORWARDINGTABLE_HPP
--- a/src/hotspot/share/gc/z/zForwardingTable.inline.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zForwardingTable.inline.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -25,85 +25,10 @@
#define SHARE_GC_Z_ZFORWARDINGTABLE_INLINE_HPP
#include "gc/z/zForwardingTable.hpp"
-#include "gc/z/zGlobals.hpp"
-#include "gc/z/zHash.inline.hpp"
-#include "runtime/atomic.hpp"
-#include "utilities/debug.hpp"
-
-inline ZForwardingTable::ZForwardingTable() :
- _table(NULL),
- _size(0) {}
-
-inline ZForwardingTable::~ZForwardingTable() {
- assert(is_null(), "Should be empty");
-}
-
-inline ZForwardingTableEntry ZForwardingTable::at(ZForwardingTableCursor* cursor) const {
- return _table[*cursor];
-}
-
-inline ZForwardingTableEntry ZForwardingTable::first(uintptr_t from_index, ZForwardingTableCursor* cursor) const {
- const size_t mask = _size - 1;
- const size_t hash = ZHash::uint32_to_uint32((uint32_t)from_index);
- *cursor = hash & mask;
- return at(cursor);
-}
-
-inline ZForwardingTableEntry ZForwardingTable::next(ZForwardingTableCursor* cursor) const {
- const size_t mask = _size - 1;
- *cursor = (*cursor + 1) & mask;
- return at(cursor);
-}
-
-inline bool ZForwardingTable::is_null() const {
- return _table == NULL;
-}
-
-inline ZForwardingTableEntry ZForwardingTable::find(uintptr_t from_index) const {
- ZForwardingTableCursor dummy;
- return find(from_index, &dummy);
-}
+#include "gc/z/zGranuleMap.inline.hpp"
-inline ZForwardingTableEntry ZForwardingTable::find(uintptr_t from_index, ZForwardingTableCursor* cursor) const {
- // Reading entries in the table races with the atomic CAS done for
- // insertion into the table. This is safe because each entry is at
- // most updated once (from -1 to something else).
- ZForwardingTableEntry entry = first(from_index, cursor);
- while (!entry.is_empty()) {
- if (entry.from_index() == from_index) {
- // Match found, return matching entry
- return entry;
- }
-
- entry = next(cursor);
- }
-
- // Match not found, return empty entry
- return entry;
-}
-
-inline uintptr_t ZForwardingTable::insert(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor) {
- const ZForwardingTableEntry new_entry(from_index, to_offset);
- const ZForwardingTableEntry old_entry; // empty
-
- for (;;) {
- const ZForwardingTableEntry prev_entry = Atomic::cmpxchg(new_entry, _table + *cursor, old_entry);
- if (prev_entry.is_empty()) {
- // Success
- return to_offset;
- }
-
- // Find next empty or matching entry
- ZForwardingTableEntry entry = at(cursor);
- while (!entry.is_empty()) {
- if (entry.from_index() == from_index) {
- // Match found, return already inserted address
- return entry.to_offset();
- }
-
- entry = next(cursor);
- }
- }
+inline ZForwarding* ZForwardingTable::get(uintptr_t addr) const {
+ return _map.get(addr);
}
#endif // SHARE_GC_Z_ZFORWARDINGTABLE_INLINE_HPP
--- a/src/hotspot/share/gc/z/zForwardingTableEntry.hpp Mon Mar 18 11:50:39 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
-#define SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
-
-#include "gc/z/zBitField.hpp"
-#include "memory/allocation.hpp"
-#include "metaprogramming/primitiveConversions.hpp"
-
-//
-// Forwarding table entry layout
-// -----------------------------
-//
-// 6 4 4 0
-// 3 2 1 0
-// +------------------------+-----------------------------------------------+
-// |11111111 11111111 111111|11 11111111 11111111 11111111 11111111 11111111|
-// +------------------------+-----------------------------------------------+
-// | |
-// | * 41-0 To Object Offset (42-bits)
-// |
-// * 63-42 From Object Index (22-bits)
-//
-
-class ZForwardingTableEntry {
- friend struct PrimitiveConversions;
-
-private:
- typedef ZBitField<uint64_t, size_t, 0, 42> field_to_offset;
- typedef ZBitField<uint64_t, size_t, 42, 22> field_from_index;
-
- uint64_t _entry;
-
- static uintptr_t empty() {
- return (uintptr_t)-1;
- }
-
-public:
- ZForwardingTableEntry() :
- _entry(empty()) {}
-
- ZForwardingTableEntry(size_t from_index, size_t to_offset) :
- _entry(field_from_index::encode(from_index) |
- field_to_offset::encode(to_offset)) {}
-
- bool is_empty() const {
- return _entry == empty();
- }
-
- size_t to_offset() const {
- return field_to_offset::decode(_entry);
- }
-
- size_t from_index() const {
- return field_from_index::decode(_entry);
- }
-};
-
-// Needed to allow atomic operations on ZForwardingTableEntry
-template <>
-struct PrimitiveConversions::Translate<ZForwardingTableEntry> : public TrueType {
- typedef ZForwardingTableEntry Value;
- typedef uint64_t Decayed;
-
- static Decayed decay(Value v) {
- return v._entry;
- }
-
- static Value recover(Decayed d) {
- ZForwardingTableEntry entry;
- entry._entry = d;
- return entry;
- }
-};
-
-#endif // SHARE_GC_Z_ZFORWARDINGTABLEENTRY_HPP
--- a/src/hotspot/share/gc/z/zGranuleMap.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zGranuleMap.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -46,6 +46,7 @@
T get(uintptr_t addr) const;
void put(uintptr_t addr, T value);
+ void put(uintptr_t addr, size_t size, T value);
};
template <typename T>
@@ -58,6 +59,7 @@
ZGranuleMapIterator(const ZGranuleMap<T>* map);
bool next(T* value);
+ bool next(T** value);
};
#endif // SHARE_GC_Z_ZGRANULEMAP_HPP
--- a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -66,6 +66,17 @@
}
template <typename T>
+inline void ZGranuleMap<T>::put(uintptr_t addr, size_t size, T value) {
+ assert(is_aligned(size, ZGranuleSize), "Misaligned");
+
+ const size_t start_index = index_for_addr(addr);
+ const size_t end_index = start_index + (size >> ZGranuleSizeShift);
+ for (size_t index = start_index; index < end_index; index++) {
+ _map[index] = value;
+ }
+}
+
+template <typename T>
inline ZGranuleMapIterator<T>::ZGranuleMapIterator(const ZGranuleMap<T>* map) :
_map(map),
_next(0) {}
@@ -81,4 +92,15 @@
return false;
}
+template <typename T>
+inline bool ZGranuleMapIterator<T>::next(T** value) {
+ if (_next < _map->size()) {
+ *value = _map->_map + _next++;
+ return true;
+ }
+
+ // End of map
+ return false;
+}
+
#endif // SHARE_GC_Z_ZGRANULEMAP_INLINE_HPP
--- a/src/hotspot/share/gc/z/zHeap.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zHeap.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -64,6 +64,7 @@
_object_allocator(_workers.nworkers()),
_page_allocator(heap_min_size(), heap_max_size(), heap_max_reserve_size()),
_pagetable(),
+ _forwarding_table(),
_mark(&_workers, &_pagetable),
_reference_processor(&_workers),
_weak_roots_processor(&_workers),
@@ -234,17 +235,11 @@
log_trace(gc)("Undo page allocation, thread: " PTR_FORMAT " (%s), page: " PTR_FORMAT ", size: " SIZE_FORMAT,
ZThread::id(), ZThread::name(), p2i(page), page->size());
- release_page(page, false /* reclaimed */);
+ free_page(page, false /* reclaimed */);
}
-bool ZHeap::retain_page(ZPage* page) {
- return page->inc_refcount();
-}
-
-void ZHeap::release_page(ZPage* page, bool reclaimed) {
- if (page->dec_refcount()) {
- _page_allocator.free_page(page, reclaimed);
- }
+void ZHeap::free_page(ZPage* page, bool reclaimed) {
+ _page_allocator.free_page(page, reclaimed);
}
void ZHeap::before_flip() {
@@ -437,7 +432,7 @@
selector.register_garbage_page(page);
// Reclaim page immediately
- release_page(page, true /* reclaimed */);
+ free_page(page, true /* reclaimed */);
}
}
@@ -454,23 +449,17 @@
void ZHeap::prepare_relocation_set() {
ZRelocationSetIterator iter(&_relocation_set);
for (ZPage* page; iter.next(&page);) {
- // Prepare for relocation
- page->set_forwarding();
-
- // Update pagetable
- _pagetable.set_relocating(page);
+ // Setup forwarding for page
+ _forwarding_table.insert(page->start(),
+ page->size(),
+ page->object_alignment_shift(),
+ page->live_objects());
}
}
void ZHeap::reset_relocation_set() {
- ZRelocationSetIterator iter(&_relocation_set);
- for (ZPage* page; iter.next(&page);) {
- // Reset relocation information
- page->reset_forwarding();
-
- // Update pagetable
- _pagetable.clear_relocating(page);
- }
+ // Clear forwarding table
+ _forwarding_table.clear();
}
void ZHeap::relocate_start() {
@@ -493,25 +482,6 @@
_relocate.start();
}
-uintptr_t ZHeap::relocate_object(uintptr_t addr) {
- assert(ZGlobalPhase == ZPhaseRelocate, "Relocate not allowed");
- ZPage* const page = _pagetable.get(addr);
- const bool retained = retain_page(page);
- const uintptr_t new_addr = _relocate.relocate_object(page, addr);
- if (retained) {
- release_page(page, true /* reclaimed */);
- }
-
- return new_addr;
-}
-
-uintptr_t ZHeap::forward_object(uintptr_t addr) {
- assert(ZGlobalPhase == ZPhaseMark ||
- ZGlobalPhase == ZPhaseMarkCompleted, "Forward not allowed");
- ZPage* const page = _pagetable.get(addr);
- return _relocate.forward_object(page, addr);
-}
-
void ZHeap::relocate() {
// Relocate relocation set
const bool success = _relocate.relocate(&_relocation_set);
--- a/src/hotspot/share/gc/z/zHeap.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zHeap.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -27,6 +27,7 @@
#include "gc/shared/gcTimer.hpp"
#include "gc/z/zAllocationFlags.hpp"
#include "gc/z/zArray.hpp"
+#include "gc/z/zForwardingTable.hpp"
#include "gc/z/zList.hpp"
#include "gc/z/zLock.hpp"
#include "gc/z/zMark.hpp"
@@ -55,6 +56,7 @@
ZObjectAllocator _object_allocator;
ZPageAllocator _page_allocator;
ZPageTable _pagetable;
+ ZForwardingTable _forwarding_table;
ZMark _mark;
ZReferenceProcessor _reference_processor;
ZWeakRootsProcessor _weak_roots_processor;
@@ -123,8 +125,7 @@
// Page allocation
ZPage* alloc_page(uint8_t type, size_t size, ZAllocationFlags flags);
void undo_alloc_page(ZPage* page);
- bool retain_page(ZPage* page);
- void release_page(ZPage* page, bool reclaimed);
+ void free_page(ZPage* page, bool reclaimed);
// Object allocation
uintptr_t alloc_tlab(size_t size);
@@ -152,10 +153,10 @@
void reset_relocation_set();
// Relocation
- bool is_relocating(uintptr_t addr) const;
+ ZForwarding* forwarding(uintptr_t addr);
void relocate_start();
uintptr_t relocate_object(uintptr_t addr);
- uintptr_t forward_object(uintptr_t addr);
+ uintptr_t remap_object(uintptr_t addr);
void relocate();
// Iteration
--- a/src/hotspot/share/gc/z/zHeap.inline.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zHeap.inline.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -25,6 +25,8 @@
#define SHARE_GC_Z_ZHEAP_INLINE_HPP
#include "gc/z/zAddress.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "gc/z/zForwardingTable.inline.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zMark.inline.hpp"
#include "gc/z/zOop.inline.hpp"
@@ -42,8 +44,8 @@
return &_reference_processor;
}
-inline bool ZHeap::is_relocating(uintptr_t addr) const {
- return _pagetable.is_relocating(addr);
+inline ZForwarding* ZHeap::forwarding(uintptr_t addr) {
+ return _forwarding_table.get(addr);
}
inline bool ZHeap::is_object_live(uintptr_t addr) const {
@@ -89,6 +91,40 @@
_object_allocator.undo_alloc_object_for_relocation(page, addr, size);
}
+inline uintptr_t ZHeap::relocate_object(uintptr_t addr) {
+ assert(ZGlobalPhase == ZPhaseRelocate, "Relocate not allowed");
+
+ ZForwarding* const forwarding = _forwarding_table.get(addr);
+ if (forwarding == NULL) {
+ // Not forwarding
+ return ZAddress::good(addr);
+ }
+
+ // Relocate object
+ const bool retained = forwarding->inc_refcount();
+ 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 */);
+ }
+
+ return new_addr;
+}
+
+inline uintptr_t ZHeap::remap_object(uintptr_t addr) {
+ assert(ZGlobalPhase == ZPhaseMark ||
+ ZGlobalPhase == ZPhaseMarkCompleted, "Forward not allowed");
+
+ ZForwarding* const forwarding = _forwarding_table.get(addr);
+ if (forwarding == NULL) {
+ // Not forwarding
+ return ZAddress::good(addr);
+ }
+
+ // Forward object
+ return _relocate.forward_object(forwarding, addr);
+}
+
inline bool ZHeap::is_alloc_stalled() const {
return _page_allocator.is_alloc_stalled();
}
--- a/src/hotspot/share/gc/z/zPage.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zPage.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -31,14 +31,12 @@
ZPage::ZPage(uint8_t type, ZVirtualMemory vmem, ZPhysicalMemory pmem) :
_type(type),
- _pinned(0),
+ _active(0),
_numa_id((uint8_t)-1),
_seqnum(0),
_virtual(vmem),
_top(start()),
_livemap(object_max_count()),
- _refcount(0),
- _forwarding(),
_physical(pmem) {
assert(!_physical.is_null(), "Should not be null");
assert(!_virtual.is_null(), "Should not be null");
@@ -55,7 +53,6 @@
void ZPage::reset() {
assert(!is_active(), "Should not be active");
- assert(!is_pinned(), "Should not be pinned");
assert(!is_detached(), "Should not be detached");
_seqnum = ZGlobalSeqNum;
@@ -66,16 +63,14 @@
// the reset of the above fields are visible.
OrderAccess::storestore();
- _refcount = 1;
+ _active = 1;
}
void ZPage::print_on(outputStream* out) const {
- out->print_cr(" %-6s " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s%s%s%s%s%s",
+ out->print_cr(" %-6s " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " %s%s%s%s",
type_to_string(), start(), top(), end(),
is_allocating() ? " Allocating" : "",
is_relocatable() ? " Relocatable" : "",
- is_forwarding() ? " Forwarding" : "",
- is_pinned() ? " Pinned" : "",
is_detached() ? " Detached" : "",
!is_active() ? " Inactive" : "");
}
--- a/src/hotspot/share/gc/z/zPage.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zPage.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -24,7 +24,6 @@
#ifndef SHARE_GC_Z_ZPAGE_HPP
#define SHARE_GC_Z_ZPAGE_HPP
-#include "gc/z/zForwardingTable.hpp"
#include "gc/z/zList.hpp"
#include "gc/z/zLiveMap.hpp"
#include "gc/z/zPhysicalMemory.hpp"
@@ -38,7 +37,7 @@
private:
// Always hot
const uint8_t _type; // Page type
- volatile uint8_t _pinned; // Pinned flag
+ volatile uint8_t _active; // Active flag
uint8_t _numa_id; // NUMA node affinity
uint32_t _seqnum; // Allocation sequence number
const ZVirtualMemory _virtual; // Virtual start/end address
@@ -46,13 +45,10 @@
ZLiveMap _livemap; // Live map
// Hot when relocated and cached
- volatile uint32_t _refcount; // Page reference count
- ZForwardingTable _forwarding; // Forwarding table
ZPhysicalMemory _physical; // Physical memory for page
ZListNode<ZPage> _node; // Page list node
const char* type_to_string() const;
- uint32_t object_max_count() const;
bool is_object_marked(uintptr_t addr) const;
bool is_object_strongly_marked(uintptr_t addr) const;
@@ -61,6 +57,7 @@
ZPage(uint8_t type, ZVirtualMemory vmem, ZPhysicalMemory pmem);
~ZPage();
+ uint32_t object_max_count() const;
size_t object_alignment_shift() const;
size_t object_alignment() const;
@@ -78,15 +75,14 @@
void reset();
- bool inc_refcount();
- bool dec_refcount();
-
bool is_in(uintptr_t addr) const;
uintptr_t block_start(uintptr_t addr) const;
bool block_is_obj(uintptr_t addr) const;
bool is_active() const;
+ void set_inactive();
+
bool is_allocating() const;
bool is_relocatable() const;
bool is_detached() const;
@@ -94,23 +90,13 @@
bool is_mapped() const;
void set_pre_mapped();
- bool is_pinned() const;
- void set_pinned();
-
- bool is_forwarding() const;
- void set_forwarding();
- void reset_forwarding();
- ZForwardingTableEntry find_forwarding(uintptr_t from_index);
- ZForwardingTableEntry find_forwarding(uintptr_t from_index, ZForwardingTableCursor* cursor);
- uintptr_t insert_forwarding(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor);
- void verify_forwarding() const;
-
bool is_marked() const;
bool is_object_live(uintptr_t addr) const;
bool is_object_strongly_live(uintptr_t addr) const;
bool mark_object(uintptr_t addr, bool finalizable, bool& inc_live);
void inc_live_atomic(uint32_t objects, size_t bytes);
+ uint32_t live_objects() const;
size_t live_bytes() const;
void object_iterate(ObjectClosure* cl);
--- a/src/hotspot/share/gc/z/zPage.inline.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zPage.inline.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -25,7 +25,6 @@
#define SHARE_GC_Z_ZPAGE_INLINE_HPP
#include "gc/z/zAddress.inline.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
#include "gc/z/zGlobals.hpp"
#include "gc/z/zLiveMap.inline.hpp"
#include "gc/z/zMark.hpp"
@@ -35,6 +34,7 @@
#include "gc/z/zVirtualMemory.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
+#include "runtime/orderAccess.hpp"
#include "utilities/align.hpp"
#include "utilities/debug.hpp"
@@ -132,20 +132,6 @@
return _numa_id;
}
-inline bool ZPage::inc_refcount() {
- for (uint32_t prev_refcount = _refcount; prev_refcount > 0; prev_refcount = _refcount) {
- if (Atomic::cmpxchg(prev_refcount + 1, &_refcount, prev_refcount) == prev_refcount) {
- return true;
- }
- }
- return false;
-}
-
-inline bool ZPage::dec_refcount() {
- assert(is_active(), "Should be active");
- return Atomic::sub(1u, &_refcount) == 0;
-}
-
inline bool ZPage::is_in(uintptr_t addr) const {
const uintptr_t offset = ZAddress::offset(addr);
return offset >= start() && offset < top();
@@ -164,7 +150,11 @@
}
inline bool ZPage::is_active() const {
- return _refcount > 0;
+ return OrderAccess::load_acquire(&_active) != 0;
+}
+
+inline void ZPage::set_inactive() {
+ OrderAccess::release_store(&_active, (uint8_t)0);
}
inline bool ZPage::is_allocating() const {
@@ -190,44 +180,6 @@
_seqnum = 1;
}
-inline bool ZPage::is_pinned() const {
- return _pinned;
-}
-
-inline void ZPage::set_pinned() {
- _pinned = 1;
-}
-
-inline bool ZPage::is_forwarding() const {
- return !_forwarding.is_null();
-}
-
-inline void ZPage::set_forwarding() {
- assert(is_marked(), "Should be marked");
- _forwarding.setup(_livemap.live_objects());
-}
-
-inline void ZPage::reset_forwarding() {
- _forwarding.reset();
- _pinned = 0;
-}
-
-inline ZForwardingTableEntry ZPage::find_forwarding(uintptr_t from_index) {
- return _forwarding.find(from_index);
-}
-
-inline ZForwardingTableEntry ZPage::find_forwarding(uintptr_t from_index, ZForwardingTableCursor* cursor) {
- return _forwarding.find(from_index, cursor);
-}
-
-inline uintptr_t ZPage::insert_forwarding(uintptr_t from_index, uintptr_t to_offset, ZForwardingTableCursor* cursor) {
- return _forwarding.insert(from_index, to_offset, cursor);
-}
-
-inline void ZPage::verify_forwarding() const {
- _forwarding.verify(object_max_count(), _livemap.live_objects());
-}
-
inline bool ZPage::is_marked() const {
assert(is_relocatable(), "Invalid page state");
return _livemap.is_marked();
@@ -265,6 +217,11 @@
_livemap.inc_live_atomic(objects, bytes);
}
+inline uint32_t ZPage::live_objects() const {
+ assert(is_marked(), "Should be marked");
+ return _livemap.live_objects();
+}
+
inline size_t ZPage::live_bytes() const {
assert(is_marked(), "Should be marked");
return _livemap.live_bytes();
--- a/src/hotspot/share/gc/z/zPageAllocator.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zPageAllocator.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -469,6 +469,9 @@
// Update used statistics
decrease_used(page->size(), reclaimed);
+ // Make page inactive
+ page->set_inactive();
+
// Cache page
_cache.free_page(page);
--- a/src/hotspot/share/gc/z/zPageCache.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zPageCache.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -119,7 +119,6 @@
void ZPageCache::free_page(ZPage* page) {
assert(!page->is_active(), "Invalid page state");
- assert(!page->is_pinned(), "Invalid page state");
assert(!page->is_detached(), "Invalid page state");
const uint8_t type = page->type();
--- a/src/hotspot/share/gc/z/zRelocate.cpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zRelocate.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/z/zAddress.inline.hpp"
#include "gc/z/zBarrier.inline.hpp"
+#include "gc/z/zForwarding.inline.hpp"
#include "gc/z/zHeap.hpp"
#include "gc/z/zOopClosures.inline.hpp"
#include "gc/z/zPage.hpp"
@@ -82,11 +83,16 @@
_workers->run_parallel(&task);
}
-uintptr_t ZRelocate::relocate_object_inner(ZPage* page, uintptr_t from_index, uintptr_t from_offset) const {
- ZForwardingTableCursor cursor;
+ZForwarding* ZRelocate::forwarding_for_page(ZPage* page) const {
+ const uintptr_t addr = ZAddress::good(page->start());
+ return ZHeap::heap()->forwarding(addr);
+}
- // Lookup address in forwarding table
- const ZForwardingTableEntry entry = page->find_forwarding(from_index, &cursor);
+uintptr_t ZRelocate::relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const {
+ ZForwardingCursor cursor;
+
+ // Lookup forwarding entry
+ const ZForwardingEntry entry = forwarding->find(from_index, &cursor);
if (entry.from_index() == from_index) {
// Already relocated, return new address
return entry.to_offset();
@@ -94,9 +100,9 @@
assert(ZHeap::heap()->is_object_live(ZAddress::good(from_offset)), "Should be live");
- if (page->is_pinned()) {
+ if (forwarding->is_pinned()) {
// In-place forward
- return page->insert_forwarding(from_index, from_offset, &cursor);
+ return forwarding->insert(from_index, from_offset, &cursor);
}
// Allocate object
@@ -105,15 +111,15 @@
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);
+ return forwarding->insert(from_index, from_offset, &cursor);
}
// Copy object
ZUtils::object_copy(from_good, to_good, size);
- // Update forwarding table
+ // Insert forwarding entry
const uintptr_t to_offset = ZAddress::offset(to_good);
- const uintptr_t to_offset_final = page->insert_forwarding(from_index, to_offset, &cursor);
+ const uintptr_t to_offset_final = forwarding->insert(from_index, to_offset, &cursor);
if (to_offset_final == to_offset) {
// Relocation succeeded
return to_offset;
@@ -121,9 +127,9 @@
// 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);
+ log_trace(gc)("Relocation contention, thread: " PTR_FORMAT " (%s), forwarding: " PTR_FORMAT
+ ", entry: " UINT32_FORMAT ", oop: " PTR_FORMAT ", size: " SIZE_FORMAT,
+ ZThread::id(), ZThread::name(), p2i(forwarding), cursor, from_good, size);
// Try undo allocation
ZHeap::heap()->undo_alloc_object_for_relocation(to_good, size);
@@ -131,44 +137,40 @@
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");
+uintptr_t ZRelocate::relocate_object(ZForwarding* forwarding, uintptr_t from_addr) const {
+ const uintptr_t from_offset = ZAddress::offset(from_addr);
+ const uintptr_t from_index = (from_offset - forwarding->start()) >> forwarding->object_alignment_shift();
+ const uintptr_t to_offset = relocate_object_inner(forwarding, from_index, from_offset);
- 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();
+ forwarding->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
+uintptr_t ZRelocate::forward_object(ZForwarding* forwarding, uintptr_t from_addr) const {
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);
+ const uintptr_t from_index = (from_offset - forwarding->start()) >> forwarding->object_alignment_shift();
+ const ZForwardingEntry entry = forwarding->find(from_index);
+
assert(entry.from_index() == from_index, "Should be forwarded");
-
return ZAddress::good(entry.to_offset());
}
class ZRelocateObjectClosure : public ObjectClosure {
private:
- ZRelocate* const _relocate;
- ZPage* const _page;
+ ZRelocate* const _relocate;
+ ZForwarding* const _forwarding;
public:
- ZRelocateObjectClosure(ZRelocate* relocate, ZPage* page) :
+ ZRelocateObjectClosure(ZRelocate* relocate, ZForwarding* forwarding) :
_relocate(relocate),
- _page(page) {}
+ _forwarding(forwarding) {}
virtual void do_object(oop o) {
- _relocate->relocate_object(_page, ZOop::to_address(o));
+ _relocate->relocate_object(_forwarding, ZOop::to_address(o));
}
};
@@ -178,19 +180,22 @@
// Relocate pages in the relocation set
for (ZPage* page; iter->next(&page);) {
// Relocate objects in page
- ZRelocateObjectClosure cl(this, page);
+ ZForwarding* const forwarding = forwarding_for_page(page);
+ ZRelocateObjectClosure cl(this, forwarding);
page->object_iterate(&cl);
if (ZVerifyForwarding) {
- page->verify_forwarding();
+ forwarding->verify(page->object_max_count(), page->live_objects());
}
- if (page->is_pinned()) {
+ if (forwarding->is_pinned()) {
// Relocation failed, page is now pinned
success = false;
} else {
// Relocation succeeded, release page
- ZHeap::heap()->release_page(page, true /* reclaimed */);
+ if (forwarding->dec_refcount()) {
+ ZHeap::heap()->free_page(page, true /* reclaimed */);
+ }
}
}
--- a/src/hotspot/share/gc/z/zRelocate.hpp Mon Mar 18 11:50:39 2019 +0100
+++ b/src/hotspot/share/gc/z/zRelocate.hpp Mon Mar 18 11:50:39 2019 +0100
@@ -28,20 +28,23 @@
#include "gc/z/zWorkers.hpp"
#include "memory/allocation.hpp"
+class ZForwarding;
+
class ZRelocate {
friend class ZRelocateTask;
private:
ZWorkers* const _workers;
- uintptr_t relocate_object_inner(ZPage* from_page, uintptr_t from_index, uintptr_t from_offset) const;
+ ZForwarding* forwarding_for_page(ZPage* page) const;
+ uintptr_t relocate_object_inner(ZForwarding* forwarding, uintptr_t from_index, uintptr_t from_offset) const;
bool work(ZRelocationSetParallelIterator* iter);
public:
ZRelocate(ZWorkers* workers);
- uintptr_t relocate_object(ZPage* from_page, uintptr_t from_addr) const;
- uintptr_t forward_object(ZPage* from_page, uintptr_t from_addr) const;
+ uintptr_t relocate_object(ZForwarding* forwarding, uintptr_t from_addr) const;
+ uintptr_t forward_object(ZForwarding* forwarding, uintptr_t from_addr) const;
void start();
bool relocate(ZRelocationSet* relocation_set);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/gc/z/test_zForwarding.cpp Mon Mar 18 11:50:39 2019 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "precompiled.hpp"
+#include "gc/z/zForwarding.inline.hpp"
+#include "unittest.hpp"
+
+using namespace testing;
+
+#define CAPTURE_DELIM "\n"
+#define CAPTURE1(expression) #expression << " evaluates to " << expression
+#define CAPTURE2(e0, e1) CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
+
+#define CAPTURE(expression) CAPTURE1(expression)
+
+class ZForwardingTest : public Test {
+public:
+ // Helper functions
+
+ static bool is_power_of_2(uint32_t value) {
+ return ::is_power_of_2((intptr_t)value);
+ }
+
+ class SequenceToFromIndex : AllStatic {
+ public:
+ static uintptr_t even(uint32_t sequence_number) {
+ return sequence_number * 2;
+ }
+ static uintptr_t odd(uint32_t sequence_number) {
+ return even(sequence_number) + 1;
+ }
+ static uintptr_t one_to_one(uint32_t sequence_number) {
+ return sequence_number;
+ }
+ };
+
+ // Test functions
+
+ static void setup(ZForwarding* forwarding) {
+ EXPECT_PRED1(is_power_of_2, forwarding->_nentries) << CAPTURE(forwarding->_nentries);
+ }
+
+ static void find_empty(ZForwarding* forwarding) {
+ uint32_t size = forwarding->_nentries;
+ uint32_t entries_to_check = size * 2;
+
+ for (uint32_t i = 0; i < entries_to_check; i++) {
+ uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+ EXPECT_TRUE(forwarding->find(from_index).is_empty()) << CAPTURE2(from_index, size);
+ }
+
+ EXPECT_TRUE(forwarding->find(uintptr_t(-1)).is_empty()) << CAPTURE(size);
+ }
+
+ static void find_full(ZForwarding* forwarding) {
+ uint32_t size = forwarding->_nentries;
+ uint32_t entries_to_populate = size;
+
+ // Populate
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+ ZForwardingCursor cursor;
+ ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ forwarding->insert(from_index, from_index, &cursor);
+ }
+
+ // Verify
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
+
+ ZForwardingEntry entry = forwarding->find(from_index);
+ ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
+ ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
+ }
+ }
+
+ static void find_every_other(ZForwarding* forwarding) {
+ uint32_t size = forwarding->_nentries;
+ uint32_t entries_to_populate = size / 2;
+
+ // Populate even from indices
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::even(i);
+
+ ZForwardingCursor cursor;
+ ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ forwarding->insert(from_index, from_index, &cursor);
+ }
+
+ // Verify populated even indices
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::even(i);
+
+ ZForwardingCursor cursor;
+ ZForwardingEntry entry = forwarding->find(from_index, &cursor);
+ ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
+
+ ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
+ ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
+ }
+
+ // Verify empty odd indices
+ //
+ // This check could be done on a larger range of sequence numbers,
+ // but currently entries_to_populate is used.
+ for (uint32_t i = 0; i < entries_to_populate; i++) {
+ uintptr_t from_index = SequenceToFromIndex::odd(i);
+
+ ZForwardingEntry entry = forwarding->find(from_index);
+
+ ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
+ }
+ }
+
+ static void test(void (*function)(ZForwarding*), uint32_t size) {
+ // Setup
+ ZForwarding* forwarding = ZForwarding::create(0 /* start */,
+ 0 /* object_alignment_shift */,
+ size);
+
+ // Actual test function
+ (*function)(forwarding);
+
+ // Teardown
+ ZForwarding::destroy(forwarding);
+ }
+
+ // Run the given function with a few different input values.
+ static void test(void (*function)(ZForwarding*)) {
+ test(function, 1);
+ test(function, 2);
+ test(function, 3);
+ test(function, 4);
+ test(function, 7);
+ test(function, 8);
+ test(function, 1023);
+ test(function, 1024);
+ test(function, 1025);
+ }
+};
+
+TEST_F(ZForwardingTest, setup) {
+ test(&ZForwardingTest::setup);
+}
+
+TEST_F(ZForwardingTest, find_empty) {
+ test(&ZForwardingTest::find_empty);
+}
+
+TEST_F(ZForwardingTest, find_full) {
+ test(&ZForwardingTest::find_full);
+}
+
+TEST_F(ZForwardingTest, find_every_other) {
+ test(&ZForwardingTest::find_every_other);
+}
--- a/test/hotspot/gtest/gc/z/test_zForwardingTable.cpp Mon Mar 18 11:50:39 2019 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "precompiled.hpp"
-#include "gc/z/zForwardingTable.inline.hpp"
-#include "unittest.hpp"
-
-using namespace testing;
-
-#define CAPTURE_DELIM "\n"
-#define CAPTURE1(expression) #expression << " evaluates to " << expression
-#define CAPTURE2(e0, e1) CAPTURE1(e0) << CAPTURE_DELIM << CAPTURE1(e1)
-
-#define CAPTURE(expression) CAPTURE1(expression)
-
-class ZForwardingTableTest : public Test {
-public:
- // Helper functions
-
- static bool is_power_of_2(size_t value) {
- return ::is_power_of_2((intptr_t)value);
- }
-
- class SequenceToFromIndex : AllStatic {
- public:
- static uintptr_t even(uint32_t sequence_number) {
- return sequence_number * 2;
- }
- static uintptr_t odd(uint32_t sequence_number) {
- return even(sequence_number) + 1;
- }
- static uintptr_t one_to_one(uint32_t sequence_number) {
- return sequence_number;
- }
- };
-
- // Test functions
-
- static void setup(ZForwardingTable& table) {
- EXPECT_PRED1(is_power_of_2, table._size) << CAPTURE(table._size);
- }
-
- static void find_empty(ZForwardingTable& table) {
- size_t size = table._size;
- size_t entries_to_check = size * 2;
-
- for (uint32_t i = 0; i < entries_to_check; i++) {
- uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
- EXPECT_TRUE(table.find(from_index).is_empty()) << CAPTURE2(from_index, size);
- }
-
- EXPECT_TRUE(table.find(uintptr_t(-1)).is_empty()) << CAPTURE(size);
- }
-
- static void find_full(ZForwardingTable& table) {
- size_t size = table._size;
- size_t entries_to_populate = size;
-
- // Populate
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
- ZForwardingTableCursor cursor;
- ZForwardingTableEntry entry = table.find(from_index, &cursor);
- ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- table.insert(from_index, from_index, &cursor);
- }
-
- // Verify
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::one_to_one(i);
-
- ZForwardingTableEntry entry = table.find(from_index);
- ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
- ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
- }
- }
-
- static void find_every_other(ZForwardingTable& table) {
- size_t size = table._size;
- size_t entries_to_populate = size / 2;
-
- // Populate even from indices
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::even(i);
-
- ZForwardingTableCursor cursor;
- ZForwardingTableEntry entry = table.find(from_index, &cursor);
- ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- table.insert(from_index, from_index, &cursor);
- }
-
- // Verify populated even indices
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::even(i);
-
- ZForwardingTableCursor cursor;
- ZForwardingTableEntry entry = table.find(from_index, &cursor);
- ASSERT_FALSE(entry.is_empty()) << CAPTURE2(from_index, size);
-
- ASSERT_EQ(entry.from_index(), from_index) << CAPTURE(size);
- ASSERT_EQ(entry.to_offset(), from_index) << CAPTURE(size);
- }
-
- // Verify empty odd indices
- //
- // This check could be done on a larger range of sequence numbers,
- // but currently entries_to_populate is used.
- for (uint32_t i = 0; i < entries_to_populate; i++) {
- uintptr_t from_index = SequenceToFromIndex::odd(i);
-
- ZForwardingTableEntry entry = table.find(from_index);
-
- ASSERT_TRUE(entry.is_empty()) << CAPTURE2(from_index, size);
- }
- }
-
- static void test(void (*function)(ZForwardingTable&), uint32_t size) {
- // Setup
- ZForwardingTable table;
- table.setup(size);
- ASSERT_FALSE(table.is_null());
-
- // Actual test function
- (*function)(table);
-
- // Teardown
- table.reset();
- ASSERT_TRUE(table.is_null());
- }
-
- // Run the given function with a few different input values.
- static void test(void (*function)(ZForwardingTable&)) {
- test(function, 1);
- test(function, 2);
- test(function, 3);
- test(function, 4);
- test(function, 7);
- test(function, 8);
- test(function, 1023);
- test(function, 1024);
- test(function, 1025);
- }
-};
-
-TEST_F(ZForwardingTableTest, setup) {
- test(&ZForwardingTableTest::setup);
-}
-
-TEST_F(ZForwardingTableTest, find_empty) {
- test(&ZForwardingTableTest::find_empty);
-}
-
-TEST_F(ZForwardingTableTest, find_full) {
- test(&ZForwardingTableTest::find_full);
-}
-
-TEST_F(ZForwardingTableTest, find_every_other) {
- test(&ZForwardingTableTest::find_every_other);
-}
--- a/test/hotspot/jtreg/ProblemList-zgc.txt Mon Mar 18 11:50:39 2019 +0100
+++ b/test/hotspot/jtreg/ProblemList-zgc.txt Mon Mar 18 11:50:39 2019 +0100
@@ -27,4 +27,16 @@
#
#############################################################################
+serviceability/sa/ClhsdbInspect.java 8220624 generic-all
+serviceability/sa/ClhsdbJdis.java 8220624 generic-all
+serviceability/sa/ClhsdbJhisto.java 8220624 generic-all
+serviceability/sa/ClhsdbJstack.java 8220624 generic-all
+serviceability/sa/ClhsdbPrintAs.java 8220624 generic-all
+serviceability/sa/ClhsdbPstack.java 8220624 generic-all
+serviceability/sa/ClhsdbSource.java 8220624 generic-all
+serviceability/sa/TestClhsdbJstackLock.java 8220624 generic-all
+serviceability/sa/TestHeapDumpForInvokeDynamic.java 8220624 generic-all
+serviceability/sa/TestHeapDumpForLargeArray.java 8220624 generic-all
+serviceability/sa/TestUniverse.java 8220624 generic-all
+serviceability/sa/TestJmapCore.java 8220624 generic-all
serviceability/sa/TestJmapCoreMetaspace.java 8219443 generic-all