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 178 public: 179 SCCEntry(uint offset, uint size, uint name_offset, uint name_size, 180 uint code_offset, uint code_size, 181 uint reloc_offset, uint reloc_size, 182 Kind kind, uint id, uint comp_level = 0, 183 uint comp_id = 0, uint decomp = 0, 184 bool has_clinit_barriers = false, 185 bool for_preload = false) { 186 _next = nullptr; 187 _method = nullptr; 188 _kind = kind; 189 _id = id; 190 191 _offset = offset; 192 _size = size; 193 _name_offset = name_offset; 194 _name_size = name_size; 195 _code_offset = code_offset; 196 _code_size = code_size; 197 _reloc_offset = reloc_offset; 198 _reloc_size = reloc_size; 199 _num_inlined_bytecodes = 0; 200 201 _comp_level = comp_level; 202 _comp_id = comp_id; 203 _decompile = decomp; 204 _has_clinit_barriers = has_clinit_barriers; 205 _for_preload = for_preload; 206 _loaded = false; 207 _not_entrant = false; 208 _load_fail = false; 209 } 210 void* operator new(size_t x, SCCache* cache); 211 // Delete is a NOP 212 void operator delete( void *ptr ) {} 213 214 SCCEntry* next() const { return _next; } 215 void set_next(SCCEntry* next) { _next = next; } 216 217 Method* method() const { return _method; } 218 void set_method(Method* method) { _method = method; } 219 void update_method_for_writing(); 220 221 Kind kind() const { return _kind; } 222 uint id() const { return _id; } 223 224 uint offset() const { return _offset; } 225 void set_offset(uint off) { _offset = off; } 226 227 uint size() const { return _size; } 228 uint name_offset() const { return _name_offset; } 229 uint name_size() const { return _name_size; } 230 uint code_offset() const { return _code_offset; } 231 uint code_size() const { return _code_size; } 232 uint reloc_offset() const { return _reloc_offset; } 233 uint reloc_size() const { return _reloc_size; } 234 uint num_inlined_bytecodes() const { return _num_inlined_bytecodes; } 235 void set_inlined_bytecodes(int bytes) { _num_inlined_bytecodes = bytes; } 236 237 uint comp_level() const { return _comp_level; } 238 uint comp_id() const { return _comp_id; } 239 240 uint decompile() const { return _decompile; } 241 bool has_clinit_barriers() const { return _has_clinit_barriers; } 242 bool for_preload() const { return _for_preload; } 243 bool is_loaded() const { return _loaded; } 244 void set_loaded() { _loaded = true; } 245 246 bool not_entrant() const { return _not_entrant; } 247 void set_not_entrant() { _not_entrant = true; } 248 void set_entrant() { _not_entrant = false; } 249 250 bool load_fail() const { return _load_fail; } 251 void set_load_fail() { _load_fail = true; } 252 253 void print(outputStream* st) const; 254 }; 255 256 // Addresses of stubs, blobs and runtime finctions called from compiled code. 257 class SCAddressTable : public CHeapObj<mtCode> { 258 private: 259 address* _extrs_addr; 260 address* _stubs_addr; 261 address* _blobs_addr; 262 address* _C1_blobs_addr; 263 address* _C2_blobs_addr; 264 uint _extrs_length; 265 uint _stubs_length; 266 uint _blobs_length; 267 uint _C1_blobs_length; 268 uint _C2_blobs_length; 269 uint _final_blobs_length; 270 271 bool _complete; 272 bool _opto_complete; 273 bool _c1_complete; 274 275 public: 276 SCAddressTable() { 277 _extrs_addr = nullptr; 278 _stubs_addr = nullptr; 279 _blobs_addr = nullptr; 280 _complete = false; 281 _opto_complete = false; 282 _c1_complete = false; 283 } 284 ~SCAddressTable(); 285 void init(); 286 void init_opto(); 287 void init_c1(); 288 void add_C_string(const char* str); 289 int id_for_C_string(address str); 290 address address_for_C_string(int idx); 291 int id_for_address(address addr, RelocIterator iter, CodeBuffer* buffer); 292 address address_for_id(int id); 293 bool opto_complete() const { return _opto_complete; } 294 bool c1_complete() const { return _c1_complete; } 295 }; 296 297 struct SCCodeSection { 298 public: 299 address _origin_address; 300 uint _size; 301 uint _offset; 302 }; 303 304 enum class DataKind: int { 305 No_Data = -1, 306 Null = 0, 307 Klass = 1, 308 Method = 2, 309 String = 3, 310 Primitive = 4, // primitive Class object 311 SysLoader = 5, // java_system_loader 312 PlaLoader = 6, // java_platform_loader 313 MethodCnts= 7, 314 Klass_Shared = 8, 315 Method_Shared = 9, 316 String_Shared = 10, 317 MH_Oop_Shared = 11 318 }; 319 320 class SCCache; 321 322 class SCCReader { // Concurent per compilation request 323 private: 324 const SCCache* _cache; 325 const SCCEntry* _entry; 326 const char* _load_buffer; // Loaded cached code buffer 327 uint _read_position; // Position in _load_buffer 328 uint read_position() const { return _read_position; } 329 void set_read_position(uint pos); 330 const char* addr(uint offset) const { return _load_buffer + offset; } 331 332 uint _compile_id; 333 uint _comp_level; 334 uint compile_id() const { return _compile_id; } 335 uint comp_level() const { return _comp_level; } 336 337 bool _preload; // Preloading code before method execution 338 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 339 void set_lookup_failed() { _lookup_failed = true; } 340 void clear_lookup_failed() { _lookup_failed = false; } 341 bool lookup_failed() const { return _lookup_failed; } 342 343 public: 344 SCCReader(SCCache* cache, SCCEntry* entry, CompileTask* task); 345 346 bool compile(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler); 347 bool compile_blob(CodeBuffer* buffer, int* pc_offset); 348 349 Klass* read_klass(const methodHandle& comp_method, bool shared); 350 Method* read_method(const methodHandle& comp_method, bool shared); 351 352 bool read_code(CodeBuffer* buffer, CodeBuffer* orig_buffer, uint code_offset); 353 bool read_relocations(CodeBuffer* buffer, CodeBuffer* orig_buffer, OopRecorder* oop_recorder, ciMethod* target); 354 DebugInformationRecorder* read_debug_info(OopRecorder* oop_recorder); 355 OopMapSet* read_oop_maps(); 356 bool read_dependencies(Dependencies* dependencies); 357 358 jobject read_oop(JavaThread* thread, const methodHandle& comp_method); 359 Metadata* read_metadata(const methodHandle& comp_method); 360 bool read_oops(OopRecorder* oop_recorder, ciMethod* target); 361 bool read_metadata(OopRecorder* oop_recorder, ciMethod* target); 362 363 void print_on(outputStream* st); 364 }; 365 366 class SCCache : public CHeapObj<mtCode> { 367 private: 368 SCCHeader* _load_header; 369 const char* _cache_path; 370 char* _load_buffer; // Aligned buffer for loading cached code 371 char* _store_buffer; // Aligned buffer for storing cached code 372 char* _C_load_buffer; // Original unaligned buffer 373 char* _C_store_buffer; // Original unaligned buffer 374 375 uint _write_position; // Position in _store_buffer 376 uint _load_size; // Used when reading cache 377 uint _store_size; // Used when writing cache 378 bool _for_read; // Open for read 379 bool _for_write; // Open for write 380 bool _use_meta_ptrs; // Store metadata pointers 381 bool _for_preload; // Code for preload 382 bool _gen_preload_code; // Generate pre-loading code 383 bool _has_clinit_barriers; // Code with clinit barriers 384 bool _closing; // Closing cache file 385 bool _failed; // Failed read/write to/from cache (cache is broken?) 386 387 SCAddressTable* _table; 388 389 SCCEntry* _load_entries; // Used when reading cache 390 uint* _search_entries; // sorted by ID table [id, index] 391 SCCEntry* _store_entries; // Used when writing cache 392 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table 393 uint _store_entries_cnt; 394 395 uint _compile_id; 396 uint _comp_level; 397 uint compile_id() const { return _compile_id; } 398 uint comp_level() const { return _comp_level; } 399 400 static SCCache* open_for_read(); 401 static SCCache* open_for_write(); 402 403 bool set_write_position(uint pos); 404 bool align_write(); 405 uint write_bytes(const void* buffer, uint nbytes); 406 const char* addr(uint offset) const { return _load_buffer + offset; } 407 408 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 409 void set_lookup_failed() { _lookup_failed = true; } 410 void clear_lookup_failed() { _lookup_failed = false; } 411 bool lookup_failed() const { return _lookup_failed; } 412 413 SCCEntry* write_nmethod(const methodHandle& method, 414 int compile_id, 415 int entry_bci, 416 CodeOffsets* offsets, 417 int orig_pc_offset, 418 DebugInformationRecorder* recorder, 419 Dependencies* dependencies, 420 CodeBuffer *code_buffer, 421 int frame_size, 422 OopMapSet* oop_maps, 423 ExceptionHandlerTable* handler_table, 424 ImplicitExceptionTable* nul_chk_table, 425 AbstractCompiler* compiler, 426 CompLevel comp_level, 427 bool has_clinit_barriers, 428 bool for_preload, 429 bool has_unsafe_access, 430 bool has_wide_vectors, 431 bool has_monitors, 432 bool has_scoped_access); 433 434 static volatile int _reading_nmethod; 435 436 class ReadingMark { 437 public: 438 ReadingMark() { 439 Atomic::inc(&_reading_nmethod); 440 } 441 ~ReadingMark() { 442 Atomic::dec(&_reading_nmethod); 443 } 444 }; 445 446 public: 447 SCCache(const char* cache_path, int fd, uint load_size); 448 ~SCCache(); 449 450 const char* cache_buffer() const { return _load_buffer; } 451 const char* cache_path() const { return _cache_path; } 452 bool failed() const { return _failed; } 453 void set_failed() { _failed = true; } 454 455 uint load_size() const { return _load_size; } 456 uint write_position() const { return _write_position; } 457 458 void load_strings(); 459 int store_strings(); 460 461 static void init_table(); 462 static void init_opto_table(); 463 static void init_c1_table(); 464 address address_for_id(int id) const { return _table->address_for_id(id); } 465 466 bool for_read() const { return _for_read && !_failed; } 467 bool for_write() const { return _for_write && !_failed; } 468 469 bool closing() const { return _closing; } 470 bool use_meta_ptrs() const { return _use_meta_ptrs; } 471 bool gen_preload_code() const { return _gen_preload_code; } 472 473 void add_new_C_string(const char* str); 474 475 SCCEntry* add_entry() { 476 _store_entries_cnt++; 477 _store_entries -= 1; 478 return _store_entries; 479 } 480 void preload_startup_code(TRAPS); 481 482 SCCEntry* find_entry(SCCEntry::Kind kind, uint id, uint comp_level = 0, uint decomp = 0); 483 void invalidate_entry(SCCEntry* entry); 484 485 bool finish_write(); 486 487 static bool load_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start); 488 static bool store_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start); 489 490 bool write_klass(Klass* klass); 491 bool write_method(Method* method); 492 493 bool write_code(CodeBuffer* buffer, uint& code_size); 494 bool write_relocations(CodeBuffer* buffer, uint& reloc_size); 495 bool write_debug_info(DebugInformationRecorder* recorder); 496 bool write_oop_maps(OopMapSet* oop_maps); 497 498 jobject read_oop(JavaThread* thread, const methodHandle& comp_method); 499 Metadata* read_metadata(const methodHandle& comp_method); 500 bool read_oops(OopRecorder* oop_recorder, ciMethod* target); 501 bool read_metadata(OopRecorder* oop_recorder, ciMethod* target); 502 503 bool write_oop(jobject& jo); 504 bool write_oops(OopRecorder* oop_recorder); 505 bool write_metadata(Metadata* m); 506 bool write_metadata(OopRecorder* oop_recorder); 507 508 static bool load_exception_blob(CodeBuffer* buffer, int* pc_offset); 509 static bool store_exception_blob(CodeBuffer* buffer, int pc_offset); 510 511 static bool load_nmethod(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler, CompLevel comp_level); 512 513 static SCCEntry* store_nmethod(const methodHandle& method, 514 int compile_id, 515 int entry_bci, 516 CodeOffsets* offsets, 517 int orig_pc_offset, 518 DebugInformationRecorder* recorder, 519 Dependencies* dependencies, 520 CodeBuffer *code_buffer, 521 int frame_size, 522 OopMapSet* oop_maps, 523 ExceptionHandlerTable* handler_table, 524 ImplicitExceptionTable* nul_chk_table, 525 AbstractCompiler* compiler, 526 CompLevel comp_level, 527 bool has_clinit_barriers, 528 bool for_preload, 529 bool has_unsafe_access, 530 bool has_wide_vectors, 531 bool has_monitors, 532 bool has_scoped_access); 533 534 static uint store_entries_cnt() { 535 if (is_on_for_write()) { 536 return cache()->_store_entries_cnt; 537 } 538 return -1; 539 } 540 541 // Static access 542 543 private: 544 static SCCache* _cache; 545 546 static bool open_cache(const char* cache_path); 547 static bool verify_vm_config() { 548 if (is_on_for_read()) { 549 return _cache->_load_header->verify_vm_config(_cache->_cache_path); 550 } 551 return true; 552 } 553 public: 554 static SCCache* cache() { return _cache; } 555 static void initialize(); 556 static void init2(); 557 static void close(); 558 static bool is_on() { return _cache != nullptr && !_cache->closing(); } 559 static bool is_C3_on(); 560 static bool is_code_load_thread_on(); 561 static bool is_on_for_read() { return is_on() && _cache->for_read(); } 562 static bool is_on_for_write() { return is_on() && _cache->for_write(); } 563 static bool gen_preload_code(ciMethod* m, int entry_bci); 564 static bool allow_const_field(ciConstant& value); 565 static void invalidate(SCCEntry* entry); 566 static bool is_loaded(SCCEntry* entry); 567 static SCCEntry* find_code_entry(const methodHandle& method, uint comp_level); 568 static void preload_code(JavaThread* thread); 569 570 template<typename Function> 571 static void iterate(Function function) { // lambda enabled API 572 SCCache* cache = open_for_read(); 573 if (cache != nullptr) { 574 ReadingMark rdmk; 575 576 uint count = cache->_load_header->entries_count(); 577 uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index] 578 SCCEntry* load_entries = (SCCEntry*)(search_entries + 2 * count); 579 580 for (uint i = 0; i < count; i++) { 581 int index = search_entries[2*i + 1]; 582 SCCEntry* entry = &(load_entries[index]); 583 function(entry); 584 } 585 } 586 } 587 588 static void add_C_string(const char* str); 589 590 static void print_on(outputStream* st); 591 static void print_statistics_on(outputStream* st); 592 static void print_timers_on(outputStream* st); 593 static void print_unused_entries_on(outputStream* st); 594 595 static void new_workflow_start_writing_cache() NOT_CDS_JAVA_HEAP_RETURN; 596 static void new_workflow_end_writing_cache() NOT_CDS_JAVA_HEAP_RETURN; 597 static void new_workflow_load_cache() NOT_CDS_JAVA_HEAP_RETURN; 598 }; 599 600 #endif // SHARE_CODE_SCCACHE_HPP