1 /* 2 * Copyright (c) 2023, 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 25 #ifndef SHARE_OOPS_RESOLVEDMETHODENTRY_HPP 26 #define SHARE_OOPS_RESOLVEDMETHODENTRY_HPP 27 28 #include "interpreter/bytecodes.hpp" 29 #include "runtime/atomic.hpp" 30 #include "utilities/sizes.hpp" 31 32 // ResolvedMethodEntry contains the resolution information for the invoke bytecodes 33 // invokestatic, invokespecial, invokeinterface, invokevirtual, and invokehandle but 34 // NOT invokedynamic (see resolvedIndyEntry.hpp). A member of this class can be initialized 35 // with the constant pool index associated with the bytecode before any resolution is done, 36 // where "resolution" refers to populating the bytecode1 and bytecode2 fields and other 37 // relevant information. These entries are contained within the ConstantPoolCache and are 38 // accessed with indices added to the bytecode after rewriting. 39 40 // Invoke bytecodes start with a constant pool index as their operand, which is then 41 // rewritten to a "method index", which is an index into the array of ResolvedMethodEntry. 42 // This structure has fields for every type of invoke bytecode but each entry may only 43 // use some of the fields. All entries have a TOS state, number of parameters, flags, 44 // and a constant pool index. 45 46 // Types of invokes 47 // invokestatic 48 // invokespecial 49 // Method* 50 // invokehandle 51 // Method* 52 // resolved references index 53 // invokevirtual 54 // Method* (if vfinal is true) 55 // vtable/itable index 56 // invokeinterface 57 // Klass* 58 // Method* 59 60 // Note: invokevirtual & invokespecial bytecodes can share the same constant 61 // pool entry and thus the same resolved method entry. 62 // The is_vfinal flag indicates method pointer for a final method or an index. 63 64 class InstanceKlass; 65 class ResolvedMethodEntry { 66 friend class VMStructs; 67 68 Method* _method; // Method for non virtual calls, adapter method for invokevirtual, final method for virtual 69 union { // These fields are mutually exclusive and are only used by some invoke codes 70 InstanceKlass* _interface_klass; // for interface and static 71 u2 _resolved_references_index; // Index of resolved references array that holds the appendix oop for invokehandle 72 u2 _table_index; // vtable/itable index for virtual and interface calls 73 } _entry_specific; 74 75 u2 _cpool_index; // Constant pool index 76 u2 _number_of_parameters; // Number of arguments for method 77 u1 _tos_state; // TOS state 78 u1 _flags; // Flags: [00|has_resolved_ref_index|has_local_signature|has_appendix|forced_virtual|final|virtual_final] 79 u1 _bytecode1, _bytecode2; // Resolved invoke codes 80 #ifdef ASSERT 81 bool _has_interface_klass; 82 bool _has_table_index; 83 #endif 84 85 // Constructors 86 public: 87 ResolvedMethodEntry(u2 cpi) : 88 _method(nullptr), 89 _cpool_index(cpi), 90 _number_of_parameters(0), 91 _tos_state(0), 92 _flags(0), 93 _bytecode1(0), 94 _bytecode2(0) { 95 _entry_specific._interface_klass = nullptr; 96 DEBUG_ONLY(_has_interface_klass = false;) 97 DEBUG_ONLY(_has_table_index = false;) 98 } 99 ResolvedMethodEntry() : 100 ResolvedMethodEntry(0) {} 101 102 // Bit shift to get flags 103 enum { 104 is_vfinal_shift = 0, 105 is_final_shift = 1, 106 is_forced_virtual_shift = 2, 107 has_appendix_shift = 3, 108 has_local_signature_shift = 4, 109 has_resolved_ref_shift = 5 110 }; 111 112 // Flags 113 bool is_vfinal() const { return (_flags & (1 << is_vfinal_shift)) != 0; } 114 bool is_final() const { return (_flags & (1 << is_final_shift)) != 0; } 115 bool is_forced_virtual() const { return (_flags & (1 << is_forced_virtual_shift)) != 0; } 116 bool has_appendix() const { return (_flags & (1 << has_appendix_shift)) != 0; } 117 bool has_local_signature() const { return (_flags & (1 << has_local_signature_shift)) != 0; } 118 bool has_resolved_references_index() const { return (_flags & (1 << has_resolved_ref_shift)) != 0; } 119 120 // Getters 121 Method* method() const { return Atomic::load_acquire(&_method); } 122 InstanceKlass* interface_klass() const { 123 assert(_bytecode1 == Bytecodes::_invokeinterface, "Only invokeinterface has a klass %d", _bytecode1); 124 assert(_has_interface_klass, "sanity"); 125 return _entry_specific._interface_klass; 126 } 127 u2 resolved_references_index() const { 128 // This index may be read before resolution completes 129 assert(has_resolved_references_index(), "sanity"); 130 return _entry_specific._resolved_references_index; 131 } 132 u2 table_index() const { 133 assert(_bytecode2 == Bytecodes::_invokevirtual, "Only invokevirtual has a vtable/itable index %d", _bytecode2); 134 assert(_has_table_index, "sanity"); 135 return _entry_specific._table_index; 136 } 137 u2 constant_pool_index() const { return _cpool_index; } 138 u1 tos_state() const { return _tos_state; } 139 u2 number_of_parameters() const { return _number_of_parameters; } 140 u1 bytecode1() const { return Atomic::load_acquire(&_bytecode1); } 141 u1 bytecode2() const { return Atomic::load_acquire(&_bytecode2); } 142 143 bool is_resolved(Bytecodes::Code code) const { 144 switch(code) { 145 case Bytecodes::_invokeinterface: 146 case Bytecodes::_invokehandle: 147 case Bytecodes::_invokespecial: 148 case Bytecodes::_invokestatic: 149 return (bytecode1() == code); 150 case Bytecodes::_invokevirtual: 151 return (bytecode2() == code); 152 default: 153 ShouldNotReachHere(); 154 return false; 155 } 156 } 157 158 void adjust_method_entry(Method* new_method) { 159 // this is done during the redefinition safepoint 160 _method = new_method; 161 } 162 bool check_no_old_or_obsolete_entry(); 163 164 // Printing 165 void print_on(outputStream* st) const; 166 167 // Setters 168 void set_flags(u1 flags) { _flags |= flags; } 169 170 inline void set_bytecode(u1* code, u1 new_code) { 171 #ifdef ASSERT 172 // Read once. 173 volatile Bytecodes::Code c = (Bytecodes::Code)*code; 174 assert(c == 0 || c == new_code || new_code == 0, "update must be consistent old: %d, new: %d", c, new_code); 175 #endif 176 Atomic::release_store(code, new_code); 177 } 178 179 void set_bytecode1(u1 b1) { 180 set_bytecode(&_bytecode1, b1); 181 } 182 183 void set_bytecode2(u1 b2) { 184 set_bytecode(&_bytecode2, b2); 185 } 186 187 void set_method(Method* m) { 188 Atomic::release_store(&_method, m); 189 } 190 191 void set_klass(InstanceKlass* klass) { 192 assert(!has_resolved_references_index() && 193 !_has_table_index, 194 "Mutually exclusive fields %d %d %d", has_resolved_references_index(), _has_interface_klass, _has_table_index); 195 DEBUG_ONLY(_has_interface_klass = true;) 196 _entry_specific._interface_klass = klass; 197 } 198 199 void set_resolved_references_index(u2 ref_index) { 200 assert(!_has_interface_klass && 201 !_has_table_index, 202 "Mutually exclusive fields %d %d %d", has_resolved_references_index(), _has_interface_klass, _has_table_index); 203 set_flags(1 << has_resolved_ref_shift); 204 _entry_specific._resolved_references_index = ref_index; 205 } 206 207 void set_table_index(u2 table_index) { 208 assert(!has_resolved_references_index() && 209 !_has_interface_klass, 210 "Mutually exclusive fields %d %d %d", has_resolved_references_index(), _has_interface_klass, _has_table_index); 211 DEBUG_ONLY(_has_table_index = true;) 212 _entry_specific._table_index = table_index; 213 } 214 215 void set_num_parameters(u2 num_params) { 216 _number_of_parameters = num_params; 217 } 218 219 void fill_in(u1 tos_state, u2 num_params) { 220 _tos_state = tos_state; 221 _number_of_parameters = num_params; 222 } 223 224 void reset_entry(); 225 226 // CDS 227 #if INCLUDE_CDS 228 void remove_unshareable_info(); 229 void mark_and_relocate(ConstantPool* src_cp); 230 #endif // INCLUDE_CDS 231 232 // Offsets 233 static ByteSize klass_offset() { return byte_offset_of(ResolvedMethodEntry, _entry_specific._interface_klass); } 234 static ByteSize method_offset() { return byte_offset_of(ResolvedMethodEntry, _method); } 235 static ByteSize resolved_references_index_offset() { return byte_offset_of(ResolvedMethodEntry, _entry_specific._resolved_references_index); } 236 static ByteSize table_index_offset() { return byte_offset_of(ResolvedMethodEntry, _entry_specific._table_index); } 237 static ByteSize num_parameters_offset() { return byte_offset_of(ResolvedMethodEntry, _number_of_parameters); } 238 static ByteSize type_offset() { return byte_offset_of(ResolvedMethodEntry, _tos_state); } 239 static ByteSize flags_offset() { return byte_offset_of(ResolvedMethodEntry, _flags); } 240 static ByteSize bytecode1_offset() { return byte_offset_of(ResolvedMethodEntry, _bytecode1); } 241 static ByteSize bytecode2_offset() { return byte_offset_of(ResolvedMethodEntry, _bytecode2); } 242 243 }; 244 245 #endif //SHARE_OOPS_RESOLVEDMETHODENTRY_HPP