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