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_RESOLVEDINDYENTRY_HPP 26 #define SHARE_OOPS_RESOLVEDINDYENTRY_HPP 27 28 // ResolvedIndyEntry contains the resolution information for invokedynamic bytecodes. 29 // A member of this class can be initialized with the resolved references index and 30 // constant pool index before any resolution is done, where "resolution" refers to finding the target 31 // method and its relevant information, like number of parameters and return type. These entries are contained 32 // within the ConstantPoolCache and are accessed with indices added to the invokedynamic bytecode after 33 // rewriting. 34 35 // The invokedynamic bytecode starts with an Constant Pool index as its operand which is then rewritten 36 // to become an "indy index", an index into the array of ResolvedIndyEntry. The method here is an adapter method 37 // which will be something like linkToTargetMethod. When an indy call is resolved, we no longer need to invoke 38 // the bootstrap method (BSM) and we can get the target method (the method actually doing stuff, i.e. a string concat) 39 // from the CallSite. The CallSite is generated when the BSM is invoked and it simply contains a MethodHandle for 40 // the target method. The adapter will propagate information to and from the target method and the JVM. 41 42 43 class Method; 44 class ResolvedIndyEntry { 45 friend class VMStructs; 46 47 Method* _method; // Adapter method for indy call 48 u2 _resolved_references_index; // Index of resolved references array that holds the appendix oop 49 u2 _cpool_index; // Constant pool index 50 u2 _number_of_parameters; // Number of arguments for adapter method 51 u1 _return_type; // Adapter method return type 52 u1 _flags; // Flags: [0000|00|has_appendix|resolution_failed] 53 54 public: 55 ResolvedIndyEntry() : 56 _method(nullptr), 57 _resolved_references_index(0), 58 _cpool_index(0), 59 _number_of_parameters(0), 60 _return_type(0), 61 _flags(0) {} 62 ResolvedIndyEntry(u2 resolved_references_index, u2 cpool_index) : 63 _method(nullptr), 64 _resolved_references_index(resolved_references_index), 65 _cpool_index(cpool_index), 66 _number_of_parameters(0), 67 _return_type(0), 68 _flags(0) {} 69 70 // Bit shift to get flags 71 // Note: Only two flags exists at the moment but more could be added 72 enum { 73 has_appendix_shift = 1, 74 }; 75 76 // Getters 77 Method* method() const { return Atomic::load_acquire(&_method); } 78 u2 resolved_references_index() const { return _resolved_references_index; } 79 u2 constant_pool_index() const { return _cpool_index; } 80 u2 num_parameters() const { return _number_of_parameters; } 81 u1 return_type() const { return _return_type; } 82 bool is_resolved() const { return method() != nullptr; } 83 bool has_appendix() const { return (_flags & (1 << has_appendix_shift)) != 0; } 84 bool resolution_failed() const { return (_flags & 1) != 0; } 85 bool is_vfinal() const { return false; } 86 bool is_final() const { return false; } 87 bool has_local_signature() const { return true; } 88 89 // Printing 90 void print_on(outputStream* st) const; 91 92 // Initialize with fields available before resolution 93 void init(u2 resolved_references_index, u2 cpool_index) { 94 _resolved_references_index = resolved_references_index; 95 _cpool_index = cpool_index; 96 } 97 98 void set_num_parameters(int value) { 99 assert(_number_of_parameters == 0 || _number_of_parameters == value, 100 "size must not change: parameter_size=%d, value=%d", _number_of_parameters, value); 101 Atomic::store(&_number_of_parameters, (u2)value); 102 guarantee(_number_of_parameters == value, 103 "size must not change: parameter_size=%d, value=%d", _number_of_parameters, value); 104 } 105 106 // Populate structure with resolution information 107 void fill_in(Method* m, u2 num_params, u1 return_type, bool has_appendix) { 108 set_num_parameters(num_params); 109 _return_type = return_type; 110 set_flags(has_appendix); 111 // Set the method last since it is read lock free. 112 // Resolution is indicated by whether or not the method is set. 113 Atomic::release_store(&_method, m); 114 } 115 116 // has_appendix is currently the only other flag besides resolution_failed 117 void set_flags(bool has_appendix) { 118 u1 new_flags = (has_appendix << has_appendix_shift); 119 assert((new_flags & 1) == 0, "New flags should not change resolution flag"); 120 // Preserve the resolution_failed bit 121 _flags = (_flags & 1) | new_flags; 122 } 123 124 void set_resolution_failed() { 125 _flags = _flags | 1; 126 } 127 128 void adjust_method_entry(Method* new_method) { _method = new_method; } 129 bool check_no_old_or_obsolete_entry(); 130 131 // CDS 132 void remove_unshareable_info(); 133 void mark_and_relocate(); 134 135 // Offsets 136 static ByteSize method_offset() { return byte_offset_of(ResolvedIndyEntry, _method); } 137 static ByteSize resolved_references_index_offset() { return byte_offset_of(ResolvedIndyEntry, _resolved_references_index); } 138 static ByteSize result_type_offset() { return byte_offset_of(ResolvedIndyEntry, _return_type); } 139 static ByteSize num_parameters_offset() { return byte_offset_of(ResolvedIndyEntry, _number_of_parameters); } 140 static ByteSize flags_offset() { return byte_offset_of(ResolvedIndyEntry, _flags); } 141 }; 142 143 #endif // SHARE_OOPS_RESOLVEDINDYENTRY_HPP