< prev index next > src/hotspot/share/memory/metaspace/blockTree.hpp
Print this page
#define SHARE_MEMORY_METASPACE_BLOCKTREE_HPP
#include "memory/allocation.hpp"
#include "memory/metaspace/chunklevel.hpp"
#include "memory/metaspace/counters.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
namespace metaspace {
// BlockTree is a rather simple binary search tree. It is used to
! // manage small to medium free memory blocks (see class FreeBlocks).
//
// There is no separation between payload (managed blocks) and nodes: the
// memory blocks themselves are the nodes, with the block size being the key.
//
// We store node pointer information in these blocks when storing them. That
#define SHARE_MEMORY_METASPACE_BLOCKTREE_HPP
#include "memory/allocation.hpp"
#include "memory/metaspace/chunklevel.hpp"
#include "memory/metaspace/counters.hpp"
+ #include "memory/metaspace/metablock.hpp"
#include "utilities/debug.hpp"
#include "utilities/globalDefinitions.hpp"
namespace metaspace {
// BlockTree is a rather simple binary search tree. It is used to
! // manage medium to large free memory blocks.
//
// There is no separation between payload (managed blocks) and nodes: the
// memory blocks themselves are the nodes, with the block size being the key.
//
// We store node pointer information in these blocks when storing them. That
static const intptr_t _canary_value =
NOT_LP64(0x4e4f4445) LP64_ONLY(0x4e4f44454e4f4445ULL); // "NODE" resp "NODENODE"
// Note: we afford us the luxury of an always-there canary value.
! // The space for that is there (these nodes are only used to manage larger blocks,
- // see FreeBlocks::MaxSmallBlocksWordSize).
// It is initialized in debug and release, but only automatically tested
// in debug.
const intptr_t _canary;
// Normal tree node stuff...
static const intptr_t _canary_value =
NOT_LP64(0x4e4f4445) LP64_ONLY(0x4e4f44454e4f4445ULL); // "NODE" resp "NODENODE"
// Note: we afford us the luxury of an always-there canary value.
! // The space for that is there (these nodes are only used to manage larger blocks).
// It is initialized in debug and release, but only automatically tested
// in debug.
const intptr_t _canary;
// Normal tree node stuff...
}
}
}
#ifdef ASSERT
! void zap_range(MetaWord* p, size_t word_size);
// Helper for verify()
void verify_node_pointer(const Node* n) const;
#endif // ASSERT
public:
BlockTree() : _root(nullptr) {}
// Add a memory block to the tree. Its content will be overwritten.
! void add_block(MetaWord* p, size_t word_size) {
! DEBUG_ONLY(zap_range(p, word_size));
assert(word_size >= MinWordSize, "invalid block size " SIZE_FORMAT, word_size);
! Node* n = new(p) Node(word_size);
if (_root == nullptr) {
_root = n;
} else {
insert(_root, n);
}
_counter.add(word_size);
}
// Given a word_size, search and return the smallest block that is equal or
! // larger than that size. Upon return, *p_real_word_size contains the actual
! // block size.
- MetaWord* remove_block(size_t word_size, size_t* p_real_word_size) {
assert(word_size >= MinWordSize, "invalid block size " SIZE_FORMAT, word_size);
Node* n = find_closest_fit(word_size);
if (n != nullptr) {
DEBUG_ONLY(check_node(n);)
assert(n->_word_size >= word_size, "sanity");
}
}
}
#ifdef ASSERT
! void zap_block(MetaBlock block);
// Helper for verify()
void verify_node_pointer(const Node* n) const;
#endif // ASSERT
public:
BlockTree() : _root(nullptr) {}
// Add a memory block to the tree. Its content will be overwritten.
! void add_block(MetaBlock block) {
! DEBUG_ONLY(zap_block(block);)
+ const size_t word_size = block.word_size();
assert(word_size >= MinWordSize, "invalid block size " SIZE_FORMAT, word_size);
! Node* n = new(block.base()) Node(word_size);
if (_root == nullptr) {
_root = n;
} else {
insert(_root, n);
}
_counter.add(word_size);
}
// Given a word_size, search and return the smallest block that is equal or
! // larger than that size.
! MetaBlock remove_block(size_t word_size) {
assert(word_size >= MinWordSize, "invalid block size " SIZE_FORMAT, word_size);
+ MetaBlock result;
Node* n = find_closest_fit(word_size);
if (n != nullptr) {
DEBUG_ONLY(check_node(n);)
assert(n->_word_size >= word_size, "sanity");
n = remove_from_list(n);
} else {
remove_node_from_tree(n);
}
! MetaWord* p = (MetaWord*)n;
- *p_real_word_size = n->_word_size;
_counter.sub(n->_word_size);
! DEBUG_ONLY(zap_range(p, n->_word_size));
- return p;
}
! return nullptr;
}
// Returns number of blocks in this structure
unsigned count() const { return _counter.count(); }
n = remove_from_list(n);
} else {
remove_node_from_tree(n);
}
! result = MetaBlock((MetaWord*)n, n->_word_size);
_counter.sub(n->_word_size);
! DEBUG_ONLY(zap_block(result);)
}
! return result;
}
// Returns number of blocks in this structure
unsigned count() const { return _counter.count(); }
< prev index next >