Mercurial > hg > graal-compiler
comparison src/share/vm/memory/heap.cpp @ 14726:92aa6797d639
Backed out merge changeset: b51e29501f30
Backed out merge revision to its first parent (8f483e200405)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 24 Mar 2014 21:30:43 +0100 |
parents | b51e29501f30 |
children |
comparison
equal
deleted
inserted
replaced
14719:0bdd0d157040 | 14726:92aa6797d639 |
---|---|
41 _segment_size = 0; | 41 _segment_size = 0; |
42 _log2_segment_size = 0; | 42 _log2_segment_size = 0; |
43 _next_segment = 0; | 43 _next_segment = 0; |
44 _freelist = NULL; | 44 _freelist = NULL; |
45 _freelist_segments = 0; | 45 _freelist_segments = 0; |
46 _freelist_length = 0; | |
47 } | 46 } |
48 | 47 |
49 | 48 |
50 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { | 49 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { |
51 assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); | 50 assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); |
52 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); | 51 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); |
53 // setup _segmap pointers for faster indexing | 52 // setup _segmap pointers for faster indexing |
54 address p = (address)_segmap.low() + beg; | 53 address p = (address)_segmap.low() + beg; |
55 address q = (address)_segmap.low() + end; | 54 address q = (address)_segmap.low() + end; |
56 // initialize interval | 55 // initialize interval |
57 while (p < q) *p++ = free_sentinel; | 56 while (p < q) *p++ = 0xFF; |
58 } | 57 } |
59 | 58 |
60 | 59 |
61 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { | 60 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { |
62 assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); | 61 assert(0 <= beg && beg < _number_of_committed_segments, "interval begin out of bounds"); |
66 address q = (address)_segmap.low() + end; | 65 address q = (address)_segmap.low() + end; |
67 // initialize interval | 66 // initialize interval |
68 int i = 0; | 67 int i = 0; |
69 while (p < q) { | 68 while (p < q) { |
70 *p++ = i++; | 69 *p++ = i++; |
71 if (i == free_sentinel) i = 1; | 70 if (i == 0xFF) i = 1; |
72 } | 71 } |
73 } | 72 } |
74 | 73 |
75 | 74 |
76 static size_t align_to_page_size(size_t size) { | 75 static size_t align_to_page_size(size_t size) { |
135 assert(_segmap.reserved_size() >= _segmap.committed_size() , "just checking"); | 134 assert(_segmap.reserved_size() >= _segmap.committed_size() , "just checking"); |
136 | 135 |
137 // initialize remaining instance variables | 136 // initialize remaining instance variables |
138 clear(); | 137 clear(); |
139 return true; | 138 return true; |
139 } | |
140 | |
141 | |
142 void CodeHeap::release() { | |
143 Unimplemented(); | |
140 } | 144 } |
141 | 145 |
142 | 146 |
143 bool CodeHeap::expand_by(size_t size) { | 147 bool CodeHeap::expand_by(size_t size) { |
144 // expand _memory space | 148 // expand _memory space |
151 _number_of_committed_segments = size_to_segments(_memory.committed_size()); | 155 _number_of_committed_segments = size_to_segments(_memory.committed_size()); |
152 assert(_number_of_reserved_segments == size_to_segments(_memory.reserved_size()), "number of reserved segments should not change"); | 156 assert(_number_of_reserved_segments == size_to_segments(_memory.reserved_size()), "number of reserved segments should not change"); |
153 assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking"); | 157 assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking"); |
154 // expand _segmap space | 158 // expand _segmap space |
155 size_t ds = align_to_page_size(_number_of_committed_segments) - _segmap.committed_size(); | 159 size_t ds = align_to_page_size(_number_of_committed_segments) - _segmap.committed_size(); |
156 if ((ds > 0) && !_segmap.expand_by(ds)) { | 160 if (ds > 0) { |
157 return false; | 161 if (!_segmap.expand_by(ds)) return false; |
158 } | 162 } |
159 assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "just checking"); | 163 assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "just checking"); |
160 // initialize additional segmap entries | 164 // initialize additional segmap entries |
161 mark_segmap_as_free(i, _number_of_committed_segments); | 165 mark_segmap_as_free(i, _number_of_committed_segments); |
162 } | 166 } |
163 return true; | 167 return true; |
164 } | 168 } |
165 | 169 |
170 | |
171 void CodeHeap::shrink_by(size_t size) { | |
172 Unimplemented(); | |
173 } | |
174 | |
175 | |
166 void CodeHeap::clear() { | 176 void CodeHeap::clear() { |
167 _next_segment = 0; | 177 _next_segment = 0; |
168 mark_segmap_as_free(0, _number_of_committed_segments); | 178 mark_segmap_as_free(0, _number_of_committed_segments); |
169 } | 179 } |
170 | 180 |
171 | 181 |
172 void* CodeHeap::allocate(size_t instance_size, bool is_critical) { | 182 void* CodeHeap::allocate(size_t instance_size, bool is_critical) { |
173 size_t number_of_segments = size_to_segments(instance_size + header_size()); | 183 size_t number_of_segments = size_to_segments(instance_size + sizeof(HeapBlock)); |
174 assert(segments_to_size(number_of_segments) >= sizeof(FreeBlock), "not enough room for FreeList"); | 184 assert(segments_to_size(number_of_segments) >= sizeof(FreeBlock), "not enough room for FreeList"); |
175 | 185 |
176 // First check if we can satisfy request from freelist | 186 // First check if we can satisfy request from freelist |
177 NOT_PRODUCT(verify()); | 187 debug_only(verify()); |
178 HeapBlock* block = search_freelist(number_of_segments, is_critical); | 188 HeapBlock* block = search_freelist(number_of_segments, is_critical); |
179 NOT_PRODUCT(verify()); | 189 debug_only(if (VerifyCodeCacheOften) verify()); |
180 | |
181 if (block != NULL) { | 190 if (block != NULL) { |
182 assert(block->length() >= number_of_segments && block->length() < number_of_segments + CodeCacheMinBlockLength, "sanity check"); | 191 assert(block->length() >= number_of_segments && block->length() < number_of_segments + CodeCacheMinBlockLength, "sanity check"); |
183 assert(!block->free(), "must be marked free"); | 192 assert(!block->free(), "must be marked free"); |
184 DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, instance_size)); | 193 #ifdef ASSERT |
194 memset((void *)block->allocated_space(), badCodeHeapNewVal, instance_size); | |
195 #endif | |
185 return block->allocated_space(); | 196 return block->allocated_space(); |
186 } | 197 } |
187 | 198 |
188 // Ensure minimum size for allocation to the heap. | 199 // Ensure minimum size for allocation to the heap. |
189 number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments); | 200 if (number_of_segments < CodeCacheMinBlockLength) { |
201 number_of_segments = CodeCacheMinBlockLength; | |
202 } | |
190 | 203 |
191 if (!is_critical) { | 204 if (!is_critical) { |
192 // Make sure the allocation fits in the unallocated heap without using | 205 // Make sure the allocation fits in the unallocated heap without using |
193 // the CodeCacheMimimumFreeSpace that is reserved for critical allocations. | 206 // the CodeCacheMimimumFreeSpace that is reserved for critical allocations. |
194 if (segments_to_size(number_of_segments) > (heap_unallocated_capacity() - CodeCacheMinimumFreeSpace)) { | 207 if (segments_to_size(number_of_segments) > (heap_unallocated_capacity() - CodeCacheMinimumFreeSpace)) { |
200 if (_next_segment + number_of_segments <= _number_of_committed_segments) { | 213 if (_next_segment + number_of_segments <= _number_of_committed_segments) { |
201 mark_segmap_as_used(_next_segment, _next_segment + number_of_segments); | 214 mark_segmap_as_used(_next_segment, _next_segment + number_of_segments); |
202 HeapBlock* b = block_at(_next_segment); | 215 HeapBlock* b = block_at(_next_segment); |
203 b->initialize(number_of_segments); | 216 b->initialize(number_of_segments); |
204 _next_segment += number_of_segments; | 217 _next_segment += number_of_segments; |
205 DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapNewVal, instance_size)); | 218 #ifdef ASSERT |
219 memset((void *)b->allocated_space(), badCodeHeapNewVal, instance_size); | |
220 #endif | |
206 return b->allocated_space(); | 221 return b->allocated_space(); |
207 } else { | 222 } else { |
208 return NULL; | 223 return NULL; |
209 } | 224 } |
210 } | 225 } |
213 void CodeHeap::deallocate(void* p) { | 228 void CodeHeap::deallocate(void* p) { |
214 assert(p == find_start(p), "illegal deallocation"); | 229 assert(p == find_start(p), "illegal deallocation"); |
215 // Find start of HeapBlock | 230 // Find start of HeapBlock |
216 HeapBlock* b = (((HeapBlock *)p) - 1); | 231 HeapBlock* b = (((HeapBlock *)p) - 1); |
217 assert(b->allocated_space() == p, "sanity check"); | 232 assert(b->allocated_space() == p, "sanity check"); |
218 DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapFreeVal, | 233 #ifdef ASSERT |
219 segments_to_size(b->length()) - sizeof(HeapBlock))); | 234 memset((void *)b->allocated_space(), |
235 badCodeHeapFreeVal, | |
236 segments_to_size(b->length()) - sizeof(HeapBlock)); | |
237 #endif | |
220 add_to_freelist(b); | 238 add_to_freelist(b); |
221 NOT_PRODUCT(verify()); | 239 |
222 } | 240 debug_only(if (VerifyCodeCacheOften) verify()); |
223 | 241 } |
224 /** | 242 |
225 * Uses segment map to find the the start (header) of a nmethod. This works as follows: | 243 |
226 * The memory of the code cache is divided into 'segments'. The size of a segment is | |
227 * determined by -XX:CodeCacheSegmentSize=XX. Allocation in the code cache can only | |
228 * happen at segment boundaries. A pointer in the code cache can be mapped to a segment | |
229 * by calling segment_for(addr). Each time memory is requested from the code cache, | |
230 * the segmap is updated accordingly. See the following example, which illustrates the | |
231 * state of code cache and the segment map: (seg -> segment, nm ->nmethod) | |
232 * | |
233 * code cache segmap | |
234 * ----------- --------- | |
235 * seg 1 | nm 1 | -> | 0 | | |
236 * seg 2 | nm 1 | -> | 1 | | |
237 * ... | nm 1 | -> | .. | | |
238 * seg m | nm 2 | -> | 0 | | |
239 * seg m+1 | nm 2 | -> | 1 | | |
240 * ... | nm 2 | -> | 2 | | |
241 * ... | nm 2 | -> | .. | | |
242 * ... | nm 2 | -> | 0xFE | | |
243 * seg m+n | nm 2 | -> | 1 | | |
244 * ... | nm 2 | -> | | | |
245 * | |
246 * A value of '0' in the segmap indicates that this segment contains the beginning of | |
247 * an nmethod. Let's walk through a simple example: If we want to find the start of | |
248 * an nmethod that falls into seg 2, we read the value of the segmap[2]. The value | |
249 * is an offset that points to the segment that contains the start of the nmethod. | |
250 * Another example: If we want to get the start of nm 2, and we happen to get a pointer | |
251 * that points to seg m+n, we first read seg[n+m], which returns '1'. So we have to | |
252 * do one more read of the segmap[m+n-1] to finally get the segment header. | |
253 */ | |
254 void* CodeHeap::find_start(void* p) const { | 244 void* CodeHeap::find_start(void* p) const { |
255 if (!contains(p)) { | 245 if (!contains(p)) { |
256 return NULL; | 246 return NULL; |
257 } | 247 } |
258 size_t seg_idx = segment_for(p); | 248 size_t i = segment_for(p); |
259 address seg_map = (address)_segmap.low(); | 249 address b = (address)_segmap.low(); |
260 if (is_segment_unused(seg_map[seg_idx])) { | 250 if (b[i] == 0xFF) { |
261 return NULL; | 251 return NULL; |
262 } | 252 } |
263 while (seg_map[seg_idx] > 0) { | 253 while (b[i] > 0) i -= (int)b[i]; |
264 seg_idx -= (int)seg_map[seg_idx]; | 254 HeapBlock* h = block_at(i); |
265 } | |
266 | |
267 HeapBlock* h = block_at(seg_idx); | |
268 if (h->free()) { | 255 if (h->free()) { |
269 return NULL; | 256 return NULL; |
270 } | 257 } |
271 return h->allocated_space(); | 258 return h->allocated_space(); |
272 } | 259 } |
283 // equal to alignment_offset (mod alignment_unit). | 270 // equal to alignment_offset (mod alignment_unit). |
284 return sizeof(HeapBlock) & (_segment_size - 1); | 271 return sizeof(HeapBlock) & (_segment_size - 1); |
285 } | 272 } |
286 | 273 |
287 // Finds the next free heapblock. If the current one is free, that it returned | 274 // Finds the next free heapblock. If the current one is free, that it returned |
288 void* CodeHeap::next_free(HeapBlock* b) const { | 275 void* CodeHeap::next_free(HeapBlock *b) const { |
289 // Since free blocks are merged, there is max. on free block | 276 // Since free blocks are merged, there is max. on free block |
290 // between two used ones | 277 // between two used ones |
291 if (b != NULL && b->free()) b = next_block(b); | 278 if (b != NULL && b->free()) b = next_block(b); |
292 assert(b == NULL || !b->free(), "must be in use or at end of heap"); | 279 assert(b == NULL || !b->free(), "must be in use or at end of heap"); |
293 return (b == NULL) ? NULL : b->allocated_space(); | 280 return (b == NULL) ? NULL : b->allocated_space(); |
298 if (_next_segment > 0) | 285 if (_next_segment > 0) |
299 return block_at(0); | 286 return block_at(0); |
300 return NULL; | 287 return NULL; |
301 } | 288 } |
302 | 289 |
303 HeapBlock* CodeHeap::block_start(void* q) const { | 290 HeapBlock *CodeHeap::block_start(void *q) const { |
304 HeapBlock* b = (HeapBlock*)find_start(q); | 291 HeapBlock* b = (HeapBlock*)find_start(q); |
305 if (b == NULL) return NULL; | 292 if (b == NULL) return NULL; |
306 return b - 1; | 293 return b - 1; |
307 } | 294 } |
308 | 295 |
323 | 310 |
324 size_t CodeHeap::max_capacity() const { | 311 size_t CodeHeap::max_capacity() const { |
325 return _memory.reserved_size(); | 312 return _memory.reserved_size(); |
326 } | 313 } |
327 | 314 |
328 int CodeHeap::allocated_segments() const { | |
329 return (int)_next_segment; | |
330 } | |
331 | |
332 size_t CodeHeap::allocated_capacity() const { | 315 size_t CodeHeap::allocated_capacity() const { |
333 // size of used heap - size on freelist | 316 // size of used heap - size on freelist |
334 return segments_to_size(_next_segment - _freelist_segments); | 317 return segments_to_size(_next_segment - _freelist_segments); |
335 } | 318 } |
336 | 319 |
340 return segments_to_size(_number_of_reserved_segments - _next_segment); | 323 return segments_to_size(_number_of_reserved_segments - _next_segment); |
341 } | 324 } |
342 | 325 |
343 // Free list management | 326 // Free list management |
344 | 327 |
345 FreeBlock* CodeHeap::following_block(FreeBlock *b) { | 328 FreeBlock *CodeHeap::following_block(FreeBlock *b) { |
346 return (FreeBlock*)(((address)b) + _segment_size * b->length()); | 329 return (FreeBlock*)(((address)b) + _segment_size * b->length()); |
347 } | 330 } |
348 | 331 |
349 // Inserts block b after a | 332 // Inserts block b after a |
350 void CodeHeap::insert_after(FreeBlock* a, FreeBlock* b) { | 333 void CodeHeap::insert_after(FreeBlock* a, FreeBlock* b) { |
358 merge_right(b); // Try to make b bigger | 341 merge_right(b); // Try to make b bigger |
359 merge_right(a); // Try to make a include b | 342 merge_right(a); // Try to make a include b |
360 } | 343 } |
361 | 344 |
362 // Try to merge this block with the following block | 345 // Try to merge this block with the following block |
363 bool CodeHeap::merge_right(FreeBlock* a) { | 346 void CodeHeap::merge_right(FreeBlock *a) { |
364 assert(a->free(), "must be a free block"); | 347 assert(a->free(), "must be a free block"); |
365 if (following_block(a) == a->link()) { | 348 if (following_block(a) == a->link()) { |
366 assert(a->link() != NULL && a->link()->free(), "must be free too"); | 349 assert(a->link() != NULL && a->link()->free(), "must be free too"); |
367 // Update block a to include the following block | 350 // Update block a to include the following block |
368 a->set_length(a->length() + a->link()->length()); | 351 a->set_length(a->length() + a->link()->length()); |
369 a->set_link(a->link()->link()); | 352 a->set_link(a->link()->link()); |
370 // Update find_start map | 353 // Update find_start map |
371 size_t beg = segment_for(a); | 354 size_t beg = segment_for(a); |
372 mark_segmap_as_used(beg, beg + a->length()); | 355 mark_segmap_as_used(beg, beg + a->length()); |
373 _freelist_length--; | 356 } |
374 return true; | 357 } |
375 } | 358 |
376 return false; | 359 void CodeHeap::add_to_freelist(HeapBlock *a) { |
377 } | |
378 | |
379 | |
380 void CodeHeap::add_to_freelist(HeapBlock* a) { | |
381 FreeBlock* b = (FreeBlock*)a; | 360 FreeBlock* b = (FreeBlock*)a; |
382 _freelist_length++; | |
383 | |
384 assert(b != _freelist, "cannot be removed twice"); | 361 assert(b != _freelist, "cannot be removed twice"); |
385 | |
386 | 362 |
387 // Mark as free and update free space count | 363 // Mark as free and update free space count |
388 _freelist_segments += b->length(); | 364 _freelist_segments += b->length(); |
389 b->set_free(); | 365 b->set_free(); |
390 | 366 |
393 _freelist = b; | 369 _freelist = b; |
394 b->set_link(NULL); | 370 b->set_link(NULL); |
395 return; | 371 return; |
396 } | 372 } |
397 | 373 |
398 // Since the freelist is ordered (smaller addresses -> larger addresses) and the | 374 // Scan for right place to put into list. List |
399 // element we want to insert into the freelist has a smaller address than the first | 375 // is sorted by increasing addresses |
400 // element, we can simply add 'b' as the first element and we are done. | 376 FreeBlock* prev = NULL; |
401 if (b < _freelist) { | 377 FreeBlock* cur = _freelist; |
378 while(cur != NULL && cur < b) { | |
379 assert(prev == NULL || prev < cur, "must be ordered"); | |
380 prev = cur; | |
381 cur = cur->link(); | |
382 } | |
383 | |
384 assert( (prev == NULL && b < _freelist) || | |
385 (prev < b && (cur == NULL || b < cur)), "list must be ordered"); | |
386 | |
387 if (prev == NULL) { | |
402 // Insert first in list | 388 // Insert first in list |
403 b->set_link(_freelist); | 389 b->set_link(_freelist); |
404 _freelist = b; | 390 _freelist = b; |
405 merge_right(_freelist); | 391 merge_right(_freelist); |
406 return; | 392 } else { |
407 } | 393 insert_after(prev, b); |
408 | 394 } |
409 // Scan for right place to put into list. List | 395 } |
410 // is sorted by increasing addresses | 396 |
411 FreeBlock* prev = _freelist; | 397 // Search freelist for an entry on the list with the best fit |
412 FreeBlock* cur = _freelist->link(); | 398 // Return NULL if no one was found |
413 while(cur != NULL && cur < b) { | |
414 assert(prev < cur, "Freelist must be ordered"); | |
415 prev = cur; | |
416 cur = cur->link(); | |
417 } | |
418 assert((prev < b) && (cur == NULL || b < cur), "free-list must be ordered"); | |
419 insert_after(prev, b); | |
420 } | |
421 | |
422 /** | |
423 * Search freelist for an entry on the list with the best fit. | |
424 * @return NULL, if no one was found | |
425 */ | |
426 FreeBlock* CodeHeap::search_freelist(size_t length, bool is_critical) { | 399 FreeBlock* CodeHeap::search_freelist(size_t length, bool is_critical) { |
427 FreeBlock* found_block = NULL; | 400 FreeBlock *best_block = NULL; |
428 FreeBlock* found_prev = NULL; | 401 FreeBlock *best_prev = NULL; |
429 size_t found_length = 0; | 402 size_t best_length = 0; |
430 | 403 |
431 FreeBlock* prev = NULL; | 404 // Search for smallest block which is bigger than length |
432 FreeBlock* cur = _freelist; | 405 FreeBlock *prev = NULL; |
433 const size_t critical_boundary = (size_t)high_boundary() - CodeCacheMinimumFreeSpace; | 406 FreeBlock *cur = _freelist; |
434 | |
435 // Search for first block that fits | |
436 while(cur != NULL) { | 407 while(cur != NULL) { |
437 if (cur->length() >= length) { | 408 size_t l = cur->length(); |
409 if (l >= length && (best_block == NULL || best_length > l)) { | |
410 | |
438 // Non critical allocations are not allowed to use the last part of the code heap. | 411 // Non critical allocations are not allowed to use the last part of the code heap. |
439 // Make sure the end of the allocation doesn't cross into the last part of the code heap. | 412 if (!is_critical) { |
440 if (!is_critical && (((size_t)cur + length) > critical_boundary)) { | 413 // Make sure the end of the allocation doesn't cross into the last part of the code heap |
441 // The freelist is sorted by address - if one fails, all consecutive will also fail. | 414 if (((size_t)cur + length) > ((size_t)high_boundary() - CodeCacheMinimumFreeSpace)) { |
442 break; | 415 // the freelist is sorted by address - if one fails, all consecutive will also fail. |
416 break; | |
417 } | |
443 } | 418 } |
444 // Remember block, its previous element, and its length | 419 |
445 found_block = cur; | 420 // Remember best block, its previous element, and its length |
446 found_prev = prev; | 421 best_block = cur; |
447 found_length = found_block->length(); | 422 best_prev = prev; |
448 | 423 best_length = best_block->length(); |
449 break; | |
450 } | 424 } |
425 | |
451 // Next element in list | 426 // Next element in list |
452 prev = cur; | 427 prev = cur; |
453 cur = cur->link(); | 428 cur = cur->link(); |
454 } | 429 } |
455 | 430 |
456 if (found_block == NULL) { | 431 if (best_block == NULL) { |
457 // None found | 432 // None found |
458 return NULL; | 433 return NULL; |
459 } | 434 } |
460 | 435 |
436 assert((best_prev == NULL && _freelist == best_block ) || | |
437 (best_prev != NULL && best_prev->link() == best_block), "sanity check"); | |
438 | |
461 // Exact (or at least good enough) fit. Remove from list. | 439 // Exact (or at least good enough) fit. Remove from list. |
462 // Don't leave anything on the freelist smaller than CodeCacheMinBlockLength. | 440 // Don't leave anything on the freelist smaller than CodeCacheMinBlockLength. |
463 if (found_length - length < CodeCacheMinBlockLength) { | 441 if (best_length < length + CodeCacheMinBlockLength) { |
464 _freelist_length--; | 442 length = best_length; |
465 length = found_length; | 443 if (best_prev == NULL) { |
466 if (found_prev == NULL) { | 444 assert(_freelist == best_block, "sanity check"); |
467 assert(_freelist == found_block, "sanity check"); | |
468 _freelist = _freelist->link(); | 445 _freelist = _freelist->link(); |
469 } else { | 446 } else { |
470 assert((found_prev->link() == found_block), "sanity check"); | |
471 // Unmap element | 447 // Unmap element |
472 found_prev->set_link(found_block->link()); | 448 best_prev->set_link(best_block->link()); |
473 } | 449 } |
474 } else { | 450 } else { |
475 // Truncate block and return a pointer to the following block | 451 // Truncate block and return a pointer to the following block |
452 best_block->set_length(best_length - length); | |
453 best_block = following_block(best_block); | |
476 // Set used bit and length on new block | 454 // Set used bit and length on new block |
477 found_block->set_length(found_length - length); | 455 size_t beg = segment_for(best_block); |
478 found_block = following_block(found_block); | |
479 | |
480 size_t beg = segment_for(found_block); | |
481 mark_segmap_as_used(beg, beg + length); | 456 mark_segmap_as_used(beg, beg + length); |
482 found_block->set_length(length); | 457 best_block->set_length(length); |
483 } | 458 } |
484 | 459 |
485 found_block->set_used(); | 460 best_block->set_used(); |
486 _freelist_segments -= length; | 461 _freelist_segments -= length; |
487 return found_block; | 462 return best_block; |
488 } | 463 } |
489 | 464 |
490 //---------------------------------------------------------------------------- | 465 //---------------------------------------------------------------------------- |
491 // Non-product code | 466 // Non-product code |
492 | 467 |
494 | 469 |
495 void CodeHeap::print() { | 470 void CodeHeap::print() { |
496 tty->print_cr("The Heap"); | 471 tty->print_cr("The Heap"); |
497 } | 472 } |
498 | 473 |
474 #endif | |
475 | |
499 void CodeHeap::verify() { | 476 void CodeHeap::verify() { |
500 if (VerifyCodeCache) { | 477 // Count the number of blocks on the freelist, and the amount of space |
501 size_t len = 0; | 478 // represented. |
502 int count = 0; | 479 int count = 0; |
503 for(FreeBlock* b = _freelist; b != NULL; b = b->link()) { | 480 size_t len = 0; |
504 len += b->length(); | 481 for(FreeBlock* b = _freelist; b != NULL; b = b->link()) { |
505 count++; | 482 len += b->length(); |
506 // Check if we have merged all free blocks | 483 count++; |
507 assert(merge_right(b) == false, "Missed merging opportunity"); | 484 } |
508 } | 485 |
509 // Verify that freelist contains the right amount of free space | 486 // Verify that freelist contains the right amount of free space |
510 assert(len == _freelist_segments, "wrong freelist"); | 487 // guarantee(len == _freelist_segments, "wrong freelist"); |
511 | 488 |
512 for(HeapBlock* h = first_block(); h != NULL; h = next_block(h)) { | 489 // Verify that the number of free blocks is not out of hand. |
513 if (h->free()) count--; | 490 static int free_block_threshold = 10000; |
514 } | 491 if (count > free_block_threshold) { |
515 // Verify that the freelist contains the same number of blocks | 492 warning("CodeHeap: # of free blocks > %d", free_block_threshold); |
516 // than free blocks found on the full list. | 493 // Double the warning limit |
517 assert(count == 0, "missing free blocks"); | 494 free_block_threshold *= 2; |
518 | 495 } |
519 // Verify that the number of free blocks is not out of hand. | 496 |
520 static int free_block_threshold = 10000; | 497 // Verify that the freelist contains the same number of free blocks that is |
521 if (count > free_block_threshold) { | 498 // found on the full list. |
522 warning("CodeHeap: # of free blocks > %d", free_block_threshold); | 499 for(HeapBlock *h = first_block(); h != NULL; h = next_block(h)) { |
523 // Double the warning limit | 500 if (h->free()) count--; |
524 free_block_threshold *= 2; | 501 } |
525 } | 502 // guarantee(count == 0, "missing free blocks"); |
526 } | 503 } |
527 } | |
528 | |
529 #endif |