Skip to content
This repository was archived by the owner on Sep 19, 2023. It is now read-only.

Commit c9111d5

Browse files
committed
8310743: assert(reserved_rgn != nullptr) failed: Add committed region, No reserved region found
Reviewed-by: ayang Backport-of: f393975d1b9423835a7aa42f6ffc0656499701d7
1 parent 8d6ef6f commit c9111d5

File tree

12 files changed

+445
-48
lines changed

12 files changed

+445
-48
lines changed

src/hotspot/share/gc/z/zGlobals.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ const size_t ZGranuleSize = (size_t)1 << ZGranuleSizeShift
3838
// Virtual memory to physical memory ratio
3939
const size_t ZVirtualToPhysicalRatio = 16; // 16:1
4040

41+
// Max virtual memory ranges
42+
const size_t ZMaxVirtualReservations = 100; // Each reservation at least 1% of total
43+
4144
// Page size shifts
4245
const size_t ZPageSizeSmallShift = ZGranuleSizeShift;
4346
extern size_t ZPageSizeMediumShift;

src/hotspot/share/gc/z/zMemory.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ ZMemoryManager::ZMemoryManager()
8181
: _freelist(),
8282
_callbacks() {}
8383

84+
bool ZMemoryManager::free_is_contiguous() const {
85+
return _freelist.size() == 1;
86+
}
87+
8488
void ZMemoryManager::register_callbacks(const Callbacks& callbacks) {
8589
_callbacks = callbacks;
8690
}

src/hotspot/share/gc/z/zMemory.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ class ZMemoryManager {
8181
public:
8282
ZMemoryManager();
8383

84+
bool free_is_contiguous() const;
85+
8486
void register_callbacks(const Callbacks& callbacks);
8587

8688
zoffset peek_low_address() const;

src/hotspot/share/gc/z/zNMT.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
#include "precompiled.hpp"
25+
#include "gc/z/zAddress.inline.hpp"
26+
#include "gc/z/zGlobals.hpp"
27+
#include "gc/z/zNMT.hpp"
28+
#include "gc/z/zVirtualMemory.hpp"
29+
#include "memory/allocation.hpp"
30+
#include "services/memTracker.hpp"
31+
#include "utilities/nativeCallStack.hpp"
32+
33+
ZNMT::Reservation ZNMT::_reservations[ZMaxVirtualReservations] = {};
34+
size_t ZNMT::_num_reservations = 0;
35+
36+
size_t ZNMT::reservation_index(zoffset offset, size_t* offset_in_reservation) {
37+
assert(_num_reservations > 0, "at least one reservation must exist");
38+
39+
size_t index = 0;
40+
*offset_in_reservation = untype(offset);
41+
for (; index < _num_reservations; ++index) {
42+
const size_t reservation_size = _reservations[index]._size;
43+
if (*offset_in_reservation < reservation_size) {
44+
break;
45+
}
46+
*offset_in_reservation -= reservation_size;
47+
}
48+
49+
assert(index != _num_reservations, "failed to find reservation index");
50+
return index;
51+
}
52+
53+
void ZNMT::process_fake_mapping(zoffset offset, size_t size, bool commit) {
54+
// In order to satisfy NTM's requirement of an 1:1 mapping between committed
55+
// and reserved addresses, a fake mapping from the offset into the reservation
56+
// is used.
57+
//
58+
// These mappings from
59+
// [offset, offset + size) -> {[virtual address range], ...}
60+
// are stable after the heap has been reserved. No commits proceed any
61+
// reservations. Committing and uncommitting the same [offset, offset + size)
62+
// range will result in same virtual memory ranges.
63+
64+
size_t left_to_process = size;
65+
size_t offset_in_reservation;
66+
for (size_t i = reservation_index(offset, &offset_in_reservation); i < _num_reservations; ++i) {
67+
const zaddress_unsafe reservation_start = _reservations[i]._start;
68+
const size_t reservation_size = _reservations[i]._size;
69+
const size_t sub_range_size = MIN2(left_to_process, reservation_size - offset_in_reservation);
70+
const uintptr_t sub_range_addr = untype(reservation_start) + offset_in_reservation;
71+
72+
// commit / uncommit memory
73+
if (commit) {
74+
MemTracker::record_virtual_memory_commit((void*)sub_range_addr, sub_range_size, CALLER_PC);
75+
} else {
76+
if (MemTracker::enabled()) {
77+
Tracker tracker(Tracker::uncommit);
78+
tracker.record((address)sub_range_addr, sub_range_size);
79+
}
80+
}
81+
82+
left_to_process -= sub_range_size;
83+
if (left_to_process == 0) {
84+
// Processed all nmt registrations
85+
return;
86+
}
87+
88+
offset_in_reservation = 0;
89+
}
90+
91+
assert(left_to_process == 0, "everything was not commited");
92+
}
93+
94+
void ZNMT::reserve(zaddress_unsafe start, size_t size) {
95+
assert(_num_reservations < ZMaxVirtualReservations, "too many reservations");
96+
// Keep track of the reservations made in order to create fake mappings
97+
// between the reserved and commited memory.
98+
// See details in ZNMT::process_fake_mapping
99+
_reservations[_num_reservations++] = {start, size};
100+
101+
MemTracker::record_virtual_memory_reserve((void*)untype(start), size, CALLER_PC, mtJavaHeap);
102+
}
103+
104+
void ZNMT::commit(zoffset offset, size_t size) {
105+
// NMT expects a 1-to-1 mapping between virtual and physical memory.
106+
// ZGC can temporarily have multiple virtual addresses pointing to
107+
// the same physical memory.
108+
//
109+
// When this function is called we don't know where in the virtual memory
110+
// this physical memory will be mapped. So we fake the virtual memory
111+
// address by mapping the physical offset into offsets in the reserved
112+
// memory space.
113+
process_fake_mapping(offset, size, true);
114+
}
115+
116+
void ZNMT::uncommit(zoffset offset, size_t size) {
117+
// We fake the virtual memory address by mapping the physical offset
118+
// into offsets in the reserved memory space.
119+
// See comment in ZNMT::commit
120+
process_fake_mapping(offset, size, false);
121+
}

src/hotspot/share/gc/z/zNMT.hpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
#ifndef SHARE_GC_Z_ZNMT_HPP
25+
#define SHARE_GC_Z_ZNMT_HPP
26+
27+
#include "gc/z/zAddress.hpp"
28+
#include "gc/z/zGlobals.hpp"
29+
#include "gc/z/zMemory.hpp"
30+
#include "gc/z/zVirtualMemory.hpp"
31+
#include "memory/allStatic.hpp"
32+
#include "utilities/globalDefinitions.hpp"
33+
#include "utilities/nativeCallStack.hpp"
34+
35+
class ZNMT : public AllStatic {
36+
private:
37+
struct Reservation {
38+
zaddress_unsafe _start;
39+
size_t _size;
40+
};
41+
static Reservation _reservations[ZMaxVirtualReservations];
42+
static size_t _num_reservations;
43+
44+
static size_t reservation_index(zoffset offset, size_t* offset_in_reservation);
45+
static void process_fake_mapping(zoffset offset, size_t size, bool commit);
46+
47+
public:
48+
static void reserve(zaddress_unsafe start, size_t size);
49+
static void commit(zoffset offset, size_t size);
50+
static void uncommit(zoffset offset, size_t size);
51+
};
52+
53+
#endif // SHARE_GC_Z_ZNMT_HPP

src/hotspot/share/gc/z/zPhysicalMemory.cpp

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@
2727
#include "gc/z/zArray.inline.hpp"
2828
#include "gc/z/zGlobals.hpp"
2929
#include "gc/z/zLargePages.inline.hpp"
30+
#include "gc/z/zNMT.hpp"
3031
#include "gc/z/zNUMA.inline.hpp"
3132
#include "gc/z/zPhysicalMemory.inline.hpp"
3233
#include "logging/log.hpp"
3334
#include "runtime/globals.hpp"
3435
#include "runtime/globals_extension.hpp"
3536
#include "runtime/init.hpp"
3637
#include "runtime/os.hpp"
37-
#include "services/memTracker.hpp"
3838
#include "utilities/align.hpp"
3939
#include "utilities/debug.hpp"
4040
#include "utilities/globalDefinitions.hpp"
@@ -275,26 +275,6 @@ void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max
275275
log_info_p(gc, init)("Uncommit Delay: " UINTX_FORMAT "s", ZUncommitDelay);
276276
}
277277

