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