1 /*
  2  * Copyright (c) 2023, 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     useEmptySlotsInSupers    = 512
 80   };
 81   uint _flags;
 82 
 83 public:
 84   void record(bool use_meta_ptrs);
 85   bool verify(const char* cache_path) 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 _jvm_version_offset;// JVM version string
 99   uint _cache_size;        // cache size in bytes
100   uint _strings_count;
101   uint _strings_offset;    // offset to recorded C strings
102   uint _entries_count;     // number of recorded entries in cache
103   uint _entries_offset;    // offset of SCCEntry array describing entries
104   uint _preload_entries_count; // entries for pre-loading code
105   uint _preload_entries_offset;
106   SCConfig _config;
107 
108 public:
109   void init(uint jvm_version_offset, uint cache_size,
110             uint strings_count, uint strings_offset,
111             uint entries_count, uint entries_offset,
112             uint preload_entries_count, uint preload_entries_offset,
113             bool use_meta_ptrs) {
114     _version        = SCC_VERSION;
115      _jvm_version_offset = jvm_version_offset;
116     _cache_size     = cache_size;
117     _strings_count  = strings_count;
118     _strings_offset = strings_offset;
119     _entries_count  = entries_count;
120     _entries_offset = entries_offset;
121     _preload_entries_count  = preload_entries_count;
122     _preload_entries_offset = preload_entries_offset;
123 
124     _config.record(use_meta_ptrs);
125   }
126 
127   uint jvm_version_offset() const { return _jvm_version_offset; }
128 
129   uint cache_size()     const { return _cache_size; }
130   uint strings_count()  const { return _strings_count; }
131   uint strings_offset() const { return _strings_offset; }
132   uint entries_count()  const { return _entries_count; }
133   uint entries_offset() const { return _entries_offset; }
134   uint preload_entries_count()  const { return _preload_entries_count; }
135   uint preload_entries_offset() const { return _preload_entries_offset; }
136   bool has_meta_ptrs()  const { return _config.has_meta_ptrs(); }
137 
138   bool verify_config(const char* cache_path, uint load_size)  const;
139   bool verify_vm_config(const char* cache_path) const { // Called after Universe initialized
140     return _config.verify(cache_path);
141   }
142 };
143 
144 // Code Cache's entry contain information from CodeBuffer
145 class SCCEntry {
146 public:
147   enum Kind {
148     None = 0,
149     Stub = 1,
150     Blob = 2,
151     Code = 3
152   };
153 
154 private:
155   SCCEntry* _next;
156   Method*   _method;
157   Kind   _kind;        //
158   uint   _id;          // vmIntrinsic::ID for stub or name's hash for nmethod
159 
160   uint   _offset;      // Offset to entry
161   uint   _size;        // Entry size
162   uint   _name_offset; // Method's or intrinsic name
163   uint   _name_size;
164   uint   _code_offset; // Start of code in cache
165   uint   _code_size;   // Total size of all code sections
166   uint   _reloc_offset;// Relocations
167   uint   _reloc_size;  // Max size of relocations per code section
168   uint   _num_inlined_bytecodes;
169 
170   uint   _comp_level;  // compilation level
171   uint   _comp_id;     // compilation id
172   uint   _decompile;   // Decompile count for this nmethod
173   bool   _has_clinit_barriers; // Generated code has class init checks
174   bool   _for_preload; // Code can be used for preload
175   bool   _loaded;      // Code was loaded
176   bool   _not_entrant; // Deoptimized
177   bool   _load_fail;   // Failed to load due to some klass state
178 
179 public:
180   SCCEntry(uint offset, uint size, uint name_offset, uint name_size,
181            uint code_offset, uint code_size,
182            uint reloc_offset, uint reloc_size,
183            Kind kind, uint id, uint comp_level = 0,
184            uint comp_id = 0, uint decomp = 0,
185            bool has_clinit_barriers = false,
186            bool for_preload = false) {
187     _next         = nullptr;
188     _method       = nullptr;
189     _kind         = kind;
190     _id           = id;
191 
192     _offset       = offset;
193     _size         = size;
194     _name_offset  = name_offset;
195     _name_size    = name_size;
196     _code_offset  = code_offset;
197     _code_size    = code_size;
198     _reloc_offset = reloc_offset;
199     _reloc_size   = reloc_size;
200     _num_inlined_bytecodes = 0;
201 
202     _comp_level   = comp_level;
203     _comp_id      = comp_id;
204     _decompile    = decomp;
205     _has_clinit_barriers = has_clinit_barriers;
206     _for_preload  = for_preload;
207     _loaded       = false;
208     _not_entrant  = false;
209     _load_fail    = false;
210   }
211   void* operator new(size_t x, SCCache* cache);
212   // Delete is a NOP
213   void operator delete( void *ptr ) {}
214 
215   SCCEntry* next()    const { return _next; }
216   void set_next(SCCEntry* next) { _next = next; }
217 
218   Method*   method()  const { return _method; }
219   void set_method(Method* method) { _method = method; }
220   void update_method_for_writing();
221 
222   Kind kind()         const { return _kind; }
223   uint id()           const { return _id; }
224 
225   uint offset()       const { return _offset; }
226   void set_offset(uint off) { _offset = off; }
227 
228   uint size()         const { return _size; }
229   uint name_offset()  const { return _name_offset; }
230   uint name_size()    const { return _name_size; }
231   uint code_offset()  const { return _code_offset; }
232   uint code_size()    const { return _code_size; }
233   uint reloc_offset() const { return _reloc_offset; }
234   uint reloc_size()   const { return _reloc_size; }
235   uint num_inlined_bytecodes() const { return _num_inlined_bytecodes; }
236   void set_inlined_bytecodes(int bytes) { _num_inlined_bytecodes = bytes; }
237 
238   uint comp_level()   const { return _comp_level; }
239   uint comp_id()      const { return _comp_id; }
240 
241   uint decompile()    const { return _decompile; }
242   bool has_clinit_barriers() const { return _has_clinit_barriers; }
243   bool for_preload()  const { return _for_preload; }
244   bool is_loaded()    const { return _loaded; }
245   void set_loaded()         { _loaded = true; }
246 
247   bool not_entrant()  const { return _not_entrant; }
248   void set_not_entrant()    { _not_entrant = true; }
249   void set_entrant()        { _not_entrant = false; }
250 
251   bool load_fail()  const { return _load_fail; }
252   void set_load_fail()    { _load_fail = true; }
253 
254   void print(outputStream* st) const;
255 };
256 
257 // Addresses of stubs, blobs and runtime finctions called from compiled code.
258 class SCAddressTable : public CHeapObj<mtCode> {
259 private:
260   address* _extrs_addr;
261   address* _stubs_addr;
262   address* _blobs_addr;
263   address* _C1_blobs_addr;
264   address* _C2_blobs_addr;
265   uint     _extrs_length;
266   uint     _stubs_length;
267   uint     _blobs_length;
268   uint     _C1_blobs_length;
269   uint     _C2_blobs_length;
270   uint     _final_blobs_length;
271 
272   bool _complete;
273   bool _opto_complete;
274   bool _c1_complete;
275 
276 public:
277   SCAddressTable() {
278     _extrs_addr = nullptr;
279     _stubs_addr = nullptr;
280     _blobs_addr = nullptr;
281     _complete = false;
282     _opto_complete = false;
283     _c1_complete = false;
284   }
285   ~SCAddressTable();
286   void init();
287   void init_opto();
288   void init_c1();
289   void add_C_string(const char* str);
290   int  id_for_C_string(address str);
291   address address_for_C_string(int idx);
292   int  id_for_address(address addr, RelocIterator iter, CodeBuffer* buffer);
293   address address_for_id(int id);
294   bool opto_complete() const { return _opto_complete; }
295   bool c1_complete() const { return _c1_complete; }
296 };
297 
298 struct SCCodeSection {
299 public:
300   address _origin_address;
301   uint _size;
302   uint _offset;
303 };
304 
305 enum class DataKind: int {
306   No_Data   = -1,
307   Null      = 0,
308   Klass     = 1,
309   Method    = 2,
310   String    = 3,
311   Primitive = 4, // primitive Class object
312   SysLoader = 5, // java_system_loader
313   PlaLoader = 6, // java_platform_loader
314   MethodCnts= 7,
315   Klass_Shared  = 8,
316   Method_Shared = 9,
317   String_Shared = 10,
318   MH_Oop_Shared = 11
319 };
320 
321 class SCCache;
322 
323 class SCCReader { // Concurent per compilation request
324 private:
325   const SCCache*  _cache;
326   const SCCEntry* _entry;
327   const char*     _load_buffer; // Loaded cached code buffer
328   uint  _read_position;            // Position in _load_buffer
329   uint  read_position() const { return _read_position; }
330   void  set_read_position(uint pos);
331   const char* addr(uint offset) const { return _load_buffer + offset; }
332 
333   uint _compile_id;
334   uint _comp_level;
335   uint compile_id() const { return _compile_id; }
336   uint comp_level() const { return _comp_level; }
337 
338   bool _preload;             // Preloading code before method execution
339   bool _lookup_failed;       // Failed to lookup for info (skip only this code load)
340   void set_lookup_failed()     { _lookup_failed = true; }
341   void clear_lookup_failed()   { _lookup_failed = false; }
342   bool lookup_failed()   const { return _lookup_failed; }
343 
344 public:
345   SCCReader(SCCache* cache, SCCEntry* entry, CompileTask* task);
346 
347   bool compile(ciEnv* env, ciMethod* target, int entry_bci, AbstractCompiler* compiler);
348   bool compile_blob(CodeBuffer* buffer, int* pc_offset);
349 
350   Klass* read_klass(const methodHandle& comp_method, bool shared);
351   Method* read_method(const methodHandle& comp_method, bool shared);
352 
353   bool read_code(CodeBuffer* buffer, CodeBuffer* orig_buffer, uint code_offset);
354   bool read_relocations(CodeBuffer* buffer, CodeBuffer* orig_buffer, OopRecorder* oop_recorder, ciMethod* target);
355   DebugInformationRecorder* read_debug_info(OopRecorder* oop_recorder);
356   OopMapSet* read_oop_maps();
357   bool read_dependencies(Dependencies* dependencies);
358 
359   jobject read_oop(JavaThread* thread, const methodHandle& comp_method);
360   Metadata* read_metadata(const methodHandle& comp_method);
361   bool read_oops(OopRecorder* oop_recorder, ciMethod* target);
362   bool read_metadata(OopRecorder* oop_recorder, ciMethod* target);
363 
364   void print_on(outputStream* st);
365 };
366 
367 class SCCache : public CHeapObj<mtCode> {
368 private:
369   SCCHeader*  _load_header;
370   const char* _cache_path;
371   char*       _load_buffer;    // Aligned buffer for loading cached code
372   char*       _store_buffer;   // Aligned buffer for storing cached code
373   char*       _C_load_buffer;  // Original unaligned buffer
374   char*       _C_store_buffer; // Original unaligned buffer
375 
376   uint        _write_position; // Position in _store_buffer
377   uint        _load_size;      // Used when reading cache
378   uint        _store_size;     // Used when writing cache
379   bool _for_read;              // Open for read
380   bool _for_write;             // Open for write
381   bool _use_meta_ptrs;         // Store metadata pointers
382   bool _for_preload;           // Code for preload
383   bool _gen_preload_code;      // Generate pre-loading code
384   bool _has_clinit_barriers;   // Code with clinit barriers
385   bool _closing;               // Closing cache file
386   bool _failed;                // Failed read/write to/from cache (cache is broken?)
387 
388   SCAddressTable* _table;
389 
390   SCCEntry* _load_entries;     // Used when reading cache
391   uint*     _search_entries;   // sorted by ID table [id, index]
392   SCCEntry* _store_entries;    // Used when writing cache
393   const char* _C_strings_buf;  // Loaded buffer for _C_strings[] table
394   uint      _store_entries_cnt;
395 
396   uint _compile_id;
397   uint _comp_level;
398   uint compile_id() const { return _compile_id; }
399   uint comp_level() const { return _comp_level; }
400 
401   static SCCache* open_for_read();
402   static SCCache* open_for_write();
403 
404   bool set_write_position(uint pos);
405   bool align_write();
406   uint write_bytes(const void* buffer, uint nbytes);
407   const char* addr(uint offset) const { return _load_buffer + offset; }
408 
409   bool _lookup_failed;       // Failed to lookup for info (skip only this code load)
410   void set_lookup_failed()     { _lookup_failed = true; }
411   void clear_lookup_failed()   { _lookup_failed = false; }
412   bool lookup_failed()   const { return _lookup_failed; }
413 
414   SCCEntry* write_nmethod(const methodHandle& method,
415                           int compile_id,
416                           int entry_bci,
417                           CodeOffsets* offsets,
418                           int orig_pc_offset,
419                           DebugInformationRecorder* recorder,
420                           Dependencies* dependencies,
421                           CodeBuffer *code_buffer,
422                           int frame_size,
423                           OopMapSet* oop_maps,
424                           ExceptionHandlerTable* handler_table,
425                           ImplicitExceptionTable* nul_chk_table,
426                           AbstractCompiler* compiler,
427                           CompLevel comp_level,
428                           bool has_clinit_barriers,
429                           bool for_preload,
430                           bool has_unsafe_access,
431                           bool has_wide_vectors,
432                           bool has_monitors);
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 
533   static uint store_entries_cnt() {
534     if (is_on_for_write()) {
535       return cache()->_store_entries_cnt;
536     }
537     return -1;
538   }
539 
540 // Static access
541 
542 private:
543   static SCCache*  _cache;
544 
545   static bool open_cache(const char* cache_path);
546   static bool verify_vm_config() {
547     if (is_on_for_read()) {
548       return _cache->_load_header->verify_vm_config(_cache->_cache_path);
549     }
550     return true;
551   }
552 public:
553   static SCCache* cache() { return _cache; }
554   static void initialize();
555   static void init2();
556   static void close();
557   static bool is_on() { return _cache != nullptr && !_cache->closing(); }
558   static bool is_C3_on();
559   static bool is_code_load_thread_on();
560   static bool is_on_for_read()  { return is_on() && _cache->for_read(); }
561   static bool is_on_for_write() { return is_on() && _cache->for_write(); }
562   static bool gen_preload_code(ciMethod* m, int entry_bci);
563   static bool allow_const_field(ciConstant& value);
564   static void invalidate(SCCEntry* entry);
565   static bool is_loaded(SCCEntry* entry);
566   static SCCEntry* find_code_entry(const methodHandle& method, uint comp_level);
567   static void preload_code(JavaThread* thread);
568 
569   template<typename Function>
570   static void iterate(Function function) { // lambda enabled API
571     SCCache* cache = open_for_read();
572     if (cache != nullptr) {
573       ReadingMark rdmk;
574 
575       uint count = cache->_load_header->entries_count();
576       uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index]
577       SCCEntry* load_entries = (SCCEntry*)(search_entries + 2 * count);
578 
579       for (uint i = 0; i < count; i++) {
580         int index = search_entries[2*i + 1];
581         SCCEntry* entry = &(load_entries[index]);
582         function(entry);
583       }
584     }
585   }
586 
587   static void add_C_string(const char* str);
588 
589   static void print_on(outputStream* st);
590   static void print_statistics_on(outputStream* st);
591   static void print_timers_on(outputStream* st);
592   static void print_unused_entries_on(outputStream* st);
593 
594   static void new_workflow_start_writing_cache() NOT_CDS_JAVA_HEAP_RETURN;
595   static void new_workflow_end_writing_cache() NOT_CDS_JAVA_HEAP_RETURN;
596   static void new_workflow_load_cache() NOT_CDS_JAVA_HEAP_RETURN;
597 };
598 
599 #endif // SHARE_CODE_SCCACHE_HPP