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