1 /*
  2  * Copyright (c) 1998, 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_CPCACHE_HPP
 26 #define SHARE_OOPS_CPCACHE_HPP
 27 
 28 #include "interpreter/bytecodes.hpp"
 29 #include "memory/allocation.hpp"
 30 #include "oops/array.hpp"
 31 #include "oops/oopHandle.hpp"
 32 #include "runtime/handles.hpp"
 33 #include "utilities/align.hpp"
 34 #include "utilities/constantTag.hpp"
 35 #include "utilities/growableArray.hpp"
 36 
 37 // The ConstantPoolCache is not a cache! It is the resolution table that the
 38 // interpreter uses to avoid going into the runtime and a way to access resolved
 39 // values.
 40 
 41 class CallInfo;
 42 class ResolvedFieldEntry;
 43 class ResolvedIndyEntry;
 44 class ResolvedMethodEntry;
 45 
 46 // A constant pool cache is a runtime data structure set aside to a constant pool. The cache
 47 // holds runtime information for all field access and invoke bytecodes. The cache
 48 // is created and initialized before a class is actively used (i.e., initialized), the indivi-
 49 // dual cache entries are filled at resolution (i.e., "link") time (see also: rewriter.*).
 50 
 51 class ConstantPoolCache: public MetaspaceObj {
 52   friend class VMStructs;
 53   friend class MetadataFactory;
 54  private:
 55   // If you add a new field that points to any metaspace object, you
 56   // must add this field to ConstantPoolCache::metaspace_pointers_do().
 57 
 58   // The narrowOop pointer to the archived resolved_references. Set at CDS dump
 59   // time when caching java heap object is supported.
 60   CDS_JAVA_HEAP_ONLY(int _archived_references_index;) // Gap on LP64
 61 
 62   ConstantPool*   _constant_pool;          // the corresponding constant pool
 63 
 64   // The following fields need to be modified at runtime, so they cannot be
 65   // stored in the ConstantPool, which is read-only.
 66   // Array of resolved objects from the constant pool and map from resolved
 67   // object index to original constant pool index
 68   OopHandle            _resolved_references;
 69   Array<u2>*           _reference_map;
 70 
 71   // RedefineClasses support
 72   uint64_t             _gc_epoch;
 73 
 74   Array<ResolvedIndyEntry>*   _resolved_indy_entries;
 75   Array<ResolvedFieldEntry>*  _resolved_field_entries;
 76   Array<ResolvedMethodEntry>* _resolved_method_entries;
 77 
 78   // Sizing
 79   debug_only(friend class ClassVerifier;)
 80 
 81   public:
 82     // specific but defiinitions for ldc
 83     enum {
 84       // high order bits are the TosState corresponding to field type or method return type
 85       tos_state_bits             = 4,
 86       tos_state_mask             = right_n_bits(tos_state_bits),
 87       tos_state_shift            = BitsPerInt - tos_state_bits,  // see verify_tos_state_shift below
 88       // low order bits give field index (for FieldInfo) or method parameter size:
 89       field_index_bits           = 16,
 90       field_index_mask           = right_n_bits(field_index_bits),
 91     };
 92 
 93   // Constructor
 94   ConstantPoolCache(const intStack& invokedynamic_references_map,
 95                     Array<ResolvedIndyEntry>* indy_info,
 96                     Array<ResolvedFieldEntry>* field_entries,
 97                     Array<ResolvedMethodEntry>* mehtod_entries);
 98 
 99   // Initialization
100   void initialize(const intArray& invokedynamic_references_map);
101  public:
102   static ConstantPoolCache* allocate(ClassLoaderData* loader_data,
103                                      const intStack& invokedynamic_references_map,
104                                      const GrowableArray<ResolvedIndyEntry> indy_entries,
105                                      const GrowableArray<ResolvedFieldEntry> field_entries,
106                                      const GrowableArray<ResolvedMethodEntry> method_entries,
107                                      TRAPS);
108 
109   void metaspace_pointers_do(MetaspaceClosure* it);
110   MetaspaceObj::Type type() const         { return ConstantPoolCacheType; }
111 
112   oop  archived_references() NOT_CDS_JAVA_HEAP_RETURN_(nullptr);
113   void set_archived_references(int root_index) NOT_CDS_JAVA_HEAP_RETURN;
114   void clear_archived_references() NOT_CDS_JAVA_HEAP_RETURN;
115 
116   inline objArrayOop resolved_references();
117   void set_resolved_references(OopHandle s) { _resolved_references = s; }
118   Array<u2>* reference_map() const        { return _reference_map; }
119   void set_reference_map(Array<u2>* o)    { _reference_map = o; }
120 
121  private:
122   void set_direct_or_vtable_call(
123     Bytecodes::Code invoke_code,                 // the bytecode used for invoking the method
124     int method_index,                            // Index into the resolved method entry array
125     const methodHandle& method,                  // the method/prototype if any (null, otherwise)
126     int             vtable_index,                // the vtable index if any, else negative
127     bool            sender_is_interface
128   );
129 
130  public:
131   void set_direct_call(                          // sets entry to exact concrete method entry
132     Bytecodes::Code invoke_code,                 // the bytecode used for invoking the method
133     int method_index,                            // Index into the resolved method entry array
134     const methodHandle& method,                  // the method to call
135     bool            sender_is_interface
136   );
137 
138   void set_vtable_call(                          // sets entry to vtable index
139     Bytecodes::Code invoke_code,                 // the bytecode used for invoking the method
140     int method_index,                            // Index into the resolved method entry array
141     const methodHandle& method,                  // resolved method which declares the vtable index
142     int             vtable_index                 // the vtable index
143   );
144 
145   void set_itable_call(
146     Bytecodes::Code invoke_code,                 // the bytecode used; must be invokeinterface
147     int method_index,                            // Index into the resolved method entry array
148     Klass* referenced_klass,                     // the referenced klass in the InterfaceMethodref
149     const methodHandle& method,                  // the resolved interface method
150     int itable_index                             // index into itable for the method
151   );
152 
153   // The "appendix" is an optional call-site-specific parameter which is
154   // pushed by the JVM at the end of the argument list.  This argument may
155   // be a MethodType for the MH.invokes and a CallSite for an invokedynamic
156   // instruction.  However, its exact type and use depends on the Java upcall,
157   // which simply returns a compiled LambdaForm along with any reference
158   // that LambdaForm needs to complete the call.  If the upcall returns a
159   // null appendix, the argument is not passed at all.
160   //
161   // The appendix is *not* represented in the signature of the symbolic
162   // reference for the call site, but (if present) it *is* represented in
163   // the Method* bound to the site.  This means that static and dynamic
164   // resolution logic needs to make slightly different assessments about the
165   // number and types of arguments.
166   ResolvedMethodEntry* set_method_handle(
167     int method_index,
168     const CallInfo &call_info                    // Call link information
169   );
170 
171   Method*      method_if_resolved(int method_index) const;
172 
173   Array<ResolvedFieldEntry>* resolved_field_entries()          { return _resolved_field_entries; }
174   inline ResolvedFieldEntry* resolved_field_entry_at(int field_index) const;
175   inline int resolved_field_entries_length() const;
176   void print_resolved_field_entries(outputStream* st) const;
177 
178   Array<ResolvedIndyEntry>* resolved_indy_entries()          { return _resolved_indy_entries; }
179   inline ResolvedIndyEntry* resolved_indy_entry_at(int index) const;
180   inline int resolved_indy_entries_length() const;
181   void print_resolved_indy_entries(outputStream* st)   const;
182 
183   Array<ResolvedMethodEntry>* resolved_method_entries()          { return _resolved_method_entries; }
184   inline ResolvedMethodEntry* resolved_method_entry_at(int method_index) const;
185   inline int resolved_method_entries_length() const;
186   void print_resolved_method_entries(outputStream* st) const;
187 
188   // Assembly code support
189   static ByteSize resolved_references_offset()     { return byte_offset_of(ConstantPoolCache, _resolved_references);     }
190   static ByteSize invokedynamic_entries_offset()   { return byte_offset_of(ConstantPoolCache, _resolved_indy_entries);   }
191   static ByteSize field_entries_offset()           { return byte_offset_of(ConstantPoolCache, _resolved_field_entries);  }
192   static ByteSize method_entries_offset()          { return byte_offset_of(ConstantPoolCache, _resolved_method_entries); }
193 
194 #if INCLUDE_CDS
195   void remove_unshareable_info();
196 #endif
197 
198  public:
199   static int size() { return align_metadata_size(sizeof(ConstantPoolCache) / wordSize); }
200 
201  private:
202 
203   // Helpers
204   ConstantPool**        constant_pool_addr()     { return &_constant_pool; }
205 
206  public:
207   // Accessors
208   void set_constant_pool(ConstantPool* pool)   { _constant_pool = pool; }
209   ConstantPool* constant_pool() const          { return _constant_pool; }
210 
211   // Code generation
212   static ByteSize base_offset()                  { return in_ByteSize(sizeof(ConstantPoolCache)); }
213 
214 #if INCLUDE_JVMTI
215   // RedefineClasses() API support:
216   // If any entry of this ConstantPoolCache points to any of
217   // old_methods, replace it with the corresponding new_method.
218   // trace_name_printed is set to true if the current call has
219   // printed the klass name so that other routines in the adjust_*
220   // group don't print the klass name.
221   void adjust_method_entries(bool* trace_name_printed);
222   bool check_no_old_or_obsolete_entries();
223   void dump_cache();
224 #endif // INCLUDE_JVMTI
225 
226   // RedefineClasses support
227   DEBUG_ONLY(bool on_stack() { return false; })
228   void deallocate_contents(ClassLoaderData* data);
229   bool is_klass() const { return false; }
230   void record_gc_epoch();
231   uint64_t gc_epoch() { return _gc_epoch; }
232 
233   // Return TRUE if resolution failed and this thread got to record the failure
234   // status.  Return FALSE if another thread succeeded or failed in resolving
235   // the method and recorded the success or failure before this thread had a
236   // chance to record its failure.
237   bool save_and_throw_indy_exc(const constantPoolHandle& cpool, int cpool_index, int index, constantTag tag, TRAPS);
238   oop set_dynamic_call(const CallInfo &call_info, int index);
239   oop appendix_if_resolved(int method_index) const;
240   oop appendix_if_resolved(ResolvedMethodEntry* method_entry) const;
241 
242   // Printing
243   void print_on(outputStream* st) const;
244   void print_value_on(outputStream* st) const;
245 
246   const char* internal_name() const { return "{constant pool cache}"; }
247 
248   // Verify
249   void verify_on(outputStream* st);
250 };
251 
252 #endif // SHARE_OOPS_CPCACHE_HPP