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