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