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_OOPS_TRAININGDATA_HPP
 26 #define SHARE_OOPS_TRAININGDATA_HPP
 27 
 28 #include "classfile/classLoaderData.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 "runtime/handles.hpp"
 36 #include "runtime/mutexLocker.hpp"
 37 #include "utilities/count_leading_zeros.hpp"
 38 #include "utilities/resizeableResourceHash.hpp"
 39 
 40 class ciEnv;
 41 class ciBaseObject;
 42 class CompileTask;
 43 class CompileTrainingData;
 44 class KlassTrainingData;
 45 class MethodTrainingData;
 46 
 47 // Base class for all the training data varieties
 48 class TrainingData : public Metadata {
 49   friend KlassTrainingData;
 50   friend MethodTrainingData;
 51   friend CompileTrainingData;
 52 public:
 53   // Key is used to insert any TrainingData (TD) object into a hash tables. The key is currently a
 54   // pointer to a metaspace object the TD is associated with. For example,
 55   // for KlassTrainingData it's an InstanceKlass, for MethodTrainingData it's a Method.
 56   // The utility of the these hash tables is to be able to find a TD object for a given metaspace
 57   // metaspace object.
 58   class Key {
 59     mutable Metadata* _meta;
 60     // These guys can get to my constructors:
 61     friend TrainingData;
 62     friend KlassTrainingData;
 63     friend MethodTrainingData;
 64     friend CompileTrainingData;
 65 
 66     // The empty key
 67     Key() : _meta(nullptr) { }
 68     bool is_empty() const { return _meta == nullptr; }
 69   public:
 70     Key(Metadata* meta) : _meta(meta) { }
 71 
 72     static bool can_compute_cds_hash(const Key* const& k);
 73     static uint cds_hash(const Key* const& k);
 74     static unsigned hash(const Key* const& k) {
 75       return primitive_hash(k->meta());
 76     }
 77     static bool equals(const Key* const& k1, const Key* const& k2) {
 78       return k1->meta() == k2->meta();
 79     }
 80     static inline bool equals(TrainingData* value, const TrainingData::Key* key, int unused) {
 81       return equals(value->key(), key);
 82     }
 83     int cmp(const Key* that) const {
 84       auto m1 = this->meta();
 85       auto m2 = that->meta();
 86       if (m1 < m2) return -1;
 87       if (m1 > m2) return +1;
 88       return 0;
 89     }
 90     Metadata* meta() const { return _meta; }
 91     void metaspace_pointers_do(MetaspaceClosure *iter);
 92     void make_empty() const { _meta = nullptr; }
 93   };
 94 
 95   // TrainingDataLocker is used to guard read/write operations on non-MT-safe data structures.
 96   // It supports recursive locking and a read-only mode (in which case no locks are taken).
 97   // It is also a part of the TD collection termination protocol (see the "spanshot" field).
 98   class TrainingDataLocker {
 99     static volatile bool _snapshot; // If true we're not allocating new training data
100     static int _lock_mode;
101     const bool _recursive;
102     static void lock() {
103       assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
104       if (_lock_mode > 0) {
105         TrainingData_lock->lock();
106       }
107     }
108     static void unlock() {
109       if (_lock_mode > 0) {
110         TrainingData_lock->unlock();
111       }
112     }
113     static bool safely_locked() {
114       assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
115       if (_lock_mode > 0) {
116         return is_self_locked();
117       } else {
118         return true;
119       }
120     }
121     static bool is_self_locked() {
122       return TrainingData_lock->owned_by_self();
123     }
124   public:
125     static void snapshot() {
126       assert_locked();
127       _snapshot = true;
128     }
129     static bool can_add() {
130       assert_locked();
131       return !_snapshot;
132     }
133     static void initialize() {
134       _lock_mode = need_data() ? +1 : -1;   // if -1, we go lock-free
135     }
136     static void assert_locked() {
137       assert(safely_locked(), "use under TrainingDataLocker");
138     }
139     static void assert_can_add() {
140       assert(can_add(), "Cannot add TrainingData objects");
141     }
142     TrainingDataLocker() : _recursive(is_self_locked()) {
143       if (!_recursive) {
144         lock();
145       }
146     }
147     ~TrainingDataLocker() {
148       if (!_recursive) {
149         unlock();
150       }
151     }
152   };
153 
154   // A set of TD objects that we collect during the training run.
155   class TrainingDataSet {
156     friend TrainingData;
157     ResizeableResourceHashtable<const Key*, TrainingData*,
158                                 AnyObj::C_HEAP, MemTag::mtCompiler,
159                                 &TrainingData::Key::hash,
160                                 &TrainingData::Key::equals>
161       _table;
162 
163   public:
164     template<typename... Arg>
165     TrainingDataSet(Arg... arg)
166       : _table(arg...) {
167     }
168     TrainingData* find(const Key* key) const {
169       TrainingDataLocker::assert_locked();
170       if (TrainingDataLocker::can_add()) {
171         auto res = _table.get(key);
172         return res == nullptr ? nullptr : *res;
173       }
174       return nullptr;
175     }
176     bool remove(const Key* key) {
177       return _table.remove(key);
178     }
179     TrainingData* install(TrainingData* td) {
180       TrainingDataLocker::assert_locked();
181       TrainingDataLocker::assert_can_add();
182       auto key = td->key();
183       if (key->is_empty()) {
184         return td;  // unkeyed TD not installed
185       }
186       bool created = false;
187       auto prior = _table.put_if_absent(key, td, &created);
188       if (prior == nullptr || *prior == td) {
189         return td;
190       }
191       assert(false, "no pre-existing elements allowed");
192       return *prior;
193     }
194     template<typename Function>
195     void iterate(const Function& fn) const { // lambda enabled API
196       iterate(const_cast<Function&>(fn));
197     }
198     template<typename Function>
199     void iterate(Function& fn) const { // lambda enabled API
200       return _table.iterate_all([&](const TrainingData::Key* k, TrainingData* td) { fn(td); });
201     }
202     int size() const { return _table.number_of_entries(); }
203 
204     void verify() const {
205       TrainingDataLocker::assert_locked();
206       iterate([&](TrainingData* td) { td->verify(); });
207     }
208   };
209 
210   // A widget to ensure that we visit TD object only once (TD objects can have pointer to
211   // other TD object that are sometimes circular).
212   class Visitor {
213     ResizeableResourceHashtable<TrainingData*, bool> _visited;
214   public:
215     Visitor(unsigned size) : _visited(size, 0x3fffffff) { }
216     bool is_visited(TrainingData* td) {
217       return _visited.contains(td);
218     }
219     void visit(TrainingData* td) {
220       bool created;
221       _visited.put_if_absent(td, &created);
222     }
223   };
224 
225   typedef OffsetCompactHashtable<const TrainingData::Key*, TrainingData*, TrainingData::Key::equals> TrainingDataDictionary;
226 private:
227   Key _key;
228 
229   // just forward all constructor arguments to the embedded key
230   template<typename... Arg>
231   TrainingData(Arg... arg)
232     : _key(arg...) { }
233 
234   // Container for recording TD during training run
235   static TrainingDataSet _training_data_set;
236   // Containter for replaying the training data (read-only, populated from the AOT image)
237   static TrainingDataDictionary _archived_training_data_dictionary;
238   // Container used for writing the AOT image
239   static TrainingDataDictionary _archived_training_data_dictionary_for_dumping;
240   class DumpTimeTrainingDataInfo {
241     TrainingData* _training_data;
242   public:
243     DumpTimeTrainingDataInfo() : DumpTimeTrainingDataInfo(nullptr) {}
244     DumpTimeTrainingDataInfo(TrainingData* training_data) : _training_data(training_data) {}
245     void metaspace_pointers_do(MetaspaceClosure* it) {
246       it->push(&_training_data);
247     }
248     TrainingData* training_data() {
249       return _training_data;
250     }
251   };
252   typedef GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared> DumptimeTrainingDataDictionary;
253   // A temporary container that is used to accumulate and filter TD during dumping
254   static DumptimeTrainingDataDictionary* _dumptime_training_data_dictionary;
255 
256   static TrainingDataSet* training_data_set() { return &_training_data_set; }
257   static TrainingDataDictionary* archived_training_data_dictionary() { return &_archived_training_data_dictionary; }
258 
259  public:
260   // Returns the key under which this TD is installed, or else
261   // Key::EMPTY if it is not installed.
262   const Key* key() const { return &_key; }
263 
264   static bool have_data() { return ReplayTraining;  } // Going to read
265   static bool need_data() { return RecordTraining;  } // Going to write
266 
267   template<typename Function>
268   static void iterate(const Function& fn) { iterate(const_cast<Function&>(fn)); }
269 
270   template<typename Function>
271   static void iterate(Function& fn) { // lambda enabled API
272     TrainingDataLocker l;
273     if (have_data()) {
274       archived_training_data_dictionary()->iterate(fn);
275     }
276     if (need_data()) {
277       training_data_set()->iterate(fn);
278     }
279   }
280 
281   virtual MethodTrainingData*   as_MethodTrainingData()  const { return nullptr; }
282   virtual KlassTrainingData*    as_KlassTrainingData()   const { return nullptr; }
283   virtual CompileTrainingData*  as_CompileTrainingData() const { return nullptr; }
284   bool is_MethodTrainingData()  const { return as_MethodTrainingData()  != nullptr; }
285   bool is_KlassTrainingData()   const { return as_KlassTrainingData()   != nullptr; }
286   bool is_CompileTrainingData() const { return as_CompileTrainingData() != nullptr; }
287 
288   virtual void prepare(Visitor& visitor) = 0;
289   virtual void cleanup(Visitor& visitor) = 0;
290 
291   static void initialize();
292 
293   static void verify();
294 
295   // Widget for recording dependencies, as an N-to-M graph relation,
296   // possibly cyclic.
297   template<typename E>
298   class DepList : public StackObj {
299     GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
300     Array<E>*                          _deps;
301   public:
302     DepList() {
303       _deps_dyn = nullptr;
304       _deps = nullptr;
305     }
306 
307     int length() const {
308       return (_deps_dyn != nullptr ? _deps_dyn->length()
309               : _deps   != nullptr ? _deps->length()
310               : 0);
311     }
312     E* adr_at(int i) const {
313       return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)
314               : _deps   != nullptr ? _deps->adr_at(i)
315               : nullptr);
316     }
317     E at(int i) const {
318       assert(i >= 0 && i < length(), "oob");
319       return *adr_at(i);
320     }
321     bool append_if_missing(E dep) {
322       if (_deps_dyn == nullptr) {
323         _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
324         _deps_dyn->append(dep);
325         return true;
326       } else {
327         return _deps_dyn->append_if_missing(dep);
328       }
329     }
330     bool remove_if_existing(E dep) {
331       if (_deps_dyn != nullptr) {
332         return _deps_dyn->remove_if_existing(dep);
333       }
334       return false;
335     }
336     void clear() {
337       if (_deps_dyn != nullptr)  {
338         _deps_dyn->clear();
339       }
340     }
341     void append(E dep) {
342       if (_deps_dyn == nullptr) {
343         _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
344       }
345       _deps_dyn->append(dep);
346     }
347     bool contains(E dep) {
348       for (int i = 0; i < length(); i++) {
349         if (dep == at(i)) {
350           return true; // found
351         }
352       }
353       return false; // not found
354     }
355 
356 #if INCLUDE_CDS
357     void remove_unshareable_info() {
358       _deps_dyn = nullptr;
359     }
360 #endif
361     void prepare(ClassLoaderData* loader_data);
362     void metaspace_pointers_do(MetaspaceClosure *iter);
363   };
364 
365   virtual void metaspace_pointers_do(MetaspaceClosure *iter);
366 
367   static void init_dumptime_table(TRAPS);
368 
369 #if INCLUDE_CDS
370   virtual void remove_unshareable_info() {}
371   static void iterate_roots(MetaspaceClosure* it);
372   static void dump_training_data();
373   static void cleanup_training_data();
374   static void serialize_training_data(SerializeClosure* soc);
375   static void print_archived_training_data_on(outputStream* st);
376   static void write_training_data_dictionary(TrainingDataDictionary* dictionary);
377   static size_t estimate_size_for_archive();
378 
379   static TrainingData* lookup_archived_training_data(const Key* k);
380 #endif
381 
382   template<typename TrainingDataType, typename... ArgTypes>
383   static TrainingDataType* allocate(ArgTypes... args) {
384     assert(need_data() || have_data(), "");
385     if (TrainingDataLocker::can_add()) {
386       return new (mtClassShared) TrainingDataType(args...);
387     }
388     return nullptr;
389   }
390 };
391 
392 // Training data that is associated with an InstanceKlass
393 class KlassTrainingData : public TrainingData {
394   friend TrainingData;
395   friend CompileTrainingData;
396 
397   // Used by CDS. These classes need to access the private default constructor.
398   template <class T> friend class CppVtableTesterA;
399   template <class T> friend class CppVtableTesterB;
400   template <class T> friend class CppVtableCloner;
401 
402   // cross-link to live klass, or null if not loaded or encountered yet
403   InstanceKlass* _holder;
404   jobject _holder_mirror;   // extra link to prevent unloading by GC
405 
406   DepList<CompileTrainingData*> _comp_deps; // compiles that depend on me
407 
408   KlassTrainingData();
409   KlassTrainingData(InstanceKlass* klass);
410 
411   int comp_dep_count() const {
412     TrainingDataLocker::assert_locked();
413     return _comp_deps.length();
414   }
415   CompileTrainingData* comp_dep(int i) const {
416     TrainingDataLocker::assert_locked();
417     return _comp_deps.at(i);
418   }
419   void add_comp_dep(CompileTrainingData* ctd) {
420     TrainingDataLocker::assert_locked();
421      _comp_deps.append_if_missing(ctd);
422   }
423   void remove_comp_dep(CompileTrainingData* ctd) {
424     TrainingDataLocker::assert_locked();
425      _comp_deps.remove_if_existing(ctd);
426   }
427 
428  public:
429   Symbol* name() const {
430     precond(has_holder());
431     return holder()->name();
432   }
433   Symbol* loader_name() const {
434     precond(has_holder());
435     return holder()->class_loader_name_and_id();
436   }
437   bool has_holder()       const { return _holder != nullptr; }
438   InstanceKlass* holder() const { return _holder; }
439 
440   static KlassTrainingData* make(InstanceKlass* holder,
441                                  bool null_if_not_found = false);
442   static KlassTrainingData* find(InstanceKlass* holder) {
443     return make(holder, true);
444   }
445   virtual KlassTrainingData* as_KlassTrainingData() const { return const_cast<KlassTrainingData*>(this); };
446 
447   ClassLoaderData* class_loader_data() {
448     assert(has_holder(), "");
449     return holder()->class_loader_data();
450   }
451   void notice_fully_initialized();
452 
453   void print_on(outputStream* st, bool name_only) const;
454   virtual void print_on(outputStream* st) const { print_on(st, false); }
455   virtual void print_value_on(outputStream* st) const { print_on(st, true); }
456 
457   virtual void prepare(Visitor& visitor);
458   virtual void cleanup(Visitor& visitor) NOT_CDS_RETURN;
459 
460   MetaspaceObj::Type type() const {
461     return KlassTrainingDataType;
462   }
463 
464 #if INCLUDE_CDS
465   virtual void remove_unshareable_info();
466 #endif
467 
468   void metaspace_pointers_do(MetaspaceClosure *iter);
469 
470   int size() const {
471     return (int)align_metadata_size(align_up(sizeof(KlassTrainingData), BytesPerWord)/BytesPerWord);
472   }
473 
474   const char* internal_name() const {
475     return "{ klass training data }";
476   };
477 
478   void verify();
479 
480   static KlassTrainingData* allocate(InstanceKlass* holder) {
481     return TrainingData::allocate<KlassTrainingData>(holder);
482   }
483 
484   template<typename Function>
485   void iterate_comp_deps(Function fn) const { // lambda enabled API
486     TrainingDataLocker l;
487     for (int i = 0; i < comp_dep_count(); i++) {
488       fn(comp_dep(i));
489     }
490   }
491 };
492 
493 // Information about particular JIT tasks.
494 class CompileTrainingData : public TrainingData {
495   friend 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 
507   // classes that should be initialized before this JIT task runs
508   DepList<KlassTrainingData*> _init_deps;
509   // Number of uninitialized classes left, when it's 0, all deps are satisfied
510   volatile int _init_deps_left;
511 
512 public:
513   // ciRecords is a generic meachanism to memoize CI responses to arbitary queries. For each function we're interested in we record
514   // (return_value, argument_values) tuples in a list. Arguments are allowed to have Metaspace pointers in them.
515   class ciRecords {
516     template <typename... Ts> class Arguments {
517     public:
518       bool operator==(const Arguments<>&) const { return true; }
519       void metaspace_pointers_do(MetaspaceClosure *iter) { }
520     };
521     template <typename T, typename... Ts> class Arguments<T, Ts...> {
522     private:
523       T _first;
524       Arguments<Ts...> _remaining;
525 
526     public:
527       constexpr Arguments(const T& first, const Ts&... remaining) noexcept
528         : _first(first), _remaining(remaining...) {}
529       constexpr Arguments() noexcept : _first(), _remaining() {}
530       bool operator==(const Arguments<T, Ts...>& that) const {
531         return _first == that._first && _remaining == that._remaining;
532       }
533       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>
534       void metaspace_pointers_do(MetaspaceClosure *iter) {
535         iter->push(&_first);
536         _remaining.metaspace_pointers_do(iter);
537       }
538       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>
539       void metaspace_pointers_do(MetaspaceClosure *iter) {
540         _remaining.metaspace_pointers_do(iter);
541       }
542     };
543 
544     template <typename ReturnType, typename... Args> class ciMemoizedFunction : public StackObj {
545     public:
546       class OptionalReturnType {
547         bool _valid;
548         ReturnType _result;
549       public:
550         OptionalReturnType(bool valid, const ReturnType& result) : _valid(valid), _result(result) {}
551         bool is_valid() const { return _valid; }
552         ReturnType result() const { return _result; }
553       };
554     private:
555       typedef Arguments<Args...> ArgumentsType;
556       class Record : public MetaspaceObj {
557         ReturnType    _result;
558         ArgumentsType _arguments;
559       public:
560         Record(const ReturnType& result, const ArgumentsType& arguments) : _result(result), _arguments(arguments) {}
561         Record() { }
562         ReturnType result() const { return _result; }
563         ArgumentsType arguments() const { return _arguments; }
564         bool operator==(const Record& that) { return _arguments == that._arguments; }
565         void metaspace_pointers_do(MetaspaceClosure *iter) { _arguments.metaspace_pointers_do(iter); }
566       };
567       DepList<Record> _data;
568     public:
569       OptionalReturnType find(const Args&... args) {
570         ArgumentsType a(args...);
571         for (int i = 0; i < _data.length(); i++) {
572           if (_data.at(i).arguments() == a) {
573             return OptionalReturnType(true, _data.at(i).result());
574           }
575         }
576         return OptionalReturnType(false, ReturnType());
577       }
578       bool append_if_missing(const ReturnType& result, const Args&... args) {
579         return _data.append_if_missing(Record(result, ArgumentsType(args...)));
580       }
581 #if INCLUDE_CDS
582       void remove_unshareable_info() { _data.remove_unshareable_info(); }
583 #endif
584       void prepare(ClassLoaderData* loader_data) {
585         _data.prepare(loader_data);
586       }
587       void metaspace_pointers_do(MetaspaceClosure *iter) {
588         _data.metaspace_pointers_do(iter);
589       }
590     };
591 
592 
593 public:
594     // Record CI answers for the InlineSmallCode heuristic. It is importance since the heuristic is non-commutative and we may want to
595     // compile methods in a different order than in the training run.
596     typedef ciMemoizedFunction<int, MethodTrainingData*> ciMethod__inline_instructions_size_type;
597     ciMethod__inline_instructions_size_type ciMethod__inline_instructions_size;
598 #if INCLUDE_CDS
599     void remove_unshareable_info() {
600       ciMethod__inline_instructions_size.remove_unshareable_info();
601     }
602 #endif
603     void prepare(ClassLoaderData* loader_data) {
604       ciMethod__inline_instructions_size.prepare(loader_data);
605     }
606     void metaspace_pointers_do(MetaspaceClosure *iter) {
607       ciMethod__inline_instructions_size.metaspace_pointers_do(iter);
608     }
609   };
610 
611 private:
612   ciRecords _ci_records;
613 
614   CompileTrainingData();
615   CompileTrainingData(MethodTrainingData* mtd,
616                       int level,
617                       int compile_id)
618       : TrainingData(),  // empty key
619         _method(mtd), _level(level), _compile_id(compile_id), _init_deps_left(0) { }
620 public:
621   ciRecords& ci_records() { return _ci_records; }
622   static CompileTrainingData* make(CompileTask* task);
623 
624   virtual CompileTrainingData* as_CompileTrainingData() const { return const_cast<CompileTrainingData*>(this); };
625 
626   MethodTrainingData* method() const { return _method; }
627 
628   int level() const { return _level; }
629 
630   int compile_id() const { return _compile_id; }
631 
632   int init_dep_count() const {
633     TrainingDataLocker::assert_locked();
634     return _init_deps.length();
635   }
636   KlassTrainingData* init_dep(int i) const {
637     TrainingDataLocker::assert_locked();
638     return _init_deps.at(i);
639   }
640   void add_init_dep(KlassTrainingData* ktd) {
641     TrainingDataLocker::assert_locked();
642     ktd->add_comp_dep(this);
643     _init_deps.append_if_missing(ktd);
644   }
645   void clear_init_deps() {
646     TrainingDataLocker::assert_locked();
647     for (int i = 0; i < _init_deps.length(); i++) {
648       _init_deps.at(i)->remove_comp_dep(this);
649     }
650     _init_deps.clear();
651   }
652   void dec_init_deps_left(KlassTrainingData* ktd);
653   int init_deps_left() const {
654     return Atomic::load(&_init_deps_left);
655   }
656   uint compute_init_deps_left(bool count_initialized = false);
657 
658   void notice_inlined_method(CompileTask* task, const methodHandle& method);
659 
660   // The JIT looks at classes and objects too and can depend on their state.
661   // These simple calls just report the *possibility* of an observation.
662   void notice_jit_observation(ciEnv* env, ciBaseObject* what);
663 
664   virtual void prepare(Visitor& visitor);
665   virtual void cleanup(Visitor& visitor) NOT_CDS_RETURN;
666 
667   void print_on(outputStream* st, bool name_only) const;
668   virtual void print_on(outputStream* st) const { print_on(st, false); }
669   virtual void print_value_on(outputStream* st) const { print_on(st, true); }
670 
671 #if INCLUDE_CDS
672   virtual void remove_unshareable_info();
673 #endif
674 
675   virtual void metaspace_pointers_do(MetaspaceClosure* iter);
676   virtual MetaspaceObj::Type type() const { return CompileTrainingDataType; }
677 
678   virtual const char* internal_name() const {
679     return "{ compile training data }";
680   };
681 
682   virtual int size() const {
683     return (int)align_metadata_size(align_up(sizeof(CompileTrainingData), BytesPerWord)/BytesPerWord);
684   }
685 
686   void verify();
687 
688   static CompileTrainingData* allocate(MethodTrainingData* mtd, int level, int compile_id) {
689     return TrainingData::allocate<CompileTrainingData>(mtd, level, compile_id);
690   }
691 };
692 
693 // Record information about a method at the time compilation is requested.
694 class MethodTrainingData : public TrainingData {
695   friend TrainingData;
696   friend CompileTrainingData;
697 
698   // Used by CDS. These classes need to access the private default constructor.
699   template <class T> friend class CppVtableTesterA;
700   template <class T> friend class CppVtableTesterB;
701   template <class T> friend class CppVtableCloner;
702 
703   KlassTrainingData* _klass;
704   Method* _holder;
705   CompileTrainingData* _last_toplevel_compiles[CompLevel_count];
706   int _highest_top_level;
707   int _level_mask;  // bit-set of all possible levels
708   bool _was_inlined;
709   bool _was_toplevel;
710   // metadata snapshots of final state:
711   MethodCounters* _final_counters;
712   MethodData*     _final_profile;
713 
714   MethodTrainingData();
715   MethodTrainingData(Method* method, KlassTrainingData* ktd) : TrainingData(method) {
716     _klass = ktd;
717     _holder = method;
718     for (int i = 0; i < CompLevel_count; i++) {
719       _last_toplevel_compiles[i] = nullptr;
720     }
721     _highest_top_level = CompLevel_none;
722     _level_mask = 0;
723     _was_inlined = _was_toplevel = false;
724   }
725 
726   static int level_mask(int level) {
727     return ((level & 0xF) != level ? 0 : 1 << level);
728   }
729   static CompLevel highest_level(int mask) {
730     if (mask == 0)  return (CompLevel) 0;
731     int diff = (count_leading_zeros(level_mask(0)) - count_leading_zeros(mask));
732     return (CompLevel) diff;
733   }
734 
735  public:
736   KlassTrainingData* klass()  const { return _klass; }
737   bool has_holder()           const { return _holder != nullptr; }
738   Method* holder()            const { return _holder; }
739   bool only_inlined()         const { return !_was_toplevel; }
740   bool never_inlined()        const { return !_was_inlined; }
741   bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }
742   int highest_level()         const { return highest_level(_level_mask); }
743   int highest_top_level()     const { return _highest_top_level; }
744   MethodData* final_profile() const { return _final_profile; }
745 
746   Symbol* name() const {
747     precond(has_holder());
748     return holder()->name();
749   }
750   Symbol* signature() const {
751     precond(has_holder());
752     return holder()->signature();
753   }
754 
755   CompileTrainingData* last_toplevel_compile(int level) const {
756     if (level > CompLevel_none) {
757       return _last_toplevel_compiles[level - 1];
758     }
759     return nullptr;
760   }
761 
762   void notice_compilation(int level, bool inlined = false) {
763     if (inlined) {
764       _was_inlined = true;
765     } else {
766       _was_toplevel = true;
767     }
768     _level_mask |= level_mask(level);
769   }
770 
771   static MethodTrainingData* make(const methodHandle& method,
772                                   bool null_if_not_found = false,
773                                   bool use_cache = true);
774   static MethodTrainingData* find_fast(const methodHandle& method) { return make(method, true, true); }
775   static MethodTrainingData* find(const methodHandle& method) { return make(method, true, false); }
776 
777   virtual MethodTrainingData* as_MethodTrainingData() const {
778     return const_cast<MethodTrainingData*>(this);
779   };
780 
781   void print_on(outputStream* st, bool name_only) const;
782   virtual void print_on(outputStream* st) const { print_on(st, false); }
783   virtual void print_value_on(outputStream* st) const { print_on(st, true); }
784 
785   virtual void prepare(Visitor& visitor);
786   virtual void cleanup(Visitor& visitor) NOT_CDS_RETURN;
787 
788   template<typename Function>
789   void iterate_compiles(Function fn) const { // lambda enabled API
790     for (int i = 0; i < CompLevel_count; i++) {
791       CompileTrainingData* ctd = _last_toplevel_compiles[i];
792       if (ctd != nullptr) {
793         fn(ctd);
794       }
795     }
796   }
797 
798   virtual void metaspace_pointers_do(MetaspaceClosure* iter);
799   virtual MetaspaceObj::Type type() const { return MethodTrainingDataType; }
800 
801 #if INCLUDE_CDS
802   virtual void remove_unshareable_info();
803 #endif
804 
805   virtual int size() const {
806     return (int)align_metadata_size(align_up(sizeof(MethodTrainingData), BytesPerWord)/BytesPerWord);
807   }
808 
809   virtual const char* internal_name() const {
810     return "{ method training data }";
811   };
812 
813   void verify();
814 
815   static MethodTrainingData* allocate(Method* m, KlassTrainingData* ktd) {
816     return TrainingData::allocate<MethodTrainingData>(m, ktd);
817   }
818 };
819 #endif // SHARE_OOPS_TRAININGDATA_HPP