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/collectedHeap.hpp"
29 #include "gc/shared/gc_globals.hpp"
30 #include "runtime/stubInfo.hpp"
31 #include "utilities/hashTable.hpp"
32
33 /*
34 * AOT Code Cache collects code from Code Cache and corresponding metadata
35 * during application training run.
36 * In following "production" runs this code and data can be loaded into
37 * Code Cache skipping its generation.
38 */
39
40 class CodeBuffer;
41 class RelocIterator;
42 class AOTCodeCache;
43 class AOTCodeReader;
44 class AdapterBlob;
45 class ExceptionBlob;
46 class ImmutableOopMapSet;
47 class AsmRemarks;
48 class DbgStrings;
49
50 enum class vmIntrinsicID : int;
51 enum CompLevel : signed char;
52
53 #define DO_AOTCODEENTRY_KIND(Fn) \
54 Fn(None) \
55 Fn(Adapter) \
56 Fn(SharedBlob) \
57 Fn(C1Blob) \
58 Fn(C2Blob) \
59 Fn(StubGenBlob) \
60
61 // Descriptor of AOT Code Cache's entry
62 class AOTCodeEntry {
63 public:
64 enum Kind : s1 {
65 #define DECL_KIND_ENUM(kind) kind,
66 DO_AOTCODEENTRY_KIND(DECL_KIND_ENUM)
67 #undef DECL_KIND_ENUM
68 Kind_count
69 };
70
71 private:
72 AOTCodeEntry* _next;
73 Kind _kind;
74 uint _id; // Adapter's id, vmIntrinsic::ID for stub or name's hash for nmethod
75 uint _offset; // Offset to entry
76 uint _size; // Entry size
77 uint _name_offset; // Code blob name
78 uint _name_size;
79 uint _blob_offset; // Start of code in cache
80 bool _has_oop_maps;
81 address _dumptime_content_start_addr; // CodeBlob::content_begin() at dump time; used for applying relocations
82
83 public:
84 AOTCodeEntry(Kind kind, uint id,
85 uint offset, uint size,
86 uint name_offset, uint name_size,
87 uint blob_offset, bool has_oop_maps,
88 address dumptime_content_start_addr) {
89 _next = nullptr;
90 _kind = kind;
91 _id = id;
92 _offset = offset;
93 _size = size;
94 _name_offset = name_offset;
95 _name_size = name_size;
96 _blob_offset = blob_offset;
97 _has_oop_maps = has_oop_maps;
98 _dumptime_content_start_addr = dumptime_content_start_addr;
99 }
100 void* operator new(size_t x, AOTCodeCache* cache);
101 // Delete is a NOP
102 void operator delete( void *ptr ) {}
103
104 AOTCodeEntry* next() const { return _next; }
105 void set_next(AOTCodeEntry* next) { _next = next; }
106
107 Kind kind() const { return _kind; }
108 uint id() const { return _id; }
109
110 uint offset() const { return _offset; }
111 void set_offset(uint off) { _offset = off; }
112
113 uint size() const { return _size; }
114 uint name_offset() const { return _name_offset; }
115 uint name_size() const { return _name_size; }
116 uint blob_offset() const { return _blob_offset; }
117 bool has_oop_maps() const { return _has_oop_maps; }
118 address dumptime_content_start_addr() const { return _dumptime_content_start_addr; }
119
120 static bool is_valid_entry_kind(Kind kind) { return kind > None && kind < Kind_count; }
121 static bool is_blob(Kind kind) { return kind == SharedBlob || kind == C1Blob || kind == C2Blob || kind == StubGenBlob; }
122 static bool is_single_stub_blob(Kind kind) { return kind == SharedBlob || kind == C1Blob || kind == C2Blob; }
123 static bool is_multi_stub_blob(Kind kind) { return kind == StubGenBlob; }
124 static bool is_adapter(Kind kind) { return kind == Adapter; }
125 };
126
127 // we use a hash table to speed up translation of external addresses
128 // or stub addresses to their corresponding indexes when dumping stubs
129 // or nmethods to the AOT code cache.
130 class AOTCodeAddressHashTable : public HashTable<
131 address,
132 int,
133 36137, // prime number
134 AnyObj::C_HEAP,
135 mtCode> {};
136
137 // Addresses of stubs, blobs and runtime finctions called from compiled code.
138 class AOTCodeAddressTable : public CHeapObj<mtCode> {
139 private:
140 address* _extrs_addr;
141 address* _stubs_addr;
142 uint _extrs_length;
143
144 bool _extrs_complete;
145 bool _shared_stubs_complete;
146 bool _c1_stubs_complete;
147 bool _c2_stubs_complete;
148 bool _stubgen_stubs_complete;
149 AOTCodeAddressHashTable* _hash_table;
150
151 void hash_address(address addr, int idx);
152 public:
153 AOTCodeAddressTable() :
154 _extrs_addr(nullptr),
155 _stubs_addr(nullptr),
156 _extrs_length(0),
157 _extrs_complete(false),
158 _shared_stubs_complete(false),
159 _c1_stubs_complete(false),
160 _c2_stubs_complete(false),
161 _stubgen_stubs_complete(false),
162 _hash_table(nullptr)
163 { }
164 void init_extrs();
165 void init_extrs2();
166 void add_stub_entry(EntryId entry_id, address entry);
167 void add_external_addresses(GrowableArray<address>& addresses) NOT_CDS_RETURN;
168 void set_shared_stubs_complete();
169 void set_c1_stubs_complete();
170 void set_c2_stubs_complete();
171 void set_stubgen_stubs_complete();
172 const char* add_C_string(const char* str);
173 int id_for_C_string(address str);
174 address address_for_C_string(int idx);
175 int id_for_address(address addr, RelocIterator iter, CodeBlob* code_blob);
176 address address_for_id(int id);
177 };
178
179 // Auxiliary class used by AOTStubData to locate addresses owned by a
180 // stub in the _address_array.
181
182 class StubAddrRange {
183 private:
184 // Index of the first address owned by a stub or -1 if none present
185 int _start_index;
186 // Total number of addresses owned by a stub, including in order:
187 // start address for stub code and first entry, (exclusive) end
188 // address for stub code, all secondary entry addresses, any
189 // auxiliary addresses
190 uint _naddr;
191 public:
192 StubAddrRange() : _start_index(-1), _naddr(0) {}
193 int start_index() { return _start_index; }
194 int count() { return _naddr; }
195
196 void default_init() {
197 _start_index = -1;
198 _naddr = 0;
199 }
200
201 void init_entry(int start_index, int naddr) {
202 _start_index = start_index;
203 _naddr = naddr;
204 }
205 };
206
207 // class used to save and restore details of stubs embedded in a
208 // multi-stub (StubGen) blob
209
210 class AOTStubData : public StackObj {
211 friend class AOTCodeCache;
212 friend class AOTCodeReader;
213 private:
214 BlobId _blob_id; // must be a stubgen blob id
215 // whatever buffer blob was successfully loaded from the AOT cache
216 // following a call to load_code_blob or nullptr
217 CodeBlob *_cached_blob;
218 // Array of addresses owned by stubs. Each stub appends addresses to
219 // this array as a block, whether at the end of generation or at the
220 // end of restoration from the cache. The first two addresses in
221 // each block are the "start" and "end2 address of the stub. Any
222 // other visible addresses located within the range [start,end)
223 // follow, either extra entries, data addresses or SEGV-protected
224 // subrange start, end and handler addresses. In the special case
225 // that the SEGV handler address is the (external) common address
226 // handler the array will hold value nullptr.
227 GrowableArray<address> _address_array;
228 // count of how many stubs exist in the current blob (not all of
229 // which may actually be generated)
230 int _stub_cnt;
231 // array identifying range of entries in _address_array for each stub
232 // indexed by offset of stub in blob
233 StubAddrRange* _ranges;
234
235 // flags indicating whether the AOT code cache is open and, if so,
236 // whether we are loading or storing stubs or have encountered any
237 // invalid stubs.
238 enum Flags {
239 OPEN = 1 << 0, // cache is open
240 USING = 1 << 1, // open and loading stubs
241 DUMPING = 1 << 2, // open and storing stubs
242 INVALID = 1 << 3, // found invalid stub when loading
243 };
244
245 uint32_t _flags;
246
247 void set_invalid() { _flags |= INVALID; }
248
249 StubAddrRange& get_range(int idx) const { return _ranges[idx]; }
250 GrowableArray<address>& address_array() { return _address_array; }
251 // accessor for entry/auxiliary addresses defaults to start entry
252 public:
253 AOTStubData(BlobId blob_id) NOT_CDS({});
254
255 ~AOTStubData() CDS_ONLY({FREE_C_HEAP_ARRAY(_ranges);}) NOT_CDS({})
256
257 bool is_open() CDS_ONLY({ return (_flags & OPEN) != 0; }) NOT_CDS_RETURN_(false);
258 bool is_using() CDS_ONLY({ return (_flags & USING) != 0; }) NOT_CDS_RETURN_(false);
259 bool is_dumping() CDS_ONLY({ return (_flags & DUMPING) != 0; }) NOT_CDS_RETURN_(false);
260 bool is_invalid() CDS_ONLY({ return (_flags & INVALID) != 0; }) NOT_CDS_RETURN_(false);
261
262 BlobId blob_id() { return _blob_id; }
263 bool load_code_blob() NOT_CDS_RETURN_(true);
264 bool store_code_blob(CodeBlob& new_blob, CodeBuffer *code_buffer) NOT_CDS_RETURN_(true);
265
266 address load_archive_data(StubId stub_id, address &end, GrowableArray<address>* entries = nullptr, GrowableArray<address>* extras = nullptr) NOT_CDS_RETURN_(nullptr);
267 void store_archive_data(StubId stub_id, address start, address end, GrowableArray<address>* entries = nullptr, GrowableArray<address>* extras = nullptr) NOT_CDS_RETURN;
268
269 void stub_epilog(StubId stub_id) NOT_CDS_RETURN;
270 #ifdef ASSERT
271 void check_stored(StubId stub_id) NOT_CDS_RETURN;
272 #endif
273 const AOTStubData* as_const() { return (const AOTStubData*)this; }
274 };
275
276 #define AOTCODECACHE_CONFIGS_GENERIC_DO(do_var, do_fun) \
277 do_var(int, AllocateInstancePrefetchLines) /* stubs and nmethods */ \
278 do_var(int, AllocatePrefetchDistance) /* stubs and nmethods */ \
279 do_var(int, AllocatePrefetchLines) /* stubs and nmethods */ \
280 do_var(int, AllocatePrefetchStepSize) /* stubs and nmethods */ \
281 do_var(uint, CodeEntryAlignment) /* array copy stubs and nmethods */ \
282 do_var(bool, UseCompressedOops) /* stubs and nmethods */ \
283 do_var(bool, EnableContended) /* nmethods */ \
284 do_var(intx, OptoLoopAlignment) /* array copy stubs and nmethods */ \
285 do_var(bool, RestrictContended) /* nmethods */ \
286 do_var(bool, UseAESCTRIntrinsics) \
287 do_var(bool, UseAESIntrinsics) \
288 do_var(bool, UseBASE64Intrinsics) \
289 do_var(bool, UseChaCha20Intrinsics) \
290 do_var(bool, UseCRC32CIntrinsics) \
291 do_var(bool, UseCRC32Intrinsics) \
292 do_var(bool, UseDilithiumIntrinsics) \
293 do_var(bool, UseGHASHIntrinsics) \
294 do_var(bool, UseIntPoly25519Intrinsics) \
295 do_var(bool, UseKyberIntrinsics) \
296 do_var(bool, UseMD5Intrinsics) \
297 do_var(bool, UsePoly1305Intrinsics) \
298 do_var(bool, UseSecondarySupersTable) \
299 do_var(bool, UseSHA1Intrinsics) \
300 do_var(bool, UseSHA256Intrinsics) \
301 do_var(bool, UseSHA3Intrinsics) \
302 do_var(bool, UseSHA512Intrinsics) \
303 do_var(bool, UseIntPolyIntrinsics) \
304 do_var(bool, UseVectorizedMismatchIntrinsic) \
305 do_fun(int, CompressedKlassPointers_shift, CompressedKlassPointers::shift()) \
306 do_fun(bool, JavaAssertions_systemClassDefault, JavaAssertions::systemClassDefault()) \
307 do_fun(bool, JavaAssertions_userClassDefault, JavaAssertions::userClassDefault()) \
308 do_fun(CollectedHeap::Name, Universe_heap_kind, Universe::heap()->kind()) \
309 // END
310
311 #ifdef COMPILER2
312 #define AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun) \
313 do_var(intx, ArrayOperationPartialInlineSize) /* array copy stubs and nmethods */ \
314 do_var(intx, MaxVectorSize) /* array copy/fill stubs */ \
315 do_var(bool, UseMontgomeryMultiplyIntrinsic) \
316 do_var(bool, UseMontgomerySquareIntrinsic) \
317 do_var(bool, UseMulAddIntrinsic) \
318 do_var(bool, UseMultiplyToLenIntrinsic) \
319 do_var(bool, UseSquareToLenIntrinsic) \
320 // END
321 #else
322 #define AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun)
323 #endif
324
325 #if defined(AARCH64) && !defined(ZERO)
326 #define AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun) \
327 do_var(intx, BlockZeroingLowLimit) /* array fill stubs */ \
328 do_var(intx, PrefetchCopyIntervalInBytes) /* array copy stubs */ \
329 do_var(int, SoftwarePrefetchHintDistance) /* array fill stubs */ \
330 do_var(bool, UseBlockZeroing) \
331 do_var(bool, UseSecondarySupersCache) \
332 do_var(bool, UseSIMDForArrayEquals) /* array copy stubs and nmethods */ \
333 do_var(bool, UseSIMDForBigIntegerShiftIntrinsics) \
334 do_var(bool, UseSIMDForMemoryOps) /* array copy stubs and nmethods */ \
335 do_var(bool, UseSIMDForSHA3Intrinsic) /* SHA3 stubs */ \
336 do_var(bool, UseSimpleArrayEquals) \
337 // END
338 #else
339 #define AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun)
340 #endif
341
342 #if defined(X86) && !defined(ZERO)
343 #define AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun) \
344 do_var(int, AVX3Threshold) /* array copy stubs and nmethods */ \
345 do_var(bool, EnableX86ECoreOpts) /* nmethods */ \
346 do_var(bool, UseLibmIntrinsic) \
347 // END
348 #else
349 #define AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun)
350 #endif
351
352 #define AOTCODECACHE_CONFIGS_DO(do_var, do_fun) \
353 AOTCODECACHE_CONFIGS_GENERIC_DO(do_var, do_fun) \
354 AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun) \
355 AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun) \
356 AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun) \
357 // END
358
359 #define AOTCODECACHE_DECLARE_VAR(type, name) type _saved_ ## name;
360 #define AOTCODECACHE_DECLARE_FUN(type, name, func) type _saved_ ## name;
361
362 class AOTCodeCache : public CHeapObj<mtCode> {
363
364 // Classes used to describe AOT code cache.
365 protected:
366 class Config {
367 AOTCODECACHE_CONFIGS_DO(AOTCODECACHE_DECLARE_VAR, AOTCODECACHE_DECLARE_FUN)
368
369 // Special configs that cannot be checked with macros
370 address _compressedOopBase;
371 int _compressedOopShift;
372
373 #if defined(X86) && !defined(ZERO)
374 bool _useUnalignedLoadStores;
375 #endif
376
377 #if defined(AARCH64) && !defined(ZERO)
378 bool _avoidUnalignedAccesses;
379 #endif
380
381 uint _cpu_features_offset; // offset in the cache where cpu features are stored
382 public:
383 void record(uint cpu_features_offset);
384 bool verify_cpu_features(AOTCodeCache* cache) const;
385 bool verify(AOTCodeCache* cache) const;
386 };
387
388 class Header : public CHeapObj<mtCode> {
389 private:
390 enum {
391 AOT_CODE_VERSION = 1
392 };
393 uint _version; // AOT code version (should match when reading code cache)
394 uint _cache_size; // cache size in bytes
395 uint _strings_count; // number of recorded C strings
396 uint _strings_offset; // offset to recorded C strings
397 uint _entries_count; // number of recorded entries
398 uint _entries_offset; // offset of AOTCodeEntry array describing entries
399 uint _adapters_count;
400 uint _shared_blobs_count;
401 uint _stubgen_blobs_count;
402 uint _C1_blobs_count;
403 uint _C2_blobs_count;
404 Config _config; // must be the last element as there is trailing data stored immediately after Config
405
406 public:
407 void init(uint cache_size,
408 uint strings_count, uint strings_offset,
409 uint entries_count, uint entries_offset,
410 uint adapters_count, uint shared_blobs_count,
411 uint stubgen_blobs_count, uint C1_blobs_count,
412 uint C2_blobs_count, uint cpu_features_offset) {
413 _version = AOT_CODE_VERSION;
414 _cache_size = cache_size;
415 _strings_count = strings_count;
416 _strings_offset = strings_offset;
417 _entries_count = entries_count;
418 _entries_offset = entries_offset;
419 _adapters_count = adapters_count;
420 _shared_blobs_count = shared_blobs_count;
421 _stubgen_blobs_count = stubgen_blobs_count;
422 _C1_blobs_count = C1_blobs_count;
423 _C2_blobs_count = C2_blobs_count;
424 _config.record(cpu_features_offset);
425 }
426
427
428 uint cache_size() const { return _cache_size; }
429 uint strings_count() const { return _strings_count; }
430 uint strings_offset() const { return _strings_offset; }
431 uint entries_count() const { return _entries_count; }
432 uint entries_offset() const { return _entries_offset; }
433 uint adapters_count() const { return _adapters_count; }
434 uint stubgen_blobs_count() const { return _stubgen_blobs_count; }
435 uint shared_blobs_count() const { return _shared_blobs_count; }
436 uint C1_blobs_count() const { return _C1_blobs_count; }
437 uint C2_blobs_count() const { return _C2_blobs_count; }
438
439 bool verify(uint load_size) const;
440 bool verify_config(AOTCodeCache* cache) const { // Called after Universe initialized
441 return _config.verify(cache);
442 }
443 };
444
445 // Continue with AOTCodeCache class definition.
446 private:
447 Header* _load_header;
448 char* _load_buffer; // Aligned buffer for loading cached code
449 char* _store_buffer; // Aligned buffer for storing cached code
450 char* _C_store_buffer; // Original unaligned buffer
451
452 uint _write_position; // Position in _store_buffer
453 uint _load_size; // Used when reading cache
454 uint _store_size; // Used when writing cache
455 bool _for_use; // AOT cache is open for using AOT code
456 bool _for_dump; // AOT cache is open for dumping AOT code
457 bool _failed; // Failed read/write to/from cache (cache is broken?)
458 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
459
460 AOTCodeAddressTable* _table;
461
462 AOTCodeEntry* _load_entries; // Used when reading cache
463 uint* _search_entries; // sorted by ID table [id, index]
464 AOTCodeEntry* _store_entries; // Used when writing cache
465 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table
466 uint _store_entries_cnt;
467
468 static AOTCodeCache* open_for_use();
469 static AOTCodeCache* open_for_dump();
470
471 bool set_write_position(uint pos);
472 bool align_write();
473 bool align_write_int();
474 bool align_write_bytes(uint alignment);
475 address reserve_bytes(uint nbytes);
476 uint write_bytes(const void* buffer, uint nbytes);
477 const char* addr(uint offset) const { return _load_buffer + offset; }
478 static AOTCodeAddressTable* addr_table() {
479 return is_on() && (cache()->_table != nullptr) ? cache()->_table : nullptr;
480 }
481
482 void set_lookup_failed() { _lookup_failed = true; }
483 void clear_lookup_failed() { _lookup_failed = false; }
484 bool lookup_failed() const { return _lookup_failed; }
485
486 void add_stub_entry(EntryId entry_id, address entry) NOT_CDS_RETURN;
487 public:
488 AOTCodeCache(bool is_dumping, bool is_using);
489
490 const char* cache_buffer() const { return _load_buffer; }
491 bool failed() const { return _failed; }
492 void set_failed() { _failed = true; }
493
494 static uint max_aot_code_size();
495
496 uint load_size() const { return _load_size; }
497 uint write_position() const { return _write_position; }
498
499 void load_strings();
500 int store_strings();
501
502 static void set_shared_stubs_complete() NOT_CDS_RETURN;
503 static void set_c1_stubs_complete() NOT_CDS_RETURN ;
504 static void set_c2_stubs_complete() NOT_CDS_RETURN;
505 static void set_stubgen_stubs_complete() NOT_CDS_RETURN;
506
507 void add_stub_entries(StubId stub_id, address start, GrowableArray<address> *entries = nullptr, int offset = -1) NOT_CDS_RETURN;
508
509 address address_for_C_string(int idx) const { return _table->address_for_C_string(idx); }
510 address address_for_id(int id) const { return _table->address_for_id(id); }
511
512 bool for_use() const { return _for_use && !_failed; }
513 bool for_dump() const { return _for_dump && !_failed; }
514
515 AOTCodeEntry* add_entry() {
516 _store_entries_cnt++;
517 _store_entries -= 1;
518 return _store_entries;
519 }
520
521 AOTCodeEntry* find_entry(AOTCodeEntry::Kind kind, uint id);
522
523 void store_cpu_features(char*& buffer, uint buffer_size);
524
525 bool finish_write();
526
527 bool write_relocations(CodeBlob& code_blob, RelocIterator& iter);
528 bool write_oop_map_set(CodeBlob& cb);
529 bool write_stub_data(CodeBlob& blob, AOTStubData *stub_data);
530 #ifndef PRODUCT
531 bool write_asm_remarks(CodeBlob& cb);
532 bool write_dbg_strings(CodeBlob& cb);
533 #endif // PRODUCT
534
535 private:
536 // internal private API to save and restore blobs
537 static bool store_code_blob(CodeBlob& blob,
538 AOTCodeEntry::Kind entry_kind,
539 uint id,
540 const char* name,
541 AOTStubData* stub_data,
542 CodeBuffer* code_buffer) NOT_CDS_RETURN_(false);
543
544 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
545 uint id,
546 const char* name,
547 AOTStubData* stub_data) NOT_CDS_RETURN_(nullptr);
548
549 public:
550 // save and restore API for non-enumerable code blobs
551 static bool store_code_blob(CodeBlob& blob,
552 AOTCodeEntry::Kind entry_kind,
553 uint id,
554 const char* name) NOT_CDS_RETURN_(false);
555
556 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
557 uint id, const char* name) NOT_CDS_RETURN_(nullptr);
558
559 // save and restore API for enumerable code blobs
560
561 // API for single-stub blobs
562 static bool store_code_blob(CodeBlob& blob,
563 AOTCodeEntry::Kind entry_kind,
564 BlobId id) NOT_CDS_RETURN_(false);
565
566 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
567 BlobId id) NOT_CDS_RETURN_(nullptr);
568
569 // API for multi-stub blobs -- for use by class StubGenerator.
570
571 static bool store_code_blob(CodeBlob& blob,
572 AOTCodeEntry::Kind kind,
573 BlobId id,
574 AOTStubData* stub_data,
575 CodeBuffer *code_buffer) NOT_CDS_RETURN_(false);
576
577 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
578 BlobId id,
579 AOTStubData* stub_data) NOT_CDS_RETURN_(nullptr);
580
581 static void publish_external_addresses(GrowableArray<address>& addresses) NOT_CDS_RETURN;
582 // publish all entries for a code blob in code cache address table
583 static void publish_stub_addresses(CodeBlob &code_blob, BlobId id, AOTStubData *stub_data) NOT_CDS_RETURN;
584
585 static uint store_entries_cnt() {
586 if (is_on_for_dump()) {
587 return cache()->_store_entries_cnt;
588 }
589 return -1;
590 }
591
592 // Static access
593
594 private:
595 static AOTCodeCache* _cache;
596 DEBUG_ONLY( static bool _passed_init2; )
597
598 static bool open_cache(bool is_dumping, bool is_using);
599 bool verify_config() {
600 if (for_use()) {
601 return _load_header->verify_config(this);
602 }
603 return true;
604 }
605 public:
606 // marker used where an address offset needs to be stored for later
607 // retrieval and the address turns out to be null
608 static const uint NULL_ADDRESS_MARKER = UINT_MAX;
609
610 static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; }
611 static void initialize() NOT_CDS_RETURN;
612 static void init2() NOT_CDS_RETURN;
613 static void init3() NOT_CDS_RETURN;
614 static void dump() NOT_CDS_RETURN;
615 static bool is_on() CDS_ONLY({ return cache() != nullptr; }) NOT_CDS_RETURN_(false);
616 static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false);
617 static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false);
618 static bool is_dumping_stub() NOT_CDS_RETURN_(false);
619 static bool is_dumping_adapter() NOT_CDS_RETURN_(false);
620 static bool is_using_stub() NOT_CDS_RETURN_(false);
621 static bool is_using_adapter() NOT_CDS_RETURN_(false);
622 static void enable_caching() NOT_CDS_RETURN;
623 static void disable_caching() NOT_CDS_RETURN;
624 static bool is_caching_enabled() NOT_CDS_RETURN_(false);
625
626 static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str);
627
628 static void print_on(outputStream* st) NOT_CDS_RETURN;
629 };
630
631 // Concurent AOT code reader
632 class AOTCodeReader {
633 private:
634 AOTCodeCache* _cache;
635 const AOTCodeEntry* _entry;
636 const char* _load_buffer; // Loaded cached code buffer
637 uint _read_position; // Position in _load_buffer
638 uint read_position() const { return _read_position; }
639 void set_read_position(uint pos);
640 uint align_read_int();
641 const char* addr(uint offset) const { return _load_buffer + offset; }
642
643 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
644 void set_lookup_failed() { _lookup_failed = true; }
645 void clear_lookup_failed() { _lookup_failed = false; }
646 bool lookup_failed() const { return _lookup_failed; }
647
648 // Values used by restore(code_blob).
649 // They should be set before calling it.
650 const char* _name;
651 address _reloc_data;
652 int _reloc_count;
653 ImmutableOopMapSet* _oop_maps;
654 AOTCodeEntry::Kind _entry_kind;
655 int _id;
656 AOTStubData* _stub_data;
657
658 AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; }
659
660 ImmutableOopMapSet* read_oop_map_set();
661 void read_stub_data(CodeBlob* code_blob, AOTStubData *stub_data);
662
663 void fix_relocations(CodeBlob* code_blob, RelocIterator& iter);
664 #ifndef PRODUCT
665 void read_asm_remarks(AsmRemarks& asm_remarks);
666 void read_dbg_strings(DbgStrings& dbg_strings);
667 #endif // PRODUCT
668
669 public:
670 AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry);
671
672 CodeBlob* compile_code_blob(const char* name, AOTCodeEntry::Kind entry_kind, int id, AOTStubData* stub_data = nullptr);
673
674 void restore(CodeBlob* code_blob);
675 };
676
677 // code cache internal runtime constants area used by AOT code
678 class AOTRuntimeConstants {
679 friend class AOTCodeCache;
680 private:
681 address _card_table_base;
682 uint _grain_shift;
683 address _cset_base;
684 static address _field_addresses_list[];
685 static AOTRuntimeConstants _aot_runtime_constants;
686 // private constructor for unique singleton
687 AOTRuntimeConstants() { }
688 // private for use by friend class AOTCodeCache
689 static void initialize_from_runtime();
690 public:
691 #if INCLUDE_CDS
692 static bool contains(address adr) {
693 address base = (address)&_aot_runtime_constants;
694 address hi = base + sizeof(AOTRuntimeConstants);
695 return (base <= adr && adr < hi);
696 }
697 static address card_table_base_address();
698 static address grain_shift_address() { return (address)&_aot_runtime_constants._grain_shift; }
699 static address cset_base_address() { return (address)&_aot_runtime_constants._cset_base; }
700 static address* field_addresses_list() {
701 return _field_addresses_list;
702 }
703 #else
704 static bool contains(address adr) { return false; }
705 static address card_table_base_address() { return nullptr; }
706 static address grain_shift_address() { return nullptr; }
707 static address cset_base_address() { return nullptr; }
708 static address* field_addresses_list() { return nullptr; }
709 #endif
710 };
711
712 #endif // SHARE_CODE_AOTCODECACHE_HPP