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