1 /* 2 * Copyright (c) 2023, 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 useEmptySlotsInSupers = 512 80 }; 81 uint _flags; 82 83 public: 84 void record(bool use_meta_ptrs); 85 bool verify(const char* cache_path) const; 86 87 bool has_meta_ptrs() const { return (_flags & metadataPointers) != 0; } 88 }; 89 90 // Code Cache file header 91 class SCCHeader : public CHeapObj<mtCode> { 92 private: 93 // Here should be version and other verification fields 94 enum { 95 SCC_VERSION = 1 96 }; 97 uint _version; // SCC version (should match when reading code cache) 98 uint _jvm_version_offset;// JVM version string 99 uint _cache_size; // cache size in bytes 100 uint _strings_count; 101 uint _strings_offset; // offset to recorded C strings 102 uint _entries_count; // number of recorded entries in cache 103 uint _entries_offset; // offset of SCCEntry array describing entries 104 uint _preload_entries_count; // entries for pre-loading code 105 uint _preload_entries_offset; 106 SCConfig _config; 107 108 public: 109 void init(uint jvm_version_offset, uint cache_size, 110 uint strings_count, uint strings_offset, 111 uint entries_count, uint entries_offset, 112 uint preload_entries_count, uint preload_entries_offset, 113 bool use_meta_ptrs) { 114 _version = SCC_VERSION; 115 _jvm_version_offset = jvm_version_offset; 116 _cache_size = cache_size; 117 _strings_count = strings_count; 118 _strings_offset = strings_offset; 119 _entries_count = entries_count; 120 _entries_offset = entries_offset; 121 _preload_entries_count = preload_entries_count; 122 _preload_entries_offset = preload_entries_offset; 123 124 _config.record(use_meta_ptrs); 125 } 126 127 uint jvm_version_offset() const { return _jvm_version_offset; } 128 129 uint cache_size() const { return _cache_size; } 130 uint strings_count() const { return _strings_count; } 131 uint strings_offset() const { return _strings_offset; } 132 uint entries_count() const { return _entries_count; } 133 uint entries_offset() const { return _entries_offset; } 134 uint preload_entries_count() const { return _preload_entries_count; } 135 uint preload_entries_offset() const { return _preload_entries_offset; } 136 bool has_meta_ptrs() const { return _config.has_meta_ptrs(); } 137 138 bool verify_config(const char* cache_path, uint load_size) const; 139 bool verify_vm_config(const char* cache_path) const { // Called after Universe initialized 140 return _config.verify(cache_path); 141 } 142 }; 143 144 // Code Cache's entry contain information from CodeBuffer 145 class SCCEntry { 146 public: 147 enum Kind { 148 None = 0, 149 Stub = 1, 150 Blob = 2, 151 Code = 3 152 }; 153 154 private: 155 SCCEntry* _next; 156 Method* _method; 157 Kind _kind; // 158 uint _id; // vmIntrinsic::ID for stub or name's hash for nmethod 159 160 uint _offset; // Offset to entry 161 uint _size; // Entry size 162 uint _name_offset; // Method's or intrinsic name 163 uint _name_size; 164 uint _code_offset; // Start of code in cache 165 uint _code_size; // Total size of all code sections 166 uint _reloc_offset;// Relocations 167 uint _reloc_size; // Max size of relocations per code section 168 uint _num_inlined_bytecodes; 169 170 uint _comp_level; // compilation level 171 uint _comp_id; // compilation id 172 uint _decompile; // Decompile count for this nmethod 173 bool _has_clinit_barriers; // Generated code has class init checks 174 bool _for_preload; // Code can be used for preload 175 bool _loaded; // Code was loaded 176 bool _not_entrant; // Deoptimized 177 bool _load_fail; // Failed to load due to some klass state 178 179 public: 180 SCCEntry(uint offset, uint size, uint name_offset, uint name_size, 181 uint code_offset, uint code_size, 182 uint reloc_offset, uint reloc_size, 183 Kind kind, uint id, uint comp_level = 0, 184 uint comp_id = 0, uint decomp = 0, 185 bool has_clinit_barriers = false, 186 bool for_preload = false) { 187 _next = nullptr; 188 _method = nullptr; 189 _kind = kind; 190 _id = id; 191 192 _offset = offset; 193 _size = size; 194 _name_offset = name_offset; 195 _name_size = name_size; 196 _code_offset = code_offset; 197 _code_size = code_size; 198 _reloc_offset = reloc_offset; 199 _reloc_size = reloc_size; 200 _num_inlined_bytecodes = 0; 201 202 _comp_level = comp_level; 203 _comp_id = comp_id; 204 _decompile = decomp; 205 _has_clinit_barriers = has_clinit_barriers; 206 _for_preload = for_preload; 207 _loaded = false; 208 _not_entrant = false; 209 _load_fail = false; 210 } 211 void* operator new(size_t x, SCCache* cache); 212 // Delete is a NOP 213 void operator delete( void *ptr ) {} 214 215 SCCEntry* next() const { return _next; } 216 void set_next(SCCEntry* next) { _next = next; } 217 218 Method* method() const { return _method; } 219 void set_method(Method* method) { _method = method; } 220 void update_method_for_writing(); 221 222 Kind kind() const { return _kind; } 223 uint id() const { return _id; } 224 225 uint offset() const { return _offset; } 226 void set_offset(uint off) { _offset = off; } 227 228 uint size() const { return _size; } 229 uint name_offset() const { return _name_offset; } 230 uint name_size() const { return _name_size; } 231 uint code_offset() const { return _code_offset; } 232 uint code_size() const { return _code_size; } 233 uint reloc_offset() const { return _reloc_offset; } 234 uint reloc_size() const { return _reloc_size; } 235 uint num_inlined_bytecodes() const { return _num_inlined_bytecodes; } 236 void set_inlined_bytecodes(int bytes) { _num_inlined_bytecodes = bytes; } 237 238 uint comp_level() const { return _comp_level; } 239 uint comp_id() const { return _comp_id; } 240 241 uint decompile() const { return _decompile; } 242 bool has_clinit_barriers() const { return _has_clinit_barriers; } 243 bool for_preload() const { return _for_preload; } 244 bool is_loaded() const { return _loaded; } 245 void set_loaded() { _loaded = true; } 246 247 bool not_entrant() const { return _not_entrant; } 248 void set_not_entrant() { _not_entrant = true; } 249 void set_entrant() { _not_entrant = false; } 250 251 bool load_fail() const { return _load_fail; } 252 void set_load_fail() { _load_fail = true; } 253 254 void print(outputStream* st) const; 255 }; 256 257 // Addresses of stubs, blobs and runtime finctions called from compiled code. 258 class SCAddressTable : public CHeapObj<mtCode> { 259 private: 260 address* _extrs_addr; 261 address* _stubs_addr; 262 address* _blobs_addr; 263 address* _C1_blobs_addr; 264 address* _C2_blobs_addr; 265 uint _extrs_length; 266 uint _stubs_length; 267 uint _blobs_length; 268 uint _C1_blobs_length; 269 uint _C2_blobs_length; 270 uint _final_blobs_length; 271 272 bool _complete; 273 bool _opto_complete; 274 bool _c1_complete; 275 276 public: 277 SCAddressTable() { 278 _extrs_addr = nullptr; 279 _stubs_addr = nullptr; 280 _blobs_addr = nullptr; 281 _complete = false; 282 _opto_complete = false; 283 _c1_complete = false; 284 } 285 ~SCAddressTable(); 286 void init(); 287 void init_opto(); 288 void init_c1(); 289 void add_C_string(const char* str); 290 int id_for_C_string(address str); 291 address address_for_C_string(int idx); 292 int id_for_address(address addr, RelocIterator iter, CodeBuffer* buffer); 293 address address_for_id(int id); 294 bool opto_complete() const { return _opto_complete; } 295 bool c1_complete() const { return _c1_complete; } 296 }; 297 298 struct SCCodeSection { 299 public: 300 address _origin_address; 301 uint _size; 302 uint _offset; 303 }; 304 305 enum class DataKind: int { 306 No_Data = -1, 307 Null = 0, 308 Klass = 1, 309 Method = 2, 310 String = 3, 311 Primitive = 4, // primitive Class object 312 SysLoader = 5, // java_system_loader 313 PlaLoader = 6, // java_platform_loader 314 MethodCnts= 7, 315 Klass_Shared = 8, 316 Method_Shared = 9, 317 String_Shared = 10, 318 MH_Oop_Shared = 11 319 }; 320 321 class SCCache; 322 323 class SCCReader { // Concurent per compilation request 324 private: 325 const SCCache* _cache; 326 const SCCEntry* _entry; 327 const char* _load_buffer; // Loaded cached code buffer 328 uint _read_position; // Position in _load_buffer 329 uint read_position() const { return _read_position; } 330 void set_read_position(uint pos); 331 const char* addr(uint offset) const { return _load_buffer + offset; } 332 333 uint _compile_id; 334 uint _comp_level; 335 uint compile_id() const { return _compile_id; } 336 uint comp_level() const { return _comp_level; } 337 338 bool _preload; // Preloading code before method execution 339 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 340 void set_lookup_failed() { _lookup_failed = true; } 341 void clear_lookup_failed() { _lookup_failed = false; } 342 bool lookup_failed() const { return _lookup_failed; } 343 344 public: 345 SCCReader(SCCache* cache, SCCEntry* entry, CompileTask* task); 346 347 bool compile(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler); 348 bool compile_blob(CodeBuffer* buffer, int* pc_offset); 349 350 Klass* read_klass(const methodHandle& comp_method, bool shared); 351 Method* read_method(const methodHandle& comp_method, bool shared); 352 353 bool read_code(CodeBuffer* buffer, CodeBuffer* orig_buffer, uint code_offset); 354 bool read_relocations(CodeBuffer* buffer, CodeBuffer* orig_buffer, OopRecorder* oop_recorder, ciMethod* target); 355 DebugInformationRecorder* read_debug_info(OopRecorder* oop_recorder); 356 OopMapSet* read_oop_maps(); 357 bool read_dependencies(Dependencies* dependencies); 358 359 jobject read_oop(JavaThread* thread, const methodHandle& comp_method); 360 Metadata* read_metadata(const methodHandle& comp_method); 361 bool read_oops(OopRecorder* oop_recorder, ciMethod* target); 362 bool read_metadata(OopRecorder* oop_recorder, ciMethod* target); 363 364 void print_on(outputStream* st); 365 }; 366 367 class SCCache : public CHeapObj<mtCode> { 368 private: 369 SCCHeader* _load_header; 370 const char* _cache_path; 371 char* _load_buffer; // Aligned buffer for loading cached code 372 char* _store_buffer; // Aligned buffer for storing cached code 373 char* _C_load_buffer; // Original unaligned buffer 374 char* _C_store_buffer; // Original unaligned buffer 375 376 uint _write_position; // Position in _store_buffer 377 uint _load_size; // Used when reading cache 378 uint _store_size; // Used when writing cache 379 bool _for_read; // Open for read 380 bool _for_write; // Open for write 381 bool _use_meta_ptrs; // Store metadata pointers 382 bool _for_preload; // Code for preload 383 bool _gen_preload_code; // Generate pre-loading code 384 bool _has_clinit_barriers; // Code with clinit barriers 385 bool _closing; // Closing cache file 386 bool _failed; // Failed read/write to/from cache (cache is broken?) 387 388 SCAddressTable* _table; 389 390 SCCEntry* _load_entries; // Used when reading cache 391 uint* _search_entries; // sorted by ID table [id, index] 392 SCCEntry* _store_entries; // Used when writing cache 393 const char* _C_strings_buf; // Loaded buffer for _C_strings[] table 394 uint _store_entries_cnt; 395 396 uint _compile_id; 397 uint _comp_level; 398 uint compile_id() const { return _compile_id; } 399 uint comp_level() const { return _comp_level; } 400 401 static SCCache* open_for_read(); 402 static SCCache* open_for_write(); 403 404 bool set_write_position(uint pos); 405 bool align_write(); 406 uint write_bytes(const void* buffer, uint nbytes); 407 const char* addr(uint offset) const { return _load_buffer + offset; } 408 409 bool _lookup_failed; // Failed to lookup for info (skip only this code load) 410 void set_lookup_failed() { _lookup_failed = true; } 411 void clear_lookup_failed() { _lookup_failed = false; } 412 bool lookup_failed() const { return _lookup_failed; } 413 414 SCCEntry* write_nmethod(const methodHandle& method, 415 int compile_id, 416 int entry_bci, 417 CodeOffsets* offsets, 418 int orig_pc_offset, 419 DebugInformationRecorder* recorder, 420 Dependencies* dependencies, 421 CodeBuffer *code_buffer, 422 int frame_size, 423 OopMapSet* oop_maps, 424 ExceptionHandlerTable* handler_table, 425 ImplicitExceptionTable* nul_chk_table, 426 AbstractCompiler* compiler, 427 CompLevel comp_level, 428 bool has_clinit_barriers, 429 bool for_preload, 430 bool has_unsafe_access, 431 bool has_wide_vectors, 432 bool has_monitors); 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 533 static uint store_entries_cnt() { 534 if (is_on_for_write()) { 535 return cache()->_store_entries_cnt; 536 } 537 return -1; 538 } 539 540 // Static access 541 542 private: 543 static SCCache* _cache; 544 545 static bool open_cache(const char* cache_path); 546 static bool verify_vm_config() { 547 if (is_on_for_read()) { 548 return _cache->_load_header->verify_vm_config(_cache->_cache_path); 549 } 550 return true; 551 } 552 public: 553 static SCCache* cache() { return _cache; } 554 static void initialize(); 555 static void init2(); 556 static void close(); 557 static bool is_on() { return _cache != nullptr && !_cache->closing(); } 558 static bool is_C3_on(); 559 static bool is_code_load_thread_on(); 560 static bool is_on_for_read() { return is_on() && _cache->for_read(); } 561 static bool is_on_for_write() { return is_on() && _cache->for_write(); } 562 static bool gen_preload_code(ciMethod* m, int entry_bci); 563 static bool allow_const_field(ciConstant& value); 564 static void invalidate(SCCEntry* entry); 565 static bool is_loaded(SCCEntry* entry); 566 static SCCEntry* find_code_entry(const methodHandle& method, uint comp_level); 567 static void preload_code(JavaThread* thread); 568 569 template<typename Function> 570 static void iterate(Function function) { // lambda enabled API 571 SCCache* cache = open_for_read(); 572 if (cache != nullptr) { 573 ReadingMark rdmk; 574 575 uint count = cache->_load_header->entries_count(); 576 uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index] 577 SCCEntry* load_entries = (SCCEntry*)(search_entries + 2 * count); 578 579 for (uint i = 0; i < count; i++) { 580 int index = search_entries[2*i + 1]; 581 SCCEntry* entry = &(load_entries[index]); 582 function(entry); 583 } 584 } 585 } 586 587 static void add_C_string(const char* str); 588 589 static void print_on(outputStream* st); 590 static void print_statistics_on(outputStream* st); 591 static void print_timers_on(outputStream* st); 592 static void print_unused_entries_on(outputStream* st); 593 594 static void new_workflow_start_writing_cache() NOT_CDS_JAVA_HEAP_RETURN; 595 static void new_workflow_end_writing_cache() NOT_CDS_JAVA_HEAP_RETURN; 596 static void new_workflow_load_cache() NOT_CDS_JAVA_HEAP_RETURN; 597 }; 598 599 #endif // SHARE_CODE_SCCACHE_HPP