1 /* 2 * Copyright (c) 2023, 2024, 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_SCCACHE_HPP 26 #define SHARE_CODE_SCCACHE_HPP 27 28 /* 29 * Startup Code Cache (SCC) collects compiled code and metadata during 30 * an application training runs. 31 * In following "deployment" runs this code can me loaded into 32 * Code Cache as normal nmethods skipping JIT compilation. 33 * In additoin special compiled code is generated with class initialization 34 * barriers which can be called on first Java method invocation. 35 */ 36 37 class AbstractCompiler; 38 class ciConstant; 39 class ciEnv; 40 class ciMethod; 41 class CodeBuffer; 42 class CodeOffsets; 43 class CompileTask; 44 class DebugInformationRecorder; 45 class Dependencies; 46 class ExceptionTable; 47 class ExceptionHandlerTable; 48 class ImplicitExceptionTable; 49 class JavaThread; 50 class methodHandle; 51 class Method; 52 class OopMapSet; 53 class OopRecorder; 54 class outputStream; 55 class RelocIterator; 56 class SCCache; 57 class StubCodeGenerator; 58 59 enum class vmIntrinsicID : int; 60 enum CompLevel : signed char; 61 62 class SCConfig { 63 uint _compressedOopShift; 64 uint _compressedKlassShift; 65 uint _contendedPaddingWidth; 66 uint _objectAlignment; 67 uint _gc; 68 enum Flags { 69 none = 0, 70 metadataPointers = 1, 71 debugVM = 2, 72 compressedOops = 4, 73 compressedClassPointers = 8, 74 useTLAB = 16, 75 systemClassAssertions = 32, 76 userClassAssertions = 64, 77 enableContendedPadding = 128, 78 restrictContendedPadding = 256, 79 }; 80 uint _flags; 81 82 public: 83 void record(bool use_meta_ptrs); 84 bool verify(const char* cache_path) const; 85 86 bool has_meta_ptrs() const { return (_flags & metadataPointers) != 0; } 87 }; 88 89 // Code Cache file header 90 class SCCHeader : public CHeapObj<mtCode> { 91 private: 92 // Here should be version and other verification fields 93 enum { 94 SCC_VERSION = 1 95 }; 96 uint _version; // SCC version (should match when reading code cache) 97 uint _jvm_version_offset;// JVM version string 98 uint _cache_size; // cache size in bytes 99 uint _strings_count; 100 uint _strings_offset; // offset to recorded C strings 101 uint _entries_count; // number of recorded entries in cache 102 uint _entries_offset; // offset of SCCEntry array describing entries 103 uint _preload_entries_count; // entries for pre-loading code 104 uint _preload_entries_offset; 105 SCConfig _config; 106 107 public: 108 void init(uint jvm_version_offset, uint cache_size, 109 uint strings_count, uint strings_offset, 110 uint entries_count, uint entries_offset, 111 uint preload_entries_count, uint preload_entries_offset, 112 bool use_meta_ptrs) { 113 _version = SCC_VERSION; 114 _jvm_version_offset = jvm_version_offset; 115 _cache_size = cache_size; 116 _strings_count = strings_count; 117 _strings_offset = strings_offset; 118 _entries_count = entries_count; 119 _entries_offset = entries_offset; 120 _preload_entries_count = preload_entries_count; 121 _preload_entries_offset = preload_entries_offset; 122 123 _config.record(use_meta_ptrs); 124 } 125 126 uint jvm_version_offset() const { return _jvm_version_offset; } 127 128 uint cache_size() const { return _cache_size; } 129 uint strings_count() const { return _strings_count; } 130 uint strings_offset() const { return _strings_offset; } 131 uint entries_count() const { return _entries_count; } 132 uint entries_offset() const { return _entries_offset; } 133 uint preload_entries_count() const { return _preload_entries_count; } 134 uint preload_entries_offset() const { return _preload_entries_offset; } 135 bool has_meta_ptrs() const { return _config.has_meta_ptrs(); } 136 137 bool verify_config(const char* cache_path, uint load_size) const; 138 bool verify_vm_config(const char* cache_path) const { // Called after Universe initialized 139 return _config.verify(cache_path); 140 } 141 }; 142 143 // Code Cache's entry contain information from CodeBuffer 144 class SCCEntry { 145 public: 146 enum Kind { 147 None = 0, 148 Stub = 1, 149 Blob = 2, 150 Code = 3 151 }; 152 153 private: 154 SCCEntry* _next; 155 Method* _method; 156 Kind _kind; // 157 uint _id; // vmIntrinsic::ID for stub or name's hash for nmethod 158 159 uint _offset; // Offset to entry 160 uint _size; // Entry size 161 uint _name_offset; // Method's or intrinsic name 162 uint _name_size; 163 uint _code_offset; // Start of code in cache 164 uint _code_size; // Total size of all code sections 165 uint _reloc_offset;// Relocations 166 uint _reloc_size; // Max size of relocations per code section 167 uint _num_inlined_bytecodes; 168 169 uint _comp_level; // compilation level 170 uint _comp_id; // compilation id 171 uint _decompile; // Decompile count for this nmethod 172 bool _has_clinit_barriers; // Generated code has class init checks 173 bool _for_preload; // Code can be used for preload 174 bool _loaded; // Code was loaded 175 bool _not_entrant; // Deoptimized 176 bool _load_fail; // Failed to load due to some klass state 177 bool _ignore_decompile; // ignore decompile counter if compilation is done 178 // during "assembly" phase without running application 179 180 public: 181 SCCEntry(uint offset, uint size, uint name_offset, uint name_size, 182 uint code_offset, uint code_size, 183 uint reloc_offset, uint reloc_size, 184 Kind kind, uint id, uint comp_level = 0, 185 uint comp_id = 0, uint decomp = 0, 186 bool has_clinit_barriers = false, 187 bool for_preload = false, 188 bool ignore_decompile = false) { 189 _next = nullptr; 190 _method = nullptr; 191 _kind = kind; 192 _id = id; 193 194 _offset = offset; 195 _size = size; 196 _name_offset = name_offset; 197 _name_size = name_size; 198 _code_offset = code_offset; 199 _code_size = code_size; 200 _reloc_offset = reloc_offset; 201 _reloc_size = reloc_size; 202 _num_inlined_bytecodes = 0; 203 204 _comp_level = comp_level; 205 _comp_id = comp_id; 206 _decompile = decomp; 207 _has_clinit_barriers = has_clinit_barriers; 208 _for_preload = for_preload; 209 _loaded = false; 210 _not_entrant = false; 211 _load_fail = false; 212 _ignore_decompile = ignore_decompile; 213 } 214 void* operator new(size_t x, SCCache* cache); 215 // Delete is a NOP 216 void operator delete( void *ptr ) {} 217 218 SCCEntry* next() const { return _next; } 219 void set_next(SCCEntry* next) { _next = next; } 220 221 Method* method() const { return _method; } 222 void set_method(Method* method) { _method = method; } 223 void update_method_for_writing(); 224 225 Kind kind() const { return _kind; } 226 uint id() const { return _id; } 227 228 uint offset() const { return _offset; } 229 void set_offset(uint off) { _offset = off; } 230 231 uint size() const { return _size; } 232 uint name_offset() const { return _name_offset; } 233 uint name_size() const { return _name_size; } 234 uint code_offset() const { return _code_offset; } 235 uint code_size() const { return _code_size; } 236 uint reloc_offset() const { return _reloc_offset; } 237 uint reloc_size() const { return _reloc_size; } 238 uint num_inlined_bytecodes() const { return _num_inlined_bytecodes; } 239 void set_inlined_bytecodes(int bytes) { _num_inlined_bytecodes = bytes; } 240 241 uint comp_level() const { return _comp_level; } 242 uint comp_id() const { return _comp_id; } 243 244 uint decompile() const { return _decompile; } 245 bool has_clinit_barriers() const { return _has_clinit_barriers; } 246 bool for_preload() const { return _for_preload; } 247 bool is_loaded() const { return _loaded; } 248 void set_loaded() { _loaded = true; } 249 bool ignore_decompile() const { return _ignore_decompile; } 250 251 bool not_entrant() const { return _not_entrant; } 252 void set_not_entrant() { _not_entrant = true; } 253 void set_entrant() { _not_entrant = false; } 254 255 bool load_fail() const { return _load_fail; } 256 void set_load_fail() { _load_fail = true; } 257 258 void print(outputStream* st) const; 259 }; 260 261 // Addresses of stubs, blobs and runtime finctions called from compiled code. 262 class SCAddressTable : public CHeapObj<mtCode> { 263 private: 264 address* _extrs_addr; 265 address* _stubs_addr; 266 address* _blobs_addr; 267 address* _C1_blobs_addr; 268 address* _C2_blobs_addr; 269 uint _extrs_length; 270 uint _stubs_length; 271 uint _blobs_length; 272 uint _C1_blobs_length; 273 uint _C2_blobs_length; 274 uint _final_blobs_length; 275 276 bool _complete; 277 bool _opto_complete; 278 bool _c1_complete; 279 280 public: 281 SCAddressTable() { 282 _extrs_addr = nullptr; 283 _stubs_addr = nullptr; 284 _blobs_addr = nullptr; 285 _complete = false; 286 _opto_complete = false; 287 _c1_complete = false; 288 } 289 ~SCAddressTable(); 290 void init(); 291 void init_opto(); 292 void init_c1(); 293 void add_C_string(const char* str); 294 int id_for_C_string(address str); 295 address address_for_C_string(int idx); 296 int id_for_address(address addr, RelocIterator iter, CodeBuffer* buffer); 297 address address_for_id(int id); 298 bool opto_complete() const { return _opto_complete; } 299 bool c1_complete() const { return _c1_complete; } 300 }; 301 302 struct SCCodeSection { 303 public: 304 address _origin_address; 305 uint _size; 306 uint _offset; 307 }; 308 309 enum class DataKind: int { 310 No_Data = -1, 311 Null = 0, 312 Klass = 1, 313 Method = 2, 314 String = 3, 315 Primitive = 4, // primitive Class object 316 SysLoader = 5, // java_system_loader 317 PlaLoader = 6, // java_platform_loader 318 MethodCnts= 7, 319 Klass_Shared = 8, 320 Method_Shared = 9, 321 String_Shared = 10, 322 MH_Oop_Shared = 11 323 }; 324 325 class SCCache; 326 327 class SCCReader { // Concurent per compilation request 328 private: 329 const SCCache* _cache; 330 const SCCEntry* _entry; 331 const char* _load_buffer; // Loaded cached code buffer 332 uint _read_position; // Position in _load_buffer 333 uint read_position() const { return _read_position; } 334 void set_read_position(uint pos); 335 const char* addr(uint offset) const { return _load_buffer + offset; } 336 337 uint _compile_id; 338 uint _comp_level; 339 uint compile_id() const { return _compile_id; } 340 uint comp_level() const { return _comp_level; } 341 342 bool _preload; // Preloading code before method execution 343 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 344 void set_lookup_failed() { _lookup_failed = true; } 345 void clear_lookup_failed() { _lookup_failed = false; } 346 bool lookup_failed() const { return _lookup_failed; } 347 348 public: 349 SCCReader(SCCache* cache, SCCEntry* entry, CompileTask* task); 350 351 bool compile(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler); 352 bool compile_blob(CodeBuffer* buffer, int* pc_offset); 353 354 Klass* read_klass(const methodHandle& comp_method, bool shared); 355 Method* read_method(const methodHandle& comp_method, bool shared); 356 357 bool read_code(CodeBuffer* buffer, CodeBuffer* orig_buffer, uint code_offset); 358 bool read_relocations(CodeBuffer* buffer, CodeBuffer* orig_buffer, OopRecorder* oop_recorder, ciMethod* target); 359 DebugInformationRecorder* read_debug_info(OopRecorder* oop_recorder); 360 OopMapSet* read_oop_maps(); 361 bool read_dependencies(Dependencies* dependencies); 362 363 jobject read_oop(JavaThread* thread, const methodHandle& comp_method); 364 Metadata* read_metadata(const methodHandle& comp_method); 365 bool read_oops(OopRecorder* oop_recorder, ciMethod* target); 366 bool read_metadata(OopRecorder* oop_recorder, ciMethod* target); 367 368 void print_on(outputStream* st); 369 }; 370 371 class SCCache : public CHeapObj<mtCode> { 372 private: 373 SCCHeader* _load_header; 374 const char* _cache_path; 375 char* _load_buffer; // Aligned buffer for loading cached code 376 char* _store_buffer; // Aligned buffer for storing cached code 377 char* _C_load_buffer; // Original unaligned buffer 378 char* _C_store_buffer; // Original unaligned buffer 379 380 uint _write_position; // Position in _store_buffer 381 uint _load_size; // Used when reading cache 382 uint _store_size; // Used when writing cache 383 bool _for_read; // Open for read 384 bool _for_write; // Open for write 385 bool _use_meta_ptrs; // Store metadata pointers 386 bool _for_preload; // Code for preload 387 bool _gen_preload_code; // Generate pre-loading code 388 bool _has_clinit_barriers; // Code with clinit barriers 389 bool _closing; // Closing cache file 390 bool _failed; // Failed read/write to/from cache (cache is broken?) 391 392 SCAddressTable* _table; 393 394 SCCEntry* _load_entries; // Used when reading cache 395 uint* _search_entries; // sorted by ID table [id, index] 396 SCCEntry* _store_entries; // Used when writing cache 397 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table 398 uint _store_entries_cnt; 399 400 uint _compile_id; 401 uint _comp_level; 402 uint compile_id() const { return _compile_id; } 403 uint comp_level() const { return _comp_level; } 404 405 static SCCache* open_for_read(); 406 static SCCache* open_for_write(); 407 408 bool set_write_position(uint pos); 409 bool align_write(); 410 uint write_bytes(const void* buffer, uint nbytes); 411 const char* addr(uint offset) const { return _load_buffer + offset; } 412 413 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 414 void set_lookup_failed() { _lookup_failed = true; } 415 void clear_lookup_failed() { _lookup_failed = false; } 416 bool lookup_failed() const { return _lookup_failed; } 417 418 SCCEntry* write_nmethod(const methodHandle& method, 419 int compile_id, 420 int entry_bci, 421 CodeOffsets* offsets, 422 int orig_pc_offset, 423 DebugInformationRecorder* recorder, 424 Dependencies* dependencies, 425 CodeBuffer *code_buffer, 426 int frame_size, 427 OopMapSet* oop_maps, 428 ExceptionHandlerTable* handler_table, 429 ImplicitExceptionTable* nul_chk_table, 430 AbstractCompiler* compiler, 431 CompLevel comp_level, 432 bool has_clinit_barriers, 433 bool for_preload, 434 bool has_unsafe_access, 435 bool has_wide_vectors, 436 bool has_monitors, 437 bool has_scoped_access); 438 439 // States: 440 // S >= 0: allow new readers, S readers are currently active 441 // S < 0: no new readers are allowed; (-S-1) readers are currently active 442 // (special case: S = -1 means no readers are active, and would never be active again) 443 static volatile int _nmethod_readers; 444 445 static void wait_for_no_nmethod_readers(); 446 447 class ReadingMark { 448 private: 449 bool _failed; 450 public: 451 ReadingMark(); 452 ~ReadingMark(); 453 bool failed() { 454 return _failed; 455 } 456 }; 457 458 public: 459 SCCache(const char* cache_path, int fd, uint load_size); 460 ~SCCache(); 461 462 const char* cache_buffer() const { return _load_buffer; } 463 const char* cache_path() const { return _cache_path; } 464 bool failed() const { return _failed; } 465 void set_failed() { _failed = true; } 466 467 uint load_size() const { return _load_size; } 468 uint write_position() const { return _write_position; } 469 470 void load_strings(); 471 int store_strings(); 472 473 static void init_table(); 474 static void init_opto_table(); 475 static void init_c1_table(); 476 address address_for_id(int id) const { return _table->address_for_id(id); } 477 478 bool for_read() const { return _for_read && !_failed; } 479 bool for_write() const { return _for_write && !_failed; } 480 481 bool closing() const { return _closing; } 482 bool use_meta_ptrs() const { return _use_meta_ptrs; } 483 bool gen_preload_code() const { return _gen_preload_code; } 484 485 void add_new_C_string(const char* str); 486 487 SCCEntry* add_entry() { 488 _store_entries_cnt++; 489 _store_entries -= 1; 490 return _store_entries; 491 } 492 void preload_startup_code(TRAPS); 493 494 SCCEntry* find_entry(SCCEntry::Kind kind, uint id, uint comp_level = 0, uint decomp = 0); 495 void invalidate_entry(SCCEntry* entry); 496 497 bool finish_write(); 498 499 static bool load_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start); 500 static bool store_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start); 501 502 bool write_klass(Klass* klass); 503 bool write_method(Method* method); 504 505 bool write_code(CodeBuffer* buffer, uint& code_size); 506 bool write_relocations(CodeBuffer* buffer, uint& reloc_size); 507 bool write_debug_info(DebugInformationRecorder* recorder); 508 bool write_oop_maps(OopMapSet* oop_maps); 509 510 jobject read_oop(JavaThread* thread, const methodHandle& comp_method); 511 Metadata* read_metadata(const methodHandle& comp_method); 512 bool read_oops(OopRecorder* oop_recorder, ciMethod* target); 513 bool read_metadata(OopRecorder* oop_recorder, ciMethod* target); 514 515 bool write_oop(jobject& jo); 516 bool write_oops(OopRecorder* oop_recorder); 517 bool write_metadata(Metadata* m); 518 bool write_metadata(OopRecorder* oop_recorder); 519 520 static bool load_exception_blob(CodeBuffer* buffer, int* pc_offset); 521 static bool store_exception_blob(CodeBuffer* buffer, int pc_offset); 522 523 static bool load_nmethod(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler, CompLevel comp_level); 524 525 static SCCEntry* store_nmethod(const methodHandle& method, 526 int compile_id, 527 int entry_bci, 528 CodeOffsets* offsets, 529 int orig_pc_offset, 530 DebugInformationRecorder* recorder, 531 Dependencies* dependencies, 532 CodeBuffer *code_buffer, 533 int frame_size, 534 OopMapSet* oop_maps, 535 ExceptionHandlerTable* handler_table, 536 ImplicitExceptionTable* nul_chk_table, 537 AbstractCompiler* compiler, 538 CompLevel comp_level, 539 bool has_clinit_barriers, 540 bool for_preload, 541 bool has_unsafe_access, 542 bool has_wide_vectors, 543 bool has_monitors, 544 bool has_scoped_access); 545 546 static uint store_entries_cnt() { 547 if (is_on_for_write()) { 548 return cache()->_store_entries_cnt; 549 } 550 return -1; 551 } 552 553 // Static access 554 555 private: 556 static SCCache* _cache; 557 558 static bool open_cache(const char* cache_path); 559 static bool verify_vm_config() { 560 if (is_on_for_read()) { 561 return _cache->_load_header->verify_vm_config(_cache->_cache_path); 562 } 563 return true; 564 } 565 public: 566 static SCCache* cache() { return _cache; } 567 static void initialize(); 568 static void init2(); 569 static void close(); 570 static bool is_on() { return _cache != nullptr && !_cache->closing(); } 571 static bool is_C3_on(); 572 static bool is_code_load_thread_on(); 573 static bool is_on_for_read() { return is_on() && _cache->for_read(); } 574 static bool is_on_for_write() { return is_on() && _cache->for_write(); } 575 static bool gen_preload_code(ciMethod* m, int entry_bci); 576 static bool allow_const_field(ciConstant& value); 577 static void invalidate(SCCEntry* entry); 578 static bool is_loaded(SCCEntry* entry); 579 static SCCEntry* find_code_entry(const methodHandle& method, uint comp_level); 580 static void preload_code(JavaThread* thread); 581 582 template<typename Function> 583 static void iterate(Function function) { // lambda enabled API 584 SCCache* cache = open_for_read(); 585 if (cache != nullptr) { 586 ReadingMark rdmk; 587 if (rdmk.failed()) { 588 // Cache is closed, cannot touch anything. 589 return; 590 } 591 592 uint count = cache->_load_header->entries_count(); 593 uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index] 594 SCCEntry* load_entries = (SCCEntry*)(search_entries + 2 * count); 595 596 for (uint i = 0; i < count; i++) { 597 int index = search_entries[2*i + 1]; 598 SCCEntry* entry = &(load_entries[index]); 599 function(entry); 600 } 601 } 602 } 603 604 static void add_C_string(const char* str); 605 606 static void print_on(outputStream* st); 607 static void print_statistics_on(outputStream* st); 608 static void print_timers_on(outputStream* st); 609 static void print_unused_entries_on(outputStream* st); 610 611 static void new_workflow_start_writing_cache() NOT_CDS_JAVA_HEAP_RETURN; 612 static void new_workflow_end_writing_cache() NOT_CDS_JAVA_HEAP_RETURN; 613 static void new_workflow_load_cache() NOT_CDS_JAVA_HEAP_RETURN; 614 }; 615 616 // code cache internal runtime constants area used by AOT code 617 class AOTRuntimeConstants { 618 friend class SCCache; 619 uint _grain_shift; 620 uint _card_shift; 621 static address _field_addresses_list[]; 622 static AOTRuntimeConstants _aot_runtime_constants; 623 // private constructor for unique singleton 624 AOTRuntimeConstants() { } 625 // private for use by friend class SCCache 626 static void initialize_from_runtime(); 627 public: 628 static bool contains(address adr) { 629 address base = (address)&_aot_runtime_constants; 630 address hi = base + sizeof(AOTRuntimeConstants); 631 return (base <= adr && adr < hi); 632 } 633 static address grain_shift_address() { return (address)&_aot_runtime_constants._grain_shift; } 634 static address card_shift_address() { return (address)&_aot_runtime_constants._card_shift; } 635 static address* field_addresses_list() { 636 return _field_addresses_list; 637 } 638 }; 639 640 #endif // SHARE_CODE_SCCACHE_HPP