43 _number_of_reserved_segments = 0; |
43 _number_of_reserved_segments = 0; |
44 _segment_size = 0; |
44 _segment_size = 0; |
45 _log2_segment_size = 0; |
45 _log2_segment_size = 0; |
46 _next_segment = 0; |
46 _next_segment = 0; |
47 _freelist = NULL; |
47 _freelist = NULL; |
|
48 _last_insert_point = NULL; |
48 _freelist_segments = 0; |
49 _freelist_segments = 0; |
49 _freelist_length = 0; |
50 _freelist_length = 0; |
50 _max_allocated_capacity = 0; |
51 _max_allocated_capacity = 0; |
51 _blob_count = 0; |
52 _blob_count = 0; |
52 _nmethod_count = 0; |
53 _nmethod_count = 0; |
53 _adapter_count = 0; |
54 _adapter_count = 0; |
54 _full_count = 0; |
55 _full_count = 0; |
55 } |
56 _fragmentation_count = 0; |
56 |
57 } |
|
58 |
|
59 // Dummy initialization of template array. |
|
60 char CodeHeap::segmap_template[] = {0}; |
|
61 |
|
62 // This template array is used to (re)initialize the segmap, |
|
63 // replacing a 1..254 loop. |
|
64 void CodeHeap::init_segmap_template() { |
|
65 assert(free_sentinel == 255, "Segment map logic changed!"); |
|
66 for (int i = 0; i <= free_sentinel; i++) { |
|
67 segmap_template[i] = i; |
|
68 } |
|
69 } |
57 |
70 |
58 // The segmap is marked free for that part of the heap |
71 // The segmap is marked free for that part of the heap |
59 // which has not been allocated yet (beyond _next_segment). |
72 // which has not been allocated yet (beyond _next_segment). |
|
73 // The range of segments to be marked is given by [beg..end). |
60 // "Allocated" space in this context means there exists a |
74 // "Allocated" space in this context means there exists a |
61 // HeapBlock or a FreeBlock describing this space. |
75 // HeapBlock or a FreeBlock describing this space. |
62 // This method takes segment map indices as range boundaries |
76 // This method takes segment map indices as range boundaries |
63 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { |
77 void CodeHeap::mark_segmap_as_free(size_t beg, size_t end) { |
64 assert( beg < _number_of_committed_segments, "interval begin out of bounds"); |
78 assert( beg < _number_of_committed_segments, "interval begin out of bounds"); |
76 // Don't get confused here. |
90 // Don't get confused here. |
77 // All existing blocks, no matter if they are used() or free(), |
91 // All existing blocks, no matter if they are used() or free(), |
78 // have their segmap marked as used. This allows to find the |
92 // have their segmap marked as used. This allows to find the |
79 // block header (HeapBlock or FreeBlock) for any pointer |
93 // block header (HeapBlock or FreeBlock) for any pointer |
80 // within the allocated range (upper limit: _next_segment). |
94 // within the allocated range (upper limit: _next_segment). |
81 // This method takes segment map indices as range boundaries |
95 // This method takes segment map indices as range boundaries. |
82 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end) { |
96 // The range of segments to be marked is given by [beg..end). |
|
97 void CodeHeap::mark_segmap_as_used(size_t beg, size_t end, bool is_FreeBlock_join) { |
83 assert( beg < _number_of_committed_segments, "interval begin out of bounds"); |
98 assert( beg < _number_of_committed_segments, "interval begin out of bounds"); |
84 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); |
99 assert(beg < end && end <= _number_of_committed_segments, "interval end out of bounds"); |
85 // Don't do unpredictable things in PRODUCT build |
100 // Don't do unpredictable things in PRODUCT build |
86 if (beg < end) { |
101 if (beg < end) { |
87 // setup _segmap pointers for faster indexing |
102 // setup _segmap pointers for faster indexing |
88 address p = (address)_segmap.low() + beg; |
103 address p = (address)_segmap.low() + beg; |
89 address q = (address)_segmap.low() + end; |
104 address q = (address)_segmap.low() + end; |
90 // initialize interval |
105 // initialize interval |
91 int i = 0; |
106 // If we are joining two free blocks, the segmap range for each |
92 while (p < q) { |
107 // block is consistent. To create a consistent segmap range for |
93 *p++ = i++; |
108 // the blocks combined, we have three choices: |
94 if (i == free_sentinel) i = 1; |
109 // 1 - Do a full init from beg to end. Not very efficient because |
|
110 // the segmap range for the left block is potentially initialized |
|
111 // over and over again. |
|
112 // 2 - Carry over the last segmap element value of the left block |
|
113 // and initialize the segmap range of the right block starting |
|
114 // with that value. Saves initializing the left block's segmap |
|
115 // over and over again. Very efficient if FreeBlocks mostly |
|
116 // are appended to the right. |
|
117 // 3 - Take full advantage of the segmap being almost correct with |
|
118 // the two blocks combined. Lets assume the left block consists |
|
119 // of m segments. The the segmap looks like |
|
120 // ... (m-2) (m-1) (m) 0 1 2 3 ... |
|
121 // By substituting the '0' by '1', we create a valid, but |
|
122 // suboptimal, segmap range covering the two blocks combined. |
|
123 // We introduced an extra hop for the find_block_for() iteration. |
|
124 // |
|
125 // When this method is called with is_FreeBlock_join == true, the |
|
126 // segmap index beg must select the first segment of the right block. |
|
127 // Otherwise, it has to select the first segment of the left block. |
|
128 // Variant 3 is used for all FreeBlock joins. |
|
129 if (is_FreeBlock_join && (beg > 0)) { |
|
130 #ifndef PRODUCT |
|
131 FreeBlock* pBlock = (FreeBlock*)block_at(beg); |
|
132 assert(beg + pBlock->length() == end, "Internal error: (%d - %d) != %d", (unsigned int)end, (unsigned int)beg, (unsigned int)(pBlock->length())); |
|
133 assert(*p == 0, "Begin index does not select a block start segment, *p = %2.2x", *p); |
|
134 #endif |
|
135 // If possible, extend the previous hop. |
|
136 if (*(p-1) < (free_sentinel-1)) { |
|
137 *p = *(p-1) + 1; |
|
138 } else { |
|
139 *p = 1; |
|
140 } |
|
141 if (_fragmentation_count++ >= fragmentation_limit) { |
|
142 defrag_segmap(true); |
|
143 _fragmentation_count = 0; |
|
144 } |
|
145 } else { |
|
146 size_t n_bulk = free_sentinel-1; // bulk processing uses template indices [1..254]. |
|
147 // Use shortcut for blocks <= 255 segments. |
|
148 // Special case bulk processing: [0..254]. |
|
149 if ((end - beg) <= n_bulk) { |
|
150 memcpy(p, &segmap_template[0], end - beg); |
|
151 } else { |
|
152 *p++ = 0; // block header marker |
|
153 while (p < q) { |
|
154 if ((p+n_bulk) <= q) { |
|
155 memcpy(p, &segmap_template[1], n_bulk); |
|
156 p += n_bulk; |
|
157 } else { |
|
158 memcpy(p, &segmap_template[1], q-p); |
|
159 p = q; |
|
160 } |
|
161 } |
|
162 } |
95 } |
163 } |
96 } |
164 } |
97 } |
165 } |
98 |
166 |
99 void CodeHeap::invalidate(size_t beg, size_t end, size_t hdr_size) { |
167 void CodeHeap::invalidate(size_t beg, size_t end, size_t hdr_size) { |
218 NOT_PRODUCT(verify()); |
287 NOT_PRODUCT(verify()); |
219 HeapBlock* block = search_freelist(number_of_segments); |
288 HeapBlock* block = search_freelist(number_of_segments); |
220 NOT_PRODUCT(verify()); |
289 NOT_PRODUCT(verify()); |
221 |
290 |
222 if (block != NULL) { |
291 if (block != NULL) { |
223 assert(!block->free(), "must be marked free"); |
292 assert(!block->free(), "must not be marked free"); |
224 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(), |
293 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(), |
225 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
294 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
226 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
295 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
227 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high())); |
296 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high())); |
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))); |
|
231 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
297 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
232 _blob_count++; |
298 _blob_count++; |
233 return block->allocated_space(); |
299 return block->allocated_space(); |
234 } |
300 } |
235 |
301 |
236 // Ensure minimum size for allocation to the heap. |
302 // Ensure minimum size for allocation to the heap. |
237 number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments); |
303 number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments); |
238 |
304 |
239 if (_next_segment + number_of_segments <= _number_of_committed_segments) { |
305 if (_next_segment + number_of_segments <= _number_of_committed_segments) { |
240 mark_segmap_as_used(_next_segment, _next_segment + number_of_segments); |
306 mark_segmap_as_used(_next_segment, _next_segment + number_of_segments, false); |
241 HeapBlock* b = block_at(_next_segment); |
307 block = block_at(_next_segment); |
242 b->initialize(number_of_segments); |
308 block->initialize(number_of_segments); |
243 _next_segment += number_of_segments; |
309 _next_segment += number_of_segments; |
244 guarantee((char*) b >= _memory.low_boundary() && (char*) block < _memory.high(), |
310 guarantee((char*) block >= _memory.low_boundary() && (char*) block < _memory.high(), |
245 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
311 "The newly allocated block " INTPTR_FORMAT " is not within the heap " |
246 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
312 "starting with " INTPTR_FORMAT " and ending with " INTPTR_FORMAT, |
247 p2i(b), p2i(_memory.low_boundary()), p2i(_memory.high())); |
313 p2i(block), p2i(_memory.low_boundary()), p2i(_memory.high())); |
248 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
314 _max_allocated_capacity = MAX2(_max_allocated_capacity, allocated_capacity()); |
249 _blob_count++; |
315 _blob_count++; |
250 return b->allocated_space(); |
316 return block->allocated_space(); |
251 } else { |
317 } else { |
252 return NULL; |
318 return NULL; |
253 } |
319 } |
254 } |
320 } |
255 |
321 |
306 add_to_freelist(b); |
372 add_to_freelist(b); |
307 NOT_PRODUCT(verify()); |
373 NOT_PRODUCT(verify()); |
308 } |
374 } |
309 |
375 |
310 /** |
376 /** |
311 * Uses segment map to find the the start (header) of a nmethod. This works as follows: |
377 * The segment map is used to quickly find the the start (header) of a |
312 * The memory of the code cache is divided into 'segments'. The size of a segment is |
378 * code block (e.g. nmethod) when only a pointer to a location inside the |
313 * determined by -XX:CodeCacheSegmentSize=XX. Allocation in the code cache can only |
379 * code block is known. This works as follows: |
314 * happen at segment boundaries. A pointer in the code cache can be mapped to a segment |
380 * - The storage reserved for the code heap is divided into 'segments'. |
315 * by calling segment_for(addr). Each time memory is requested from the code cache, |
381 * - The size of a segment is determined by -XX:CodeCacheSegmentSize=<#bytes>. |
316 * the segmap is updated accordingly. See the following example, which illustrates the |
382 * - The size must be a power of two to allow the use of shift operations |
317 * state of code cache and the segment map: (seg -> segment, nm ->nmethod) |
383 * to quickly convert between segment index and segment address. |
|
384 * - Segment start addresses should be aligned to be multiples of CodeCacheSegmentSize. |
|
385 * - It seems beneficial for CodeCacheSegmentSize to be equal to os::page_size(). |
|
386 * - Allocation in the code cache can only happen at segment start addresses. |
|
387 * - Allocation in the code cache is in units of CodeCacheSegmentSize. |
|
388 * - A pointer in the code cache can be mapped to a segment by calling |
|
389 * segment_for(addr). |
|
390 * - The segment map is a byte array where array element [i] is related |
|
391 * to the i-th segment in the code heap. |
|
392 * - Each time memory is allocated/deallocated from the code cache, |
|
393 * the segment map is updated accordingly. |
|
394 * Note: deallocation does not cause the memory to become "free", as |
|
395 * indicated by the segment map state "free_sentinel". Deallocation |
|
396 * just changes the block state from "used" to "free". |
|
397 * - Elements of the segment map (byte) array are interpreted |
|
398 * as unsigned integer. |
|
399 * - Element values normally identify an offset backwards (in segment |
|
400 * size units) from the associated segment towards the start of |
|
401 * the block. |
|
402 * - Some values have a special meaning: |
|
403 * 0 - This segment is the start of a block (HeapBlock or FreeBlock). |
|
404 * 255 - The free_sentinel value. This is a free segment, i.e. it is |
|
405 * not yet allocated and thus does not belong to any block. |
|
406 * - The value of the current element has to be subtracted from the |
|
407 * current index to get closer to the start. |
|
408 * - If the value of the then current element is zero, the block start |
|
409 * segment is found and iteration stops. Otherwise, start over with the |
|
410 * previous step. |
|
411 * |
|
412 * The following example illustrates a possible state of code cache |
|
413 * and the segment map: (seg -> segment, nm ->nmethod) |
318 * |
414 * |
319 * code cache segmap |
415 * code cache segmap |
320 * ----------- --------- |
416 * ----------- --------- |
321 * seg 1 | nm 1 | -> | 0 | |
417 * seg 1 | nm 1 | -> | 0 | |
322 * seg 2 | nm 1 | -> | 1 | |
418 * seg 2 | nm 1 | -> | 1 | |
323 * ... | nm 1 | -> | .. | |
419 * ... | nm 1 | -> | .. | |
|
420 * seg m-1 | nm 1 | -> | m-1 | |
324 * seg m | nm 2 | -> | 0 | |
421 * seg m | nm 2 | -> | 0 | |
325 * seg m+1 | nm 2 | -> | 1 | |
422 * seg m+1 | nm 2 | -> | 1 | |
326 * ... | nm 2 | -> | 2 | |
423 * ... | nm 2 | -> | 2 | |
327 * ... | nm 2 | -> | .. | |
424 * ... | nm 2 | -> | .. | |
328 * ... | nm 2 | -> | 0xFE | |
425 * ... | nm 2 | -> | 0xFE | (free_sentinel-1) |
329 * seg m+n | nm 2 | -> | 1 | |
426 * ... | nm 2 | -> | 1 | |
|
427 * seg m+n | nm 2 | -> | 2 | |
330 * ... | nm 2 | -> | | |
428 * ... | nm 2 | -> | | |
331 * |
429 * |
332 * A value of '0' in the segmap indicates that this segment contains the beginning of |
430 * How to read: |
333 * an nmethod. Let's walk through a simple example: If we want to find the start of |
431 * A value of '0' in the segmap indicates that this segment contains the |
334 * an nmethod that falls into seg 2, we read the value of the segmap[2]. The value |
432 * beginning of a CodeHeap block. Let's walk through a simple example: |
335 * is an offset that points to the segment that contains the start of the nmethod. |
433 * |
336 * Another example: If we want to get the start of nm 2, and we happen to get a pointer |
434 * We want to find the start of the block that contains nm 1, and we are |
337 * that points to seg m+n, we first read seg[n+m], which returns '1'. So we have to |
435 * given a pointer that points into segment m-2. We then read the value |
338 * do one more read of the segmap[m+n-1] to finally get the segment header. |
436 * of segmap[m-2]. The value is an offset that points to the segment |
|
437 * which contains the start of the block. |
|
438 * |
|
439 * Another example: We want to locate the start of nm 2, and we happen to |
|
440 * get a pointer that points into seg m+n. We first read seg[n+m], which |
|
441 * returns '2'. So we have to update our segment map index (ix -= segmap[n+m]) |
|
442 * and start over. |
339 */ |
443 */ |
340 void* CodeHeap::find_start(void* p) const { |
444 |
|
445 // Find block which contains the passed pointer, |
|
446 // regardless of the block being used or free. |
|
447 // NULL is returned if anything invalid is detected. |
|
448 void* CodeHeap::find_block_for(void* p) const { |
|
449 // Check the pointer to be in committed range. |
341 if (!contains(p)) { |
450 if (!contains(p)) { |
342 return NULL; |
451 return NULL; |
343 } |
452 } |
344 size_t seg_idx = segment_for(p); |
453 |
345 address seg_map = (address)_segmap.low(); |
454 address seg_map = (address)_segmap.low(); |
|
455 size_t seg_idx = segment_for(p); |
|
456 |
|
457 // This may happen in special cases. Just ignore. |
|
458 // Example: PPC ICache stub generation. |
346 if (is_segment_unused(seg_map[seg_idx])) { |
459 if (is_segment_unused(seg_map[seg_idx])) { |
347 return NULL; |
460 return NULL; |
348 } |
461 } |
|
462 |
|
463 // Iterate the segment map chain to find the start of the block. |
349 while (seg_map[seg_idx] > 0) { |
464 while (seg_map[seg_idx] > 0) { |
|
465 // Don't check each segment index to refer to a used segment. |
|
466 // This method is called extremely often. Therefore, any checking |
|
467 // has a significant impact on performance. Rely on CodeHeap::verify() |
|
468 // to do the job on request. |
350 seg_idx -= (int)seg_map[seg_idx]; |
469 seg_idx -= (int)seg_map[seg_idx]; |
351 } |
470 } |
352 |
471 |
353 HeapBlock* h = block_at(seg_idx); |
472 return address_for(seg_idx); |
354 if (h->free()) { |
473 } |
355 return NULL; |
474 |
356 } |
475 // Find block which contains the passed pointer. |
357 return h->allocated_space(); |
476 // The block must be used, i.e. must not be a FreeBlock. |
358 } |
477 // Return a pointer that points past the block header. |
359 |
478 void* CodeHeap::find_start(void* p) const { |
|
479 HeapBlock* h = (HeapBlock*)find_block_for(p); |
|
480 return ((h == NULL) || h->free()) ? NULL : h->allocated_space(); |
|
481 } |
|
482 |
|
483 // Find block which contains the passed pointer. |
|
484 // Same as find_start(p), but with additional safety net. |
360 CodeBlob* CodeHeap::find_blob_unsafe(void* start) const { |
485 CodeBlob* CodeHeap::find_blob_unsafe(void* start) const { |
361 CodeBlob* result = (CodeBlob*)CodeHeap::find_start(start); |
486 CodeBlob* result = (CodeBlob*)CodeHeap::find_start(start); |
362 if (result != NULL && result->blob_contains((address)start)) { |
487 return (result != NULL && result->blob_contains((address)start)) ? result : NULL; |
363 return result; |
|
364 } |
|
365 return NULL; |
|
366 } |
488 } |
367 |
489 |
368 size_t CodeHeap::alignment_unit() const { |
490 size_t CodeHeap::alignment_unit() const { |
369 // this will be a power of two |
491 // this will be a power of two |
370 return _segment_size; |
492 return _segment_size; |
380 // Returns the current block if available and used. |
502 // Returns the current block if available and used. |
381 // If not, it returns the subsequent block (if available), NULL otherwise. |
503 // If not, it returns the subsequent block (if available), NULL otherwise. |
382 // Free blocks are merged, therefore there is at most one free block |
504 // Free blocks are merged, therefore there is at most one free block |
383 // between two used ones. As a result, the subsequent block (if available) is |
505 // between two used ones. As a result, the subsequent block (if available) is |
384 // guaranteed to be used. |
506 // guaranteed to be used. |
|
507 // The returned pointer points past the block header. |
385 void* CodeHeap::next_used(HeapBlock* b) const { |
508 void* CodeHeap::next_used(HeapBlock* b) const { |
386 if (b != NULL && b->free()) b = next_block(b); |
509 if (b != NULL && b->free()) b = next_block(b); |
387 assert(b == NULL || !b->free(), "must be in use or at end of heap"); |
510 assert(b == NULL || !b->free(), "must be in use or at end of heap"); |
388 return (b == NULL) ? NULL : b->allocated_space(); |
511 return (b == NULL) ? NULL : b->allocated_space(); |
389 } |
512 } |
390 |
513 |
391 // Returns the first used HeapBlock |
514 // Returns the first used HeapBlock |
|
515 // The returned pointer points to the block header. |
392 HeapBlock* CodeHeap::first_block() const { |
516 HeapBlock* CodeHeap::first_block() const { |
393 if (_next_segment > 0) |
517 if (_next_segment > 0) |
394 return block_at(0); |
518 return block_at(0); |
395 return NULL; |
519 return NULL; |
396 } |
520 } |
397 |
521 |
|
522 // The returned pointer points to the block header. |
398 HeapBlock* CodeHeap::block_start(void* q) const { |
523 HeapBlock* CodeHeap::block_start(void* q) const { |
399 HeapBlock* b = (HeapBlock*)find_start(q); |
524 HeapBlock* b = (HeapBlock*)find_start(q); |
400 if (b == NULL) return NULL; |
525 if (b == NULL) return NULL; |
401 return b - 1; |
526 return b - 1; |
402 } |
527 } |
403 |
528 |
404 // Returns the next Heap block an offset into one |
529 // Returns the next Heap block. |
|
530 // The returned pointer points to the block header. |
405 HeapBlock* CodeHeap::next_block(HeapBlock *b) const { |
531 HeapBlock* CodeHeap::next_block(HeapBlock *b) const { |
406 if (b == NULL) return NULL; |
532 if (b == NULL) return NULL; |
407 size_t i = segment_for(b) + b->length(); |
533 size_t i = segment_for(b) + b->length(); |
408 if (i < _next_segment) |
534 if (i < _next_segment) |
409 return block_at(i); |
535 return block_at(i); |
457 // Try to merge this block with the following block |
583 // Try to merge this block with the following block |
458 bool CodeHeap::merge_right(FreeBlock* a) { |
584 bool CodeHeap::merge_right(FreeBlock* a) { |
459 assert(a->free(), "must be a free block"); |
585 assert(a->free(), "must be a free block"); |
460 if (following_block(a) == a->link()) { |
586 if (following_block(a) == a->link()) { |
461 assert(a->link() != NULL && a->link()->free(), "must be free too"); |
587 assert(a->link() != NULL && a->link()->free(), "must be free too"); |
462 // Update block a to include the following block |
588 |
|
589 // Remember linked (following) block. invalidate should only zap header of this block. |
|
590 size_t follower = segment_for(a->link()); |
|
591 // Merge block a to include the following block. |
463 a->set_length(a->length() + a->link()->length()); |
592 a->set_length(a->length() + a->link()->length()); |
464 a->set_link(a->link()->link()); |
593 a->set_link(a->link()->link()); |
465 // Update find_start map |
594 |
466 size_t beg = segment_for(a); |
595 // Update the segment map and invalidate block contents. |
467 mark_segmap_as_used(beg, beg + a->length()); |
596 mark_segmap_as_used(follower, segment_for(a) + a->length(), true); |
468 invalidate(beg, beg + a->length(), sizeof(FreeBlock)); |
597 // Block contents has already been invalidated by add_to_freelist. |
|
598 // What's left is the header of the following block which now is |
|
599 // in the middle of the merged block. Just zap one segment. |
|
600 invalidate(follower, follower + 1, 0); |
|
601 |
469 _freelist_length--; |
602 _freelist_length--; |
470 return true; |
603 return true; |
471 } |
604 } |
472 return false; |
605 return false; |
473 } |
606 } |
501 _freelist = b; |
634 _freelist = b; |
502 merge_right(_freelist); |
635 merge_right(_freelist); |
503 return; |
636 return; |
504 } |
637 } |
505 |
638 |
506 // Scan for right place to put into list. List |
639 // Scan for right place to put into list. |
507 // is sorted by increasing addresses |
640 // List is sorted by increasing addresses. |
508 FreeBlock* prev = _freelist; |
641 FreeBlock* prev = _freelist; |
509 FreeBlock* cur = _freelist->link(); |
642 FreeBlock* cur = _freelist->link(); |
|
643 if ((_freelist_length > freelist_limit) && (_last_insert_point != NULL)) { |
|
644 _last_insert_point = (FreeBlock*)find_block_for(_last_insert_point); |
|
645 if ((_last_insert_point != NULL) && _last_insert_point->free() && (_last_insert_point < b)) { |
|
646 prev = _last_insert_point; |
|
647 cur = prev->link(); |
|
648 } |
|
649 } |
510 while(cur != NULL && cur < b) { |
650 while(cur != NULL && cur < b) { |
511 assert(prev < cur, "Freelist must be ordered"); |
651 assert(prev < cur, "Freelist must be ordered"); |
512 prev = cur; |
652 prev = cur; |
513 cur = cur->link(); |
653 cur = cur->link(); |
514 } |
654 } |
515 assert((prev < b) && (cur == NULL || b < cur), "free-list must be ordered"); |
655 assert((prev < b) && (cur == NULL || b < cur), "free-list must be ordered"); |
516 insert_after(prev, b); |
656 insert_after(prev, b); |
|
657 _last_insert_point = prev; |
517 } |
658 } |
518 |
659 |
519 /** |
660 /** |
520 * Search freelist for an entry on the list with the best fit. |
661 * Search freelist for an entry on the list with the best fit. |
521 * @return NULL, if no one was found |
662 * @return NULL, if no one was found |
579 } |
726 } |
580 |
727 |
581 res->set_used(); |
728 res->set_used(); |
582 _freelist_segments -= length; |
729 _freelist_segments -= length; |
583 return res; |
730 return res; |
|
731 } |
|
732 |
|
733 int CodeHeap::defrag_segmap(bool do_defrag) { |
|
734 int extra_hops_used = 0; |
|
735 int extra_hops_free = 0; |
|
736 int blocks_used = 0; |
|
737 int blocks_free = 0; |
|
738 for(HeapBlock* h = first_block(); h != NULL; h = next_block(h)) { |
|
739 size_t beg = segment_for(h); |
|
740 size_t end = segment_for(h) + h->length(); |
|
741 int extra_hops = segmap_hops(beg, end); |
|
742 if (h->free()) { |
|
743 extra_hops_free += extra_hops; |
|
744 blocks_free++; |
|
745 } else { |
|
746 extra_hops_used += extra_hops; |
|
747 blocks_used++; |
|
748 } |
|
749 if (do_defrag && (extra_hops > 0)) { |
|
750 mark_segmap_as_used(beg, end, false); |
|
751 } |
|
752 } |
|
753 return extra_hops_used + extra_hops_free; |
|
754 } |
|
755 |
|
756 // Count the hops required to get from the last segment of a |
|
757 // heap block to the block header segment. For the optimal case, |
|
758 // #hops = ((#segments-1)+(free_sentinel-2))/(free_sentinel-1) |
|
759 // The range of segments to be checked is given by [beg..end). |
|
760 // Return the number of extra hops required. There may be extra hops |
|
761 // due to the is_FreeBlock_join optimization in mark_segmap_as_used(). |
|
762 int CodeHeap::segmap_hops(size_t beg, size_t end) { |
|
763 if (beg < end) { |
|
764 // setup _segmap pointers for faster indexing |
|
765 address p = (address)_segmap.low() + beg; |
|
766 int hops_expected = (int)(((end-beg-1)+(free_sentinel-2))/(free_sentinel-1)); |
|
767 int nhops = 0; |
|
768 size_t ix = end-beg-1; |
|
769 while (p[ix] > 0) { |
|
770 ix -= p[ix]; |
|
771 nhops++; |
|
772 } |
|
773 return (nhops > hops_expected) ? nhops - hops_expected : 0; |
|
774 } |
|
775 return 0; |
584 } |
776 } |
585 |
777 |
586 //---------------------------------------------------------------------------- |
778 //---------------------------------------------------------------------------- |
587 // Non-product code |
779 // Non-product code |
588 |
780 |
617 for (char* c = (char*)b + sizeof(FreeBlock); c < (char*)b + segments_to_size(b->length()); c++) { |
809 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)); |
810 assert(*c == (char)badCodeHeapNewVal, "FreeBlock@" PTR_FORMAT "(" PTR_FORMAT ") not invalidated @byte %d", p2i(b), b->length(), (int)(c - (char*)b)); |
619 } |
811 } |
620 } |
812 } |
621 |
813 |
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(); |
814 address seg_map = (address)_segmap.low(); |
626 size_t nseg = 0; |
815 size_t nseg = 0; |
|
816 int extra_hops = 0; |
|
817 count = 0; |
627 for(HeapBlock* b = first_block(); b != NULL; b = next_block(b)) { |
818 for(HeapBlock* b = first_block(); b != NULL; b = next_block(b)) { |
628 size_t seg1 = segment_for(b); |
819 size_t seg1 = segment_for(b); |
629 size_t segn = seg1 + b->length(); |
820 size_t segn = seg1 + b->length(); |
|
821 extra_hops += segmap_hops(seg1, segn); |
|
822 count++; |
630 for (size_t i = seg1; i < segn; i++) { |
823 for (size_t i = seg1; i < segn; i++) { |
631 nseg++; |
824 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"); |
825 //---< Verify segment map marking >--- |
|
826 // All allocated segments, no matter if in a free or used block, |
|
827 // must be marked "in use". |
|
828 assert(!is_segment_unused(seg_map[i]), "CodeHeap: unused segment. seg_map[%d]([%d..%d]) = %d, %s block", (int)i, (int)seg1, (int)segn, seg_map[i], b->free()? "free":"used"); |
|
829 assert((unsigned char)seg_map[i] < free_sentinel, "CodeHeap: seg_map[%d]([%d..%d]) = %d (out of range)", (int)i, (int)seg1, (int)segn, seg_map[i]); |
633 } |
830 } |
634 } |
831 } |
635 assert(nseg == _next_segment, "CodeHeap: segment count mismatch. found %d, expected %d.", (int)nseg, (int)_next_segment); |
832 assert(nseg == _next_segment, "CodeHeap: segment count mismatch. found %d, expected %d.", (int)nseg, (int)_next_segment); |
|
833 assert((count == 0) || (extra_hops < (16 + 2*count)), "CodeHeap: many extra hops due to optimization. blocks: %d, extra hops: %d.", count, extra_hops); |
636 |
834 |
637 // Verify that the number of free blocks is not out of hand. |
835 // Verify that the number of free blocks is not out of hand. |
638 static int free_block_threshold = 10000; |
836 static int free_block_threshold = 10000; |
639 if (count > free_block_threshold) { |
837 if (count > free_block_threshold) { |
640 warning("CodeHeap: # of free blocks > %d", free_block_threshold); |
838 warning("CodeHeap: # of free blocks > %d", free_block_threshold); |