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