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