1 /*
2 * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
38
39 CodeHeap::CodeHeap(const char* name, const int code_blob_type)
40 : _code_blob_type(code_blob_type) {
41 _name = name;
42 _number_of_committed_segments = 0;
43 _number_of_reserved_segments = 0;
44 _segment_size = 0;
45 _log2_segment_size = 0;
46 _next_segment = 0;
47 _freelist = NULL;
48 _freelist_segments = 0;
49 _freelist_length = 0;
50 _max_allocated_capacity = 0;
51 _blob_count = 0;
52 _nmethod_count = 0;
53 _adapter_count = 0;
54 _full_count = 0;
55 }
56
57
58 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) {
59 assert( 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 while (p < q) *p++ = free_sentinel;
66 }
67
68
69 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) {
70 assert( beg < _number_of_committed_segments, "interval begin out of bounds");
71 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds");
72 // setup _segmap pointers for faster indexing
73 address p = (address)_segmap.low() + beg;
74 address q = (address)_segmap.low() + end;
75 // initialize interval
76 int i = 0;
77 while (p < q) {
78 *p++ = i++;
79 if (i == free_sentinel) i = 1;
80 }
81 }
82
83
84 static size_t align_to_page_size(size_t size) {
85 const size_t alignment = (size_t)os::vm_page_size();
86 assert(is_power_of_2(alignment), "no kidding ???");
87 return (size + alignment - 1) & ~(alignment - 1);
88 }
172 }
173 return true;
174 }
175
176 void CodeHeap::clear() {
177 _next_segment = 0;
178 mark_segmap_as_free(0, _number_of_committed_segments);
179 }
180
181
182 void* CodeHeap::allocate(size_t instance_size) {
183 size_t number_of_segments = size_to_segments(instance_size + header_size());
184 assert(segments_to_size(number_of_segments) >= sizeof(FreeBlock), "not enough room for FreeList");
185
186 // First check if we can satisfy request from freelist
187 NOT_PRODUCT(verify());
188 HeapBlock* block = search_freelist(number_of_segments);
189 NOT_PRODUCT(verify());
190
191 if (block != NULL) {
192 assert(block->length() >= number_of_segments && block->length() < number_of_segments + CodeCacheMinBlockLength, "sanity check");
193 assert(!block->free(), "must be marked free");
194 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(),
195 "The newly allocated block " INTPTR_FORMAT " is not within the heap "
196 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
197 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high()));
198 DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, instance_size));
199 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
200 _blob_count++;
201 return block->allocated_space();
202 }
203
204 // Ensure minimum size for allocation to the heap.
205 number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments);
206
207 if (_next_segment + number_of_segments <= _number_of_committed_segments) {
208 mark_segmap_as_used(_next_segment, _next_segment + number_of_segments);
209 HeapBlock* b = block_at(_next_segment);
210 b->initialize(number_of_segments);
211 _next_segment += number_of_segments;
212 guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(),
213 "The newly allocated block " INTPTR_FORMAT " is not within the heap "
214 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
215 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
216 DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapNewVal, instance_size));
217 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
218 _blob_count++;
219 return b->allocated_space();
220 } else {
221 return NULL;
222 }
223 }
224
225 void CodeHeap::deallocate_tail(void* p, size_t used_size) {
226 assert(p == find_start(p), "illegal deallocation");
227 // Find start of HeapBlock
228 HeapBlock* b = (((HeapBlock *)p) - 1);
229 assert(b->allocated_space() == p, "sanity check");
230 size_t used_number_of_segments = size_to_segments(used_size + header_size());
231 size_t actual_number_of_segments = b->length();
232 guarantee(used_number_of_segments <= actual_number_of_segments, "Must be!");
233 guarantee(b == block_at(_next_segment - actual_number_of_segments), "Intermediate allocation!");
234 size_t number_of_segments_to_deallocate = actual_number_of_segments - used_number_of_segments;
235 _next_segment -= number_of_segments_to_deallocate;
236 mark_segmap_as_free(_next_segment, _next_segment + number_of_segments_to_deallocate);
237 b->initialize(used_number_of_segments);
238 }
239
240 void CodeHeap::deallocate(void* p) {
241 assert(p == find_start(p), "illegal deallocation");
242 // Find start of HeapBlock
243 HeapBlock* b = (((HeapBlock *)p) - 1);
244 assert(b->allocated_space() == p, "sanity check");
245 guarantee((char*) b >= _memory.low_boundary() && (char*) b < _memory.high(),
246 "The block to be deallocated " INTPTR_FORMAT " is not within the heap "
247 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
248 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
249 DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapFreeVal,
250 segments_to_size(b->length()) - sizeof(HeapBlock)));
251 add_to_freelist(b);
252 NOT_PRODUCT(verify());
253 }
254
255 /**
256 * Uses segment map to find the the start (header) of a nmethod. This works as follows:
257 * The memory of the code cache is divided into 'segments'. The size of a segment is
413 _freelist_length--;
414 return true;
415 }
416 return false;
417 }
418
419
420 void CodeHeap::add_to_freelist(HeapBlock* a) {
421 FreeBlock* b = (FreeBlock*)a;
422 _freelist_length++;
423
424 assert(b != _freelist, "cannot be removed twice");
425
426
427 // Mark as free and update free space count
428 _freelist_segments += b->length();
429 b->set_free();
430
431 // First element in list?
432 if (_freelist == NULL) {
433 _freelist = b;
434 b->set_link(NULL);
435 return;
436 }
437
438 // Since the freelist is ordered (smaller addresses -> larger addresses) and the
439 // element we want to insert into the freelist has a smaller address than the first
440 // element, we can simply add 'b' as the first element and we are done.
441 if (b < _freelist) {
442 // Insert first in list
443 b->set_link(_freelist);
444 _freelist = b;
445 merge_right(_freelist);
446 return;
447 }
448
449 // Scan for right place to put into list. List
450 // is sorted by increasing addresses
451 FreeBlock* prev = _freelist;
452 FreeBlock* cur = _freelist->link();
453 while(cur != NULL && cur < b) {
454 assert(prev < cur, "Freelist must be ordered");
455 prev = cur;
456 cur = cur->link();
457 }
458 assert((prev < b) && (cur == NULL || b < cur), "free-list must be ordered");
459 insert_after(prev, b);
460 }
461
462 /**
463 * Search freelist for an entry on the list with the best fit.
464 * @return NULL, if no one was found
465 */
466 FreeBlock* CodeHeap::search_freelist(size_t length) {
467 FreeBlock* found_block = NULL;
468 FreeBlock* found_prev = NULL;
469 size_t found_length = 0;
470
471 FreeBlock* prev = NULL;
472 FreeBlock* cur = _freelist;
473
474 // Search for first block that fits
475 while(cur != NULL) {
476 if (cur->length() >= length) {
477 // Remember block, its previous element, and its length
478 found_block = cur;
479 found_prev = prev;
480 found_length = found_block->length();
481
482 break;
483 }
484 // Next element in list
485 prev = cur;
486 cur = cur->link();
487 }
488
489 if (found_block == NULL) {
490 // None found
491 return NULL;
492 }
493
494 // Exact (or at least good enough) fit. Remove from list.
495 // Don't leave anything on the freelist smaller than CodeCacheMinBlockLength.
496 if (found_length - length < CodeCacheMinBlockLength) {
497 _freelist_length--;
498 length = found_length;
499 if (found_prev == NULL) {
500 assert(_freelist == found_block, "sanity check");
501 _freelist = _freelist->link();
502 } else {
503 assert((found_prev->link() == found_block), "sanity check");
504 // Unmap element
505 found_prev->set_link(found_block->link());
506 }
507 } else {
508 // Truncate block and return a pointer to the following block
509 // Set used bit and length on new block
510 found_block->set_length(found_length - length);
511 found_block = following_block(found_block);
512
513 size_t beg = segment_for(found_block);
514 mark_segmap_as_used(beg, beg + length);
515 found_block->set_length(length);
516 }
517
518 found_block->set_used();
519 _freelist_segments -= length;
520 return found_block;
521 }
522
523 //----------------------------------------------------------------------------
524 // Non-product code
525
526 #ifndef PRODUCT
527
528 void CodeHeap::print() {
529 tty->print_cr("The Heap");
530 }
531
532 void CodeHeap::verify() {
533 if (VerifyCodeCache) {
534 size_t len = 0;
535 int count = 0;
536 for(FreeBlock* b = _freelist; b != NULL; b = b->link()) {
537 len += b->length();
538 count++;
539 // Check if we have merged all free blocks
540 assert(merge_right(b) == false, "Missed merging opportunity");
541 }
542 // Verify that freelist contains the right amount of free space
543 assert(len == _freelist_segments, "wrong freelist");
544
545 for(HeapBlock* h = first_block(); h != NULL; h = next_block(h)) {
546 if (h->free()) count--;
547 }
548 // Verify that the freelist contains the same number of blocks
549 // than free blocks found on the full list.
550 assert(count == 0, "missing free blocks");
551
552 // Verify that the number of free blocks is not out of hand.
553 static int free_block_threshold = 10000;
554 if (count > free_block_threshold) {
555 warning("CodeHeap: # of free blocks > %d", free_block_threshold);
556 // Double the warning limit
557 free_block_threshold *= 2;
558 }
559 }
560 }
561
562 #endif
|
1 /*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
38
39 CodeHeap::CodeHeap(const char* name, const int code_blob_type)
40 : _code_blob_type(code_blob_type) {
41 _name = name;
42 _number_of_committed_segments = 0;
43 _number_of_reserved_segments = 0;
44 _segment_size = 0;
45 _log2_segment_size = 0;
46 _next_segment = 0;
47 _freelist = NULL;
48 _freelist_segments = 0;
49 _freelist_length = 0;
50 _max_allocated_capacity = 0;
51 _blob_count = 0;
52 _nmethod_count = 0;
53 _adapter_count = 0;
54 _full_count = 0;
55 }
56
57
58 // The segmap is marked free for that part of the heap
59 // which has not been allocated yet (beyond _next_segment).
60 // "Allocated" space in this context means there exists a
61 // HeapBlock or a FreeBlock describing this space.
62 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) {
63 assert( beg < _number_of_committed_segments, "interval begin out of bounds");
64 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds");
65 // setup _segmap pointers for faster indexing
66 address p = (address)_segmap.low() + beg;
67 address q = (address)_segmap.low() + end;
68 // initialize interval
69 memset(p, free_sentinel, q-p);
70 }
71
72 // Don't get confused here.
73 // All existing blocks, no matter if they are used() or free(),
74 // have their segmap marked as used. This allows to find the
75 // block header (HeapBlock or FreeBlock) for any pointer
76 // within the allocated range (upper limit: _next_segment).
77 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) {
78 assert( beg < _number_of_committed_segments, "interval begin out of bounds");
79 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds");
80 // setup _segmap pointers for faster indexing
81 address p = (address)_segmap.low() + beg;
82 address q = (address)_segmap.low() + end;
83 // initialize interval
84 int i = 0;
85 while (p < q) {
86 *p++ = i++;
87 if (i == free_sentinel) i = 1;
88 }
89 }
90
91
92 static size_t align_to_page_size(size_t size) {
93 const size_t alignment = (size_t)os::vm_page_size();
94 assert(is_power_of_2(alignment), "no kidding ???");
95 return (size + alignment - 1) & ~(alignment - 1);
96 }
180 }
181 return true;
182 }
183
184 void CodeHeap::clear() {
185 _next_segment = 0;
186 mark_segmap_as_free(0, _number_of_committed_segments);
187 }
188
189
190 void* CodeHeap::allocate(size_t instance_size) {
191 size_t number_of_segments = size_to_segments(instance_size + header_size());
192 assert(segments_to_size(number_of_segments) >= sizeof(FreeBlock), "not enough room for FreeList");
193
194 // First check if we can satisfy request from freelist
195 NOT_PRODUCT(verify());
196 HeapBlock* block = search_freelist(number_of_segments);
197 NOT_PRODUCT(verify());
198
199 if (block != NULL) {
200 assert(!block->free(), "must be marked free");
201 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(),
202 "The newly allocated block " INTPTR_FORMAT " is not within the heap "
203 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
204 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high()));
205 DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, instance_size));
206 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
207 _blob_count++;
208 return block->allocated_space();
209 }
210
211 // Ensure minimum size for allocation to the heap.
212 number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments);
213
214 if (_next_segment + number_of_segments <= _number_of_committed_segments) {
215 mark_segmap_as_used(_next_segment, _next_segment + number_of_segments);
216 HeapBlock* b = block_at(_next_segment);
217 b->initialize(number_of_segments);
218 _next_segment += number_of_segments;
219 guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(),
220 "The newly allocated block " INTPTR_FORMAT " is not within the heap "
221 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
222 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
223 DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapNewVal, instance_size));
224 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity());
225 _blob_count++;
226 return b->allocated_space();
227 } else {
228 return NULL;
229 }
230 }
231
232 // Split the given block into two at the given segment.
233 // This is helpful when a block was allocated too large
234 // to trim off the unused space at the end (interpreter).
235 // It also helps with splitting a large free block during allocation.
236 // Usage state (used or free) must be set by caller since
237 // we don't know if the resulting blocks will be used or free.
238 // split_at is the segment number (relative to segment_for(b))
239 // where the split happens. The segment with relative
240 // number split_at is the first segment of the split-off block.
241 HeapBlock* CodeHeap::split_block(HeapBlock *b, size_t split_at) {
242 if (b == NULL) return NULL;
243 // After the split, both blocks must have a size of at least CodeCacheMinBlockLength
244 assert((split_at >= CodeCacheMinBlockLength) && (split_at + CodeCacheMinBlockLength <= b->length()),
245 "split position(%d) out of range [0..%d]", (int)split_at, (int)b->length());
246 size_t split_segment = segment_for(b) + split_at;
247 size_t b_size = b->length();
248 size_t newb_size = b_size - split_at;
249
250 HeapBlock* newb = block_at(split_segment);
251 newb->set_length(newb_size);
252 mark_segmap_as_used(segment_for(newb), segment_for(newb) + newb_size);
253 b->set_length(split_at);
254 return newb;
255 }
256
257 void CodeHeap::deallocate_tail(void* p, size_t used_size) {
258 assert(p == find_start(p), "illegal deallocation");
259 // Find start of HeapBlock
260 HeapBlock* b = (((HeapBlock *)p) - 1);
261 assert(b->allocated_space() == p, "sanity check");
262
263 size_t actual_number_of_segments = b->length();
264 size_t used_number_of_segments = size_to_segments(used_size + header_size());
265 size_t unused_number_of_segments = actual_number_of_segments - used_number_of_segments;
266 guarantee(used_number_of_segments <= actual_number_of_segments, "Must be!");
267
268 HeapBlock* f = split_block(b, used_number_of_segments);
269 DEBUG_ONLY(memset((void *)f->allocated_space(), badCodeHeapFreeVal,
270 segments_to_size(unused_number_of_segments) - sizeof(HeapBlock)));
271 add_to_freelist(f);
272 NOT_PRODUCT(verify());
273 }
274
275 void CodeHeap::deallocate(void* p) {
276 assert(p == find_start(p), "illegal deallocation");
277 // Find start of HeapBlock
278 HeapBlock* b = (((HeapBlock *)p) - 1);
279 assert(b->allocated_space() == p, "sanity check");
280 guarantee((char*) b >= _memory.low_boundary() && (char*) b < _memory.high(),
281 "The block to be deallocated " INTPTR_FORMAT " is not within the heap "
282 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT,
283 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high()));
284 DEBUG_ONLY(memset((void *)b->allocated_space(), badCodeHeapFreeVal,
285 segments_to_size(b->length()) - sizeof(HeapBlock)));
286 add_to_freelist(b);
287 NOT_PRODUCT(verify());
288 }
289
290 /**
291 * Uses segment map to find the the start (header) of a nmethod. This works as follows:
292 * The memory of the code cache is divided into 'segments'. The size of a segment is
448 _freelist_length--;
449 return true;
450 }
451 return false;
452 }
453
454
455 void CodeHeap::add_to_freelist(HeapBlock* a) {
456 FreeBlock* b = (FreeBlock*)a;
457 _freelist_length++;
458
459 assert(b != _freelist, "cannot be removed twice");
460
461
462 // Mark as free and update free space count
463 _freelist_segments += b->length();
464 b->set_free();
465
466 // First element in list?
467 if (_freelist == NULL) {
468 b->set_link(NULL);
469 _freelist = b;
470 return;
471 }
472
473 // Since the freelist is ordered (smaller addresses -> larger addresses) and the
474 // element we want to insert into the freelist has a smaller address than the first
475 // element, we can simply add 'b' as the first element and we are done.
476 if (b < _freelist) {
477 // Insert first in list
478 b->set_link(_freelist);
479 _freelist = b;
480 merge_right(_freelist);
481 return;
482 }
483
484 // Scan for right place to put into list. List
485 // is sorted by increasing addresses
486 FreeBlock* prev = _freelist;
487 FreeBlock* cur = _freelist->link();
488 while(cur != NULL && cur < b) {
489 assert(prev < cur, "Freelist must be ordered");
490 prev = cur;
491 cur = cur->link();
492 }
493 assert((prev < b) && (cur == NULL || b < cur), "free-list must be ordered");
494 insert_after(prev, b);
495 }
496
497 /**
498 * Search freelist for an entry on the list with the best fit.
499 * @return NULL, if no one was found
500 */
501 HeapBlock* CodeHeap::search_freelist(size_t length) {
502 FreeBlock* found_block = NULL;
503 FreeBlock* found_prev = NULL;
504 size_t found_length = _next_segment; // max it out to begin with
505
506 HeapBlock* res = NULL;
507 FreeBlock* prev = NULL;
508 FreeBlock* cur = _freelist;
509
510 length = length < CodeCacheMinBlockLength ? CodeCacheMinBlockLength : length;
511
512 // Search for best-fitting block
513 while(cur != NULL) {
514 size_t cur_length = cur->length();
515 if (cur_length == length) {
516 // We have a perfect fit
517 found_block = cur;
518 found_prev = prev;
519 found_length = cur_length;
520 break;
521 } else if ((cur_length > length) && (cur_length < found_length)) {
522 // This is a new, closer fit. Remember block, its previous element, and its length
523 found_block = cur;
524 found_prev = prev;
525 found_length = cur_length;
526 }
527 // Next element in list
528 prev = cur;
529 cur = cur->link();
530 }
531
532 if (found_block == NULL) {
533 // None found
534 return NULL;
535 }
536
537 // Exact (or at least good enough) fit. Remove from list.
538 // Don't leave anything on the freelist smaller than CodeCacheMinBlockLength.
539 if (found_length - length < CodeCacheMinBlockLength) {
540 _freelist_length--;
541 length = found_length;
542 if (found_prev == NULL) {
543 assert(_freelist == found_block, "sanity check");
544 _freelist = _freelist->link();
545 } else {
546 assert((found_prev->link() == found_block), "sanity check");
547 // Unmap element
548 found_prev->set_link(found_block->link());
549 }
550 res = found_block;
551 } else {
552 // Truncate the free block and return the truncated part
553 // as new HeapBlock. The remaining free block does not
554 // need to be updated, except for it's length. Truncating
555 // the segment map does not invalidate the leading part.
556 res = split_block(found_block, found_length - length);
557 }
558
559 res->set_used();
560 _freelist_segments -= length;
561 return res;
562 }
563
564 //----------------------------------------------------------------------------
565 // Non-product code
566
567 #ifndef PRODUCT
568
569 void CodeHeap::print() {
570 tty->print_cr("The Heap");
571 }
572
573 void CodeHeap::verify() {
574 if (VerifyCodeCache) {
575 size_t len = 0;
576 int count = 0;
577 for(FreeBlock* b = _freelist; b != NULL; b = b->link()) {
578 len += b->length();
579 count++;
580 // Check if we have merged all free blocks
581 assert(merge_right(b) == false, "Missed merging opportunity");
582 }
583 // Verify that freelist contains the right amount of free space
584 assert(len == _freelist_segments, "wrong freelist");
585
586 for(HeapBlock* h = first_block(); h != NULL; h = next_block(h)) {
587 if (h->free()) count--;
588 }
589 // Verify that the freelist contains the same number of blocks
590 // than free blocks found on the full list.
591 assert(count == 0, "missing free blocks");
592
593 // Verify segment map marking.
594 // All allocated segments, no matter if in a free or used block,
595 // must be marked "in use".
596 address seg_map = (address)_segmap.low();
597 size_t nseg = 0;
598 for(HeapBlock* b = first_block(); b != NULL; b = next_block(b)) {
599 size_t seg1 = segment_for(b);
600 size_t segn = seg1 + b->length();
601 for (size_t i = seg1; i < segn; i++) {
602 nseg++;
603 if (is_segment_unused(seg_map[i])) {
604 warning("CodeHeap: unused segment. %d [%d..%d], %s block", (int)i, (int)seg1, (int)segn, b->free()? "free":"used");
605 }
606 }
607 }
608 if (nseg != _next_segment) {
609 warning("CodeHeap: segment count mismatch. found %d, expected %d.", (int)nseg, (int)_next_segment);
610 }
611
612 // Verify that the number of free blocks is not out of hand.
613 static int free_block_threshold = 10000;
614 if (count > free_block_threshold) {
615 warning("CodeHeap: # of free blocks > %d", free_block_threshold);
616 // Double the warning limit
617 free_block_threshold *= 2;
618 }
619 }
620 }
621
622 #endif
|