Path: blob/master/src/hotspot/share/jvmci/metadataHandles.hpp
40949 views
/*1* Copyright (c) 2019, 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#ifndef SHARE_JVMCI_METADATAHANDLES_HPP24#define SHARE_JVMCI_METADATAHANDLES_HPP2526#include "oops/constantPool.hpp"27#include "oops/metadata.hpp"28#include "oops/method.hpp"29#include "runtime/handles.hpp"30#include "runtime/os.hpp"3132#ifdef ASSERT33#define METADATA_TRACK_NAMES34#endif3536struct _jmetadata {37private:38Metadata* _value;39#ifdef METADATA_TRACK_NAMES40// Debug data for tracking stale metadata41const char* _name;42#endif4344public:45Metadata* value() { return _value; }4647#ifdef METADATA_TRACK_NAMES48void initialize() {49_value = NULL;50_name = NULL;51}52#endif5354void set_value(Metadata* value) {55_value = value;56}5758#ifdef METADATA_TRACK_NAMES59const char* name() { return _name; }60void set_name(const char* name) {61if (_name != NULL) {62os::free((void*) _name);63_name = NULL;64}65if (name != NULL) {66_name = os::strdup(name);67}68}69#endif70};7172typedef struct _jmetadata HandleRecord;73typedef struct _jmetadata *jmetadata;74class MetadataHandles;7576class MetadataHandleBlock : public CHeapObj<mtJVMCI> {77friend class MetadataHandles;78private:79enum SomeConstants {80block_size_in_handles = 32 // Number of handles per handle block81};8283// Free handles always have their low bit set so those pointers can84// be distinguished from handles which are in use. The last handle85// on the free list has a NULL pointer with the tag bit set, so it's86// clear that the handle has been reclaimed. The _free_list is87// always a real pointer to a handle.8889HandleRecord _handles[block_size_in_handles]; // The handles90int _top; // Index of next unused handle91MetadataHandleBlock* _next; // Link to next block9293MetadataHandleBlock() {94_top = 0;95_next = NULL;96#ifdef METADATA_TRACK_NAMES97for (int i = 0; i < block_size_in_handles; i++) {98_handles[i].initialize();99}100#endif101}102103const char* get_name(int index) {104#ifdef METADATA_TRACK_NAMES105return _handles[index].name();106#else107return "<missing>";108#endif109}110};111112// JVMCI maintains direct references to metadata. To make these references safe in the face of113// class redefinition, they are held in handles so they can be scanned during GC. They are114// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and115// passed back to the Java code which is responsible for setting the handle to NULL when it116// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The117// rebuild_free_list function notices when the handle is clear and reclaims it for re-use.118class MetadataHandles : public CHeapObj<mtJVMCI> {119private:120enum SomeConstants {121ptr_tag = 1,122ptr_mask = ~((intptr_t)ptr_tag)123};124125MetadataHandleBlock* _head; // First block126MetadataHandleBlock* _last; // Last block in use127intptr_t _free_list; // Handle free list128int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list129int _num_blocks; // Number of blocks130int _num_handles;131int _num_free_handles;132133HandleRecord* get_free_handle() {134HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);135_free_list = (ptr_mask & (intptr_t) (handle->value()));136assert(_free_list != ptr_tag, "should be null");137_num_free_handles--;138return handle;139}140141HandleRecord* get_handle() {142assert(_last != NULL, "sanity");143// Try last block144if (_last->_top < MetadataHandleBlock::block_size_in_handles) {145_num_handles++;146return &(_last->_handles)[_last->_top++];147} else if (_free_list != 0) {148// Try free list149return get_free_handle();150}151return NULL;152}153154void rebuild_free_list();155156jmetadata allocate_metadata_handle(Metadata* metadata);157158public:159MetadataHandles() {160_head = NULL;161_last = NULL;162_free_list = 0;163_allocate_before_rebuild = 0;164_num_blocks = 0;165_num_handles = 0;166_num_free_handles = 0;167}168169int num_handles() const { return _num_handles; }170int num_free_handles() const { return _num_free_handles; }171int num_blocks() const { return _num_blocks; }172173jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); }174jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }175176// Adds `handle` to the free list177void chain_free_list(HandleRecord* handle) {178handle->set_value((Metadata*) (ptr_tag | _free_list));179#ifdef METADATA_TRACK_NAMES180handle->set_name(NULL);181#endif182_free_list = (intptr_t) handle;183_num_free_handles++;184}185186// Clears all handles without releasing any handle memory.187void clear();188189void metadata_do(void f(Metadata*));190191void do_unloading();192};193194#endif // SHARE_JVMCI_METADATAHANDLES_HPP195196197