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