Mercurial > hg > graal-jvmci-8
comparison src/share/vm/runtime/virtualspace.cpp @ 1618:5f249b390094
6947341: JVM Crash running Oracle ATG CRMDemo
Summary: Missing protected page below heap with compressed oops on Linux with large pages use.
Reviewed-by: never, phh, jcoomes
author | kvn |
---|---|
date | Wed, 23 Jun 2010 09:40:11 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1617:9887b5e57f9e | 1618:5f249b390094 |
---|---|
109 #endif | 109 #endif |
110 | 110 |
111 return result; | 111 return result; |
112 } | 112 } |
113 | 113 |
114 // Helper method. | |
115 static bool failed_to_reserve_as_requested(char* base, char* requested_address, | |
116 const size_t size, bool special) | |
117 { | |
118 if (base == requested_address || requested_address == NULL) | |
119 return false; // did not fail | |
120 | |
121 if (base != NULL) { | |
122 // Different reserve address may be acceptable in other cases | |
123 // but for compressed oops heap should be at requested address. | |
124 assert(UseCompressedOops, "currently requested address used only for compressed oops"); | |
125 if (PrintCompressedOopsMode) { | |
126 tty->cr(); | |
127 tty->print_cr("Reserved memory at not requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address); | |
128 } | |
129 // OS ignored requested address. Try different address. | |
130 if (special) { | |
131 if (!os::release_memory_special(base, size)) { | |
132 fatal("os::release_memory_special failed"); | |
133 } | |
134 } else { | |
135 if (!os::release_memory(base, size)) { | |
136 fatal("os::release_memory failed"); | |
137 } | |
138 } | |
139 } | |
140 return true; | |
141 } | |
142 | |
114 ReservedSpace::ReservedSpace(const size_t prefix_size, | 143 ReservedSpace::ReservedSpace(const size_t prefix_size, |
115 const size_t prefix_align, | 144 const size_t prefix_align, |
116 const size_t suffix_size, | 145 const size_t suffix_size, |
117 const size_t suffix_align, | 146 const size_t suffix_align, |
118 char* requested_address, | 147 char* requested_address, |
127 assert((suffix_size & suffix_align - 1) == 0, | 156 assert((suffix_size & suffix_align - 1) == 0, |
128 "suffix_size not divisible by suffix_align"); | 157 "suffix_size not divisible by suffix_align"); |
129 assert((suffix_align & prefix_align - 1) == 0, | 158 assert((suffix_align & prefix_align - 1) == 0, |
130 "suffix_align not divisible by prefix_align"); | 159 "suffix_align not divisible by prefix_align"); |
131 | 160 |
161 // Assert that if noaccess_prefix is used, it is the same as prefix_align. | |
162 assert(noaccess_prefix == 0 || | |
163 noaccess_prefix == prefix_align, "noaccess prefix wrong"); | |
164 | |
132 // Add in noaccess_prefix to prefix_size; | 165 // Add in noaccess_prefix to prefix_size; |
133 const size_t adjusted_prefix_size = prefix_size + noaccess_prefix; | 166 const size_t adjusted_prefix_size = prefix_size + noaccess_prefix; |
134 const size_t size = adjusted_prefix_size + suffix_size; | 167 const size_t size = adjusted_prefix_size + suffix_size; |
135 | 168 |
136 // On systems where the entire region has to be reserved and committed up | 169 // On systems where the entire region has to be reserved and committed up |
148 _alignment = 0; | 181 _alignment = 0; |
149 _special = false; | 182 _special = false; |
150 _noaccess_prefix = 0; | 183 _noaccess_prefix = 0; |
151 _executable = false; | 184 _executable = false; |
152 | 185 |
153 // Assert that if noaccess_prefix is used, it is the same as prefix_align. | |
154 assert(noaccess_prefix == 0 || | |
155 noaccess_prefix == prefix_align, "noaccess prefix wrong"); | |
156 | |
157 // Optimistically try to reserve the exact size needed. | 186 // Optimistically try to reserve the exact size needed. |
158 char* addr; | 187 char* addr; |
159 if (requested_address != 0) { | 188 if (requested_address != 0) { |
160 addr = os::attempt_reserve_memory_at(size, | 189 requested_address -= noaccess_prefix; // adjust address |
161 requested_address-noaccess_prefix); | 190 assert(requested_address != NULL, "huge noaccess prefix?"); |
191 addr = os::attempt_reserve_memory_at(size, requested_address); | |
192 if (failed_to_reserve_as_requested(addr, requested_address, size, false)) { | |
193 // OS ignored requested address. Try different address. | |
194 addr = NULL; | |
195 } | |
162 } else { | 196 } else { |
163 addr = os::reserve_memory(size, NULL, prefix_align); | 197 addr = os::reserve_memory(size, NULL, prefix_align); |
164 } | 198 } |
165 if (addr == NULL) return; | 199 if (addr == NULL) return; |
166 | 200 |
220 // If OS doesn't support demand paging for large page memory, we need | 254 // If OS doesn't support demand paging for large page memory, we need |
221 // to use reserve_memory_special() to reserve and pin the entire region. | 255 // to use reserve_memory_special() to reserve and pin the entire region. |
222 bool special = large && !os::can_commit_large_page_memory(); | 256 bool special = large && !os::can_commit_large_page_memory(); |
223 char* base = NULL; | 257 char* base = NULL; |
224 | 258 |
259 if (requested_address != 0) { | |
260 requested_address -= noaccess_prefix; // adjust requested address | |
261 assert(requested_address != NULL, "huge noaccess prefix?"); | |
262 } | |
263 | |
225 if (special) { | 264 if (special) { |
226 | 265 |
227 base = os::reserve_memory_special(size, requested_address, executable); | 266 base = os::reserve_memory_special(size, requested_address, executable); |
228 | 267 |
229 if (base != NULL) { | 268 if (base != NULL) { |
269 if (failed_to_reserve_as_requested(base, requested_address, size, true)) { | |
270 // OS ignored requested address. Try different address. | |
271 return; | |
272 } | |
230 // Check alignment constraints | 273 // Check alignment constraints |
231 if (alignment > 0) { | 274 if (alignment > 0) { |
232 assert((uintptr_t) base % alignment == 0, | 275 assert((uintptr_t) base % alignment == 0, |
233 "Large pages returned a non-aligned address"); | 276 "Large pages returned a non-aligned address"); |
234 } | 277 } |
235 _special = true; | 278 _special = true; |
236 } else { | 279 } else { |
237 // failed; try to reserve regular memory below | 280 // failed; try to reserve regular memory below |
281 if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || | |
282 !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { | |
283 if (PrintCompressedOopsMode) { | |
284 tty->cr(); | |
285 tty->print_cr("Reserve regular memory without large pages."); | |
286 } | |
287 } | |
238 } | 288 } |
239 } | 289 } |
240 | 290 |
241 if (base == NULL) { | 291 if (base == NULL) { |
242 // Optimistically assume that the OSes returns an aligned base pointer. | 292 // Optimistically assume that the OSes returns an aligned base pointer. |
246 // If the memory was requested at a particular address, use | 296 // If the memory was requested at a particular address, use |
247 // os::attempt_reserve_memory_at() to avoid over mapping something | 297 // os::attempt_reserve_memory_at() to avoid over mapping something |
248 // important. If available space is not detected, return NULL. | 298 // important. If available space is not detected, return NULL. |
249 | 299 |
250 if (requested_address != 0) { | 300 if (requested_address != 0) { |
251 base = os::attempt_reserve_memory_at(size, | 301 base = os::attempt_reserve_memory_at(size, requested_address); |
252 requested_address-noaccess_prefix); | 302 if (failed_to_reserve_as_requested(base, requested_address, size, false)) { |
303 // OS ignored requested address. Try different address. | |
304 base = NULL; | |
305 } | |
253 } else { | 306 } else { |
254 base = os::reserve_memory(size, NULL, alignment); | 307 base = os::reserve_memory(size, NULL, alignment); |
255 } | 308 } |
256 | 309 |
257 if (base == NULL) return; | 310 if (base == NULL) return; |
363 _executable = false; | 416 _executable = false; |
364 } | 417 } |
365 } | 418 } |
366 | 419 |
367 void ReservedSpace::protect_noaccess_prefix(const size_t size) { | 420 void ReservedSpace::protect_noaccess_prefix(const size_t size) { |
368 // If there is noaccess prefix, return. | 421 assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL && |
422 (size_t(_base + _size) > OopEncodingHeapMax) && | |
423 Universe::narrow_oop_use_implicit_null_checks()), | |
424 "noaccess_prefix should be used only with non zero based compressed oops"); | |
425 | |
426 // If there is no noaccess prefix, return. | |
369 if (_noaccess_prefix == 0) return; | 427 if (_noaccess_prefix == 0) return; |
370 | 428 |
371 assert(_noaccess_prefix >= (size_t)os::vm_page_size(), | 429 assert(_noaccess_prefix >= (size_t)os::vm_page_size(), |
372 "must be at least page size big"); | 430 "must be at least page size big"); |
373 | 431 |
374 // Protect memory at the base of the allocated region. | 432 // Protect memory at the base of the allocated region. |
375 // If special, the page was committed (only matters on windows) | 433 // If special, the page was committed (only matters on windows) |
376 if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE, | 434 if (!os::protect_memory(_base, _noaccess_prefix, os::MEM_PROT_NONE, |
377 _special)) { | 435 _special)) { |
378 fatal("cannot protect protection page"); | 436 fatal("cannot protect protection page"); |
437 } | |
438 if (PrintCompressedOopsMode) { | |
439 tty->cr(); | |
440 tty->print_cr("Protected page at the reserved heap base: " PTR_FORMAT " / " INTX_FORMAT " bytes", _base, _noaccess_prefix); | |
379 } | 441 } |
380 | 442 |
381 _base += _noaccess_prefix; | 443 _base += _noaccess_prefix; |
382 _size -= _noaccess_prefix; | 444 _size -= _noaccess_prefix; |
383 assert((size == _size) && ((uintptr_t)_base % _alignment == 0), | 445 assert((size == _size) && ((uintptr_t)_base % _alignment == 0), |