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_OOPS_TRAININGDATA_HPP
 26 #define SHARE_OOPS_TRAININGDATA_HPP
 27 
 28 #include "cds/archiveUtils.hpp"
 29 #include "classfile/compactHashtable.hpp"
 30 #include "compiler/compilerDefinitions.hpp"
 31 #include "compiler/compiler_globals.hpp"
 32 #include "memory/allocation.hpp"
 33 #include "memory/metaspaceClosure.hpp"
 34 #include "oops/instanceKlass.hpp"
 35 #include "oops/symbolHandle.hpp"
 36 #include "runtime/fieldDescriptor.inline.hpp"
 37 #include "runtime/handles.hpp"
 38 #include "runtime/mutexLocker.hpp"
 39 #include "utilities/count_leading_zeros.hpp"
 40 #include "utilities/resizeableResourceHash.hpp"
 41 
 42 class ciEnv;
 43 class ciBaseObject;
 44 class CompileTask;
 45 class xmlStream;
 46 class CompileTrainingData;
 47 class KlassTrainingData;
 48 class MethodTrainingData;
 49 class TrainingDataDumper;
 50 class TrainingDataSetLocker;
 51 class DumpTimeTrainingDataInfo;
 52 class TrainingDataDictionary;
 53 class RunTimeClassInfo;
 54 class RunTimeMethodDataInfo;
 55 
 56 
 57 class TrainingData : public Metadata {
 58   friend KlassTrainingData;
 59   friend MethodTrainingData;
 60   friend CompileTrainingData;
 61  public:
 62   class Key {
 63     Symbol* _name1;   // Klass::name or Method::name
 64     Symbol* _name2;   // class_loader_name_and_id or signature
 65     const TrainingData* const _holder; // TD for containing klass or method
 66 
 67     // These guys can get to my constructors:
 68     friend TrainingData;
 69     friend KlassTrainingData;
 70     friend MethodTrainingData;
 71     friend CompileTrainingData;
 72 
 73     // The empty key
 74     Key() : _name1(nullptr), _name2(nullptr), _holder(nullptr) { }
 75     bool is_empty() const {
 76       return _name1 == nullptr && _name2 == nullptr && _holder == nullptr;
 77     }
 78 
 79   public:
 80     Key(Symbol* name1, Symbol* name2,
 81         const TrainingData* holder = nullptr)
 82       : _name1(name1), _name2(name2), _holder(holder)
 83       // Since we are using SymbolHandles here, the reference counts
 84       // are incremented here, in this constructor.  We assume that
 85       // the symbols are already kept alive by some other means, but
 86       // after this point the Key object keeps them alive as well.
 87     { }
 88     Key(const KlassTrainingData* klass, Symbol* method_name, Symbol* signature);
 89     Key(const MethodTrainingData* method);
 90     Key(const InstanceKlass* klass);
 91     Key(const Method* method, KlassTrainingData* holder);
 92 
 93     static unsigned cds_hash(const Key* const& k);
 94     static bool can_compute_cds_hash(const Key* const& k);
 95     static unsigned hash(const Key* const& k) {
 96       // A symmetric hash code is usually a bad idea, except in cases
 97       // like this where it is very unlikely that any one string might
 98       // appear in two positions, and even less likely that two
 99       // strings might trade places in two otherwise equal keys.
100       return (Symbol::identity_hash(k->name1()) +
101               Symbol::identity_hash(k->name2()) +
102               (k->holder() == nullptr ? 0 : hash(k->holder()->key())));
103     }
104     static bool equals(const Key* const& k1, const Key* const& k2) {
105       // We assume that all Symbols come for SymbolTable and therefore are unique.
106       // Hence pointer comparison is enough to prove equality.
107       return (k1->name1()   == k2->name1() &&
108               k1->name2()   == k2->name2() &&
109               k1->holder()  == k2->holder());
110     }
111     static inline bool equals(TrainingData* value, const TrainingData::Key* key, int unused) {
112       return equals(value->key(), key);
113     }
114     int cmp(const Key* that) const {
115       auto h1 = this->holder();
116       auto h2 = that->holder();
117       #define NULL_CHECKS(x1, x2, cmpx1x2)                      \
118         ((x1) == nullptr ? -1 : (x2) == nullptr ? +1 : cmpx1x2)
119       if (h1 != h2) {
120         return NULL_CHECKS(h1, h2, h1->key()->cmp(h2->key()));
121       }
122       Symbol* k1; Symbol* k2;
123       #define CHECK_COMPONENT(name)                             \
124         if ((k1 = this->name()) != (k2 = that->name()))         \
125           return NULL_CHECKS(k1, k2, k1->cmp(k2))
126       CHECK_COMPONENT(name1);
127       CHECK_COMPONENT(name2);
128       #undef CHECK_COMPONENT
129       #undef NULL_CHECKS
130       return 0; // no pair of differing components
131     }
132     Symbol* name1() const       { return _name1; }
133     Symbol* name2() const       { return _name2; }
134     const TrainingData* holder() const { return _holder; }
135 
136     void metaspace_pointers_do(MetaspaceClosure *iter);
137   };
138   class TrainingDataLocker {
139     static volatile bool _snapshot;
140     static int _lock_mode;
141     static void lock() {
142       assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
143       if (_lock_mode > 0) {
144         TrainingData_lock->lock();
145       }
146     }
147     static void unlock() {
148       if (_lock_mode > 0) {
149         TrainingData_lock->unlock();
150       }
151     }
152     static bool safely_locked() {
153       assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
154       if (_lock_mode > 0) {
155         return TrainingData_lock->owned_by_self();
156       } else {
157         return true;
158       }
159     }
160   public:
161     static void snapshot() {
162       assert_locked();
163       _snapshot = true;
164     }
165     static bool can_add() {
166       assert_locked();
167       return !_snapshot;
168     }
169     static void initialize() {
170       _lock_mode = need_data() ? +1 : -1;   // if -1, we go lock-free
171     }
172     static void assert_locked() {
173       assert(safely_locked(), "use under TrainingDataLocker");
174     }
175     static void assert_can_add() {
176       assert(can_add(), "Cannot add TrainingData objects");
177     }
178     TrainingDataLocker() {
179       lock();
180     }
181     ~TrainingDataLocker() {
182       unlock();
183     }
184   };
185   class TrainingDataSet {
186     friend TrainingData;
187     ResizeableResourceHashtable<const Key*, TrainingData*,
188                                 AnyObj::C_HEAP, MEMFLAGS::mtCompiler,
189                                 &TrainingData::Key::hash,
190                                 &TrainingData::Key::equals>
191       _table;
192 
193   public:
194     template<typename... Arg>
195     TrainingDataSet(Arg... arg)
196       : _table(arg...) {
197     }
198     TrainingData* find(const Key* key) const {
199       TrainingDataLocker::assert_locked();
200       auto res = _table.get(key);
201       return res == nullptr ? nullptr : *res;
202     }
203     bool remove(const Key* key) {
204       return _table.remove(key);
205     }
206     TrainingData* install(TrainingData* tdata) {
207       TrainingDataLocker::assert_locked();
208       TrainingDataLocker::assert_can_add();
209       auto key = tdata->key();
210       if (key->is_empty())   return tdata;  // unkeyed TD not installed
211       bool created = false;
212       auto prior = _table.put_if_absent(key, tdata, &created);
213       if (prior == nullptr || *prior == tdata) {
214         return tdata;
215       }
216       assert(false, "no pre-existing elements allowed");
217       return *prior;
218     }
219     template<typename FN>
220     void iterate_all(FN fn) const { // lambda enabled API
221       return _table.iterate_all(fn);
222     }
223     int size() const { return _table.number_of_entries(); }
224 
225     void verify() const {
226       TrainingDataLocker::assert_locked();
227       iterate_all([&](const TrainingData::Key* k, TrainingData* td) {
228         td->verify();
229       });
230     }
231   };
232 
233   class Visitor {
234     ResizeableResourceHashtable<TrainingData*, bool> _visited;
235   public:
236     Visitor(unsigned size) : _visited(size, 0x3fffffff) { }
237     bool is_visited(TrainingData* td) {
238       return _visited.contains(td);
239     }
240     void visit(TrainingData* td) {
241       bool created;
242       _visited.put_if_absent(td, &created);
243     }
244   };
245 
246 private:
247   Key _key;
248 
249   // just forward all constructor arguments to the embedded key
250   template<typename... Arg>
251   TrainingData(Arg... arg)
252     : _key(arg...) { }
253 
254   static TrainingDataSet _training_data_set;
255   static TrainingDataDictionary _archived_training_data_dictionary;
256   static TrainingDataDictionary _archived_training_data_dictionary_for_dumping;
257   static GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared>* _dumptime_training_data_dictionary;
258   static Array<MethodTrainingData*>* _recompilation_schedule;
259   static Array<MethodTrainingData*>* _recompilation_schedule_for_dumping;
260   static volatile bool* _recompilation_status;
261   static void prepare_recompilation_schedule(TRAPS);
262 
263 public:
264   // Returns the key under which this TD is installed, or else
265   // Key::EMPTY if it is not installed.
266   const Key* key() const { return &_key; }
267 
268   static bool have_data() { return ReplayTraining;  } // Going to read
269   static bool need_data() { return RecordTraining;  } // Going to write
270 
271   static TrainingDataSet* training_data_set() { return &_training_data_set; }
272   static TrainingDataDictionary* archived_training_data_dictionary() { return &_archived_training_data_dictionary; }
273   static bool have_recompilation_schedule() { return _recompilation_schedule != nullptr; }
274   static Array<MethodTrainingData*>* recompilation_schedule() { return _recompilation_schedule; }
275   static volatile bool* recompilation_status() { return _recompilation_status; }
276 
277   virtual MethodTrainingData*   as_MethodTrainingData()  const { return nullptr; }
278   virtual KlassTrainingData*    as_KlassTrainingData()   const { return nullptr; }
279   virtual CompileTrainingData*  as_CompileTrainingData() const { return nullptr; }
280   bool is_MethodTrainingData()  const { return as_MethodTrainingData() != nullptr; }
281   bool is_KlassTrainingData()   const { return as_KlassTrainingData()  != nullptr; }
282   bool is_CompileTrainingData() const { return as_CompileTrainingData()  != nullptr; }
283 
284   virtual void prepare(Visitor& visitor) = 0;
285   virtual void cleanup(Visitor& visitor) = 0;
286 
287   static void initialize();
288 
289   static void verify();
290 
291   // Widget for recording dependencies, as an N-to-M graph relation,
292   // possibly cyclic.
293   template<typename E>
294   class DepList : public StackObj {
295     GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
296     Array<E>*                          _deps;
297     // (hmm, could we have state-selected union of these two?)
298   public:
299     DepList() {
300       _deps_dyn = nullptr;
301       _deps = nullptr;
302     }
303 
304     int length() const {
305       return (_deps_dyn != nullptr ? _deps_dyn->length()
306               : _deps   != nullptr ? _deps->length()
307               : 0);
308     }
309     E* adr_at(int i) const {
310       return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)
311               : _deps   != nullptr ? _deps->adr_at(i)
312               : nullptr);
313     }
314     E at(int i) const {
315       assert(i >= 0 && i < length(), "oob");
316       return *adr_at(i);
317     }
318     bool append_if_missing(E dep) {
319       if (_deps_dyn == nullptr) {
320         _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
321         _deps_dyn->append(dep);
322         return true;
323       } else {
324         return _deps_dyn->append_if_missing(dep);
325       }
326     }
327     bool remove_if_existing(E dep) {
328       if (_deps_dyn != nullptr) {
329         return _deps_dyn->remove_if_existing(dep);
330       }
331       return false;
332     }
333     void clear() {
334       if (_deps_dyn != nullptr)  {
335         _deps_dyn->clear();
336       }
337     }
338     void append(E dep) {
339       if (_deps_dyn == nullptr) {
340         _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
341       }
342       _deps_dyn->append(dep);
343     }
344     bool contains(E dep) {
345       for (int i = 0; i < length(); i++) {
346         if (dep == at(i)) {
347           return true; // found
348         }
349       }
350       return false; // not found
351     }
352 
353 #if INCLUDE_CDS
354     void remove_unshareable_info() {
355       _deps_dyn = nullptr;
356     }
357 #endif
358     void prepare(ClassLoaderData* loader_data);
359     void metaspace_pointers_do(MetaspaceClosure *iter);
360   };
361 
362   virtual void metaspace_pointers_do(MetaspaceClosure *iter);
363 
364 #if INCLUDE_CDS
365   virtual void remove_unshareable_info() {}
366 #endif
367   static void init_dumptime_table(TRAPS);
368   static void iterate_roots(MetaspaceClosure* it);
369   static void dump_training_data();
370   static void cleanup_training_data();
371   static void serialize_training_data(SerializeClosure* soc);
372   static void print_archived_training_data_on(outputStream* st);
373   static void write_training_data_dictionary(TrainingDataDictionary* dictionary);
374   static size_t estimate_size_for_archive();
375 
376   static TrainingData* lookup_archived_training_data(const Key* k);
377 
378   static KlassTrainingData*  lookup_for(InstanceKlass* ik);
379   static MethodTrainingData* lookup_for(Method* m);
380 };
381 
382 class KlassTrainingData : public TrainingData {
383   friend TrainingData;
384   friend CompileTrainingData;
385 
386   // Used by CDS. These classes need to access the private default constructor.
387   template <class T> friend class CppVtableTesterA;
388   template <class T> friend class CppVtableTesterB;
389   template <class T> friend class CppVtableCloner;
390 
391   // cross-link to live klass, or null if not loaded or encountered yet
392   InstanceKlass* _holder;
393   jobject _holder_mirror;   // extra link to prevent unloading by GC
394 
395   DepList<CompileTrainingData*> _comp_deps; // compiles that depend on me
396 
397   void init() {
398     _holder_mirror = nullptr;
399     _holder = nullptr;
400   }
401 
402   KlassTrainingData();
403   KlassTrainingData(Symbol* klass_name, Symbol* loader_name)
404     : TrainingData(klass_name, loader_name)
405   {
406     init();
407   }
408   KlassTrainingData(InstanceKlass* klass)
409     : TrainingData(klass)
410   {
411     init();
412   }
413   int comp_dep_count() const {
414     TrainingDataLocker::assert_locked();
415     return _comp_deps.length();
416   }
417   CompileTrainingData* comp_dep(int i) const {
418     TrainingDataLocker::assert_locked();
419     return _comp_deps.at(i);
420   }
421   void add_comp_dep(CompileTrainingData* ctd) {
422     TrainingDataLocker::assert_locked();
423      _comp_deps.append_if_missing(ctd);
424   }
425   void remove_comp_dep(CompileTrainingData* ctd) {
426     TrainingDataLocker::assert_locked();
427      _comp_deps.remove_if_existing(ctd);
428   }
429 
430  public:
431   Symbol* name()                const { return _key.name1(); }
432   Symbol* loader_name()         const { return _key.name2(); }
433   bool    has_holder()          const { return _holder != nullptr; }
434   InstanceKlass* holder()       const { return _holder; }
435 
436   // This sets up the mirror as well, and may scan for field metadata.
437   void init_holder(const InstanceKlass* klass);
438 
439   // Update any copied data.
440   void refresh_from(const InstanceKlass* klass);
441 
442   static KlassTrainingData* make(InstanceKlass* holder,
443                                  bool null_if_not_found = false);
444   static KlassTrainingData* find(InstanceKlass* holder) {
445     return make(holder, true);
446   }
447 
448   virtual KlassTrainingData* as_KlassTrainingData() const { return const_cast<KlassTrainingData*>(this); };
449 
450   ClassLoaderData* class_loader_data() {
451     assert(has_holder(), "");
452     return holder()->class_loader_data();
453   }
454   void notice_fully_initialized();
455 
456   void print_on(outputStream* st, bool name_only) const;
457   virtual void print_on(outputStream* st) const { print_on(st, false); }
458   virtual void print_value_on(outputStream* st) const { print_on(st, true); }
459 
460   virtual void prepare(Visitor& visitor);
461   virtual void cleanup(Visitor& visitor);
462 
463   MetaspaceObj::Type type() const {
464     return KlassTrainingDataType;
465   }
466 
467 #if INCLUDE_CDS
468   virtual void remove_unshareable_info();
469 #endif
470 
471   void metaspace_pointers_do(MetaspaceClosure *iter);
472 
473   int size() const {
474     return (int)align_metadata_size(align_up(sizeof(KlassTrainingData), BytesPerWord)/BytesPerWord);
475   }
476 
477   const char* internal_name() const {
478     return "{ klass training data }";
479   };
480 
481   void verify();
482 
483   static KlassTrainingData* allocate(InstanceKlass* holder);
484 
485   template<typename FN>
486   void iterate_all_comp_deps(FN fn) const { // lambda enabled API
487     TrainingDataLocker l;
488     for (int i = 0; i < comp_dep_count(); i++) {
489       fn(comp_dep(i));
490     }
491   }
492 };
493 
494 // Information about particular JIT tasks.
495 class CompileTrainingData : public TrainingData {
496   friend KlassTrainingData;
497 
498   // Used by CDS. These classes need to access the private default constructor.
499   template <class T> friend class CppVtableTesterA;
500   template <class T> friend class CppVtableTesterB;
501   template <class T> friend class CppVtableCloner;
502 
503   MethodTrainingData* _method;
504   const short _level;
505   const int _compile_id;
506   int _nm_total_size;
507   float _qtime, _stime, _etime;   // time queued, started, ended
508 
509   // classes that should be initialized before this JIT task runs
510   DepList<KlassTrainingData*> _init_deps;
511   volatile int _init_deps_left;
512 
513 public:
514   class ciRecords {
515     template <typename... Ts> class Arguments {
516     public:
517       bool operator==(const Arguments<>&) const { return true; }
518       void metaspace_pointers_do(MetaspaceClosure *iter) { }
519     };
520     template <typename T, typename... Ts> class Arguments<T, Ts...> {
521     private:
522       T _first;
523       Arguments<Ts...> _remaining;
524 
525     public:
526       constexpr Arguments(const T& first, const Ts&... remaining) noexcept
527         : _first(first), _remaining(remaining...) {}
528       constexpr Arguments() noexcept : _first(), _remaining() {}
529       bool operator==(const Arguments<T, Ts...>& that) const {
530         return _first == that._first && _remaining == that._remaining;
531       }
532       template<typename U = T, std::enable_if_t<std::is_pointer<U>::value && std::is_base_of<MetaspaceObj, typename std::remove_pointer<U>::type>::value, int> = 0>
533       void metaspace_pointers_do(MetaspaceClosure *iter) {
534         iter->push(&_first);
535         _remaining.metaspace_pointers_do(iter);
536       }
537       template<typename U = T, std::enable_if_t<!(std::is_pointer<U>::value && std::is_base_of<MetaspaceObj, typename std::remove_pointer<U>::type>::value), int> = 0>
538       void metaspace_pointers_do(MetaspaceClosure *iter) {
539         _remaining.metaspace_pointers_do(iter);
540       }
541     };
542 
543     template <typename ReturnType, typename... Args> class ciMemoizedFunction : public StackObj {
544     public:
545       class OptionalReturnType {
546         bool _valid;
547         ReturnType _result;
548       public:
549         OptionalReturnType(bool valid, const ReturnType& result) : _valid(valid), _result(result) {}
550         bool is_valid() const { return _valid; }
551         ReturnType result() const { return _result; }
552       };
553     private:
554       typedef Arguments<Args...> ArgumentsType;
555       class Record : public MetaspaceObj {
556         ReturnType    _result;
557         ArgumentsType _arguments;
558       public:
559         Record(const ReturnType& result, const ArgumentsType& arguments) : _result(result), _arguments(arguments) {}
560         Record() { }
561         ReturnType result() const { return _result; }
562         ArgumentsType arguments() const { return _arguments; }
563         bool operator==(const Record& that) { return _arguments == that._arguments; }
564         void metaspace_pointers_do(MetaspaceClosure *iter) { _arguments.metaspace_pointers_do(iter); }
565       };
566       DepList<Record> _data;
567     public:
568       OptionalReturnType find(const Args&... args) {
569         ArgumentsType a(args...);
570         for (int i = 0; i < _data.length(); i++) {
571           if (_data.at(i).arguments() == a) {
572             return OptionalReturnType(true, _data.at(i).result());
573           }
574         }
575         return OptionalReturnType(false, ReturnType());
576       }
577       bool append_if_missing(const ReturnType& result, const Args&... args) {
578         return _data.append_if_missing(Record(result, ArgumentsType(args...)));
579       }
580 #if INCLUDE_CDS
581       void remove_unshareable_info() { _data.remove_unshareable_info(); }
582 #endif
583       void prepare(ClassLoaderData* loader_data) {
584         _data.prepare(loader_data);
585       }
586       void metaspace_pointers_do(MetaspaceClosure *iter) {
587         _data.metaspace_pointers_do(iter);
588       }
589     };
590 
591 
592 public:
593     typedef ciMemoizedFunction<int, MethodTrainingData*> ciMethod__inline_instructions_size_type;
594     ciMethod__inline_instructions_size_type ciMethod__inline_instructions_size;
595 #if INCLUDE_CDS
596     void remove_unshareable_info() {
597       ciMethod__inline_instructions_size.remove_unshareable_info();
598     }
599 #endif
600     void prepare(ClassLoaderData* loader_data) {
601       ciMethod__inline_instructions_size.prepare(loader_data);
602     }
603     void metaspace_pointers_do(MetaspaceClosure *iter) {
604       ciMethod__inline_instructions_size.metaspace_pointers_do(iter);
605     }
606   };
607 
608 private:
609   ciRecords _ci_records;
610 
611   CompileTrainingData();
612   // (should we also capture counters or MDO state or replay data?)
613   CompileTrainingData(MethodTrainingData* method,
614                       int level,
615                       int compile_id)
616       : TrainingData(),  // empty key
617         _method(method), _level(level), _compile_id(compile_id)
618   {
619     _qtime = _stime = _etime = 0;
620     _nm_total_size = 0;
621     _init_deps_left = 0;
622   }
623 
624 public:
625   ciRecords& ci_records() { return _ci_records; }
626   static CompileTrainingData* make(CompileTask* task);
627 
628   virtual CompileTrainingData* as_CompileTrainingData() const { return const_cast<CompileTrainingData*>(this); };
629 
630   MethodTrainingData* method() const { return _method; }
631 
632   int level() const { return _level; }
633 
634   int compile_id() const { return _compile_id; }
635 
636   int init_dep_count() const {
637     TrainingDataLocker::assert_locked();
638     return _init_deps.length();
639   }
640   KlassTrainingData* init_dep(int i) const {
641     TrainingDataLocker::assert_locked();
642     return _init_deps.at(i);
643   }
644   void add_init_dep(KlassTrainingData* ktd) {
645     TrainingDataLocker::assert_locked();
646     ktd->add_comp_dep(this);
647     _init_deps.append_if_missing(ktd);
648   }
649   void clear_init_deps() {
650     TrainingDataLocker::assert_locked();
651     for (int i = 0; i < _init_deps.length(); i++) {
652       _init_deps.at(i)->remove_comp_dep(this);
653     }
654     _init_deps.clear();
655   }
656   void dec_init_deps_left(KlassTrainingData* ktd);
657   int init_deps_left() const {
658     return Atomic::load(&_init_deps_left);
659   }
660   uint compute_init_deps_left(bool count_initialized = false);
661 
662   void record_compilation_queued(CompileTask* task);
663   void record_compilation_start(CompileTask* task);
664   void record_compilation_end(CompileTask* task);
665   void notice_inlined_method(CompileTask* task, const methodHandle& method);
666 
667   // The JIT looks at classes and objects too and can depend on their state.
668   // These simple calls just report the *possibility* of an observation.
669   void notice_jit_observation(ciEnv* env, ciBaseObject* what);
670 
671   virtual void prepare(Visitor& visitor);
672   virtual void cleanup(Visitor& visitor);
673 
674   void print_on(outputStream* st, bool name_only) const;
675   virtual void print_on(outputStream* st) const { print_on(st, false); }
676   virtual void print_value_on(outputStream* st) const { print_on(st, true); }
677 
678 #if INCLUDE_CDS
679   virtual void remove_unshareable_info();
680 #endif
681 
682   virtual void metaspace_pointers_do(MetaspaceClosure* iter);
683   virtual MetaspaceObj::Type type() const { return CompileTrainingDataType; }
684 
685   virtual const char* internal_name() const {
686     return "{ compile training data }";
687   };
688 
689   virtual int size() const {
690     return (int)align_metadata_size(align_up(sizeof(CompileTrainingData), BytesPerWord)/BytesPerWord);
691   }
692 
693   void verify();
694 
695   static CompileTrainingData* allocate(MethodTrainingData* mtd, int level, int compile_id);
696 };
697 
698 // Record information about a method at the time compilation is requested.
699 class MethodTrainingData : public TrainingData {
700   friend TrainingData;
701   friend CompileTrainingData;
702 
703   // Used by CDS. These classes need to access the private default constructor.
704   template <class T> friend class CppVtableTesterA;
705   template <class T> friend class CppVtableTesterB;
706   template <class T> friend class CppVtableCloner;
707 
708   KlassTrainingData* _klass;
709   const Method* _holder;  // can be null
710   CompileTrainingData* _last_toplevel_compiles[CompLevel_count];
711   int _highest_top_level;
712   int _level_mask;  // bit-set of all possible levels
713   bool _was_inlined;
714   bool _was_toplevel;
715   // metadata snapshots of final state:
716   MethodCounters* _final_counters;
717   MethodData*     _final_profile;
718 
719   MethodTrainingData();
720   MethodTrainingData(KlassTrainingData* klass,
721                      Symbol* name, Symbol* signature)
722     : TrainingData(klass, name, signature)
723   {
724     _klass = klass;
725     _holder = nullptr;
726     for (int i = 0; i < CompLevel_count; i++) {
727       _last_toplevel_compiles[i] = nullptr;
728     }
729     _highest_top_level = CompLevel_none;
730     _level_mask = 0;
731     _was_inlined = _was_toplevel = false;
732   }
733 
734   static int level_mask(int level) {
735     return ((level & 0xF) != level ? 0 : 1 << level);
736   }
737   static CompLevel highest_level(int mask) {
738     if (mask == 0)  return (CompLevel) 0;
739     int diff = (count_leading_zeros(level_mask(0)) - count_leading_zeros(mask));
740     return (CompLevel) diff;
741   }
742 
743  public:
744   KlassTrainingData* klass()  const { return _klass; }
745   bool has_holder()           const { return _holder != nullptr; }
746   const Method* holder()      const { return _holder; }
747   Symbol* name()              const { return _key.name1(); }
748   Symbol* signature()         const { return _key.name2(); }
749   bool only_inlined()         const { return !_was_toplevel; }
750   bool never_inlined()        const { return !_was_inlined; }
751   bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }
752   int highest_level()         const { return highest_level(_level_mask); }
753   int highest_top_level()     const { return _highest_top_level; }
754   MethodData* final_profile() const { return _final_profile; }
755 
756   CompileTrainingData* last_toplevel_compile(int level) const {
757     if (level > CompLevel_none) {
758       return _last_toplevel_compiles[level - 1];
759     }
760     return nullptr;
761   }
762 
763   void notice_compilation(int level, bool inlined = false) {
764     if (inlined) {
765       _was_inlined = true;
766     } else {
767       _was_toplevel = true;
768     }
769     _level_mask |= level_mask(level);
770   }
771 
772   // Update any copied data.
773   void refresh_from(const Method* method);
774   static MethodTrainingData* make(const methodHandle& method,
775                                   bool null_if_not_found = false);
776   static MethodTrainingData* find(const methodHandle& method) {
777     return make(method, true);
778   }
779 
780   virtual MethodTrainingData* as_MethodTrainingData() const {
781     return const_cast<MethodTrainingData*>(this);
782   };
783 
784   void print_on(outputStream* st, bool name_only) const;
785   virtual void print_on(outputStream* st) const { print_on(st, false); }
786   virtual void print_value_on(outputStream* st) const { print_on(st, true); }
787 
788   virtual void prepare(Visitor& visitor);
789   virtual void cleanup(Visitor& visitor);
790 
791   template<typename FN>
792   void iterate_all_compiles(FN fn) const { // lambda enabled API
793     for (int i = 0; i < CompLevel_count; i++) {
794       CompileTrainingData* ctd = _last_toplevel_compiles[i];
795       if (ctd != nullptr) {
796         fn(ctd);
797       }
798     }
799   }
800 
801   virtual void metaspace_pointers_do(MetaspaceClosure* iter);
802   virtual MetaspaceObj::Type type() const { return MethodTrainingDataType; }
803 
804 #if INCLUDE_CDS
805   virtual void remove_unshareable_info();
806 #endif
807 
808   virtual int size() const {
809     return (int)align_metadata_size(align_up(sizeof(MethodTrainingData), BytesPerWord)/BytesPerWord);
810   }
811 
812   virtual const char* internal_name() const {
813     return "{ method training data }";
814   };
815 
816   void verify();
817 
818   static MethodTrainingData* allocate(KlassTrainingData* ktd, Method* m);
819 };
820 
821 // CDS support
822 
823 class DumpTimeTrainingDataInfo {
824   TrainingData* _training_data;
825 public:
826   DumpTimeTrainingDataInfo() : DumpTimeTrainingDataInfo(nullptr) {}
827 
828   DumpTimeTrainingDataInfo(TrainingData* training_data)
829       : _training_data(training_data) {}
830 
831   void metaspace_pointers_do(MetaspaceClosure* it) {
832     it->push(&_training_data);
833   }
834 
835   TrainingData* training_data() {
836     return _training_data;
837   }
838 };
839 
840 class TrainingDataDictionary : public OffsetCompactHashtable<
841     const TrainingData::Key*, TrainingData*,
842     TrainingData::Key::equals> {};
843 
844 class TrainingDataPrinter : StackObj {
845   outputStream* _st;
846   int _index;
847 public:
848   TrainingDataPrinter(outputStream* st) : _st(st), _index(0) {}
849   void do_value(TrainingData* record);
850 };
851 
852 #endif // SHARE_OOPS_TRAININGDATA_HPP