1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #ifndef SHARE_JVMCI_METADATAHANDLEBLOCK_HPP 25 #define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP 26 27 #include "oops/constantPool.hpp" 28 #include "oops/metadata.hpp" 29 #include "oops/method.hpp" 30 #include "runtime/handles.hpp" 31 #include "runtime/os.hpp" 32 33 #ifdef ASSERT 34 #define METADATA_TRACK_NAMES 35 #endif 36 37 struct _jmetadata { 38 private: 39 Metadata* _value; 40 #ifdef METADATA_TRACK_NAMES 41 // Debug data for tracking stale metadata 42 const char* _name; 43 #endif 44 45 public: 46 Metadata* value() { return _value; } 47 48 #ifdef METADATA_TRACK_NAMES 49 void initialize() { 50 _value = NULL; 51 _name = NULL; 52 } 53 #endif 54 55 void set_value(Metadata* value) { 56 _value = value; 57 } 58 59 #ifdef METADATA_TRACK_NAMES 60 const char* name() { return _name; } 61 void set_name(const char* name) { 62 if (_name != NULL) { 63 os::free((void*) _name); 64 _name = NULL; 65 } 66 if (name != NULL) { 67 _name = os::strdup(name); 68 } 69 } 70 #endif 71 }; 72 73 typedef struct _jmetadata HandleRecord; 74 typedef struct _jmetadata *jmetadata; 75 76 // JVMCI maintains direct references to metadata. To make these references safe in the face of 77 // class redefinition, they are held in handles so they can be scanned during GC. They are 78 // managed in a cooperative way between the Java code and HotSpot. A handle is filled in and 79 // passed back to the Java code which is responsible for setting the handle to NULL when it 80 // is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The 81 // rebuild_free_list function notices when the handle is clear and reclaims it for re-use. 82 class MetadataHandleBlock : public CHeapObj<mtJVMCI> { 83 private: 84 enum SomeConstants { 85 block_size_in_handles = 32, // Number of handles per handle block 86 ptr_tag = 1, 87 ptr_mask = ~((intptr_t)ptr_tag) 88 }; 89 90 91 // Free handles always have their low bit set so those pointers can 92 // be distinguished from handles which are in use. The last handle 93 // on the free list has a NULL pointer with the tag bit set, so it's 94 // clear that the handle has been reclaimed. The _free_list is 95 // always a real pointer to a handle. 96 97 HandleRecord _handles[block_size_in_handles]; // The handles 98 int _top; // Index of next unused handle 99 MetadataHandleBlock* _next; // Link to next block 100 101 // The following instance variables are only used by the first block in a chain. 102 // Having two types of blocks complicates the code and the space overhead is negligible. 103 static MetadataHandleBlock* _last; // Last block in use 104 static intptr_t _free_list; // Handle free list 105 static int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list 106 107 MetadataHandleBlock() { 108 _top = 0; 109 _next = NULL; 110 #ifdef METADATA_TRACK_NAMES 111 for (int i = 0; i < block_size_in_handles; i++) { 112 _handles[i].initialize(); 113 } 114 #endif 115 } 116 117 const char* get_name(int index) { 118 #ifdef METADATA_TRACK_NAMES 119 return _handles[index].name(); 120 #else 121 return "<missing>"; 122 #endif 123 } 124 125 static HandleRecord* get_free_handle() { 126 assert(_free_list != 0, "should check before calling"); 127 HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask); 128 _free_list = (ptr_mask & (intptr_t) (handle->value())); 129 assert(_free_list != ptr_tag, "should be null"); 130 handle->set_value(NULL); 131 return handle; 132 } 133 134 static HandleRecord* get_handle() { 135 assert(_last != NULL, "sanity"); 136 // Try last block 137 if (_last->_top < block_size_in_handles) { 138 return &(_last->_handles)[_last->_top++]; 139 } else if (_free_list != 0) { 140 // Try free list 141 return get_free_handle(); 142 } 143 return NULL; 144 } 145 146 void rebuild_free_list(); 147 148 jmetadata allocate_metadata_handle(Metadata* metadata); 149 150 public: 151 jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); } 152 jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); } 153 154 static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); } 155 156 // Adds `handle` to the free list in this block 157 static void chain_free_list(HandleRecord* handle) { 158 handle->set_value((Metadata*) (ptr_tag | _free_list)); 159 #ifdef METADATA_TRACK_NAMES 160 handle->set_name(NULL); 161 #endif 162 _free_list = (intptr_t) handle; 163 } 164 165 void metadata_do(void f(Metadata*)); 166 167 void do_unloading(); 168 }; 169 170 #endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP