< prev index next >
src/hotspot/share/jvmci/metadataHandles.cpp
Print this page
*** 20,41 ****
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "precompiled.hpp"
! #include "jvmci/metadataHandleBlock.hpp"
! MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
! intptr_t MetadataHandleBlock::_free_list = 0;
! int MetadataHandleBlock::_allocate_before_rebuild = 0;
!
! jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
assert(obj->is_valid() && obj->is_metadata(), "must be");
! if (_last == NULL) {
// This is the first allocation.
! _last = this;
}
HandleRecord* handle = get_handle();
if (handle != NULL) {
--- 20,39 ----
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "precompiled.hpp"
! #include "jvmci/metadataHandles.hpp"
! jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {
assert(obj->is_valid() && obj->is_metadata(), "must be");
! if (_head == NULL) {
// This is the first allocation.
! _head = new MetadataHandleBlock();
! _last = _head;
! _num_blocks++;
}
HandleRecord* handle = get_handle();
if (handle != NULL) {
*** 44,54 ****
handle->set_name(obj->print_value_string());
#endif
return (jmetadata) handle;
}
! // Check if unused block follow last
if (_last->_next != NULL) {
// update last and retry
_last = _last->_next;
return allocate_metadata_handle(obj);
}
--- 42,52 ----
handle->set_name(obj->print_value_string());
#endif
return (jmetadata) handle;
}
! // Check if an unused block follows last
if (_last->_next != NULL) {
// update last and retry
_last = _last->_next;
return allocate_metadata_handle(obj);
}
*** 56,125 ****
// No space available, we have to rebuild free list or expand
if (_allocate_before_rebuild == 0) {
rebuild_free_list(); // updates _allocate_before_rebuild counter
} else {
// Append new block
! // This can block, but the caller has a metadata handle around this object.
! _last->_next = allocate_block();
_last = _last->_next;
_allocate_before_rebuild--;
}
return allocate_metadata_handle(obj); // retry
}
! void MetadataHandleBlock::rebuild_free_list() {
assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
int free = 0;
int blocks = 0;
! for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
HandleRecord* handle = &(current->_handles)[index];
if (handle->value() == NULL) {
// this handle was cleared out by a delete call, reuse it
chain_free_list(handle);
free++;
}
}
// we should not rebuild free list if there are unused handles at the end
! assert(current->_top == block_size_in_handles, "just checking");
blocks++;
}
// Heuristic: if more than half of the handles are NOT free we rebuild next time
// as well, otherwise we append a corresponding number of new blocks before
// attempting a free list rebuild again.
! int total = blocks * block_size_in_handles;
int extra = total - 2*free;
if (extra > 0) {
// Not as many free handles as we would like - compute number of new blocks to append
! _allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles;
}
}
! void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
! for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
HandleRecord* root = &(current->_handles)[index];
Metadata* value = root->value();
// traverse heap pointers only, not deleted handles or free list
// pointers
if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
! assert(value->is_valid(), "invalid metadata %s", get_name(index));
f(value);
}
}
// the next handle block is valid only if current block is full
! if (current->_top < block_size_in_handles) {
break;
}
}
}
// Visit any live metadata handles and clean them up. Since clearing of these handles is driven by
// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
! void MetadataHandleBlock::do_unloading() {
! for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
HandleRecord* handle = &(current->_handles)[index];
Metadata* value = handle->value();
// traverse heap pointers only, not deleted handles or free list
// pointers
--- 54,137 ----
// No space available, we have to rebuild free list or expand
if (_allocate_before_rebuild == 0) {
rebuild_free_list(); // updates _allocate_before_rebuild counter
} else {
// Append new block
! _last->_next = new MetadataHandleBlock();
_last = _last->_next;
_allocate_before_rebuild--;
+ _num_blocks++;
}
return allocate_metadata_handle(obj); // retry
}
! void MetadataHandles::rebuild_free_list() {
assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
int free = 0;
int blocks = 0;
! for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
HandleRecord* handle = &(current->_handles)[index];
if (handle->value() == NULL) {
// this handle was cleared out by a delete call, reuse it
chain_free_list(handle);
free++;
}
}
// we should not rebuild free list if there are unused handles at the end
! assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");
blocks++;
}
+ assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);
+ assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);
// Heuristic: if more than half of the handles are NOT free we rebuild next time
// as well, otherwise we append a corresponding number of new blocks before
// attempting a free list rebuild again.
! int total = blocks * MetadataHandleBlock::block_size_in_handles;
int extra = total - 2*free;
if (extra > 0) {
// Not as many free handles as we would like - compute number of new blocks to append
! _allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;
! }
! }
!
! void MetadataHandles::clear() {
! _free_list = 0;
! _last = _head;
! if (_head != NULL) {
! for (MetadataHandleBlock* block = _head; block != NULL; block = block->_next) {
! block->_top = 0;
! }
}
+ _num_handles = 0;
+ _num_free_handles = 0;
}
! void MetadataHandles::metadata_do(void f(Metadata*)) {
! for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
HandleRecord* root = &(current->_handles)[index];
Metadata* value = root->value();
// traverse heap pointers only, not deleted handles or free list
// pointers
if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
! assert(value->is_valid(), "invalid metadata %s", current->get_name(index));
f(value);
}
}
// the next handle block is valid only if current block is full
! if (current->_top < MetadataHandleBlock::block_size_in_handles) {
break;
}
}
}
// Visit any live metadata handles and clean them up. Since clearing of these handles is driven by
// weak references they will be cleared at some point in the future when the reference cleaning logic is run.
! void MetadataHandles::do_unloading() {
! for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
HandleRecord* handle = &(current->_handles)[index];
Metadata* value = handle->value();
// traverse heap pointers only, not deleted handles or free list
// pointers
*** 149,158 ****
}
}
}
}
// the next handle block is valid only if current block is full
! if (current->_top < block_size_in_handles) {
break;
}
}
}
--- 161,170 ----
}
}
}
}
// the next handle block is valid only if current block is full
! if (current->_top < MetadataHandleBlock::block_size_in_handles) {
break;
}
}
}
< prev index next >