/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "oops/oop.inline.hpp"
#include "services/memTracker.hpp"
return sizeof(HeapBlock);
}
// Implementation of Heap
_segment_size = 0;
_log2_segment_size = 0;
_next_segment = 0;
_free_segments = 0;
}
// setup _segmap pointers for faster indexing
// initialize interval
while (p < q) *p++ = 0xFF;
}
// setup _segmap pointers for faster indexing
// initialize interval
int i = 0;
while (p < q) {
*p++ = i++;
if (i == 0xFF) i = 1;
}
}
}
}
#ifdef LINUX
#endif
}
// Reserve and initialize space for _memory.
os::vm_page_size();
return false;
}
// reserve space for _segmap
if (!_segmap.initialize(align_to_page_size(_number_of_reserved_segments), align_to_page_size(_number_of_committed_segments))) {
return false;
}
assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "could not commit enough space for segment map");
assert(_segmap.reserved_size() >= (size_t) _number_of_reserved_segments , "could not reserve enough space for segment map");
// initialize remaining instance variables
clear();
return true;
}
}
// expand _memory space
if (dm > 0) {
assert(_number_of_reserved_segments == number_of_segments(_memory.reserved_size()), "number of reserved segments should not change");
// expand _segmap space
if (ds > 0) {
}
// initialize additional segmap entries
}
return true;
}
}
_next_segment = 0;
}
// First check if we can satify request from freelist
debug_only(verify());
assert(block->length() >= length && block->length() < length + CodeCacheMinBlockLength, "sanity check");
#ifdef ASSERT
#endif
return block->allocated_space();
}
if (length < CodeCacheMinBlockLength) {
}
b->initialize(length);
_next_segment += length;
#ifdef ASSERT
#endif
return b->allocated_space();
} else {
return NULL;
}
}
// Find start of HeapBlock
#ifdef ASSERT
memset((void *)b->allocated_space(),
#endif
add_to_freelist(b);
}
if (!contains(p)) {
return NULL;
}
size_t i = segment_for(p);
if (b[i] == 0xFF) {
return NULL;
}
while (b[i] > 0) i -= (int)b[i];
if (h->free()) {
return NULL;
}
return h->allocated_space();
}
// this will be a power of two
return _segment_size;
}
// The lowest address in any allocated block will be
// equal to alignment_offset (mod alignment_unit).
}
// Finds the next free heapblock. If the current one is free, that it returned
// Since free blocks are merged, there is max. on free block
// between two used ones
}
// Returns the first used HeapBlock
if (_next_segment > 0)
return block_at(0);
return NULL;
}
return b - 1;
}
// Returns the next Heap block an offset into one
if (i < _next_segment)
return block_at(i);
return NULL;
}
// Returns current capacity
return _memory.committed_size();
}
return _memory.reserved_size();
}
// Start with the committed size in _memory;
// Subtract the committed, but unused, segments
// Subtract the size of the freelist
l -= size(_free_segments);
return l;
}
// First check unused space excluding free blocks.
return unused;
// Now check largest free block.
}
}
// Free list management
}
// Inserts block b after a
// Link b into the list after a
a->set_link(b);
// See if we can merge blocks
merge_right(b); // Try to make b bigger
merge_right(a); // Try to make a include b
}
// Try to merge this block with the following block
if (following_block(a) == a->link()) {
// Update block a to include the following block
// Update find_start map
}
}
// Mark as free and update free space count
_free_segments += b->length();
b->set_free();
// First element in list?
_freelist = b;
return;
}
// Scan for right place to put into list. List
// is sorted by increasing addresseses
}
// Insert first in list
_freelist = b;
} else {
insert_after(prev, b);
}
}
// Search freelist for an entry on the list with the best fit
// Return NULL if no one was found
// Search for smallest block which is bigger than length
// Remember best block, its previous element, and its length
best_block = cur;
}
// Next element in list
}
if (best_block == NULL) {
// None found
return NULL;
}
// Exact (or at least good enough) fit. Remove from list.
// Don't leave anything on the freelist smaller than CodeCacheMinBlockLength.
} else {
// Unmap element
}
} else {
// Truncate block and return a pointer to the following block
// Set used bit and length on new block
}
best_block->set_used();
_free_segments -= length;
return best_block;
}
//----------------------------------------------------------------------------
// Non-product code
#ifndef PRODUCT
}
#endif
// Count the number of blocks on the freelist, and the amount of space
// represented.
int count = 0;
count++;
}
// Verify that freelist contains the right amount of free space
// guarantee(len == _free_segments, "wrong freelist");
// Verify that the number of free blocks is not out of hand.
if (count > free_block_threshold) {
// Double the warning limit
free_block_threshold *= 2;
}
// Verify that the freelist contains the same number of free blocks that is
// found on the full list.
}
// guarantee(count == 0, "missing free blocks");
}