1 /*
2 * Copyright (c) 1998, 2026, 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 clear_archived_references() NOT_CDS_JAVA_HEAP_RETURN;
114 CDS_JAVA_HEAP_ONLY(int archived_references_index() { return _archived_references_index; })
115
116 inline refArrayOop 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 // Helpers
203 ConstantPool** constant_pool_addr() { return &_constant_pool; }
204
205 public:
206 // Accessors
207 void set_constant_pool(ConstantPool* pool) { _constant_pool = pool; }
208 ConstantPool* constant_pool() const { return _constant_pool; }
209
210 // Code generation
211 static ByteSize base_offset() { return in_ByteSize(sizeof(ConstantPoolCache)); }
212
213 #if INCLUDE_JVMTI
214 // RedefineClasses() API support:
215 // If any entry of this ConstantPoolCache points to any of
216 // old_methods, replace it with the corresponding new_method.
217 // trace_name_printed is set to true if the current call has
218 // printed the klass name so that other routines in the adjust_*
219 // group don't print the klass name.
220 void adjust_method_entries(bool* trace_name_printed);
221 bool check_no_old_or_obsolete_entries();
222 void dump_cache();
223 #endif // INCLUDE_JVMTI
224
225 #if INCLUDE_CDS
226 void remove_resolved_field_entries_if_non_deterministic();
227 void remove_resolved_indy_entries_if_non_deterministic();
228 void remove_resolved_method_entries_if_non_deterministic();
229 bool can_archive_resolved_method(ConstantPool* src_cp, ResolvedMethodEntry* method_entry);
230 #endif
231
232 // RedefineClasses support
233 DEBUG_ONLY(bool on_stack() { return false; })
234 void deallocate_contents(ClassLoaderData* data);
235 void record_gc_epoch();
236 uint64_t gc_epoch() { return _gc_epoch; }
237
238 // Return TRUE if resolution failed and this thread got to record the failure
239 // status. Return FALSE if another thread succeeded or failed in resolving
240 // the method and recorded the success or failure before this thread had a
241 // chance to record its failure.
242 bool save_and_throw_indy_exc(const constantPoolHandle& cpool, int cpool_index, int index, constantTag tag, TRAPS);
243 oop set_dynamic_call(const CallInfo &call_info, int index);
244 oop appendix_if_resolved(int method_index) const;
245 oop appendix_if_resolved(ResolvedMethodEntry* method_entry) const;
246
247 // Printing
248 void print_on(outputStream* st) const;
249 void print_value_on(outputStream* st) const;
250
251 const char* internal_name() const { return "{constant pool cache}"; }
252
253 // Verify
254 void verify_on(outputStream* st);
255 };
256
257 #endif // SHARE_OOPS_CPCACHE_HPP