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 /*
 29  * Startup Code Cache (SCC) collects compiled code and metadata during
 30  * an application training runs.
 31  * In following "deployment" runs this code can me loaded into
 32  * Code Cache as normal nmethods skipping JIT compilation.
 33  * In additoin special compiled code is generated with class initialization
 34  * barriers which can be called on first Java method invocation.
 35  */
 36  
 37 class AbstractCompiler;
 38 class ciConstant;
 39 class ciEnv;
 40 class ciMethod;
 41 class CodeBuffer;
 42 class CodeOffsets;
 43 class CompileTask;
 44 class DebugInformationRecorder;
 45 class Dependencies;
 46 class ExceptionTable;
 47 class ExceptionHandlerTable;
 48 class ImplicitExceptionTable;
 49 class JavaThread;
 50 class methodHandle;
 51 class Method;
 52 class OopMapSet;
 53 class OopRecorder;
 54 class outputStream;
 55 class RelocIterator;
 56 class SCCache;
 57 class StubCodeGenerator;
 58 
 59 enum class vmIntrinsicID : int;
 60 enum CompLevel : signed char;
 61 
 62 class SCConfig {
 63   uint _compressedOopShift;
 64   uint _compressedKlassShift;
 65   uint _contendedPaddingWidth;
 66   uint _objectAlignment;
 67   uint _gc;
 68   enum Flags {
 69     none                     = 0,
 70     metadataPointers         = 1,
 71     debugVM                  = 2,
 72     compressedOops           = 4,
 73     compressedClassPointers  = 8,
 74     useTLAB                  = 16,
 75     systemClassAssertions    = 32,
 76     userClassAssertions      = 64,
 77     enableContendedPadding   = 128,
 78     restrictContendedPadding = 256,
 79   };
 80   uint _flags;
 81 
 82 public:
 83   void record(bool use_meta_ptrs);
 84   bool verify(const char* cache_path) const;
 85 
 86   bool has_meta_ptrs()  const { return (_flags & metadataPointers) != 0; }
 87 };
 88 
 89 // Code Cache file header
 90 class SCCHeader : public CHeapObj<mtCode> {
 91 private:
 92   // Here should be version and other verification fields
 93   enum {
 94     SCC_VERSION = 1
 95   };
 96   uint _version;           // SCC version (should match when reading code cache)
 97   uint _jvm_version_offset;// JVM version string
 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 jvm_version_offset, 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      _jvm_version_offset = jvm_version_offset;
115     _cache_size     = cache_size;
116     _strings_count  = strings_count;
117     _strings_offset = strings_offset;
118     _entries_count  = entries_count;
119     _entries_offset = entries_offset;
120     _preload_entries_count  = preload_entries_count;
121     _preload_entries_offset = preload_entries_offset;
122 
123     _config.record(use_meta_ptrs);
124   }
125 
126   uint jvm_version_offset() const { return _jvm_version_offset; }
127 
128   uint cache_size()     const { return _cache_size; }
129   uint strings_count()  const { return _strings_count; }
130   uint strings_offset() const { return _strings_offset; }
131   uint entries_count()  const { return _entries_count; }
132   uint entries_offset() const { return _entries_offset; }
133   uint preload_entries_count()  const { return _preload_entries_count; }
134   uint preload_entries_offset() const { return _preload_entries_offset; }
135   bool has_meta_ptrs()  const { return _config.has_meta_ptrs(); }
136 
137   bool verify_config(const char* cache_path, uint load_size)  const;
138   bool verify_vm_config(const char* cache_path) const { // Called after Universe initialized
139     return _config.verify(cache_path);
140   }
141 };
142 
143 // Code Cache's entry contain information from CodeBuffer
144 class SCCEntry {
145 public:
146   enum Kind {
147     None = 0,
148     Stub = 1,
149     Blob = 2,
150     Code = 3
151   };
152 
153 private:
154   SCCEntry* _next;
155   Method*   _method;
156   Kind   _kind;        //
157   uint   _id;          // vmIntrinsic::ID for stub or name's hash for nmethod
158 
159   uint   _offset;      // Offset to entry
160   uint   _size;        // Entry size
161   uint   _name_offset; // Method's or intrinsic name
162   uint   _name_size;
163   uint   _code_offset; // Start of code in cache
164   uint   _code_size;   // Total size of all code sections
165   uint   _reloc_offset;// Relocations
166   uint   _reloc_size;  // Max size of relocations per code section
167   uint   _num_inlined_bytecodes;
168 
169   uint   _comp_level;  // compilation level
170   uint   _comp_id;     // compilation id
171   uint   _decompile;   // Decompile count for this nmethod
172   bool   _has_clinit_barriers; // Generated code has class init checks
173   bool   _for_preload; // Code can be used for preload
174   bool   _loaded;      // Code was loaded
175   bool   _not_entrant; // Deoptimized
176   bool   _load_fail;   // Failed to load due to some klass state
177 
178 public:
179   SCCEntry(uint offset, uint size, uint name_offset, uint name_size,
180            uint code_offset, uint code_size,
181            uint reloc_offset, uint reloc_size,
182            Kind kind, uint id, uint comp_level = 0,
183            uint comp_id = 0, uint decomp = 0,
184            bool has_clinit_barriers = false,
185            bool for_preload = false) {
186     _next         = nullptr;
187     _method       = nullptr;
188     _kind         = kind;
189     _id           = id;
190 
191     _offset       = offset;
192     _size         = size;
193     _name_offset  = name_offset;
194     _name_size    = name_size;
195     _code_offset  = code_offset;
196     _code_size    = code_size;
197     _reloc_offset = reloc_offset;
198     _reloc_size   = reloc_size;
199     _num_inlined_bytecodes = 0;
200 
201     _comp_level   = comp_level;
202     _comp_id      = comp_id;
203     _decompile    = decomp;
204     _has_clinit_barriers = has_clinit_barriers;
205     _for_preload  = for_preload;
206     _loaded       = false;
207     _not_entrant  = false;
208     _load_fail    = false;
209   }
210   void* operator new(size_t x, SCCache* cache);
211   // Delete is a NOP
212   void operator delete( void *ptr ) {}
213 
214   SCCEntry* next()    const { return _next; }
215   void set_next(SCCEntry* next) { _next = next; }
216 
217   Method*   method()  const { return _method; }
218   void set_method(Method* method) { _method = method; }
219   void update_method_for_writing();
220 
221   Kind kind()         const { return _kind; }
222   uint id()           const { return _id; }
223 
224   uint offset()       const { return _offset; }
225   void set_offset(uint off) { _offset = off; }
226 
227   uint size()         const { return _size; }
228   uint name_offset()  const { return _name_offset; }
229   uint name_size()    const { return _name_size; }
230   uint code_offset()  const { return _code_offset; }
231   uint code_size()    const { return _code_size; }
232   uint reloc_offset() const { return _reloc_offset; }
233   uint reloc_size()   const { return _reloc_size; }
234   uint num_inlined_bytecodes() const { return _num_inlined_bytecodes; }
235   void set_inlined_bytecodes(int bytes) { _num_inlined_bytecodes = bytes; }
236 
237   uint comp_level()   const { return _comp_level; }
238   uint comp_id()      const { return _comp_id; }
239 
240   uint decompile()    const { return _decompile; }
241   bool has_clinit_barriers() const { return _has_clinit_barriers; }
242   bool for_preload()  const { return _for_preload; }
243   bool is_loaded()    const { return _loaded; }
244   void set_loaded()         { _loaded = true; }
245 
246   bool not_entrant()  const { return _not_entrant; }
247   void set_not_entrant()    { _not_entrant = true; }
248   void set_entrant()        { _not_entrant = false; }
249 
250   bool load_fail()  const { return _load_fail; }
251   void set_load_fail()    { _load_fail = true; }
252 
253   void print(outputStream* st) const;
254 };
255 
256 // Addresses of stubs, blobs and runtime finctions called from compiled code.
257 class SCAddressTable : public CHeapObj<mtCode> {
258 private:
259   address* _extrs_addr;
260   address* _stubs_addr;
261   address* _blobs_addr;
262   address* _C1_blobs_addr;
263   address* _C2_blobs_addr;
264   uint     _extrs_length;
265   uint     _stubs_length;
266   uint     _blobs_length;
267   uint     _C1_blobs_length;
268   uint     _C2_blobs_length;
269   uint     _final_blobs_length;
270 
271   bool _complete;
272   bool _opto_complete;
273   bool _c1_complete;
274 
275 public:
276   SCAddressTable() {
277     _extrs_addr = nullptr;
278     _stubs_addr = nullptr;
279     _blobs_addr = nullptr;
280     _complete = false;
281     _opto_complete = false;
282     _c1_complete = false;
283   }
284   ~SCAddressTable();
285   void init();
286   void init_opto();
287   void init_c1();
288   void add_C_string(const char* str);
289   int  id_for_C_string(address str);
290   address address_for_C_string(int idx);
291   int  id_for_address(address addr, RelocIterator iter, CodeBuffer* buffer);
292   address address_for_id(int id);
293   bool opto_complete() const { return _opto_complete; }
294   bool c1_complete() const { return _c1_complete; }
295 };
296 
297 struct SCCodeSection {
298 public:
299   address _origin_address;
300   uint _size;
301   uint _offset;
302 };
303 
304 enum class DataKind: int {
305   No_Data   = -1,
306   Null      = 0,
307   Klass     = 1,
308   Method    = 2,
309   String    = 3,
310   Primitive = 4, // primitive Class object
311   SysLoader = 5, // java_system_loader
312   PlaLoader = 6, // java_platform_loader
313   MethodCnts= 7,
314   Klass_Shared  = 8,
315   Method_Shared = 9,
316   String_Shared = 10,
317   MH_Oop_Shared = 11
318 };
319 
320 class SCCache;
321 
322 class SCCReader { // Concurent per compilation request
323 private:
324   const SCCache*  _cache;
325   const SCCEntry* _entry;
326   const char*     _load_buffer; // Loaded cached code buffer
327   uint  _read_position;            // Position in _load_buffer
328   uint  read_position() const { return _read_position; }
329   void  set_read_position(uint pos);
330   const char* addr(uint offset) const { return _load_buffer + offset; }
331 
332   uint _compile_id;
333   uint _comp_level;
334   uint compile_id() const { return _compile_id; }
335   uint comp_level() const { return _comp_level; }
336 
337   bool _preload;             // Preloading code before method execution
338   bool _lookup_failed;       // Failed to lookup for info (skip only this code load)
339   void set_lookup_failed()     { _lookup_failed = true; }
340   void clear_lookup_failed()   { _lookup_failed = false; }
341   bool lookup_failed()   const { return _lookup_failed; }
342 
343 public:
344   SCCReader(SCCache* cache, SCCEntry* entry, CompileTask* task);
345 
346   bool compile(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler);
347   bool compile_blob(CodeBuffer* buffer, int* pc_offset);
348 
349   Klass* read_klass(const methodHandle& comp_method, bool shared);
350   Method* read_method(const methodHandle& comp_method, bool shared);
351 
352   bool read_code(CodeBuffer* buffer, CodeBuffer* orig_buffer, uint code_offset);
353   bool read_relocations(CodeBuffer* buffer, CodeBuffer* orig_buffer, OopRecorder* oop_recorder, ciMethod* target);
354   DebugInformationRecorder* read_debug_info(OopRecorder* oop_recorder);
355   OopMapSet* read_oop_maps();
356   bool read_dependencies(Dependencies* dependencies);
357 
358   jobject read_oop(JavaThread* thread, const methodHandle& comp_method);
359   Metadata* read_metadata(const methodHandle& comp_method);
360   bool read_oops(OopRecorder* oop_recorder, ciMethod* target);
361   bool read_metadata(OopRecorder* oop_recorder, ciMethod* target);
362 
363   void print_on(outputStream* st);
364 };
365 
366 class SCCache : public CHeapObj<mtCode> {
367 private:
368   SCCHeader*  _load_header;
369   const char* _cache_path;
370   char*       _load_buffer;    // Aligned buffer for loading cached code
371   char*       _store_buffer;   // Aligned buffer for storing cached code
372   char*       _C_load_buffer;  // Original unaligned buffer
373   char*       _C_store_buffer; // Original unaligned buffer
374 
375   uint        _write_position; // Position in _store_buffer
376   uint        _load_size;      // Used when reading cache
377   uint        _store_size;     // Used when writing cache
378   bool _for_read;              // Open for read
379   bool _for_write;             // Open for write
380   bool _use_meta_ptrs;         // Store metadata pointers
381   bool _for_preload;           // Code for preload
382   bool _gen_preload_code;      // Generate pre-loading code
383   bool _has_clinit_barriers;   // Code with clinit barriers
384   bool _closing;               // Closing cache file
385   bool _failed;                // Failed read/write to/from cache (cache is broken?)
386 
387   SCAddressTable* _table;
388 
389   SCCEntry* _load_entries;     // Used when reading cache
390   uint*     _search_entries;   // sorted by ID table [id, index]
391   SCCEntry* _store_entries;    // Used when writing cache
392   const char* _C_strings_buf;  // Loaded buffer for _C_strings[] table
393   uint      _store_entries_cnt;
394 
395   uint _compile_id;
396   uint _comp_level;
397   uint compile_id() const { return _compile_id; }
398   uint comp_level() const { return _comp_level; }
399 
400   static SCCache* open_for_read();
401   static SCCache* open_for_write();
402 
403   bool set_write_position(uint pos);
404   bool align_write();
405   uint write_bytes(const void* buffer, uint nbytes);
406   const char* addr(uint offset) const { return _load_buffer + offset; }
407 
408   bool _lookup_failed;       // Failed to lookup for info (skip only this code load)
409   void set_lookup_failed()     { _lookup_failed = true; }
410   void clear_lookup_failed()   { _lookup_failed = false; }
411   bool lookup_failed()   const { return _lookup_failed; }
412 
413   SCCEntry* write_nmethod(const methodHandle& method,
414                           int compile_id,
415                           int entry_bci,
416                           CodeOffsets* offsets,
417                           int orig_pc_offset,
418                           DebugInformationRecorder* recorder,
419                           Dependencies* dependencies,
420                           CodeBuffer *code_buffer,
421                           int frame_size,
422                           OopMapSet* oop_maps,
423                           ExceptionHandlerTable* handler_table,
424                           ImplicitExceptionTable* nul_chk_table,
425                           AbstractCompiler* compiler,
426                           CompLevel comp_level,
427                           bool has_clinit_barriers,
428                           bool for_preload,
429                           bool has_unsafe_access,
430                           bool has_wide_vectors,
431                           bool has_monitors,
432                           bool has_scoped_access);
433 
434   static volatile int _reading_nmethod;
435 
436   class ReadingMark {
437   public:
438     ReadingMark() {
439       Atomic::inc(&_reading_nmethod);
440     }
441     ~ReadingMark() {
442       Atomic::dec(&_reading_nmethod);
443     }
444   };
445 
446 public:
447   SCCache(const char* cache_path, int fd, uint load_size);
448   ~SCCache();
449 
450   const char* cache_buffer() const { return _load_buffer; }
451   const char* cache_path()   const { return _cache_path; }
452   bool failed() const { return _failed; }
453   void set_failed()   { _failed = true; }
454 
455   uint load_size() const { return _load_size; }
456   uint write_position() const { return _write_position; }
457 
458   void load_strings();
459   int store_strings();
460 
461   static void init_table();
462   static void init_opto_table();
463   static void init_c1_table();
464   address address_for_id(int id) const { return _table->address_for_id(id); }
465 
466   bool for_read()  const { return _for_read  && !_failed; }
467   bool for_write() const { return _for_write && !_failed; }
468 
469   bool closing()          const { return _closing; }
470   bool use_meta_ptrs()    const { return _use_meta_ptrs; }
471   bool gen_preload_code() const { return _gen_preload_code; }
472 
473   void add_new_C_string(const char* str);
474 
475   SCCEntry* add_entry() {
476     _store_entries_cnt++;
477     _store_entries -= 1;
478     return _store_entries;
479   }
480   void preload_startup_code(TRAPS);
481 
482   SCCEntry* find_entry(SCCEntry::Kind kind, uint id, uint comp_level = 0, uint decomp = 0);
483   void invalidate_entry(SCCEntry* entry);
484 
485   bool finish_write();
486 
487   static bool load_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start);
488   static bool store_stub(StubCodeGenerator* cgen, vmIntrinsicID id, const char* name, address start);
489 
490   bool write_klass(Klass* klass);
491   bool write_method(Method* method);
492 
493   bool write_code(CodeBuffer* buffer, uint& code_size);
494   bool write_relocations(CodeBuffer* buffer, uint& reloc_size);
495   bool write_debug_info(DebugInformationRecorder* recorder);
496   bool write_oop_maps(OopMapSet* oop_maps);
497 
498   jobject read_oop(JavaThread* thread, const methodHandle& comp_method);
499   Metadata* read_metadata(const methodHandle& comp_method);
500   bool read_oops(OopRecorder* oop_recorder, ciMethod* target);
501   bool read_metadata(OopRecorder* oop_recorder, ciMethod* target);
502 
503   bool write_oop(jobject& jo);
504   bool write_oops(OopRecorder* oop_recorder);
505   bool write_metadata(Metadata* m);
506   bool write_metadata(OopRecorder* oop_recorder);
507 
508   static bool load_exception_blob(CodeBuffer* buffer, int* pc_offset);
509   static bool store_exception_blob(CodeBuffer* buffer, int pc_offset);
510 
511   static bool load_nmethod(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler, CompLevel comp_level);
512 
513   static SCCEntry* store_nmethod(const methodHandle& method,
514                      int compile_id,
515                      int entry_bci,
516                      CodeOffsets* offsets,
517                      int orig_pc_offset,
518                      DebugInformationRecorder* recorder,
519                      Dependencies* dependencies,
520                      CodeBuffer *code_buffer,
521                      int frame_size,
522                      OopMapSet* oop_maps,
523                      ExceptionHandlerTable* handler_table,
524                      ImplicitExceptionTable* nul_chk_table,
525                      AbstractCompiler* compiler,
526                      CompLevel comp_level,
527                      bool has_clinit_barriers,
528                      bool for_preload,
529                      bool has_unsafe_access,
530                      bool has_wide_vectors,
531                      bool has_monitors,
532                      bool has_scoped_access);
533 
534   static uint store_entries_cnt() {
535     if (is_on_for_write()) {
536       return cache()->_store_entries_cnt;
537     }
538     return -1;
539   }
540 
541 // Static access
542 
543 private:
544   static SCCache*  _cache;
545 
546   static bool open_cache(const char* cache_path);
547   static bool verify_vm_config() {
548     if (is_on_for_read()) {
549       return _cache->_load_header->verify_vm_config(_cache->_cache_path);
550     }
551     return true;
552   }
553 public:
554   static SCCache* cache() { return _cache; }
555   static void initialize();
556   static void init2();
557   static void close();
558   static bool is_on() { return _cache != nullptr && !_cache->closing(); }
559   static bool is_C3_on();
560   static bool is_code_load_thread_on();
561   static bool is_on_for_read()  { return is_on() && _cache->for_read(); }
562   static bool is_on_for_write() { return is_on() && _cache->for_write(); }
563   static bool gen_preload_code(ciMethod* m, int entry_bci);
564   static bool allow_const_field(ciConstant& value);
565   static void invalidate(SCCEntry* entry);
566   static bool is_loaded(SCCEntry* entry);
567   static SCCEntry* find_code_entry(const methodHandle& method, uint comp_level);
568   static void preload_code(JavaThread* thread);
569 
570   template<typename Function>
571   static void iterate(Function function) { // lambda enabled API
572     SCCache* cache = open_for_read();
573     if (cache != nullptr) {
574       ReadingMark rdmk;
575 
576       uint count = cache->_load_header->entries_count();
577       uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index]
578       SCCEntry* load_entries = (SCCEntry*)(search_entries + 2 * count);
579 
580       for (uint i = 0; i < count; i++) {
581         int index = search_entries[2*i + 1];
582         SCCEntry* entry = &(load_entries[index]);
583         function(entry);
584       }
585     }
586   }
587 
588   static void add_C_string(const char* str);
589 
590   static void print_on(outputStream* st);
591   static void print_statistics_on(outputStream* st);
592   static void print_timers_on(outputStream* st);
593   static void print_unused_entries_on(outputStream* st);
594 
595   static void new_workflow_start_writing_cache() NOT_CDS_JAVA_HEAP_RETURN;
596   static void new_workflow_end_writing_cache() NOT_CDS_JAVA_HEAP_RETURN;
597   static void new_workflow_load_cache() NOT_CDS_JAVA_HEAP_RETURN;
598 };
599 
600 #endif // SHARE_CODE_SCCACHE_HPP