< 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 >