3434#include " utilities/align.hpp"
3535#include " utilities/debug.hpp"
3636
37+ class ZVirtualReservation {
38+ private:
39+ ZMemoryManager _reserved;
40+ size_t _size;
41+ size_t _min_range;
42+
43+ static size_t limit_max_reservation (size_t size) {
44+ const size_t limit = MIN2 (ZAddressOffsetMax, ZAddressSpaceLimit::heap ());
45+ return MIN2 (size * ZVirtualToPhysicalRatio, limit);
46+ }
47+
48+ static size_t calculate_min_range (size_t size) {
49+ // Don't try to reserve address ranges smaller than 1% of the requested size.
50+ // This avoids an explosion of reservation attempts in case large parts of the
51+ // address space is already occupied.
52+ return align_up (size / ZMaxVirtualReservations, ZGranuleSize);
53+ }
54+
55+ public:
56+ ZVirtualReservation (size_t size)
57+ : _reserved(),
58+ _size (limit_max_reservation(size)),
59+ _min_range(calculate_min_range(size)) {
60+ assert (is_aligned (size, ZGranuleSize), " Must be granule aligned 0x%zx" , size);
61+ }
62+
63+ void reserve (zoffset start, size_t size) {
64+ _reserved.free (start, size);
65+ }
66+
67+ void transfer (ZMemoryManager& other, size_t size) {
68+ _reserved.transfer_low_address (other, size);
69+ }
70+
71+ size_t size () const {
72+ return _size;
73+ }
74+
75+ bool set_size (size_t size) {
76+ assert (is_aligned (size, ZGranuleSize), " Misaligned" );
77+ if (size < _min_range) {
78+ return false ;
79+ }
80+
81+ _size = size;
82+
83+ return true ;
84+ }
85+
86+ size_t min_range () const {
87+ return _min_range;
88+ }
89+
90+ bool is_contiguous () const {
91+ return _reserved.free_is_contiguous ();
92+ }
93+ };
94+
3795ZVirtualMemoryManager::ZVirtualMemoryManager (size_t max_capacity)
3896 : _reserved_memory(),
3997 _managers(),
@@ -46,7 +104,8 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity)
46104 pd_initialize_before_reserve ();
47105
48106 // Reserve address space
49- const size_t reserved_total = reserve (max_capacity);
107+ ZVirtualReservation reservation (max_capacity);
108+ const size_t reserved_total = reserve (&reservation);
50109 if (reserved_total < max_capacity) {
51110 ZInitialize::error_d (" Failed to reserve enough address space for Java heap" );
52111 return ;
@@ -60,7 +119,7 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity)
60119 ZMemoryManager& manager = _managers.get (numa_id);
61120
62121 // Transfer reserved memory
63- _reserved_memory. transfer_low_address (manager, reserved);
122+ reservation. transfer (manager, reserved);
64123
65124 // Store the range for the manager
66125 _vmem_ranges.set (manager.total_range (), numa_id);
@@ -71,9 +130,9 @@ ZVirtualMemoryManager::ZVirtualMemoryManager(size_t max_capacity)
71130}
72131
73132#ifdef ASSERT
74- size_t ZVirtualMemoryManager::force_reserve_discontiguous (size_t size ) {
75- const size_t min_range = calculate_min_range ( size);
76- const size_t max_range = MAX2 (align_down (size / ZForceDiscontiguousHeapReservations, ZGranuleSize), min_range);
133+ size_t ZVirtualMemoryManager::force_reserve_discontiguous (ZVirtualReservation* reservation ) {
134+ const size_t size = reservation-> size ( );
135+ const size_t max_range = MAX2 (align_down (size / ZForceDiscontiguousHeapReservations, ZGranuleSize), reservation-> min_range () );
77136 size_t reserved = 0 ;
78137
79138 // Try to reserve ZForceDiscontiguousHeapReservations number of virtual memory
@@ -84,7 +143,8 @@ size_t ZVirtualMemoryManager::force_reserve_discontiguous(size_t size) {
84143 const size_t reserve_size = MIN2 (max_range, remaining);
85144 const uintptr_t reserve_start = end - reserve_size;
86145
87- if (reserve_contiguous (to_zoffset (reserve_start), reserve_size)) {
146+ reservation->set_size (reserve_size);
147+ if (reserve_contiguous (reservation, to_zoffset (reserve_start))) {
88148 reserved += reserve_size;
89149 }
90150
@@ -95,64 +155,59 @@ size_t ZVirtualMemoryManager::force_reserve_discontiguous(size_t size) {
95155 uintptr_t start = 0 ;
96156 while (reserved < size && start < ZAddressOffsetMax) {
97157 const size_t remaining = MIN2 (size - reserved, ZAddressOffsetMax - start);
98- reserved += reserve_discontiguous (to_zoffset (start), remaining, min_range);
158+ if (reservation->set_size (remaining)) {
159+ reserved += reserve_discontiguous (reservation, to_zoffset (start));
160+ }
99161 start += remaining;
100162 }
101163
102164 return reserved;
103165}
104166#endif
105167
106- size_t ZVirtualMemoryManager::reserve_discontiguous (zoffset start, size_t size, size_t min_range) {
107- if (size < min_range) {
108- // Too small
109- return 0 ;
110- }
111-
112- assert (is_aligned (size, ZGranuleSize), " Misaligned" );
113-
114- if (reserve_contiguous (start, size)) {
115- return size;
168+ size_t ZVirtualMemoryManager::reserve_discontiguous (ZVirtualReservation* reservation, zoffset start) {
169+ if (reserve_contiguous (reservation, start)) {
170+ return reservation->size ();
116171 }
117172
173+ const size_t size = reservation->size ();
118174 const size_t half = size / 2 ;
119- if (half < min_range) {
175+ if (half < reservation-> min_range () ) {
120176 // Too small
121177 return 0 ;
122178 }
123179
124180 // Divide and conquer
125181 const size_t first_part = align_down (half, ZGranuleSize);
182+ reservation->set_size (first_part);
183+ const size_t first_size = reserve_discontiguous (reservation, start);
184+
126185 const size_t second_part = size - first_part;
127- const size_t first_size = reserve_discontiguous (start, first_part, min_range);
128- const size_t second_size = reserve_discontiguous (start + first_part, second_part, min_range);
129- return first_size + second_size;
130- }
186+ reservation->set_size (second_part);
187+ const size_t second_size = reserve_discontiguous (reservation, start + first_part);
131188
132- size_t ZVirtualMemoryManager::calculate_min_range (size_t size) {
133- // Don't try to reserve address ranges smaller than 1% of the requested size.
134- // This avoids an explosion of reservation attempts in case large parts of the
135- // address space is already occupied.
136- return align_up (size / ZMaxVirtualReservations, ZGranuleSize);
189+ return first_size + second_size;
137190}
138191
139- size_t ZVirtualMemoryManager::reserve_discontiguous (size_t size ) {
140- const size_t min_range = calculate_min_range ( size);
192+ size_t ZVirtualMemoryManager::reserve_discontiguous (ZVirtualReservation* reservation ) {
193+ const size_t size = reservation-> size ( );
141194 uintptr_t start = 0 ;
142195 size_t reserved = 0 ;
143196
144197 // Reserve size somewhere between [0, ZAddressOffsetMax)
145198 while (reserved < size && start < ZAddressOffsetMax) {
146199 const size_t remaining = MIN2 (size - reserved, ZAddressOffsetMax - start);
147- reserved += reserve_discontiguous (to_zoffset (start), remaining, min_range);
200+ if (reservation->set_size (remaining)) {
201+ reserved += reserve_discontiguous (reservation, to_zoffset (start));
202+ }
148203 start += remaining;
149204 }
150205
151206 return reserved;
152207}
153208
154- bool ZVirtualMemoryManager::reserve_contiguous (zoffset start, size_t size ) {
155- assert ( is_aligned (size, ZGranuleSize), " Must be granule aligned 0x%zx " , size);
209+ bool ZVirtualMemoryManager::reserve_contiguous (ZVirtualReservation* reservation, zoffset start ) {
210+ const size_t size = reservation-> size ( );
156211
157212 // Reserve address views
158213 const zaddress_unsafe addr = ZOffset::address_unsafe (start);
@@ -165,18 +220,19 @@ bool ZVirtualMemoryManager::reserve_contiguous(zoffset start, size_t size) {
165220 // Register address views with native memory tracker
166221 ZNMT::reserve (addr, size);
167222
168- _reserved_memory. free (start, size);
223+ reservation-> reserve (start, size);
169224
170225 return true ;
171226}
172227
173- bool ZVirtualMemoryManager::reserve_contiguous (size_t size ) {
228+ bool ZVirtualMemoryManager::reserve_contiguous (ZVirtualReservation* reservation ) {
174229 // Allow at most 8192 attempts spread evenly across [0, ZAddressOffsetMax)
230+ const size_t size = reservation->size ();
175231 const size_t unused = ZAddressOffsetMax - size;
176232 const size_t increment = MAX2 (align_up (unused / 8192 , ZGranuleSize), ZGranuleSize);
177233
178234 for (uintptr_t start = 0 ; start + size <= ZAddressOffsetMax; start += increment) {
179- if (reserve_contiguous (to_zoffset (start), size )) {
235+ if (reserve_contiguous (reservation, to_zoffset (start))) {
180236 // Success
181237 return true ;
182238 }
@@ -186,33 +242,33 @@ bool ZVirtualMemoryManager::reserve_contiguous(size_t size) {
186242 return false ;
187243}
188244
189- size_t ZVirtualMemoryManager::reserve (size_t max_capacity) {
190- const size_t limit = MIN2 (ZAddressOffsetMax, ZAddressSpaceLimit::heap ());
191- const size_t size = MIN2 (max_capacity * ZVirtualToPhysicalRatio, limit);
192- bool contiguous_reservation = false ;
245+ size_t ZVirtualMemoryManager::reserve (ZVirtualReservation* reservation) {
246+ const size_t size = reservation->size ();
193247
194248 auto do_reserve = [&]() {
195249#ifdef ASSERT
196250 if (ZForceDiscontiguousHeapReservations > 0 ) {
197- return force_reserve_discontiguous (size );
251+ return force_reserve_discontiguous (reservation );
198252 }
199253#endif
200254
201255 // Prefer a contiguous address space
202- if (reserve_contiguous (size)) {
203- contiguous_reservation = true ;
204- return size;
256+ if (reserve_contiguous (reservation)) {
257+ return reservation->size ();
205258 }
206259
207260 // Fall back to a discontiguous address space
208- return reserve_discontiguous (size );
261+ return reserve_discontiguous (reservation );
209262 };
210263
211264 const size_t reserved = do_reserve ();
212265
266+ const bool contiguous = reservation->is_contiguous ();
267+ const bool limited = ZAddressSpaceLimit::heap () == ZAddressOffsetMax;
268+
213269 log_info_p (gc, init)(" Address Space Type: %s/%s/%s" ,
214- (contiguous_reservation ? " Contiguous" : " Discontiguous" ),
215- (limit == ZAddressOffsetMax ? " Unrestricted" : " Restricted" ),
270+ (contiguous ? " Contiguous" : " Discontiguous" ),
271+ (limited ? " Unrestricted" : " Restricted" ),
216272 (reserved == size ? " Complete" : " Degraded" ));
217273 log_info_p (gc, init)(" Address Space Size: %zuM" , reserved / M);
218274
0 commit comments