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_var(bool, InlineTypeReturnedAsFields) \
306 do_fun(int, CompressedKlassPointers_shift, CompressedKlassPointers::shift()) \
307 do_fun(bool, JavaAssertions_systemClassDefault, JavaAssertions::systemClassDefault()) \
308 do_fun(bool, JavaAssertions_userClassDefault, JavaAssertions::userClassDefault()) \
309 do_fun(CollectedHeap::Name, Universe_heap_kind, Universe::heap()->kind()) \
310 // END
311
312 #ifdef COMPILER2
313 #define AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun) \
314 do_var(intx, ArrayOperationPartialInlineSize) /* array copy stubs and nmethods */ \
315 do_var(intx, MaxVectorSize) /* array copy/fill stubs */ \
316 do_var(bool, UseMontgomeryMultiplyIntrinsic) \
317 do_var(bool, UseMontgomerySquareIntrinsic) \
318 do_var(bool, UseMulAddIntrinsic) \
319 do_var(bool, UseMultiplyToLenIntrinsic) \
320 do_var(bool, UseSquareToLenIntrinsic) \
321 // END
322 #else
323 #define AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun)
324 #endif
325
326 #if defined(AARCH64) && !defined(ZERO)
327 #define AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun) \
328 do_var(intx, BlockZeroingLowLimit) /* array fill stubs */ \
329 do_var(intx, PrefetchCopyIntervalInBytes) /* array copy stubs */ \
330 do_var(int, SoftwarePrefetchHintDistance) /* array fill stubs */ \
331 do_var(bool, UseBlockZeroing) \
332 do_var(bool, UseSecondarySupersCache) \
333 do_var(bool, UseSIMDForArrayEquals) /* array copy stubs and nmethods */ \
334 do_var(bool, UseSIMDForBigIntegerShiftIntrinsics) \
335 do_var(bool, UseSIMDForMemoryOps) /* array copy stubs and nmethods */ \
336 do_var(bool, UseSIMDForSHA3Intrinsic) /* SHA3 stubs */ \
337 do_var(bool, UseSimpleArrayEquals) \
338 // END
339 #else
340 #define AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun)
341 #endif
342
343 #if defined(X86) && !defined(ZERO)
344 #define AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun) \
345 do_var(int, AVX3Threshold) /* array copy stubs and nmethods */ \
346 do_var(bool, EnableX86ECoreOpts) /* nmethods */ \
347 do_var(bool, UseLibmIntrinsic) \
348 // END
349 #else
350 #define AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun)
351 #endif
352
353 #define AOTCODECACHE_CONFIGS_DO(do_var, do_fun) \
354 AOTCODECACHE_CONFIGS_GENERIC_DO(do_var, do_fun) \
355 AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun) \
356 AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun) \
357 AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun) \
358 // END
359
360 #define AOTCODECACHE_DECLARE_VAR(type, name) type _saved_ ## name;
361 #define AOTCODECACHE_DECLARE_FUN(type, name, func) type _saved_ ## name;
362
363 class AOTCodeCache : public CHeapObj<mtCode> {
364
365 // Classes used to describe AOT code cache.
366 protected:
367 class Config {
368 AOTCODECACHE_CONFIGS_DO(AOTCODECACHE_DECLARE_VAR, AOTCODECACHE_DECLARE_FUN)
369
370 // Special configs that cannot be checked with macros
371 address _compressedOopBase;
372 int _compressedOopShift;
373
374 #if defined(X86) && !defined(ZERO)
375 bool _useUnalignedLoadStores;
376 #endif
377
378 #if defined(AARCH64) && !defined(ZERO)
379 bool _avoidUnalignedAccesses;
380 #endif
381
382 uint _cpu_features_offset; // offset in the cache where cpu features are stored
383 public:
384 void record(uint cpu_features_offset);
385 bool verify_cpu_features(AOTCodeCache* cache) const;
386 bool verify(AOTCodeCache* cache) const;
387 };
388
389 class Header : public CHeapObj<mtCode> {
390 private:
391 enum {
392 AOT_CODE_VERSION = 1
393 };
394 uint _version; // AOT code version (should match when reading code cache)
395 uint _cache_size; // cache size in bytes
396 uint _strings_count; // number of recorded C strings
397 uint _strings_offset; // offset to recorded C strings
398 uint _entries_count; // number of recorded entries
399 uint _entries_offset; // offset of AOTCodeEntry array describing entries
400 uint _adapters_count;
401 uint _shared_blobs_count;
402 uint _stubgen_blobs_count;
403 uint _C1_blobs_count;
404 uint _C2_blobs_count;
405 Config _config; // must be the last element as there is trailing data stored immediately after Config
406
407 public:
408 void init(uint cache_size,
409 uint strings_count, uint strings_offset,
410 uint entries_count, uint entries_offset,
411 uint adapters_count, uint shared_blobs_count,
412 uint stubgen_blobs_count, uint C1_blobs_count,
413 uint C2_blobs_count, uint cpu_features_offset) {
414 _version = AOT_CODE_VERSION;
415 _cache_size = cache_size;
416 _strings_count = strings_count;
417 _strings_offset = strings_offset;
418 _entries_count = entries_count;
419 _entries_offset = entries_offset;
420 _adapters_count = adapters_count;
421 _shared_blobs_count = shared_blobs_count;
422 _stubgen_blobs_count = stubgen_blobs_count;
423 _C1_blobs_count = C1_blobs_count;
424 _C2_blobs_count = C2_blobs_count;
425 _config.record(cpu_features_offset);
426 }
427
428
429 uint cache_size() const { return _cache_size; }
430 uint strings_count() const { return _strings_count; }
431 uint strings_offset() const { return _strings_offset; }
432 uint entries_count() const { return _entries_count; }
433 uint entries_offset() const { return _entries_offset; }
434 uint adapters_count() const { return _adapters_count; }
435 uint stubgen_blobs_count() const { return _stubgen_blobs_count; }
436 uint shared_blobs_count() const { return _shared_blobs_count; }
437 uint C1_blobs_count() const { return _C1_blobs_count; }
438 uint C2_blobs_count() const { return _C2_blobs_count; }
439
440 bool verify(uint load_size) const;
441 bool verify_config(AOTCodeCache* cache) const { // Called after Universe initialized
442 return _config.verify(cache);
443 }
444 };
445
446 // Continue with AOTCodeCache class definition.
447 private:
448 Header* _load_header;
449 char* _load_buffer; // Aligned buffer for loading cached code
450 char* _store_buffer; // Aligned buffer for storing cached code
451 char* _C_store_buffer; // Original unaligned buffer
452
453 uint _write_position; // Position in _store_buffer
454 uint _load_size; // Used when reading cache
455 uint _store_size; // Used when writing cache
456 bool _for_use; // AOT cache is open for using AOT code
457 bool _for_dump; // AOT cache is open for dumping AOT code
458 bool _failed; // Failed read/write to/from cache (cache is broken?)
459 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
460
461 AOTCodeAddressTable* _table;
462
463 AOTCodeEntry* _load_entries; // Used when reading cache
464 uint* _search_entries; // sorted by ID table [id, index]
465 AOTCodeEntry* _store_entries; // Used when writing cache
466 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table
467 uint _store_entries_cnt;
468
469 static AOTCodeCache* open_for_use();
470 static AOTCodeCache* open_for_dump();
471
472 bool set_write_position(uint pos);
473 bool align_write();
474 bool align_write_int();
475 bool align_write_bytes(uint alignment);
476 address reserve_bytes(uint nbytes);
477 uint write_bytes(const void* buffer, uint nbytes);
478 const char* addr(uint offset) const { return _load_buffer + offset; }
479 static AOTCodeAddressTable* addr_table() {
480 return is_on() && (cache()->_table != nullptr) ? cache()->_table : nullptr;
481 }
482
483 void set_lookup_failed() { _lookup_failed = true; }
484 void clear_lookup_failed() { _lookup_failed = false; }
485 bool lookup_failed() const { return _lookup_failed; }
486
487 void add_stub_entry(EntryId entry_id, address entry) NOT_CDS_RETURN;
488 public:
489 AOTCodeCache(bool is_dumping, bool is_using);
490
491 const char* cache_buffer() const { return _load_buffer; }
492 bool failed() const { return _failed; }
493 void set_failed() { _failed = true; }
494
495 static uint max_aot_code_size();
496
497 uint load_size() const { return _load_size; }
498 uint write_position() const { return _write_position; }
499
500 void load_strings();
501 int store_strings();
502
503 static void set_shared_stubs_complete() NOT_CDS_RETURN;
504 static void set_c1_stubs_complete() NOT_CDS_RETURN ;
505 static void set_c2_stubs_complete() NOT_CDS_RETURN;
506 static void set_stubgen_stubs_complete() NOT_CDS_RETURN;
507
508 void add_stub_entries(StubId stub_id, address start, GrowableArray<address> *entries = nullptr, int offset = -1) NOT_CDS_RETURN;
509
510 address address_for_C_string(int idx) const { return _table->address_for_C_string(idx); }
511 address address_for_id(int id) const { return _table->address_for_id(id); }
512
513 bool for_use() const { return _for_use && !_failed; }
514 bool for_dump() const { return _for_dump && !_failed; }
515
516 AOTCodeEntry* add_entry() {
517 _store_entries_cnt++;
518 _store_entries -= 1;
519 return _store_entries;
520 }
521
522 AOTCodeEntry* find_entry(AOTCodeEntry::Kind kind, uint id);
523
524 void store_cpu_features(char*& buffer, uint buffer_size);
525
526 bool finish_write();
527
528 bool write_relocations(CodeBlob& code_blob, RelocIterator& iter);
529 bool write_oop_map_set(CodeBlob& cb);
530 bool write_stub_data(CodeBlob& blob, AOTStubData *stub_data);
531 #ifndef PRODUCT
532 bool write_asm_remarks(CodeBlob& cb);
533 bool write_dbg_strings(CodeBlob& cb);
534 #endif // PRODUCT
535
536 private:
537 // internal private API to save and restore blobs
538 static bool store_code_blob(CodeBlob& blob,
539 AOTCodeEntry::Kind entry_kind,
540 uint id,
541 const char* name,
542 AOTStubData* stub_data,
543 CodeBuffer* code_buffer) NOT_CDS_RETURN_(false);
544
545 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
546 uint id,
547 const char* name,
548 AOTStubData* stub_data) NOT_CDS_RETURN_(nullptr);
549
550 public:
551 // save and restore API for non-enumerable code blobs
552 static bool store_code_blob(CodeBlob& blob,
553 AOTCodeEntry::Kind entry_kind,
554 uint id,
555 const char* name) NOT_CDS_RETURN_(false);
556
557 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
558 uint id, const char* name) NOT_CDS_RETURN_(nullptr);
559
560 // save and restore API for enumerable code blobs
561
562 // API for single-stub blobs
563 static bool store_code_blob(CodeBlob& blob,
564 AOTCodeEntry::Kind entry_kind,
565 BlobId id) NOT_CDS_RETURN_(false);
566
567 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
568 BlobId id) NOT_CDS_RETURN_(nullptr);
569
570 // API for multi-stub blobs -- for use by class StubGenerator.
571
572 static bool store_code_blob(CodeBlob& blob,
573 AOTCodeEntry::Kind kind,
574 BlobId id,
575 AOTStubData* stub_data,
576 CodeBuffer *code_buffer) NOT_CDS_RETURN_(false);
577
578 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind,
579 BlobId id,
580 AOTStubData* stub_data) NOT_CDS_RETURN_(nullptr);
581
582 static void publish_external_addresses(GrowableArray<address>& addresses) NOT_CDS_RETURN;
583 // publish all entries for a code blob in code cache address table
584 static void publish_stub_addresses(CodeBlob &code_blob, BlobId id, AOTStubData *stub_data) NOT_CDS_RETURN;
585
586 static uint store_entries_cnt() {
587 if (is_on_for_dump()) {
588 return cache()->_store_entries_cnt;
589 }
590 return -1;
591 }
592
593 // Static access
594
595 private:
596 static AOTCodeCache* _cache;
597 DEBUG_ONLY( static bool _passed_init2; )
598
599 static bool open_cache(bool is_dumping, bool is_using);
600 bool verify_config() {
601 if (for_use()) {
602 return _load_header->verify_config(this);
603 }
604 return true;
605 }
606 public:
607 // marker used where an address offset needs to be stored for later
608 // retrieval and the address turns out to be null
609 static const uint NULL_ADDRESS_MARKER = UINT_MAX;
610
611 static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; }
612 static void initialize() NOT_CDS_RETURN;
613 static void init2() NOT_CDS_RETURN;
614 static void init3() NOT_CDS_RETURN;
615 static void dump() NOT_CDS_RETURN;
616 static bool is_on() CDS_ONLY({ return cache() != nullptr; }) NOT_CDS_RETURN_(false);
617 static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false);
618 static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false);
619 static bool is_dumping_stub() NOT_CDS_RETURN_(false);
620 static bool is_dumping_adapter() NOT_CDS_RETURN_(false);
621 static bool is_using_stub() NOT_CDS_RETURN_(false);
622 static bool is_using_adapter() NOT_CDS_RETURN_(false);
623 static void enable_caching() NOT_CDS_RETURN;
624 static void disable_caching() NOT_CDS_RETURN;
625 static bool is_caching_enabled() NOT_CDS_RETURN_(false);
626
627 static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str);
628
629 static void print_on(outputStream* st) NOT_CDS_RETURN;
630 };
631
632 // Concurent AOT code reader
633 class AOTCodeReader {
634 private:
635 AOTCodeCache* _cache;
636 const AOTCodeEntry* _entry;
637 const char* _load_buffer; // Loaded cached code buffer
638 uint _read_position; // Position in _load_buffer
639 uint read_position() const { return _read_position; }
640 void set_read_position(uint pos);
641 uint align_read_int();
642 const char* addr(uint offset) const { return _load_buffer + offset; }
643
644 bool _lookup_failed; // Failed to lookup for info (skip only this code load)
645 void set_lookup_failed() { _lookup_failed = true; }
646 void clear_lookup_failed() { _lookup_failed = false; }
647 bool lookup_failed() const { return _lookup_failed; }
648
649 // Values used by restore(code_blob).
650 // They should be set before calling it.
651 const char* _name;
652 address _reloc_data;
653 int _reloc_count;
654 ImmutableOopMapSet* _oop_maps;
655 AOTCodeEntry::Kind _entry_kind;
656 int _id;
657 AOTStubData* _stub_data;
658
659 AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; }
660
661 ImmutableOopMapSet* read_oop_map_set();
662 void read_stub_data(CodeBlob* code_blob, AOTStubData *stub_data);
663
664 void fix_relocations(CodeBlob* code_blob, RelocIterator& iter);
665 #ifndef PRODUCT
666 void read_asm_remarks(AsmRemarks& asm_remarks);
667 void read_dbg_strings(DbgStrings& dbg_strings);
668 #endif // PRODUCT
669
670 public:
671 AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry);
672
673 CodeBlob* compile_code_blob(const char* name, AOTCodeEntry::Kind entry_kind, int id, AOTStubData* stub_data = nullptr);
674
675 void restore(CodeBlob* code_blob);
676 };
677
678 // code cache internal runtime constants area used by AOT code
679 class AOTRuntimeConstants {
680 friend class AOTCodeCache;
681 private:
682 address _card_table_base;
683 uint _grain_shift;
684 address _cset_base;
685 static address _field_addresses_list[];
686 static AOTRuntimeConstants _aot_runtime_constants;
687 // private constructor for unique singleton
688 AOTRuntimeConstants() { }
689 // private for use by friend class AOTCodeCache
690 static void initialize_from_runtime();
691 public:
692 #if INCLUDE_CDS
693 static bool contains(address adr) {
694 address base = (address)&_aot_runtime_constants;
695 address hi = base + sizeof(AOTRuntimeConstants);
696 return (base <= adr && adr < hi);
697 }
698 static address card_table_base_address();
699 static address grain_shift_address() { return (address)&_aot_runtime_constants._grain_shift; }
700 static address cset_base_address() { return (address)&_aot_runtime_constants._cset_base; }
701 static address* field_addresses_list() {
702 return _field_addresses_list;
703 }
704 #else
705 static bool contains(address adr) { return false; }
706 static address card_table_base_address() { return nullptr; }
707 static address grain_shift_address() { return nullptr; }
708 static address cset_base_address() { return nullptr; }
709 static address* field_addresses_list() { return nullptr; }
710 #endif
711 };
712
713 #endif // SHARE_CODE_AOTCODECACHE_HPP