Skip to content

Commit 6ab1647

Browse files
stefankxmas92
andcommitted
8353637: ZGC: Discontiguous memory reservation is broken on Windows
Co-authored-by: Axel Boldt-Christmas <aboldtch@openjdk.org> Reviewed-by: jsikstro, aboldtch, eosterlund
1 parent c494a00 commit 6ab1647

17 files changed

+625
-289
lines changed

src/hotspot/os/posix/gc/z/zVirtualMemory_posix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ void ZVirtualMemoryManager::pd_initialize_before_reserve() {
3232
// Does nothing
3333
}
3434

35-
void ZVirtualMemoryManager::pd_initialize_after_reserve() {
35+
void ZVirtualMemoryManager::pd_register_callbacks(ZMemoryManager* manager) {
3636
// Does nothing
3737
}
3838

src/hotspot/os/windows/gc/z/zVirtualMemory_windows.cpp

Lines changed: 63 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
class ZVirtualMemoryManagerImpl : public CHeapObj<mtGC> {
3434
public:
3535
virtual void initialize_before_reserve() {}
36-
virtual void initialize_after_reserve(ZMemoryManager* manager) {}
36+
virtual void register_callbacks(ZMemoryManager* manager) {}
3737
virtual bool reserve(zaddress_unsafe addr, size_t size) = 0;
3838
virtual void unreserve(zaddress_unsafe addr, size_t size) = 0;
3939
};
@@ -47,7 +47,7 @@ class ZVirtualMemoryManagerImpl : public CHeapObj<mtGC> {
4747
class ZVirtualMemoryManagerSmallPages : public ZVirtualMemoryManagerImpl {
4848
private:
4949
class PlaceholderCallbacks : public AllStatic {
50-
public:
50+
private:
5151
static void split_placeholder(zoffset start, size_t size) {
5252
ZMapper::split_placeholder(ZOffset::address_unsafe(start), size);
5353
}
@@ -79,99 +79,93 @@ class ZVirtualMemoryManagerSmallPages : public ZVirtualMemoryManagerImpl {
7979
}
8080
}
8181

82-
// Called when a memory area is returned to the memory manager but can't
83-
// be merged with an already existing area. Make sure this area is covered
84-
// by a single placeholder.
85-
static void create_callback(const ZMemory* area) {
86-
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
87-
88-
coalesce_into_one_placeholder(area->start(), area->size());
89-
}
82+
// Callback implementations
9083

91-
// Called when a complete memory area in the memory manager is allocated.
92-
// Create granule sized placeholders for the entire area.
93-
static void destroy_callback(const ZMemory* area) {
94-
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
84+
// Called when a memory area is going to be handed out to be used.
85+
//
86+
// Splits the memory area into granule-sized placeholders.
87+
static void prepare_for_hand_out_callback(const ZMemory& area) {
88+
assert(is_aligned(area.size(), ZGranuleSize), "Must be granule aligned");
9589

96-
split_into_granule_sized_placeholders(area->start(), area->size());
90+
split_into_granule_sized_placeholders(area.start(), area.size());
9791
}
9892

99-
// Called when a memory area is allocated at the front of an exising memory area.
100-
// Turn the first part of the memory area into granule sized placeholders.
101-
static void shrink_from_front_callback(const ZMemory* area, size_t size) {
102-
assert(area->size() > size, "Must be larger than what we try to split out");
103-
assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");
93+
// Called when a memory area is handed back to the memory manager.
94+
//
95+
// Combines the granule-sized placeholders into one placeholder.
96+
static void prepare_for_hand_back_callback(const ZMemory& area) {
97+
assert(is_aligned(area.size(), ZGranuleSize), "Must be granule aligned");
10498

105-
// Split the area into two placeholders
106-
split_placeholder(area->start(), size);
107-
108-
// Split the first part into granule sized placeholders
109-
split_into_granule_sized_placeholders(area->start(), size);
99+
coalesce_into_one_placeholder(area.start(), area.size());
110100
}
111101

112-
// Called when a memory area is allocated at the end of an existing memory area.
113-
// Turn the second part of the memory area into granule sized placeholders.
114-
static void shrink_from_back_callback(const ZMemory* area, size_t size) {
115-
assert(area->size() > size, "Must be larger than what we try to split out");
116-
assert(is_aligned(size, ZGranuleSize), "Must be granule aligned");
117-
118-
// Split the area into two placeholders
119-
const zoffset start = to_zoffset(area->end() - size);
120-
split_placeholder(start, size);
121-
122-
// Split the second part into granule sized placeholders
123-
split_into_granule_sized_placeholders(start, size);
124-
}
125-
126-
// Called when freeing a memory area and it can be merged at the start of an
127-
// existing area. Coalesce the underlying placeholders into one.
128-
static void grow_from_front_callback(const ZMemory* area, size_t size) {
129-
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
130-
131-
const zoffset start = area->start() - size;
132-
coalesce_into_one_placeholder(start, area->size() + size);
102+
// Called when inserting a memory area and it can be merged with an
103+
// existing, adjacent memory area.
104+
//
105+
// Coalesces the underlying placeholders into one.
106+
static void grow_callback(const ZMemory& from, const ZMemory& to) {
107+
assert(is_aligned(from.size(), ZGranuleSize), "Must be granule aligned");
108+
assert(is_aligned(to.size(), ZGranuleSize), "Must be granule aligned");
109+
assert(from != to, "Must have grown");
110+
assert(to.contains(from), "Must be within");
111+
112+
coalesce_into_one_placeholder(to.start(), to.size());
133113
}
134114

135-
// Called when freeing a memory area and it can be merged at the end of an
136-
// existing area. Coalesce the underlying placeholders into one.
137-
static void grow_from_back_callback(const ZMemory* area, size_t size) {
138-
assert(is_aligned(area->size(), ZGranuleSize), "Must be granule aligned");
115+
// Called when a memory area is removed from the front or back of an existing
116+
// memory area.
117+
//
118+
// Splits the memory into two placeholders.
119+
static void shrink_callback(const ZMemory& from, const ZMemory& to) {
120+
assert(is_aligned(from.size(), ZGranuleSize), "Must be granule aligned");
121+
assert(is_aligned(to.size(), ZGranuleSize), "Must be granule aligned");
122+
assert(from != to, "Must have shrunk");
123+
assert(from.contains(to), "Must be larger than what we try to split out");
124+
assert(from.start() == to.start() || from.end() == to.end(),
125+
"Only verified to work if we split a placeholder into two placeholders");
139126

140-
coalesce_into_one_placeholder(area->start(), area->size() + size);
127+
// Split the area into two placeholders
128+
split_placeholder(to.start(), to.size());
141129
}
142130

143-
static void register_with(ZMemoryManager* manager) {
131+
public:
132+
static ZMemoryManager::Callbacks callbacks() {
144133
// Each reserved virtual memory address area registered in _manager is
145134
// exactly covered by a single placeholder. Callbacks are installed so
146135
// that whenever a memory area changes, the corresponding placeholder
147136
// is adjusted.
148137
//
149-
// The create and grow callbacks are called when virtual memory is
150-
// returned to the memory manager. The new memory area is then covered
151-
// by a new single placeholder.
138+
// The prepare_for_hand_out callback is called when virtual memory is
139+
// handed out to callers. The memory area is split into granule-sized
140+
// placeholders.
141+
//
142+
// The prepare_for_hand_back callback is called when previously handed
143+
// out virtual memory is handed back to the memory manager. The
144+
// returned memory area is then covered by a new single placeholder.
145+
//
146+
// The grow callback is called when a virtual memory area grows. The
147+
// resulting memory area is then covered by a single placeholder.
152148
//
153-
// The destroy and shrink callbacks are called when virtual memory is
154-
// allocated from the memory manager. The memory area is then is split
155-
// into granule-sized placeholders.
149+
// The shrink callback is called when a virtual memory area is split into
150+
// two parts. The two resulting memory areas are then covered by two
151+
// separate placeholders.
156152
//
157153
// See comment in zMapper_windows.cpp explaining why placeholders are
158154
// split into ZGranuleSize sized placeholders.
159155

160156
ZMemoryManager::Callbacks callbacks;
161157

162-
callbacks._create = &create_callback;
163-
callbacks._destroy = &destroy_callback;
164-
callbacks._shrink_from_front = &shrink_from_front_callback;
165-
callbacks._shrink_from_back = &shrink_from_back_callback;
166-
callbacks._grow_from_front = &grow_from_front_callback;
167-
callbacks._grow_from_back = &grow_from_back_callback;
158+
callbacks._prepare_for_hand_out = &prepare_for_hand_out_callback;
159+
callbacks._prepare_for_hand_back = &prepare_for_hand_back_callback;
160+
callbacks._grow = &grow_callback;
161+
callbacks._shrink = &shrink_callback;
168162

169-
manager->register_callbacks(callbacks);
163+
return callbacks;
170164
}
171165
};
172166

173-
virtual void initialize_after_reserve(ZMemoryManager* manager) {
174-
PlaceholderCallbacks::register_with(manager);
167+
virtual void register_callbacks(ZMemoryManager* manager) {
168+
manager->register_callbacks(PlaceholderCallbacks::callbacks());
175169
}
176170

177171
virtual bool reserve(zaddress_unsafe addr, size_t size) {
@@ -220,8 +214,8 @@ void ZVirtualMemoryManager::pd_initialize_before_reserve() {
220214
_impl->initialize_before_reserve();
221215
}
222216

223-
void ZVirtualMemoryManager::pd_initialize_after_reserve() {
224-
_impl->initialize_after_reserve(&_manager);
217+
void ZVirtualMemoryManager::pd_register_callbacks(ZMemoryManager* manager) {
218+
_impl->register_callbacks(manager);
225219
}
226220

227221
bool ZVirtualMemoryManager::pd_reserve(zaddress_unsafe addr, size_t size) {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
class CollectedHeap;
3030

3131
class ZArguments : public GCArguments {
32+
friend class ZTest;
33+
3234
private:
3335
static void select_max_gc_threads();
3436

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class ZInitializer {
3737
};
3838

3939
class ZInitialize : public AllStatic {
40+
friend class ZTest;
41+
4042
private:
4143
static constexpr size_t ErrorMessageLength = 256;
4244

0 commit comments

Comments
 (0)