1 /*
2 * Copyright (c) 2023, 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_CODE_AOTCODECACHE_HPP
26 #define SHARE_CODE_AOTCODECACHE_HPP
27
28 #include "gc/shared/gc_globals.hpp"
29 #include "runtime/stubInfo.hpp"
30
31 /*
32 * AOT Code Cache collects code from Code Cache and corresponding metadata
33 * during application training run.
34 * In following "production" runs this code and data can be loaded into
35 * Code Cache skipping its generation.
36 */
37
38 class CodeBuffer;
39 class RelocIterator;
40 class AOTCodeCache;
41 class AdapterBlob;
42 class ExceptionBlob;
43 class ImmutableOopMapSet;
44 class AsmRemarks;
45 class DbgStrings;
46
47 enum class vmIntrinsicID : int;
48 enum CompLevel : signed char;
49
50 #define DO_AOTCODEENTRY_KIND(Fn) \
51 Fn(None) \
52 Fn(Adapter) \
53 Fn(SharedBlob) \
54 Fn(C1Blob) \
55 Fn(C2Blob) \
56
57 // Descriptor of AOT Code Cache's entry
58 class AOTCodeEntry {
59 public:
60 enum Kind : s1 {
61 #define DECL_KIND_ENUM(kind) kind,
62 DO_AOTCODEENTRY_KIND(DECL_KIND_ENUM)
63 #undef DECL_KIND_ENUM
64 Kind_count
65 };
66
67 private:
68 AOTCodeEntry* _next;
69 Kind _kind;
70 uint _id; // Adapter's id, vmIntrinsic::ID for stub or name's hash for nmethod
71 uint _offset; // Offset to entry
72 uint _size; // Entry size
73 uint _name_offset; // Code blob name
74 uint _name_size;
75 uint _blob_offset; // Start of code in cache
76 bool _has_oop_maps;
77 address _dumptime_content_start_addr; // CodeBlob::content_begin() at dump time; used for applying relocations
78
79 public:
80 AOTCodeEntry(Kind kind, uint id,
81 uint offset, uint size,
82 uint name_offset, uint name_size,
83 uint blob_offset, bool has_oop_maps,
84 address dumptime_content_start_addr) {
85 _next = nullptr;
86 _kind = kind;
87 _id = id;
88 _offset = offset;
89 _size = size;
90 _name_offset = name_offset;
91 _name_size = name_size;
92 _blob_offset = blob_offset;
93 _has_oop_maps = has_oop_maps;
94 _dumptime_content_start_addr = dumptime_content_start_addr;
95 }
96 void* operator new(size_t x, AOTCodeCache* cache);
97 // Delete is a NOP
98 void operator delete( void *ptr ) {}
99
100 AOTCodeEntry* next() const { return _next; }
101 void set_next(AOTCodeEntry* next) { _next = next; }
102
103 Kind kind() const { return _kind; }
104 uint id() const { return _id; }
105
106 uint offset() const { return _offset; }
107 void set_offset(uint off) { _offset = off; }
108
109 uint size() const { return _size; }
110 uint name_offset() const { return _name_offset; }
111 uint name_size() const { return _name_size; }
112 uint blob_offset() const { return _blob_offset; }
113 bool has_oop_maps() const { return _has_oop_maps; }
114 address dumptime_content_start_addr() const { return _dumptime_content_start_addr; }
115
116 static bool is_valid_entry_kind(Kind kind) { return kind > None && kind < Kind_count; }
117 static bool is_blob(Kind kind) { return kind == SharedBlob || kind == C1Blob || kind == C2Blob; }
118 static bool is_adapter(Kind kind) { return kind == Adapter; }
119 };
120
121 // Addresses of stubs, blobs and runtime finctions called from compiled code.
122 class AOTCodeAddressTable : public CHeapObj<mtCode> {
123 private:
124 address* _extrs_addr;
125 address* _stubs_addr;
126 address* _shared_blobs_addr;
127 address* _C1_blobs_addr;
128 uint _extrs_length;
129 uint _stubs_length;
130 uint _shared_blobs_length;
131 uint _C1_blobs_length;
132
133 bool _extrs_complete;
134 bool _early_stubs_complete;
135 bool _shared_blobs_complete;
136 bool _early_c1_complete;
137 bool _complete;
138
139 public:
140 AOTCodeAddressTable() :
141 _extrs_addr(nullptr),
142 _stubs_addr(nullptr),
143 _shared_blobs_addr(nullptr),
144 _C1_blobs_addr(nullptr),
145 _extrs_length(0),
146 _stubs_length(0),
147 _shared_blobs_length(0),
148 _C1_blobs_length(0),
149 _extrs_complete(false),
150 _early_stubs_complete(false),
151 _shared_blobs_complete(false),
152 _early_c1_complete(false),
153 _complete(false)
154 { }
155 ~AOTCodeAddressTable();
156 void init_extrs();
157 void init_early_stubs();
158 void init_shared_blobs();
159 void init_early_c1();
160 const char* add_C_string(const char* str);
161 int id_for_C_string(address str);
162 address address_for_C_string(int idx);
163 int id_for_address(address addr, RelocIterator iter, CodeBlob* code_blob);
164 address address_for_id(int id);
165 };
166
167 class AOTCodeCache : public CHeapObj<mtCode> {
168
169 // Classes used to describe AOT code cache.
170 protected:
171 class Config {
172 address _compressedOopBase;
173 uint _compressedOopShift;
174 uint _compressedKlassShift;
175 uint _contendedPaddingWidth;
176 uint _gc;
177 enum Flags {
178 none = 0,
179 debugVM = 1,
180 compressedOops = 2,
181 compressedClassPointers = 4,
182 useTLAB = 8,
183 systemClassAssertions = 16,
184 userClassAssertions = 32,
185 enableContendedPadding = 64,
186 restrictContendedPadding = 128
187 };
188 uint _flags;
189 uint _cpu_features_offset; // offset in the cache where cpu features are stored
190
191 public:
192 void record(uint cpu_features_offset);
193 bool verify_cpu_features(AOTCodeCache* cache) const;
194 bool verify(AOTCodeCache* cache) const;
195 };
196
197 class Header : public CHeapObj<mtCode> {
198 private:
199 enum {
200 AOT_CODE_VERSION = 1
201 };
202 uint _version; // AOT code version (should match when reading code cache)
203 uint _cache_size; // cache size in bytes
204 uint _strings_count; // number of recorded C strings
205 uint _strings_offset; // offset to recorded C strings
206 uint _entries_count; // number of recorded entries
207 uint _entries_offset; // offset of AOTCodeEntry array describing entries
208 uint _adapters_count;
209 uint _shared_blobs_count;
210 uint _C1_blobs_count;
211 uint _C2_blobs_count;
212 Config _config; // must be the last element as there is trailing data stored immediately after Config
213
214 public:
215 void init(uint cache_size,
216 uint strings_count, uint strings_offset,
217 uint entries_count, uint entries_offset,
218 uint adapters_count, uint shared_blobs_count,
219 uint C1_blobs_count, uint C2_blobs_count,
220 uint cpu_features_offset) {
221 _version = AOT_CODE_VERSION;
222 _cache_size = cache_size;
223 _strings_count = strings_count;
224 _strings_offset = strings_offset;
225 _entries_count = entries_count;
226 _entries_offset = entries_offset;
227 _adapters_count = adapters_count;
228 _shared_blobs_count = shared_blobs_count;
229 _C1_blobs_count = C1_blobs_count;
230 _C2_blobs_count = C2_blobs_count;
231 _config.record(cpu_features_offset);
232 }
233
234
235 uint cache_size() const { return _cache_size; }
236 uint strings_count() const { return _strings_count; }
237 uint strings_offset() const { return _strings_offset; }
238 uint entries_count() const { return _entries_count; }
239 uint entries_offset() const { return _entries_offset; }
240 uint adapters_count() const { return _adapters_count; }
241 uint shared_blobs_count() const { return _shared_blobs_count; }
242 uint C1_blobs_count() const { return _C1_blobs_count; }
243 uint C2_blobs_count() const { return _C2_blobs_count; }
244
245 bool verify(uint load_size) const;
246 bool verify_config(AOTCodeCache* cache) const { // Called after Universe initialized
247 return _config.verify(cache);
248 }
249 };
250
251 // Continue with AOTCodeCache class definition.
252 private:
253 Header* _load_header;
254 char* _load_buffer; // Aligned buffer for loading cached code
255 char* _store_buffer; // Aligned buffer for storing cached code
256 char* _C_store_buffer; // Original unaligned buffer
257
258 uint _write_position; // Position in _store_buffer
259 uint _load_size; // Used when reading cache
260 uint _store_size; // Used when writing cache
261 bool _for_use; // AOT cache is open for using AOT code
262 bool _for_dump; // AOT cache is open for dumping AOT code
263 bool _closing; // Closing cache file
264 bool _failed; // Failed read/write to/from cache (cache is broken?)
265 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
266
267 AOTCodeAddressTable* _table;
268
269 AOTCodeEntry* _load_entries; // Used when reading cache
270 uint* _search_entries; // sorted by ID table [id, index]
271 AOTCodeEntry* _store_entries; // Used when writing cache
272 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table
273 uint _store_entries_cnt;
274
275 static AOTCodeCache* open_for_use();
276 static AOTCodeCache* open_for_dump();
277
278 bool set_write_position(uint pos);
279 bool align_write();
280 address reserve_bytes(uint nbytes);
281 uint write_bytes(const void* buffer, uint nbytes);
282 const char* addr(uint offset) const { return _load_buffer + offset; }
283 static AOTCodeAddressTable* addr_table() {
284 return is_on() && (cache()->_table != nullptr) ? cache()->_table : nullptr;
285 }
286
287 void set_lookup_failed() { _lookup_failed = true; }
288 void clear_lookup_failed() { _lookup_failed = false; }
289 bool lookup_failed() const { return _lookup_failed; }
290
291 public:
292 AOTCodeCache(bool is_dumping, bool is_using);
293 ~AOTCodeCache();
294
295 const char* cache_buffer() const { return _load_buffer; }
296 bool failed() const { return _failed; }
297 void set_failed() { _failed = true; }
298
299 static uint max_aot_code_size();
300
301 uint load_size() const { return _load_size; }
302 uint write_position() const { return _write_position; }
303
304 void load_strings();
305 int store_strings();
306
307 static void init_early_stubs_table() NOT_CDS_RETURN;
308 static void init_shared_blobs_table() NOT_CDS_RETURN;
309 static void init_early_c1_table() NOT_CDS_RETURN;
310
311 address address_for_C_string(int idx) const { return _table->address_for_C_string(idx); }
312 address address_for_id(int id) const { return _table->address_for_id(id); }
313
314 bool for_use() const { return _for_use && !_failed; }
315 bool for_dump() const { return _for_dump && !_failed; }
316
317 bool closing() const { return _closing; }
318
319 AOTCodeEntry* add_entry() {
320 _store_entries_cnt++;
321 _store_entries -= 1;
322 return _store_entries;
323 }
324
325 AOTCodeEntry* find_entry(AOTCodeEntry::Kind kind, uint id);
326
327 void store_cpu_features(char*& buffer, uint buffer_size);
328
329 bool finish_write();
330
331 bool write_relocations(CodeBlob& code_blob);
332 bool write_oop_map_set(CodeBlob& cb);
333 #ifndef PRODUCT
334 bool write_asm_remarks(CodeBlob& cb);
335 bool write_dbg_strings(CodeBlob& cb);
336 #endif // PRODUCT
337
338 // save and restore API for non-enumerable code blobs
339 static bool store_code_blob(CodeBlob& blob,
340 AOTCodeEntry::Kind entry_kind,
341 uint id, const char* name) NOT_CDS_RETURN_(false);
342
343 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
344 uint id, const char* name) NOT_CDS_RETURN_(nullptr);
345
346 // save and restore API for enumerable code blobs
347 static bool store_code_blob(CodeBlob& blob,
348 AOTCodeEntry::Kind entry_kind,
349 BlobId id) NOT_CDS_RETURN_(false);
350
351 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
352 BlobId id) NOT_CDS_RETURN_(nullptr);
353
354 static uint store_entries_cnt() {
355 if (is_on_for_dump()) {
356 return cache()->_store_entries_cnt;
357 }
358 return -1;
359 }
360
361 // Static access
362
363 private:
364 static AOTCodeCache* _cache;
365 DEBUG_ONLY( static bool _passed_init2; )
366
367 static bool open_cache(bool is_dumping, bool is_using);
368 bool verify_config() {
369 if (for_use()) {
370 return _load_header->verify_config(this);
371 }
372 return true;
373 }
374 public:
375 static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; }
376 static void initialize() NOT_CDS_RETURN;
377 static void init2() NOT_CDS_RETURN;
378 static void close() NOT_CDS_RETURN;
379 static bool is_on() CDS_ONLY({ return cache() != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false);
380 static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false);
381 static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false);
382 static bool is_dumping_stub() NOT_CDS_RETURN_(false);
383 static bool is_dumping_adapter() NOT_CDS_RETURN_(false);
384 static bool is_using_stub() NOT_CDS_RETURN_(false);
385 static bool is_using_adapter() NOT_CDS_RETURN_(false);
386 static void enable_caching() NOT_CDS_RETURN;
387 static void disable_caching() NOT_CDS_RETURN;
388 static bool is_caching_enabled() NOT_CDS_RETURN_(false);
389
390 static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str);
391
392 static void print_on(outputStream* st) NOT_CDS_RETURN;
393 };
394
395 // Concurent AOT code reader
396 class AOTCodeReader {
397 private:
398 const AOTCodeCache* _cache;
399 const AOTCodeEntry* _entry;
400 const char* _load_buffer; // Loaded cached code buffer
401 uint _read_position; // Position in _load_buffer
402 uint read_position() const { return _read_position; }
403 void set_read_position(uint pos);
404 const char* addr(uint offset) const { return _load_buffer + offset; }
405
406 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
407 void set_lookup_failed() { _lookup_failed = true; }
408 void clear_lookup_failed() { _lookup_failed = false; }
409 bool lookup_failed() const { return _lookup_failed; }
410
411 AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; }
412 public:
413 AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry);
414
415 CodeBlob* compile_code_blob(const char* name);
416
417 ImmutableOopMapSet* read_oop_map_set();
418
419 void fix_relocations(CodeBlob* code_blob);
420 #ifndef PRODUCT
421 void read_asm_remarks(AsmRemarks& asm_remarks);
422 void read_dbg_strings(DbgStrings& dbg_strings);
423 #endif // PRODUCT
424 };
425
426 // code cache internal runtime constants area used by AOT code
427 class AOTRuntimeConstants {
428 friend class AOTCodeCache;
429 private:
430 address _card_table_base;
431 uint _grain_shift;
432 static address _field_addresses_list[];
433 static AOTRuntimeConstants _aot_runtime_constants;
434 // private constructor for unique singleton
435 AOTRuntimeConstants() { }
436 // private for use by friend class AOTCodeCache
437 static void initialize_from_runtime();
438 public:
439 #if INCLUDE_CDS
440 static bool contains(address adr) {
441 address base = (address)&_aot_runtime_constants;
442 address hi = base + sizeof(AOTRuntimeConstants);
443 return (base <= adr && adr < hi);
444 }
445 static address card_table_base_address();
446 static address grain_shift_address() { return (address)&_aot_runtime_constants._grain_shift; }
447 static address* field_addresses_list() {
448 return _field_addresses_list;
449 }
450 #else
451 static bool contains(address adr) { return false; }
452 static address card_table_base_address() { return nullptr; }
453 static address grain_shift_address() { return nullptr; }
454 static address* field_addresses_list() { return nullptr; }
455 #endif
456 };
457
458 #endif // SHARE_CODE_AOTCODECACHE_HPP