53 _adapter_count = 0; |
53 _adapter_count = 0; |
54 _full_count = 0; |
54 _full_count = 0; |
55 } |
55 } |
56 |
56 |
57 |
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 // This method takes segment map indices as range boundaries |
58 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { |
63 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { |
59 assert( beg < _number_of_committed_segments, "interval begin out of bounds"); |
64 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"); |
65 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); |
61 // setup _segmap pointers for faster indexing |
66 // Don't do unpredictable things in PRODUCT build |
62 address p = (address)_segmap.low() + beg; |
67 if (beg < end) { |
63 address q = (address)_segmap.low() + end; |
68 // setup _segmap pointers for faster indexing |
64 // initialize interval |
69 address p = (address)_segmap.low() + beg; |
65 while (p < q) *p++ = free_sentinel; |
70 address q = (address)_segmap.low() + end; |
66 } |
71 // initialize interval |
67 |
72 memset(p, free_sentinel, q-p); |
68 |
73 } |
|
74 } |
|
75 |
|
76 // Don't get confused here. |
|
77 // All existing blocks, no matter if they are used() or free(), |
|
78 // have their segmap marked as used. This allows to find the |
|
79 // block header (HeapBlock or FreeBlock) for any pointer |
|
80 // within the allocated range (upper limit: _next_segment). |
|
81 // This method takes segment map indices as range boundaries |
69 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { |
82 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { |
70 assert( beg < _number_of_committed_segments, "interval begin out of bounds"); |
83 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"); |
84 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); |
72 // setup _segmap pointers for faster indexing |
85 // Don't do unpredictable things in PRODUCT build |
73 address p = (address)_segmap.low() + beg; |
86 if (beg < end) { |
74 address q = (address)_segmap.low() + end; |
87 // setup _segmap pointers for faster indexing |
75 // initialize interval |
88 address p = (address)_segmap.low() + beg; |
76 int i = 0; |
89 address q = (address)_segmap.low() + end; |
77 while (p < q) { |
90 // initialize interval |
78 *p++ = i++; |
91 int i = 0; |
79 if (i == free_sentinel) i = 1; |
92 while (p < q) { |
80 } |
93 *p++ = i++; |
|
94 if (i == free_sentinel) i = 1; |
|
95 } |
|
96 } |
|
97 } |
|
98 |
|
99 void CodeHeap::invalidate(size_t beg, size_t end, size_t hdr_size) { |
|
100 #ifndef PRODUCT |
|
101 // Fill the given range with some bad value. |
|
102 // length is expected to be in segment_size units. |
|
103 // This prevents inadvertent execution of code leftover from previous use. |
|
104 char* p = low_boundary() + segments_to_size(beg) + hdr_size; |
|
105 memset(p, badCodeHeapNewVal, segments_to_size(end-beg)-hdr_size); |
|
106 #endif |
|
107 } |
|
108 |
|
109 void CodeHeap::clear(size_t beg, size_t end) { |
|
110 mark_segmap_as_free(beg, end); |
|
111 invalidate(beg, end, 0); |
|
112 } |
|
113 |
|
114 void CodeHeap::clear() { |
|
115 _next_segment = 0; |
|
116 clear(_next_segment, _number_of_committed_segments); |
81 } |
117 } |
82 |
118 |
83 |
119 |
84 static size_t align_to_page_size(size_t size) { |
120 static size_t align_to_page_size(size_t size) { |
85 const size_t alignment = (size_t)os::vm_page_size(); |
121 const size_t alignment = (size_t)os::vm_page_size(); |
165 size_t ds = align_to_page_size(_number_of_committed_segments) - _segmap.committed_size(); |
201 size_t ds = align_to_page_size(_number_of_committed_segments) - _segmap.committed_size(); |
166 if ((ds > 0) && !_segmap.expand_by(ds)) { |
202 if ((ds > 0) && !_segmap.expand_by(ds)) { |
167 return false; |
203 return false; |
168 } |
204 } |
169 assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "just checking"); |
205 assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "just checking"); |
170 // initialize additional segmap entries |
206 // initialize additional space (heap memory and segmap) |
171 mark_segmap_as_free(i, _number_of_committed_segments); |
207 clear(i, _number_of_committed_segments); |
172 } |
208 } |
173 return true; |
209 return true; |
174 } |
|
175 |
|
176 void CodeHeap::clear() { |
|
177 _next_segment = 0; |
|
178 mark_segmap_as_free(0, _number_of_committed_segments); |
|
179 } |
210 } |
180 |
211 |
181 |
212 |
182 void* CodeHeap::allocate(size_t instance_size) { |
213 void* CodeHeap::allocate(size_t instance_size) { |
183 size_t number_of_segments = size_to_segments(instance_size + header_size()); |
214 size_t number_of_segments = size_to_segments(instance_size + header_size()); |
187 NOT_PRODUCT(verify()); |
218 NOT_PRODUCT(verify()); |
188 HeapBlock* block = search_freelist(number_of_segments); |
219 HeapBlock* block = search_freelist(number_of_segments); |
189 NOT_PRODUCT(verify()); |
220 NOT_PRODUCT(verify()); |
190 |
221 |
191 if (block != NULL) { |
222 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"); |
223 assert(!block->free(), "must be marked free"); |
194 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(), |
224 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(), |
195 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
225 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
196 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
226 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
197 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high())); |
227 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high())); |
198 DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, instance_size)); |
228 // Invalidate the additional space that FreeBlock occupies. The rest of the block should already be invalidated. |
|
229 // This is necessary due to a dubious assert in nmethod.cpp(PcDescCache::reset_to()). |
|
230 DEBUG_ONLY(memset((void*)block->allocated_space(), badCodeHeapNewVal, sizeof(FreeBlock) - sizeof(HeapBlock))); |
199 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
231 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
200 _blob_count++; |
232 _blob_count++; |
201 return block->allocated_space(); |
233 return block->allocated_space(); |
202 } |
234 } |
203 |
235 |
211 _next_segment += number_of_segments; |
243 _next_segment += number_of_segments; |
212 guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(), |
244 guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(), |
213 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
245 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
214 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
246 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
215 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high())); |
247 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()); |
248 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
218 _blob_count++; |
249 _blob_count++; |
219 return b->allocated_space(); |
250 return b->allocated_space(); |
220 } else { |
251 } else { |
221 return NULL; |
252 return NULL; |
222 } |
253 } |
223 } |
254 } |
224 |
255 |
|
256 // Split the given block into two at the given segment. |
|
257 // This is helpful when a block was allocated too large |
|
258 // to trim off the unused space at the end (interpreter). |
|
259 // It also helps with splitting a large free block during allocation. |
|
260 // Usage state (used or free) must be set by caller since |
|
261 // we don't know if the resulting blocks will be used or free. |
|
262 // split_at is the segment number (relative to segment_for(b)) |
|
263 // where the split happens. The segment with relative |
|
264 // number split_at is the first segment of the split-off block. |
|
265 HeapBlock* CodeHeap::split_block(HeapBlock *b, size_t split_at) { |
|
266 if (b == NULL) return NULL; |
|
267 // After the split, both blocks must have a size of at least CodeCacheMinBlockLength |
|
268 assert((split_at >= CodeCacheMinBlockLength) && (split_at + CodeCacheMinBlockLength <= b->length()), |
|
269 "split position(%d) out of range [0..%d]", (int)split_at, (int)b->length()); |
|
270 size_t split_segment = segment_for(b) + split_at; |
|
271 size_t b_size = b->length(); |
|
272 size_t newb_size = b_size - split_at; |
|
273 |
|
274 HeapBlock* newb = block_at(split_segment); |
|
275 newb->set_length(newb_size); |
|
276 mark_segmap_as_used(segment_for(newb), segment_for(newb) + newb_size); |
|
277 b->set_length(split_at); |
|
278 return newb; |
|
279 } |
|
280 |
225 void CodeHeap::deallocate_tail(void* p, size_t used_size) { |
281 void CodeHeap::deallocate_tail(void* p, size_t used_size) { |
226 assert(p == find_start(p), "illegal deallocation"); |
282 assert(p == find_start(p), "illegal deallocation"); |
227 // Find start of HeapBlock |
283 // Find start of HeapBlock |
228 HeapBlock* b = (((HeapBlock *)p) - 1); |
284 HeapBlock* b = (((HeapBlock *)p) - 1); |
229 assert(b->allocated_space() == p, "sanity check"); |
285 assert(b->allocated_space() == p, "sanity check"); |
230 size_t used_number_of_segments = size_to_segments(used_size + header_size()); |
286 |
231 size_t actual_number_of_segments = b->length(); |
287 size_t actual_number_of_segments = b->length(); |
|
288 size_t used_number_of_segments = size_to_segments(used_size + header_size()); |
|
289 size_t unused_number_of_segments = actual_number_of_segments - used_number_of_segments; |
232 guarantee(used_number_of_segments <= actual_number_of_segments, "Must be!"); |
290 guarantee(used_number_of_segments <= actual_number_of_segments, "Must be!"); |
233 guarantee(b == block_at(_next_segment - actual_number_of_segments), "Intermediate allocation!"); |
291 |
234 size_t number_of_segments_to_deallocate = actual_number_of_segments - used_number_of_segments; |
292 HeapBlock* f = split_block(b, used_number_of_segments); |
235 _next_segment -= number_of_segments_to_deallocate; |
293 add_to_freelist(f); |
236 mark_segmap_as_free(_next_segment, _next_segment + number_of_segments_to_deallocate); |
294 NOT_PRODUCT(verify()); |
237 b->initialize(used_number_of_segments); |
|
238 } |
295 } |
239 |
296 |
240 void CodeHeap::deallocate(void* p) { |
297 void CodeHeap::deallocate(void* p) { |
241 assert(p == find_start(p), "illegal deallocation"); |
298 assert(p == find_start(p), "illegal deallocation"); |
242 // Find start of HeapBlock |
299 // Find start of HeapBlock |
244 assert(b->allocated_space() == p, "sanity check"); |
301 assert(b->allocated_space() == p, "sanity check"); |
245 guarantee((char*) b >= _memory.low_boundary() && (char*) b < _memory.high(), |
302 guarantee((char*) b >= _memory.low_boundary() && (char*) b < _memory.high(), |
246 "The block to be deallocated " INTPTR_FORMAT " is not within the heap " |
303 "The block to be deallocated " INTPTR_FORMAT " is not within the heap " |
247 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
304 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
248 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high())); |
305 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); |
306 add_to_freelist(b); |
252 NOT_PRODUCT(verify()); |
307 NOT_PRODUCT(verify()); |
253 } |
308 } |
254 |
309 |
255 /** |
310 /** |
408 a->set_length(a->length() + a->link()->length()); |
463 a->set_length(a->length() + a->link()->length()); |
409 a->set_link(a->link()->link()); |
464 a->set_link(a->link()->link()); |
410 // Update find_start map |
465 // Update find_start map |
411 size_t beg = segment_for(a); |
466 size_t beg = segment_for(a); |
412 mark_segmap_as_used(beg, beg + a->length()); |
467 mark_segmap_as_used(beg, beg + a->length()); |
|
468 invalidate(beg, beg + a->length(), sizeof(FreeBlock)); |
413 _freelist_length--; |
469 _freelist_length--; |
414 return true; |
470 return true; |
415 } |
471 } |
416 return false; |
472 return false; |
417 } |
473 } |
418 |
474 |
419 |
475 |
420 void CodeHeap::add_to_freelist(HeapBlock* a) { |
476 void CodeHeap::add_to_freelist(HeapBlock* a) { |
421 FreeBlock* b = (FreeBlock*)a; |
477 FreeBlock* b = (FreeBlock*)a; |
|
478 size_t bseg = segment_for(b); |
422 _freelist_length++; |
479 _freelist_length++; |
423 |
480 |
424 assert(b != _freelist, "cannot be removed twice"); |
481 assert(b != _freelist, "cannot be removed twice"); |
425 |
|
426 |
482 |
427 // Mark as free and update free space count |
483 // Mark as free and update free space count |
428 _freelist_segments += b->length(); |
484 _freelist_segments += b->length(); |
429 b->set_free(); |
485 b->set_free(); |
|
486 invalidate(bseg, bseg + b->length(), sizeof(FreeBlock)); |
430 |
487 |
431 // First element in list? |
488 // First element in list? |
432 if (_freelist == NULL) { |
489 if (_freelist == NULL) { |
|
490 b->set_link(NULL); |
433 _freelist = b; |
491 _freelist = b; |
434 b->set_link(NULL); |
|
435 return; |
492 return; |
436 } |
493 } |
437 |
494 |
438 // Since the freelist is ordered (smaller addresses -> larger addresses) and the |
495 // 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 |
496 // element we want to insert into the freelist has a smaller address than the first |
461 |
518 |
462 /** |
519 /** |
463 * Search freelist for an entry on the list with the best fit. |
520 * Search freelist for an entry on the list with the best fit. |
464 * @return NULL, if no one was found |
521 * @return NULL, if no one was found |
465 */ |
522 */ |
466 FreeBlock* CodeHeap::search_freelist(size_t length) { |
523 HeapBlock* CodeHeap::search_freelist(size_t length) { |
467 FreeBlock* found_block = NULL; |
524 FreeBlock* found_block = NULL; |
468 FreeBlock* found_prev = NULL; |
525 FreeBlock* found_prev = NULL; |
469 size_t found_length = 0; |
526 size_t found_length = _next_segment; // max it out to begin with |
470 |
527 |
|
528 HeapBlock* res = NULL; |
471 FreeBlock* prev = NULL; |
529 FreeBlock* prev = NULL; |
472 FreeBlock* cur = _freelist; |
530 FreeBlock* cur = _freelist; |
473 |
531 |
474 // Search for first block that fits |
532 length = length < CodeCacheMinBlockLength ? CodeCacheMinBlockLength : length; |
|
533 |
|
534 // Search for best-fitting block |
475 while(cur != NULL) { |
535 while(cur != NULL) { |
476 if (cur->length() >= length) { |
536 size_t cur_length = cur->length(); |
477 // Remember block, its previous element, and its length |
537 if (cur_length == length) { |
478 found_block = cur; |
538 // We have a perfect fit |
479 found_prev = prev; |
539 found_block = cur; |
480 found_length = found_block->length(); |
540 found_prev = prev; |
481 |
541 found_length = cur_length; |
482 break; |
542 break; |
|
543 } else if ((cur_length > length) && (cur_length < found_length)) { |
|
544 // This is a new, closer fit. Remember block, its previous element, and its length |
|
545 found_block = cur; |
|
546 found_prev = prev; |
|
547 found_length = cur_length; |
483 } |
548 } |
484 // Next element in list |
549 // Next element in list |
485 prev = cur; |
550 prev = cur; |
486 cur = cur->link(); |
551 cur = cur->link(); |
487 } |
552 } |
502 } else { |
567 } else { |
503 assert((found_prev->link() == found_block), "sanity check"); |
568 assert((found_prev->link() == found_block), "sanity check"); |
504 // Unmap element |
569 // Unmap element |
505 found_prev->set_link(found_block->link()); |
570 found_prev->set_link(found_block->link()); |
506 } |
571 } |
|
572 res = found_block; |
507 } else { |
573 } else { |
508 // Truncate block and return a pointer to the following block |
574 // Truncate the free block and return the truncated part |
509 // Set used bit and length on new block |
575 // as new HeapBlock. The remaining free block does not |
510 found_block->set_length(found_length - length); |
576 // need to be updated, except for it's length. Truncating |
511 found_block = following_block(found_block); |
577 // the segment map does not invalidate the leading part. |
512 |
578 res = split_block(found_block, found_length - length); |
513 size_t beg = segment_for(found_block); |
579 } |
514 mark_segmap_as_used(beg, beg + length); |
580 |
515 found_block->set_length(length); |
581 res->set_used(); |
516 } |
|
517 |
|
518 found_block->set_used(); |
|
519 _freelist_segments -= length; |
582 _freelist_segments -= length; |
520 return found_block; |
583 return res; |
521 } |
584 } |
522 |
585 |
523 //---------------------------------------------------------------------------- |
586 //---------------------------------------------------------------------------- |
524 // Non-product code |
587 // Non-product code |
525 |
588 |
547 } |
610 } |
548 // Verify that the freelist contains the same number of blocks |
611 // Verify that the freelist contains the same number of blocks |
549 // than free blocks found on the full list. |
612 // than free blocks found on the full list. |
550 assert(count == 0, "missing free blocks"); |
613 assert(count == 0, "missing free blocks"); |
551 |
614 |
|
615 //---< all free block memory must have been invalidated >--- |
|
616 for(FreeBlock* b = _freelist; b != NULL; b = b->link()) { |
|
617 for (char* c = (char*)b + sizeof(FreeBlock); c < (char*)b + segments_to_size(b->length()); c++) { |
|
618 assert(*c == (char)badCodeHeapNewVal, "FreeBlock@" PTR_FORMAT "(" PTR_FORMAT ") not invalidated @byte %d", p2i(b), b->length(), (int)(c - (char*)b)); |
|
619 } |
|
620 } |
|
621 |
|
622 // Verify segment map marking. |
|
623 // All allocated segments, no matter if in a free or used block, |
|
624 // must be marked "in use". |
|
625 address seg_map = (address)_segmap.low(); |
|
626 size_t nseg = 0; |
|
627 for(HeapBlock* b = first_block(); b != NULL; b = next_block(b)) { |
|
628 size_t seg1 = segment_for(b); |
|
629 size_t segn = seg1 + b->length(); |
|
630 for (size_t i = seg1; i < segn; i++) { |
|
631 nseg++; |
|
632 assert(!is_segment_unused(seg_map[i]), "CodeHeap: unused segment. %d [%d..%d], %s block", (int)i, (int)seg1, (int)segn, b->free()? "free":"used"); |
|
633 } |
|
634 } |
|
635 assert(nseg == _next_segment, "CodeHeap: segment count mismatch. found %d, expected %d.", (int)nseg, (int)_next_segment); |
|
636 |
552 // Verify that the number of free blocks is not out of hand. |
637 // Verify that the number of free blocks is not out of hand. |
553 static int free_block_threshold = 10000; |
638 static int free_block_threshold = 10000; |
554 if (count > free_block_threshold) { |
639 if (count > free_block_threshold) { |
555 warning("CodeHeap: # of free blocks > %d", free_block_threshold); |
640 warning("CodeHeap: # of free blocks > %d", free_block_threshold); |
556 // Double the warning limit |
641 // Double the warning limit |