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/gc_globals.hpp" 29 #include "runtime/stubInfo.hpp" 30 31 /* 32 * AOT Code Cache collects code from Code Cache and corresponding metadata 33 * during application training run. 34 * In following "production" runs this code and data can be loaded into 35 * Code Cache skipping its generation. 36 */ 37 38 class CodeBuffer; 39 class RelocIterator; 40 class AOTCodeCache; 41 class AdapterBlob; 42 class ExceptionBlob; 43 class ImmutableOopMapSet; 44 class AsmRemarks; 45 class DbgStrings; 46 47 enum class vmIntrinsicID : int; 48 enum CompLevel : signed char; 49 50 #define DO_AOTCODEENTRY_KIND(Fn) \ 51 Fn(None) \ 52 Fn(Adapter) \ 53 Fn(SharedBlob) \ 54 Fn(C1Blob) \ 55 Fn(C2Blob) \ 56 57 // Descriptor of AOT Code Cache's entry 58 class AOTCodeEntry { 59 public: 60 enum Kind : s1 { 61 #define DECL_KIND_ENUM(kind) kind, 62 DO_AOTCODEENTRY_KIND(DECL_KIND_ENUM) 63 #undef DECL_KIND_ENUM 64 Kind_count 65 }; 66 67 private: 68 AOTCodeEntry* _next; 69 Kind _kind; 70 uint _id; // Adapter's id, vmIntrinsic::ID for stub or name's hash for nmethod 71 uint _offset; // Offset to entry 72 uint _size; // Entry size 73 uint _name_offset; // Code blob name 74 uint _name_size; 75 uint _blob_offset; // Start of code in cache 76 bool _has_oop_maps; 77 address _dumptime_content_start_addr; // CodeBlob::content_begin() at dump time; used for applying relocations 78 79 public: 80 AOTCodeEntry(Kind kind, uint id, 81 uint offset, uint size, 82 uint name_offset, uint name_size, 83 uint blob_offset, bool has_oop_maps, 84 address dumptime_content_start_addr) { 85 _next = nullptr; 86 _kind = kind; 87 _id = id; 88 _offset = offset; 89 _size = size; 90 _name_offset = name_offset; 91 _name_size = name_size; 92 _blob_offset = blob_offset; 93 _has_oop_maps = has_oop_maps; 94 _dumptime_content_start_addr = dumptime_content_start_addr; 95 } 96 void* operator new(size_t x, AOTCodeCache* cache); 97 // Delete is a NOP 98 void operator delete( void *ptr ) {} 99 100 AOTCodeEntry* next() const { return _next; } 101 void set_next(AOTCodeEntry* next) { _next = next; } 102 103 Kind kind() const { return _kind; } 104 uint id() const { return _id; } 105 106 uint offset() const { return _offset; } 107 void set_offset(uint off) { _offset = off; } 108 109 uint size() const { return _size; } 110 uint name_offset() const { return _name_offset; } 111 uint name_size() const { return _name_size; } 112 uint blob_offset() const { return _blob_offset; } 113 bool has_oop_maps() const { return _has_oop_maps; } 114 address dumptime_content_start_addr() const { return _dumptime_content_start_addr; } 115 116 static bool is_valid_entry_kind(Kind kind) { return kind > None && kind < Kind_count; } 117 static bool is_blob(Kind kind) { return kind == SharedBlob || kind == C1Blob || kind == C2Blob; } 118 static bool is_adapter(Kind kind) { return kind == Adapter; } 119 }; 120 121 // Addresses of stubs, blobs and runtime finctions called from compiled code. 122 class AOTCodeAddressTable : public CHeapObj<mtCode> { 123 private: 124 address* _extrs_addr; 125 address* _stubs_addr; 126 address* _shared_blobs_addr; 127 address* _C1_blobs_addr; 128 uint _extrs_length; 129 uint _stubs_length; 130 uint _shared_blobs_length; 131 uint _C1_blobs_length; 132 133 bool _extrs_complete; 134 bool _early_stubs_complete; 135 bool _shared_blobs_complete; 136 bool _early_c1_complete; 137 bool _complete; 138 139 public: 140 AOTCodeAddressTable() : 141 _extrs_addr(nullptr), 142 _stubs_addr(nullptr), 143 _shared_blobs_addr(nullptr), 144 _C1_blobs_addr(nullptr), 145 _extrs_length(0), 146 _stubs_length(0), 147 _shared_blobs_length(0), 148 _C1_blobs_length(0), 149 _extrs_complete(false), 150 _early_stubs_complete(false), 151 _shared_blobs_complete(false), 152 _early_c1_complete(false), 153 _complete(false) 154 { } 155 ~AOTCodeAddressTable(); 156 void init_extrs(); 157 void init_early_stubs(); 158 void init_shared_blobs(); 159 void init_early_c1(); 160 const char* add_C_string(const char* str); 161 int id_for_C_string(address str); 162 address address_for_C_string(int idx); 163 int id_for_address(address addr, RelocIterator iter, CodeBlob* code_blob); 164 address address_for_id(int id); 165 }; 166 167 class AOTCodeCache : public CHeapObj<mtCode> { 168 169 // Classes used to describe AOT code cache. 170 protected: 171 class Config { 172 address _compressedOopBase; 173 uint _compressedOopShift; 174 uint _compressedKlassShift; 175 uint _contendedPaddingWidth; 176 uint _gc; 177 enum Flags { 178 none = 0, 179 debugVM = 1, 180 compressedOops = 2, 181 compressedClassPointers = 4, 182 useTLAB = 8, 183 systemClassAssertions = 16, 184 userClassAssertions = 32, 185 enableContendedPadding = 64, 186 restrictContendedPadding = 128 187 }; 188 uint _flags; 189 uint _cpu_features_offset; // offset in the cache where cpu features are stored 190 191 public: 192 void record(uint cpu_features_offset); 193 bool verify_cpu_features(AOTCodeCache* cache) const; 194 bool verify(AOTCodeCache* cache) const; 195 }; 196 197 class Header : public CHeapObj<mtCode> { 198 private: 199 enum { 200 AOT_CODE_VERSION = 1 201 }; 202 uint _version; // AOT code version (should match when reading code cache) 203 uint _cache_size; // cache size in bytes 204 uint _strings_count; // number of recorded C strings 205 uint _strings_offset; // offset to recorded C strings 206 uint _entries_count; // number of recorded entries 207 uint _entries_offset; // offset of AOTCodeEntry array describing entries 208 uint _adapters_count; 209 uint _shared_blobs_count; 210 uint _C1_blobs_count; 211 uint _C2_blobs_count; 212 Config _config; // must be the last element as there is trailing data stored immediately after Config 213 214 public: 215 void init(uint cache_size, 216 uint strings_count, uint strings_offset, 217 uint entries_count, uint entries_offset, 218 uint adapters_count, uint shared_blobs_count, 219 uint C1_blobs_count, uint C2_blobs_count, 220 uint cpu_features_offset) { 221 _version = AOT_CODE_VERSION; 222 _cache_size = cache_size; 223 _strings_count = strings_count; 224 _strings_offset = strings_offset; 225 _entries_count = entries_count; 226 _entries_offset = entries_offset; 227 _adapters_count = adapters_count; 228 _shared_blobs_count = shared_blobs_count; 229 _C1_blobs_count = C1_blobs_count; 230 _C2_blobs_count = C2_blobs_count; 231 _config.record(cpu_features_offset); 232 } 233 234 235 uint cache_size() const { return _cache_size; } 236 uint strings_count() const { return _strings_count; } 237 uint strings_offset() const { return _strings_offset; } 238 uint entries_count() const { return _entries_count; } 239 uint entries_offset() const { return _entries_offset; } 240 uint adapters_count() const { return _adapters_count; } 241 uint shared_blobs_count() const { return _shared_blobs_count; } 242 uint C1_blobs_count() const { return _C1_blobs_count; } 243 uint C2_blobs_count() const { return _C2_blobs_count; } 244 245 bool verify(uint load_size) const; 246 bool verify_config(AOTCodeCache* cache) const { // Called after Universe initialized 247 return _config.verify(cache); 248 } 249 }; 250 251 // Continue with AOTCodeCache class definition. 252 private: 253 Header* _load_header; 254 char* _load_buffer; // Aligned buffer for loading cached code 255 char* _store_buffer; // Aligned buffer for storing cached code 256 char* _C_store_buffer; // Original unaligned buffer 257 258 uint _write_position; // Position in _store_buffer 259 uint _load_size; // Used when reading cache 260 uint _store_size; // Used when writing cache 261 bool _for_use; // AOT cache is open for using AOT code 262 bool _for_dump; // AOT cache is open for dumping AOT code 263 bool _closing; // Closing cache file 264 bool _failed; // Failed read/write to/from cache (cache is broken?) 265 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 266 267 AOTCodeAddressTable* _table; 268 269 AOTCodeEntry* _load_entries; // Used when reading cache 270 uint* _search_entries; // sorted by ID table [id, index] 271 AOTCodeEntry* _store_entries; // Used when writing cache 272 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table 273 uint _store_entries_cnt; 274 275 static AOTCodeCache* open_for_use(); 276 static AOTCodeCache* open_for_dump(); 277 278 bool set_write_position(uint pos); 279 bool align_write(); 280 address reserve_bytes(uint nbytes); 281 uint write_bytes(const void* buffer, uint nbytes); 282 const char* addr(uint offset) const { return _load_buffer + offset; } 283 static AOTCodeAddressTable* addr_table() { 284 return is_on() && (cache()->_table != nullptr) ? cache()->_table : nullptr; 285 } 286 287 void set_lookup_failed() { _lookup_failed = true; } 288 void clear_lookup_failed() { _lookup_failed = false; } 289 bool lookup_failed() const { return _lookup_failed; } 290 291 public: 292 AOTCodeCache(bool is_dumping, bool is_using); 293 ~AOTCodeCache(); 294 295 const char* cache_buffer() const { return _load_buffer; } 296 bool failed() const { return _failed; } 297 void set_failed() { _failed = true; } 298 299 static uint max_aot_code_size(); 300 301 uint load_size() const { return _load_size; } 302 uint write_position() const { return _write_position; } 303 304 void load_strings(); 305 int store_strings(); 306 307 static void init_early_stubs_table() NOT_CDS_RETURN; 308 static void init_shared_blobs_table() NOT_CDS_RETURN; 309 static void init_early_c1_table() NOT_CDS_RETURN; 310 311 address address_for_C_string(int idx) const { return _table->address_for_C_string(idx); } 312 address address_for_id(int id) const { return _table->address_for_id(id); } 313 314 bool for_use() const { return _for_use && !_failed; } 315 bool for_dump() const { return _for_dump && !_failed; } 316 317 bool closing() const { return _closing; } 318 319 AOTCodeEntry* add_entry() { 320 _store_entries_cnt++; 321 _store_entries -= 1; 322 return _store_entries; 323 } 324 325 AOTCodeEntry* find_entry(AOTCodeEntry::Kind kind, uint id); 326 327 void store_cpu_features(char*& buffer, uint buffer_size); 328 329 bool finish_write(); 330 331 bool write_relocations(CodeBlob& code_blob); 332 bool write_oop_map_set(CodeBlob& cb); 333 #ifndef PRODUCT 334 bool write_asm_remarks(CodeBlob& cb); 335 bool write_dbg_strings(CodeBlob& cb); 336 #endif // PRODUCT 337 338 // save and restore API for non-enumerable code blobs 339 static bool store_code_blob(CodeBlob& blob, 340 AOTCodeEntry::Kind entry_kind, 341 uint id, const char* name) NOT_CDS_RETURN_(false); 342 343 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind, 344 uint id, const char* name) NOT_CDS_RETURN_(nullptr); 345 346 // save and restore API for enumerable code blobs 347 static bool store_code_blob(CodeBlob& blob, 348 AOTCodeEntry::Kind entry_kind, 349 BlobId id) NOT_CDS_RETURN_(false); 350 351 static CodeBlob* load_code_blob(AOTCodeEntry::Kind kind, 352 BlobId id) NOT_CDS_RETURN_(nullptr); 353 354 static uint store_entries_cnt() { 355 if (is_on_for_dump()) { 356 return cache()->_store_entries_cnt; 357 } 358 return -1; 359 } 360 361 // Static access 362 363 private: 364 static AOTCodeCache* _cache; 365 DEBUG_ONLY( static bool _passed_init2; ) 366 367 static bool open_cache(bool is_dumping, bool is_using); 368 bool verify_config() { 369 if (for_use()) { 370 return _load_header->verify_config(this); 371 } 372 return true; 373 } 374 public: 375 static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; } 376 static void initialize() NOT_CDS_RETURN; 377 static void init2() NOT_CDS_RETURN; 378 static void close() NOT_CDS_RETURN; 379 static bool is_on() CDS_ONLY({ return cache() != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false); 380 static bool is_on_for_use() CDS_ONLY({ return is_on() && _cache->for_use(); }) NOT_CDS_RETURN_(false); 381 static bool is_on_for_dump() CDS_ONLY({ return is_on() && _cache->for_dump(); }) NOT_CDS_RETURN_(false); 382 static bool is_dumping_stub() NOT_CDS_RETURN_(false); 383 static bool is_dumping_adapter() NOT_CDS_RETURN_(false); 384 static bool is_using_stub() NOT_CDS_RETURN_(false); 385 static bool is_using_adapter() NOT_CDS_RETURN_(false); 386 static void enable_caching() NOT_CDS_RETURN; 387 static void disable_caching() NOT_CDS_RETURN; 388 static bool is_caching_enabled() NOT_CDS_RETURN_(false); 389 390 static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str); 391 392 static void print_on(outputStream* st) NOT_CDS_RETURN; 393 }; 394 395 // Concurent AOT code reader 396 class AOTCodeReader { 397 private: 398 const AOTCodeCache* _cache; 399 const AOTCodeEntry* _entry; 400 const char* _load_buffer; // Loaded cached code buffer 401 uint _read_position; // Position in _load_buffer 402 uint read_position() const { return _read_position; } 403 void set_read_position(uint pos); 404 const char* addr(uint offset) const { return _load_buffer + offset; } 405 406 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 407 void set_lookup_failed() { _lookup_failed = true; } 408 void clear_lookup_failed() { _lookup_failed = false; } 409 bool lookup_failed() const { return _lookup_failed; } 410 411 AOTCodeEntry* aot_code_entry() { return (AOTCodeEntry*)_entry; } 412 public: 413 AOTCodeReader(AOTCodeCache* cache, AOTCodeEntry* entry); 414 415 CodeBlob* compile_code_blob(const char* name); 416 417 ImmutableOopMapSet* read_oop_map_set(); 418 419 void fix_relocations(CodeBlob* code_blob); 420 #ifndef PRODUCT 421 void read_asm_remarks(AsmRemarks& asm_remarks); 422 void read_dbg_strings(DbgStrings& dbg_strings); 423 #endif // PRODUCT 424 }; 425 426 // code cache internal runtime constants area used by AOT code 427 class AOTRuntimeConstants { 428 friend class AOTCodeCache; 429 private: 430 address _card_table_base; 431 uint _grain_shift; 432 static address _field_addresses_list[]; 433 static AOTRuntimeConstants _aot_runtime_constants; 434 // private constructor for unique singleton 435 AOTRuntimeConstants() { } 436 // private for use by friend class AOTCodeCache 437 static void initialize_from_runtime(); 438 public: 439 #if INCLUDE_CDS 440 static bool contains(address adr) { 441 address base = (address)&_aot_runtime_constants; 442 address hi = base + sizeof(AOTRuntimeConstants); 443 return (base <= adr && adr < hi); 444 } 445 static address card_table_base_address(); 446 static address grain_shift_address() { return (address)&_aot_runtime_constants._grain_shift; } 447 static address* field_addresses_list() { 448 return _field_addresses_list; 449 } 450 #else 451 static bool contains(address adr) { return false; } 452 static address card_table_base_address() { return nullptr; } 453 static address grain_shift_address() { return nullptr; } 454 static address* field_addresses_list() { return nullptr; } 455 #endif 456 }; 457 458 #endif // SHARE_CODE_AOTCODECACHE_HPP --- EOF ---