278-
void ZPhysicalMemoryManager::nmt_commit(zoffset offset, size_t size) const {
279-
// NMT expects a 1-to-1 mapping between virtual and physical memory.
280-
// ZGC can temporarily have multiple virtual addresses pointing to
281-
// the same physical memory.
282-
//
283-
// When this function is called we don't know where in the virtual memory
284-
// this physical memory will be mapped. So we fake that the virtual memory
285-
// address is the heap base + the given offset.
286-
const uintptr_t addr = ZAddressHeapBase + untype(offset);
287-
MemTracker::record_virtual_memory_commit((void*)addr, size, CALLER_PC);
288-
}
289-
290-
void ZPhysicalMemoryManager::nmt_uncommit(zoffset offset, size_t size) const {
291-
if (MemTracker::enabled()) {
292-
const uintptr_t addr = ZAddressHeapBase + untype(offset);
293-
Tracker tracker(Tracker::uncommit);
294-
tracker.record((address)addr, size);
295-
}
296-
}
297-
298278
void ZPhysicalMemoryManager::alloc(ZPhysicalMemory& pmem, size_t size) {
299279
assert(is_aligned(size, ZGranuleSize), "Invalid size");
300280

@@ -329,7 +309,7 @@ bool ZPhysicalMemoryManager::commit(ZPhysicalMemory& pmem) {
329309
const size_t committed = _backing.commit(segment.start(), segment.size());
330310

331311
// Register with NMT
332-
nmt_commit(segment.start(), committed);
312+
ZNMT::commit(segment.start(), committed);
333313

334314
// Register committed segment
335315
if (!pmem.commit_segment(i, committed)) {
@@ -355,7 +335,7 @@ bool ZPhysicalMemoryManager::uncommit(ZPhysicalMemory& pmem) {
355335
const size_t uncommitted = _backing.uncommit(segment.start(), segment.size());
356336

357337
// Unregister with NMT
358-
nmt_uncommit(segment.start(), uncommitted);
338+
ZNMT::uncommit(segment.start(), uncommitted);
359339

360340
// Deregister uncommitted segment
361341
if (!pmem.uncommit_segment(i, uncommitted)) {

src/hotspot/share/gc/z/zPhysicalMemory.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ class ZPhysicalMemoryManager {
8484
ZPhysicalMemoryBacking _backing;
8585
ZMemoryManager _manager;
8686

87-
void nmt_commit(zoffset offset, size_t size) const;
88-
void nmt_uncommit(zoffset offset, size_t size) const;
89-
9087
void pretouch_view(zaddress addr, size_t size) const;
9188
void map_view(zaddress_unsafe addr, const ZPhysicalMemory& pmem) const;
9289
void unmap_view(zaddress_unsafe addr, size_t size) const;

0 commit comments

Comments
 (0)