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