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