Path: blob/master/src/hotspot/share/jvmci/metadataHandles.cpp
40950 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include "precompiled.hpp"24#include "classfile/classLoaderData.hpp"25#include "jvmci/metadataHandles.hpp"26#include "runtime/atomic.hpp"2728jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {29assert(obj->is_valid() && obj->is_metadata(), "must be");3031if (_head == NULL) {32// This is the first allocation.33_head = new MetadataHandleBlock();34_last = _head;35_num_blocks++;36}3738HandleRecord* handle = get_handle();3940if (handle != NULL) {41handle->set_value(obj);42#ifdef METADATA_TRACK_NAMES43handle->set_name(obj->print_value_string());44#endif45return (jmetadata) handle;46}4748// Check if an unused block follows last49if (_last->_next != NULL) {50// update last and retry51_last = _last->_next;52return allocate_metadata_handle(obj);53}5455// No space available, we have to rebuild free list or expand56if (_allocate_before_rebuild == 0) {57rebuild_free_list(); // updates _allocate_before_rebuild counter58} else {59// Append new block60_last->_next = new MetadataHandleBlock();61_last = _last->_next;62_allocate_before_rebuild--;63_num_blocks++;64}65return allocate_metadata_handle(obj); // retry66}676869void MetadataHandles::rebuild_free_list() {70assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");71int free = 0;72int blocks = 0;73for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {74for (int index = 0; index < current->_top; index++) {75HandleRecord* handle = &(current->_handles)[index];76if (handle->value() == NULL) {77// this handle was cleared out by a delete call, reuse it78chain_free_list(handle);79free++;80}81}82// we should not rebuild free list if there are unused handles at the end83assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");84blocks++;85}86assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);87assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);88// Heuristic: if more than half of the handles are NOT free we rebuild next time89// as well, otherwise we append a corresponding number of new blocks before90// attempting a free list rebuild again.91int total = blocks * MetadataHandleBlock::block_size_in_handles;92int extra = total - 2*free;93if (extra > 0) {94// Not as many free handles as we would like - compute number of new blocks to append95_allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;96}97}9899void MetadataHandles::clear() {100_free_list = 0;101_last = _head;102if (_head != NULL) {103for (MetadataHandleBlock* block = _head; block != NULL; block = block->_next) {104block->_top = 0;105}106}107_num_handles = 0;108_num_free_handles = 0;109}110111void MetadataHandles::metadata_do(void f(Metadata*)) {112for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {113for (int index = 0; index < current->_top; index++) {114HandleRecord* root = &(current->_handles)[index];115Metadata* value = root->value();116// traverse heap pointers only, not deleted handles or free list117// pointers118if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {119assert(value->is_valid(), "invalid metadata %s", current->get_name(index));120f(value);121}122}123// the next handle block is valid only if current block is full124if (current->_top < MetadataHandleBlock::block_size_in_handles) {125break;126}127}128}129130// Visit any live metadata handles and clean them up. Since clearing of these handles is driven by131// weak references they will be cleared at some point in the future when the reference cleaning logic is run.132void MetadataHandles::do_unloading() {133for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {134for (int index = 0; index < current->_top; index++) {135HandleRecord* handle = &(current->_handles)[index];136Metadata* value = handle->value();137// traverse heap pointers only, not deleted handles or free list138// pointers139if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {140Klass* klass = NULL;141if (value->is_klass()) {142klass = (Klass*)value;143} else if (value->is_method()) {144Method* m = (Method*)value;145klass = m->method_holder();146} else if (value->is_constantPool()) {147ConstantPool* cp = (ConstantPool*)value;148klass = cp->pool_holder();149} else {150ShouldNotReachHere();151}152if (klass->class_loader_data()->is_unloading()) {153// This needs to be marked so that it's no longer scanned154// but can't be put on the free list yet. The155// HandleCleaner will set this to NULL and156// put it on the free list.157jlong old_value = Atomic::cmpxchg((jlong*)handle, (jlong) value, (jlong) (ptr_tag));158if (old_value == (jlong) value) {159// Success160} else {161guarantee(old_value == 0, "only other possible value");162}163}164}165}166// the next handle block is valid only if current block is full167if (current->_top < MetadataHandleBlock::block_size_in_handles) {168break;169}170}171}172173174