Mercurial > hg > truffle
annotate src/share/vm/memory/heap.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1123
diff
changeset
|
2 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1123
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1123
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1123
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 # include "incls/_precompiled.incl" | |
26 # include "incls/_heap.cpp.incl" | |
27 | |
28 | |
29 size_t CodeHeap::header_size() { | |
30 return sizeof(HeapBlock); | |
31 } | |
32 | |
33 | |
34 // Implementation of Heap | |
35 | |
36 CodeHeap::CodeHeap() { | |
37 _number_of_committed_segments = 0; | |
38 _number_of_reserved_segments = 0; | |
39 _segment_size = 0; | |
40 _log2_segment_size = 0; | |
41 _next_segment = 0; | |
42 _freelist = NULL; | |
43 _free_segments = 0; | |
44 } | |
45 | |
46 | |
47 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { | |
48 assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); | |
49 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); | |
50 // setup _segmap pointers for faster indexing | |
51 address p = (address)_segmap.low() + beg; | |
52 address q = (address)_segmap.low() + end; | |
53 // initialize interval | |
54 while (p < q) *p++ = 0xFF; | |
55 } | |
56 | |
57 | |
58 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { | |
59 assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); | |
60 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); | |
61 // setup _segmap pointers for faster indexing | |
62 address p = (address)_segmap.low() + beg; | |
63 address q = (address)_segmap.low() + end; | |
64 // initialize interval | |
65 int i = 0; | |
66 while (p < q) { | |
67 *p++ = i++; | |
68 if (i == 0xFF) i = 1; | |
69 } | |
70 } | |
71 | |
72 | |
73 static size_t align_to_page_size(size_t size) { | |
74 const size_t alignment = (size_t)os::vm_page_size(); | |
75 assert(is_power_of_2(alignment), "no kidding ???"); | |
76 return (size + alignment - 1) & ~(alignment - 1); | |
77 } | |
78 | |
79 | |
80 static size_t align_to_allocation_size(size_t size) { | |
81 const size_t alignment = (size_t)os::vm_allocation_granularity(); | |
82 assert(is_power_of_2(alignment), "no kidding ???"); | |
83 return (size + alignment - 1) & ~(alignment - 1); | |
84 } | |
85 | |
86 | |
87 void CodeHeap::on_code_mapping(char* base, size_t size) { | |
88 #ifdef LINUX | |
89 extern void linux_wrap_code(char* base, size_t size); | |
90 linux_wrap_code(base, size); | |
91 #endif | |
92 } | |
93 | |
94 | |
95 bool CodeHeap::reserve(size_t reserved_size, size_t committed_size, | |
96 size_t segment_size) { | |
97 assert(reserved_size >= committed_size, "reserved < committed"); | |
98 assert(segment_size >= sizeof(FreeBlock), "segment size is too small"); | |
99 assert(is_power_of_2(segment_size), "segment_size must be a power of 2"); | |
100 | |
101 _segment_size = segment_size; | |
102 _log2_segment_size = exact_log2(segment_size); | |
103 | |
104 // Reserve and initialize space for _memory. | |
79
82db0859acbe
6642862: Code cache allocation fails with large pages after 6588638
jcoomes
parents:
0
diff
changeset
|
105 const size_t page_size = os::can_execute_large_page_memory() ? |
82db0859acbe
6642862: Code cache allocation fails with large pages after 6588638
jcoomes
parents:
0
diff
changeset
|
106 os::page_size_for_region(committed_size, reserved_size, 8) : |
82db0859acbe
6642862: Code cache allocation fails with large pages after 6588638
jcoomes
parents:
0
diff
changeset
|
107 os::vm_page_size(); |
0 | 108 const size_t granularity = os::vm_allocation_granularity(); |
109 const size_t r_align = MAX2(page_size, granularity); | |
110 const size_t r_size = align_size_up(reserved_size, r_align); | |
111 const size_t c_size = align_size_up(committed_size, page_size); | |
112 | |
113 const size_t rs_align = page_size == (size_t) os::vm_page_size() ? 0 : | |
114 MAX2(page_size, granularity); | |
656 | 115 ReservedCodeSpace rs(r_size, rs_align, rs_align > 0); |
0 | 116 os::trace_page_sizes("code heap", committed_size, reserved_size, page_size, |
117 rs.base(), rs.size()); | |
118 if (!_memory.initialize(rs, c_size)) { | |
119 return false; | |
120 } | |
121 | |
122 on_code_mapping(_memory.low(), _memory.committed_size()); | |
123 _number_of_committed_segments = number_of_segments(_memory.committed_size()); | |
124 _number_of_reserved_segments = number_of_segments(_memory.reserved_size()); | |
125 assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking"); | |
126 | |
127 // reserve space for _segmap | |
128 if (!_segmap.initialize(align_to_page_size(_number_of_reserved_segments), align_to_page_size(_number_of_committed_segments))) { | |
129 return false; | |
130 } | |
131 assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "could not commit enough space for segment map"); | |
132 assert(_segmap.reserved_size() >= (size_t) _number_of_reserved_segments , "could not reserve enough space for segment map"); | |
133 assert(_segmap.reserved_size() >= _segmap.committed_size() , "just checking"); | |
134 | |
135 // initialize remaining instance variables | |
136 clear(); | |
137 return true; | |
138 } | |
139 | |
140 | |
141 void CodeHeap::release() { | |
142 Unimplemented(); | |
143 } | |
144 | |
145 | |
146 bool CodeHeap::expand_by(size_t size) { | |
147 // expand _memory space | |
148 size_t dm = align_to_page_size(_memory.committed_size() + size) - _memory.committed_size(); | |
149 if (dm > 0) { | |
150 char* base = _memory.low() + _memory.committed_size(); | |
151 if (!_memory.expand_by(dm)) return false; | |
152 on_code_mapping(base, dm); | |
153 size_t i = _number_of_committed_segments; | |
154 _number_of_committed_segments = number_of_segments(_memory.committed_size()); | |
155 assert(_number_of_reserved_segments == number_of_segments(_memory.reserved_size()), "number of reserved segments should not change"); | |
156 assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking"); | |
157 // expand _segmap space | |
158 size_t ds = align_to_page_size(_number_of_committed_segments) - _segmap.committed_size(); | |
159 if (ds > 0) { | |
160 if (!_segmap.expand_by(ds)) return false; | |
161 } | |
162 assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "just checking"); | |
163 // initialize additional segmap entries | |
164 mark_segmap_as_free(i, _number_of_committed_segments); | |
165 } | |
166 return true; | |
167 } | |
168 | |
169 | |
170 void CodeHeap::shrink_by(size_t size) { | |
171 Unimplemented(); | |
172 } | |
173 | |
174 | |
175 void CodeHeap::clear() { | |
176 _next_segment = 0; | |
177 mark_segmap_as_free(0, _number_of_committed_segments); | |
178 } | |
179 | |
180 | |
181 void* CodeHeap::allocate(size_t size) { | |
182 size_t length = number_of_segments(size + sizeof(HeapBlock)); | |
183 assert(length *_segment_size >= sizeof(FreeBlock), "not enough room for FreeList"); | |
184 | |
185 // First check if we can satify request from freelist | |
186 debug_only(verify()); | |
187 HeapBlock* block = search_freelist(length); | |
188 debug_only(if (VerifyCodeCacheOften) verify()); | |
189 if (block != NULL) { | |
190 assert(block->length() >= length && block->length() < length + CodeCacheMinBlockLength, "sanity check"); | |
191 assert(!block->free(), "must be marked free"); | |
192 #ifdef ASSERT | |
193 memset((void *)block->allocated_space(), badCodeHeapNewVal, size); | |
194 #endif | |
195 return block->allocated_space(); | |
196 } | |
197 | |
198 if (length < CodeCacheMinBlockLength) { | |
199 length = CodeCacheMinBlockLength; | |
200 } | |
201 if (_next_segment + length <= _number_of_committed_segments) { | |
202 mark_segmap_as_used(_next_segment, _next_segment + length); | |
203 HeapBlock* b = block_at(_next_segment); | |
204 b->initialize(length); | |
205 _next_segment += length; | |
206 #ifdef ASSERT | |
207 memset((void *)b->allocated_space(), badCodeHeapNewVal, size); | |
208 #endif | |
209 return b->allocated_space(); | |
210 } else { | |
211 return NULL; | |
212 } | |
213 } | |
214 | |
215 | |
216 void CodeHeap::deallocate(void* p) { | |
217 assert(p == find_start(p), "illegal deallocation"); | |
218 // Find start of HeapBlock | |
219 HeapBlock* b = (((HeapBlock *)p) - 1); | |
220 assert(b->allocated_space() == p, "sanity check"); | |
221 #ifdef ASSERT | |
222 memset((void *)b->allocated_space(), | |
223 badCodeHeapFreeVal, | |
224 size(b->length()) - sizeof(HeapBlock)); | |
225 #endif | |
226 add_to_freelist(b); | |
227 | |
228 debug_only(if (VerifyCodeCacheOften) verify()); | |
229 } | |
230 | |
231 | |
232 void* CodeHeap::find_start(void* p) const { | |
233 if (!contains(p)) { | |
234 return NULL; | |
235 } | |
236 size_t i = segment_for(p); | |
237 address b = (address)_segmap.low(); | |
238 if (b[i] == 0xFF) { | |
239 return NULL; | |
240 } | |
241 while (b[i] > 0) i -= (int)b[i]; | |
242 HeapBlock* h = block_at(i); | |
243 if (h->free()) { | |
244 return NULL; | |
245 } | |
246 return h->allocated_space(); | |
247 } | |
248 | |
249 | |
250 size_t CodeHeap::alignment_unit() const { | |
251 // this will be a power of two | |
252 return _segment_size; | |
253 } | |
254 | |
255 | |
256 size_t CodeHeap::alignment_offset() const { | |
257 // The lowest address in any allocated block will be | |
258 // equal to alignment_offset (mod alignment_unit). | |
259 return sizeof(HeapBlock) & (_segment_size - 1); | |
260 } | |
261 | |
262 // Finds the next free heapblock. If the current one is free, that it returned | |
263 void* CodeHeap::next_free(HeapBlock *b) const { | |
264 // Since free blocks are merged, there is max. on free block | |
265 // between two used ones | |
266 if (b != NULL && b->free()) b = next_block(b); | |
267 assert(b == NULL || !b->free(), "must be in use or at end of heap"); | |
268 return (b == NULL) ? NULL : b->allocated_space(); | |
269 } | |
270 | |
271 // Returns the first used HeapBlock | |
272 HeapBlock* CodeHeap::first_block() const { | |
273 if (_next_segment > 0) | |
274 return block_at(0); | |
275 return NULL; | |
276 } | |
277 | |
278 HeapBlock *CodeHeap::block_start(void *q) const { | |
279 HeapBlock* b = (HeapBlock*)find_start(q); | |
280 if (b == NULL) return NULL; | |
281 return b - 1; | |
282 } | |
283 | |
284 // Returns the next Heap block an offset into one | |
285 HeapBlock* CodeHeap::next_block(HeapBlock *b) const { | |
286 if (b == NULL) return NULL; | |
287 size_t i = segment_for(b) + b->length(); | |
288 if (i < _next_segment) | |
289 return block_at(i); | |
290 return NULL; | |
291 } | |
292 | |
293 | |
294 // Returns current capacity | |
295 size_t CodeHeap::capacity() const { | |
296 return _memory.committed_size(); | |
297 } | |
298 | |
299 size_t CodeHeap::max_capacity() const { | |
300 return _memory.reserved_size(); | |
301 } | |
302 | |
303 size_t CodeHeap::allocated_capacity() const { | |
304 // Start with the committed size in _memory; | |
305 size_t l = _memory.committed_size(); | |
306 | |
307 // Subtract the committed, but unused, segments | |
308 l -= size(_number_of_committed_segments - _next_segment); | |
309 | |
310 // Subtract the size of the freelist | |
311 l -= size(_free_segments); | |
312 | |
313 return l; | |
314 } | |
315 | |
316 // Free list management | |
317 | |
318 FreeBlock *CodeHeap::following_block(FreeBlock *b) { | |
319 return (FreeBlock*)(((address)b) + _segment_size * b->length()); | |
320 } | |
321 | |
322 // Inserts block b after a | |
323 void CodeHeap::insert_after(FreeBlock* a, FreeBlock* b) { | |
324 assert(a != NULL && b != NULL, "must be real pointers"); | |
325 | |
326 // Link b into the list after a | |
327 b->set_link(a->link()); | |
328 a->set_link(b); | |
329 | |
330 // See if we can merge blocks | |
331 merge_right(b); // Try to make b bigger | |
332 merge_right(a); // Try to make a include b | |
333 } | |
334 | |
335 // Try to merge this block with the following block | |
336 void CodeHeap::merge_right(FreeBlock *a) { | |
337 assert(a->free(), "must be a free block"); | |
338 if (following_block(a) == a->link()) { | |
339 assert(a->link() != NULL && a->link()->free(), "must be free too"); | |
340 // Update block a to include the following block | |
341 a->set_length(a->length() + a->link()->length()); | |
342 a->set_link(a->link()->link()); | |
343 // Update find_start map | |
344 size_t beg = segment_for(a); | |
345 mark_segmap_as_used(beg, beg + a->length()); | |
346 } | |
347 } | |
348 | |
349 void CodeHeap::add_to_freelist(HeapBlock *a) { | |
350 FreeBlock* b = (FreeBlock*)a; | |
351 assert(b != _freelist, "cannot be removed twice"); | |
352 | |
353 // Mark as free and update free space count | |
354 _free_segments += b->length(); | |
355 b->set_free(); | |
356 | |
357 // First element in list? | |
358 if (_freelist == NULL) { | |
359 _freelist = b; | |
360 b->set_link(NULL); | |
361 return; | |
362 } | |
363 | |
364 // Scan for right place to put into list. List | |
365 // is sorted by increasing addresseses | |
366 FreeBlock* prev = NULL; | |
367 FreeBlock* cur = _freelist; | |
368 while(cur != NULL && cur < b) { | |
369 assert(prev == NULL || prev < cur, "must be ordered"); | |
370 prev = cur; | |
371 cur = cur->link(); | |
372 } | |
373 | |
374 assert( (prev == NULL && b < _freelist) || | |
375 (prev < b && (cur == NULL || b < cur)), "list must be ordered"); | |
376 | |
377 if (prev == NULL) { | |
378 // Insert first in list | |
379 b->set_link(_freelist); | |
380 _freelist = b; | |
381 merge_right(_freelist); | |
382 } else { | |
383 insert_after(prev, b); | |
384 } | |
385 } | |
386 | |
387 // Search freelist for an entry on the list with the best fit | |
388 // Return NULL if no one was found | |
389 FreeBlock* CodeHeap::search_freelist(size_t length) { | |
390 FreeBlock *best_block = NULL; | |
391 FreeBlock *best_prev = NULL; | |
392 size_t best_length = 0; | |
393 | |
394 // Search for smallest block which is bigger than length | |
395 FreeBlock *prev = NULL; | |
396 FreeBlock *cur = _freelist; | |
397 while(cur != NULL) { | |
398 size_t l = cur->length(); | |
399 if (l >= length && (best_block == NULL || best_length > l)) { | |
400 // Remember best block, its previous element, and its length | |
401 best_block = cur; | |
402 best_prev = prev; | |
403 best_length = best_block->length(); | |
404 } | |
405 | |
406 // Next element in list | |
407 prev = cur; | |
408 cur = cur->link(); | |
409 } | |
410 | |
411 if (best_block == NULL) { | |
412 // None found | |
413 return NULL; | |
414 } | |
415 | |
416 assert((best_prev == NULL && _freelist == best_block ) || | |
417 (best_prev != NULL && best_prev->link() == best_block), "sanity check"); | |
418 | |
419 // Exact (or at least good enough) fit. Remove from list. | |
420 // Don't leave anything on the freelist smaller than CodeCacheMinBlockLength. | |
421 if (best_length < length + CodeCacheMinBlockLength) { | |
422 length = best_length; | |
423 if (best_prev == NULL) { | |
424 assert(_freelist == best_block, "sanity check"); | |
425 _freelist = _freelist->link(); | |
426 } else { | |
427 // Unmap element | |
428 best_prev->set_link(best_block->link()); | |
429 } | |
430 } else { | |
431 // Truncate block and return a pointer to the following block | |
432 best_block->set_length(best_length - length); | |
433 best_block = following_block(best_block); | |
434 // Set used bit and length on new block | |
435 size_t beg = segment_for(best_block); | |
436 mark_segmap_as_used(beg, beg + length); | |
437 best_block->set_length(length); | |
438 } | |
439 | |
440 best_block->set_used(); | |
441 _free_segments -= length; | |
442 return best_block; | |
443 } | |
444 | |
445 //---------------------------------------------------------------------------- | |
446 // Non-product code | |
447 | |
448 #ifndef PRODUCT | |
449 | |
450 void CodeHeap::print() { | |
451 tty->print_cr("The Heap"); | |
452 } | |
453 | |
454 #endif | |
455 | |
456 void CodeHeap::verify() { | |
457 // Count the number of blocks on the freelist, and the amount of space | |
458 // represented. | |
459 int count = 0; | |
460 size_t len = 0; | |
461 for(FreeBlock* b = _freelist; b != NULL; b = b->link()) { | |
462 len += b->length(); | |
463 count++; | |
464 } | |
465 | |
466 // Verify that freelist contains the right amount of free space | |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
844
diff
changeset
|
467 // guarantee(len == _free_segments, "wrong freelist"); |
0 | 468 |
469 // Verify that the number of free blocks is not out of hand. | |
470 static int free_block_threshold = 10000; | |
471 if (count > free_block_threshold) { | |
472 warning("CodeHeap: # of free blocks > %d", free_block_threshold); | |
473 // Double the warning limit | |
474 free_block_threshold *= 2; | |
475 } | |
476 | |
477 // Verify that the freelist contains the same number of free blocks that is | |
478 // found on the full list. | |
479 for(HeapBlock *h = first_block(); h != NULL; h = next_block(h)) { | |
480 if (h->free()) count--; | |
481 } | |
1123
167c2986d91b
6843629: Make current hotspot build part of jdk5 control build
phh
parents:
844
diff
changeset
|
482 // guarantee(count == 0, "missing free blocks"); |
0 | 483 } |