/*
 * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

#ifndef SHARE_OOPS_TRAININGDATA_HPP
#define SHARE_OOPS_TRAININGDATA_HPP

#include "cds/cdsConfig.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/compactHashtable.hpp"
#include "compiler/compilerDefinitions.hpp"
#include "compiler/compiler_globals.hpp"
#include "memory/allocation.hpp"
#include "memory/metaspaceClosure.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/method.hpp"
#include "oops/objArrayKlass.hpp"
#include "runtime/handles.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/resizeableResourceHash.hpp"

class ciEnv;
class ciBaseObject;
class CompileTask;
class CompileTrainingData;
class KlassTrainingData;
class MethodTrainingData;

// Base class for all the training data varieties
class TrainingData : public Metadata {
  friend KlassTrainingData;
  friend MethodTrainingData;
  friend CompileTrainingData;
public:
  // Key is used to insert any TrainingData (TD) object into a hash tables. The key is currently a
  // pointer to a metaspace object the TD is associated with. For example,
  // for KlassTrainingData it's an InstanceKlass, for MethodTrainingData it's a Method.
  // The utility of the these hash tables is to be able to find a TD object for a given metaspace
  // metaspace object.
  class Key {
    mutable Metadata* _meta;
    // These guys can get to my constructors:
    friend TrainingData;
    friend KlassTrainingData;
    friend MethodTrainingData;
    friend CompileTrainingData;

    // The empty key
    Key() : _meta(nullptr) { }
    bool is_empty() const { return _meta == nullptr; }
  public:
    Key(Metadata* meta) : _meta(meta) { }

    static bool can_compute_cds_hash(const Key* const& k);
    static uint cds_hash(const Key* const& k);
    static unsigned hash(const Key* const& k) {
      return primitive_hash(k->meta());
    }
    static bool equals(const Key* const& k1, const Key* const& k2) {
      return k1->meta() == k2->meta();
    }
    static inline bool equals(TrainingData* value, const TrainingData::Key* key, int unused) {
      return equals(value->key(), key);
    }
    int cmp(const Key* that) const {
      auto m1 = this->meta();
      auto m2 = that->meta();
      if (m1 < m2) return -1;
      if (m1 > m2) return +1;
      return 0;
    }
    Metadata* meta() const { return _meta; }
    void metaspace_pointers_do(MetaspaceClosure *iter);
    void make_empty() const { _meta = nullptr; }
  };

  // TrainingDataLocker is used to guard read/write operations on non-MT-safe data structures.
  // It supports recursive locking and a read-only mode (in which case no locks are taken).
  // It is also a part of the TD collection termination protocol (see the "snapshot" field).
  class TrainingDataLocker {
#if INCLUDE_CDS
    static volatile bool _snapshot; // If true we're not allocating new training data
#endif
    static int _lock_mode;
    const bool _recursive;
    static void lock() {
#if INCLUDE_CDS
      assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
      if (_lock_mode > 0) {
        TrainingData_lock->lock_without_safepoint_check();
      }
#endif
    }
    static void unlock() {
#if INCLUDE_CDS
      if (_lock_mode > 0) {
        TrainingData_lock->unlock();
      }
#endif
    }
    static bool safely_locked() {
#if INCLUDE_CDS
      assert(_lock_mode != 0, "Forgot to call TrainingDataLocker::initialize()");
      if (_lock_mode > 0) {
        return is_self_locked();
      } else {
        return true;
      }
#else
      return true;
#endif
    }
    static bool is_self_locked() {
      return CDS_ONLY(TrainingData_lock->owned_by_self()) NOT_CDS(false);
    }

  public:
    static void snapshot() {
#if INCLUDE_CDS
      assert_locked();
      _snapshot = true;
#endif
    }
    static bool can_add() {
#if INCLUDE_CDS
      assert_locked();
      return !_snapshot;
#else
      return false;
#endif
    }
    static void initialize() {
#if INCLUDE_CDS
      _lock_mode = need_data() ? +1 : -1;   // if -1, we go lock-free
#endif
    }
    static void assert_locked_or_snapshotted() {
#if INCLUDE_CDS
      assert(safely_locked() || _snapshot, "use under TrainingDataLocker or after snapshot");
#endif
    }
    static void assert_locked() {
      assert(safely_locked(), "use under TrainingDataLocker");
    }
    static void assert_can_add() {
      assert(can_add(), "Cannot add TrainingData objects");
    }
    TrainingDataLocker() : _recursive(is_self_locked()) {
      if (!_recursive) {
        lock();
      }
    }
    ~TrainingDataLocker() {
      if (!_recursive) {
        unlock();
      }
    }
  };

  // A set of TD objects that we collect during the training run.
  class TrainingDataSet {
    friend TrainingData;
    ResizeableResourceHashtable<const Key*, TrainingData*,
                                AnyObj::C_HEAP, MemTag::mtCompiler,
                                &TrainingData::Key::hash,
                                &TrainingData::Key::equals>
      _table;

  public:
    template<typename... Arg>
    TrainingDataSet(Arg... arg)
      : _table(arg...) {
    }
    TrainingData* find(const Key* key) const {
      TrainingDataLocker::assert_locked();
      if (TrainingDataLocker::can_add()) {
        auto res = _table.get(key);
        return res == nullptr ? nullptr : *res;
      }
      return nullptr;
    }
    bool remove(const Key* key) {
      return _table.remove(key);
    }
    TrainingData* install(TrainingData* td) {
      TrainingDataLocker::assert_locked();
      TrainingDataLocker::assert_can_add();
      auto key = td->key();
      if (key->is_empty()) {
        return td;  // unkeyed TD not installed
      }
      bool created = false;
      auto prior = _table.put_if_absent(key, td, &created);
      if (prior == nullptr || *prior == td) {
        return td;
      }
      assert(false, "no pre-existing elements allowed");
      return *prior;
    }
    template<typename Function>
    void iterate(const Function& fn) const { // lambda enabled API
      iterate(const_cast<Function&>(fn));
    }
    template<typename Function>
    void iterate(Function& fn) const { // lambda enabled API
      return _table.iterate_all([&](const TrainingData::Key* k, TrainingData* td) { fn(td); });
    }
    int size() const { return _table.number_of_entries(); }

    void verify() const {
      TrainingDataLocker::assert_locked();
      iterate([&](TrainingData* td) { td->verify(); });
    }
  };

  // A widget to ensure that we visit TD object only once (TD objects can have pointer to
  // other TD object that are sometimes circular).
  class Visitor {
    ResizeableResourceHashtable<TrainingData*, bool> _visited;
  public:
    Visitor(unsigned size) : _visited(size, 0x3fffffff) { }
    bool is_visited(TrainingData* td) {
      return _visited.contains(td);
    }
    void visit(TrainingData* td) {
      bool created;
      _visited.put_if_absent(td, &created);
    }
  };

  typedef OffsetCompactHashtable<const TrainingData::Key*, TrainingData*, TrainingData::Key::equals> TrainingDataDictionary;
private:
  Key _key;

  // just forward all constructor arguments to the embedded key
  template<typename... Arg>
  TrainingData(Arg... arg)
    : _key(arg...) { }

  // Container for recording TD during training run
  static TrainingDataSet _training_data_set;
  // Containter for replaying the training data (read-only, populated from the AOT image)
  static TrainingDataDictionary _archived_training_data_dictionary;
  // Container used for writing the AOT image
  static TrainingDataDictionary _archived_training_data_dictionary_for_dumping;
  class DumpTimeTrainingDataInfo {
    TrainingData* _training_data;
  public:
    DumpTimeTrainingDataInfo() : DumpTimeTrainingDataInfo(nullptr) {}
    DumpTimeTrainingDataInfo(TrainingData* training_data) : _training_data(training_data) {}
    void metaspace_pointers_do(MetaspaceClosure* it) {
      it->push(&_training_data);
    }
    TrainingData* training_data() {
      return _training_data;
    }
  };
  typedef GrowableArrayCHeap<DumpTimeTrainingDataInfo, mtClassShared> DumptimeTrainingDataDictionary;
  // A temporary container that is used to accumulate and filter TD during dumping
  static DumptimeTrainingDataDictionary* _dumptime_training_data_dictionary;

  static TrainingDataSet* training_data_set() { return &_training_data_set; }
  static TrainingDataDictionary* archived_training_data_dictionary() { return &_archived_training_data_dictionary; }

 public:
  // Returns the key under which this TD is installed, or else
  // Key::EMPTY if it is not installed.
  const Key* key() const { return &_key; }

  static bool have_data() { return AOTReplayTraining;  } // Going to read
  static bool need_data() { return AOTRecordTraining;  } // Going to write
  static bool assembling_data() { return have_data() && CDSConfig::is_dumping_final_static_archive() && CDSConfig::is_dumping_aot_linked_classes(); }

  static bool is_klass_loaded(Klass* k) {
    if (have_data()) {
      // If we're running in AOT mode some classes may not be loaded yet
      if (k->is_objArray_klass()) {
        k = ObjArrayKlass::cast(k)->bottom_klass();
      }
      if (k->is_instance_klass()) {
        return InstanceKlass::cast(k)->is_loaded();
      }
    }
    return true;
  }

  template<typename Function>
  static void iterate(const Function& fn) { iterate(const_cast<Function&>(fn)); }

  template<typename Function>
  static void iterate(Function& fn) { // lambda enabled API
    TrainingDataLocker l;
    if (have_data()) {
      archived_training_data_dictionary()->iterate(fn);
    }
    if (need_data()) {
      training_data_set()->iterate(fn);
    }
  }

  virtual MethodTrainingData*   as_MethodTrainingData()  const { return nullptr; }
  virtual KlassTrainingData*    as_KlassTrainingData()   const { return nullptr; }
  virtual CompileTrainingData*  as_CompileTrainingData() const { return nullptr; }
  bool is_MethodTrainingData()  const { return as_MethodTrainingData()  != nullptr; }
  bool is_KlassTrainingData()   const { return as_KlassTrainingData()   != nullptr; }
  bool is_CompileTrainingData() const { return as_CompileTrainingData() != nullptr; }

  virtual void prepare(Visitor& visitor) = 0;
  virtual void cleanup(Visitor& visitor) = 0;

  static void initialize() NOT_CDS_RETURN;

  static void verify();

  // Widget for recording dependencies, as an N-to-M graph relation,
  // possibly cyclic.
  template<typename E>
  class DepList : public StackObj {
    GrowableArrayCHeap<E, mtCompiler>* _deps_dyn;
    Array<E>*                          _deps;
  public:
    DepList() {
      _deps_dyn = nullptr;
      _deps = nullptr;
    }

    int length() const {
      TrainingDataLocker::assert_locked_or_snapshotted();
      return (_deps_dyn != nullptr ? _deps_dyn->length()
              : _deps   != nullptr ? _deps->length()
              : 0);
    }
    E* adr_at(int i) const {
      TrainingDataLocker::assert_locked_or_snapshotted();
      return (_deps_dyn != nullptr ? _deps_dyn->adr_at(i)
              : _deps   != nullptr ? _deps->adr_at(i)
              : nullptr);
    }
    E at(int i) const {
      TrainingDataLocker::assert_locked_or_snapshotted();
      assert(i >= 0 && i < length(), "oob");
      return *adr_at(i);
    }
    bool append_if_missing(E dep) {
      TrainingDataLocker::assert_can_add();
      if (_deps_dyn == nullptr) {
        _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
        _deps_dyn->append(dep);
        return true;
      } else {
        return _deps_dyn->append_if_missing(dep);
      }
    }
    bool remove_if_existing(E dep) {
      TrainingDataLocker::assert_can_add();
      if (_deps_dyn != nullptr) {
        return _deps_dyn->remove_if_existing(dep);
      }
      return false;
    }
    void clear() {
      TrainingDataLocker::assert_can_add();
      if (_deps_dyn != nullptr)  {
        _deps_dyn->clear();
      }
    }
    void append(E dep) {
      TrainingDataLocker::assert_can_add();
      if (_deps_dyn == nullptr) {
        _deps_dyn = new GrowableArrayCHeap<E, mtCompiler>(10);
      }
      _deps_dyn->append(dep);
    }
    bool contains(E dep) {
      TrainingDataLocker::assert_locked();
      for (int i = 0; i < length(); i++) {
        if (dep == at(i)) {
          return true; // found
        }
      }
      return false; // not found
    }

#if INCLUDE_CDS
    void remove_unshareable_info() {
      _deps_dyn = nullptr;
    }
#endif
    void prepare(ClassLoaderData* loader_data);
    void metaspace_pointers_do(MetaspaceClosure *iter);
  };

  virtual void metaspace_pointers_do(MetaspaceClosure *iter);

  static void init_dumptime_table(TRAPS);

#if INCLUDE_CDS
  virtual void remove_unshareable_info() {}
  static void iterate_roots(MetaspaceClosure* it);
  static void dump_training_data();
  static void cleanup_training_data();
  static void serialize(SerializeClosure* soc);
  static void print_archived_training_data_on(outputStream* st);
  static TrainingData* lookup_archived_training_data(const Key* k);
#endif

  template<typename TrainingDataType, typename... ArgTypes>
  static TrainingDataType* allocate(ArgTypes... args) {
    assert(need_data() || have_data(), "");
    if (TrainingDataLocker::can_add()) {
      return new (mtClassShared) TrainingDataType(args...);
    }
    return nullptr;
  }
};

// Training data that is associated with an InstanceKlass
class KlassTrainingData : public TrainingData {
  friend TrainingData;
  friend CompileTrainingData;

  // Used by CDS. These classes need to access the private default constructor.
  template <class T> friend class CppVtableTesterA;
  template <class T> friend class CppVtableTesterB;
  template <class T> friend class CppVtableCloner;

  // cross-link to live klass, or null if not loaded or encountered yet
  InstanceKlass* _holder;
  jobject _holder_mirror;   // extra link to prevent unloading by GC

  DepList<CompileTrainingData*> _comp_deps; // compiles that depend on me

  KlassTrainingData();
  KlassTrainingData(InstanceKlass* klass);

  int comp_dep_count() const {
    TrainingDataLocker::assert_locked();
    return _comp_deps.length();
  }
  CompileTrainingData* comp_dep(int i) const {
    TrainingDataLocker::assert_locked();
    return _comp_deps.at(i);
  }
  void add_comp_dep(CompileTrainingData* ctd) {
    TrainingDataLocker::assert_locked();
     _comp_deps.append_if_missing(ctd);
  }
  void remove_comp_dep(CompileTrainingData* ctd) {
    TrainingDataLocker::assert_locked();
     _comp_deps.remove_if_existing(ctd);
  }

 public:
  Symbol* name() const {
    precond(has_holder());
    return holder()->name();
  }
  bool has_holder()       const { return _holder != nullptr; }
  InstanceKlass* holder() const { return _holder; }

  static KlassTrainingData* make(InstanceKlass* holder,
                                 bool null_if_not_found = false) NOT_CDS_RETURN_(nullptr);
  static KlassTrainingData* find(InstanceKlass* holder) {
    return make(holder, true);
  }
  virtual KlassTrainingData* as_KlassTrainingData() const { return const_cast<KlassTrainingData*>(this); };

  ClassLoaderData* class_loader_data() {
    assert(has_holder(), "");
    return holder()->class_loader_data();
  }
  void notice_fully_initialized() NOT_CDS_RETURN;

  void print_on(outputStream* st, bool name_only) const;
  virtual void print_on(outputStream* st) const { print_on(st, false); }
  virtual void print_value_on(outputStream* st) const { print_on(st, true); }

  virtual void prepare(Visitor& visitor);
  virtual void cleanup(Visitor& visitor) NOT_CDS_RETURN;

  MetaspaceObj::Type type() const {
    return KlassTrainingDataType;
  }

#if INCLUDE_CDS
  virtual void remove_unshareable_info();
#endif

  void metaspace_pointers_do(MetaspaceClosure *iter);

  int size() const {
    return (int)align_metadata_size(align_up(sizeof(KlassTrainingData), BytesPerWord)/BytesPerWord);
  }

  const char* internal_name() const {
    return "{ klass training data }";
  };

  void verify();

  static KlassTrainingData* allocate(InstanceKlass* holder) {
    return TrainingData::allocate<KlassTrainingData>(holder);
  }

  template<typename Function>
  void iterate_comp_deps(Function fn) const { // lambda enabled API
    TrainingDataLocker l;
    for (int i = 0; i < comp_dep_count(); i++) {
      fn(comp_dep(i));
    }
  }
};

// Information about particular JIT tasks.
class CompileTrainingData : public TrainingData {
  friend TrainingData;
  friend KlassTrainingData;

  // Used by CDS. These classes need to access the private default constructor.
  template <class T> friend class CppVtableTesterA;
  template <class T> friend class CppVtableTesterB;
  template <class T> friend class CppVtableCloner;

  MethodTrainingData* _method;
  const short _level;
  const int _compile_id;

  // classes that should be initialized before this JIT task runs
  DepList<KlassTrainingData*> _init_deps;
  // Number of uninitialized classes left, when it's 0, all deps are satisfied
  volatile int _init_deps_left;

public:
  // ciRecords is a generic meachanism to memoize CI responses to arbitary queries. For each function we're interested in we record
  // (return_value, argument_values) tuples in a list. Arguments are allowed to have Metaspace pointers in them.
  class ciRecords {
    template <typename... Ts> class Arguments {
    public:
      bool operator==(const Arguments<>&) const { return true; }
      void metaspace_pointers_do(MetaspaceClosure *iter) { }
    };
    template <typename T, typename... Ts> class Arguments<T, Ts...> {
    private:
      T _first;
      Arguments<Ts...> _remaining;

    public:
      constexpr Arguments(const T& first, const Ts&... remaining) noexcept
        : _first(first), _remaining(remaining...) {}
      constexpr Arguments() noexcept : _first(), _remaining() {}
      bool operator==(const Arguments<T, Ts...>& that) const {
        return _first == that._first && _remaining == that._remaining;
      }
      template<typename U = T, ENABLE_IF(std::is_pointer<U>::value && std::is_base_of<MetaspaceObj, typename std::remove_pointer<U>::type>::value)>
      void metaspace_pointers_do(MetaspaceClosure *iter) {
        iter->push(&_first);
        _remaining.metaspace_pointers_do(iter);
      }
      template<typename U = T, ENABLE_IF(!(std::is_pointer<U>::value && std::is_base_of<MetaspaceObj, typename std::remove_pointer<U>::type>::value))>
      void metaspace_pointers_do(MetaspaceClosure *iter) {
        _remaining.metaspace_pointers_do(iter);
      }
    };

    template <typename ReturnType, typename... Args> class ciMemoizedFunction : public StackObj {
    public:
      class OptionalReturnType {
        bool _valid;
        ReturnType _result;
      public:
        OptionalReturnType(bool valid, const ReturnType& result) : _valid(valid), _result(result) {}
        bool is_valid() const { return _valid; }
        ReturnType result() const { return _result; }
      };
    private:
      typedef Arguments<Args...> ArgumentsType;
      class Record : public MetaspaceObj {
        ReturnType    _result;
        ArgumentsType _arguments;
      public:
        Record(const ReturnType& result, const ArgumentsType& arguments) : _result(result), _arguments(arguments) {}
        Record() { }
        ReturnType result() const { return _result; }
        ArgumentsType arguments() const { return _arguments; }
        bool operator==(const Record& that) { return _arguments == that._arguments; }
        void metaspace_pointers_do(MetaspaceClosure *iter) { _arguments.metaspace_pointers_do(iter); }
      };
      DepList<Record> _data;
    public:
      OptionalReturnType find(const Args&... args) {
        TrainingDataLocker l;
        ArgumentsType a(args...);
        for (int i = 0; i < _data.length(); i++) {
          if (_data.at(i).arguments() == a) {
            return OptionalReturnType(true, _data.at(i).result());
          }
        }
        return OptionalReturnType(false, ReturnType());
      }
      void append_if_missing(const ReturnType& result, const Args&... args) {
        TrainingDataLocker l;
        if (l.can_add()) {
          _data.append_if_missing(Record(result, ArgumentsType(args...)));
        }
      }
#if INCLUDE_CDS
      void remove_unshareable_info() { _data.remove_unshareable_info(); }
#endif
      void prepare(ClassLoaderData* loader_data) {
        _data.prepare(loader_data);
      }
      void metaspace_pointers_do(MetaspaceClosure *iter) {
        _data.metaspace_pointers_do(iter);
      }
    };


public:
    // Record CI answers for the InlineSmallCode heuristic. It is importance since the heuristic is non-commutative and we may want to
    // compile methods in a different order than in the training run.
    typedef ciMemoizedFunction<int, MethodTrainingData*> ciMethod__inline_instructions_size_type;
    ciMethod__inline_instructions_size_type ciMethod__inline_instructions_size;
#if INCLUDE_CDS
    void remove_unshareable_info() {
      ciMethod__inline_instructions_size.remove_unshareable_info();
    }
#endif
    void prepare(ClassLoaderData* loader_data) {
      ciMethod__inline_instructions_size.prepare(loader_data);
    }
    void metaspace_pointers_do(MetaspaceClosure *iter) {
      ciMethod__inline_instructions_size.metaspace_pointers_do(iter);
    }
  };

private:
  ciRecords _ci_records;

  CompileTrainingData();
  CompileTrainingData(MethodTrainingData* mtd,
                      int level,
                      int compile_id)
      : TrainingData(),  // empty key
        _method(mtd), _level(level), _compile_id(compile_id), _init_deps_left(0) { }
public:
  ciRecords& ci_records() { return _ci_records; }
  static CompileTrainingData* make(CompileTask* task) NOT_CDS_RETURN_(nullptr);

  virtual CompileTrainingData* as_CompileTrainingData() const { return const_cast<CompileTrainingData*>(this); };

  MethodTrainingData* method() const { return _method; }

  int level() const { return _level; }

  int compile_id() const { return _compile_id; }

  int init_dep_count() const {
    TrainingDataLocker::assert_locked();
    return _init_deps.length();
  }
  KlassTrainingData* init_dep(int i) const {
    TrainingDataLocker::assert_locked();
    return _init_deps.at(i);
  }
  void add_init_dep(KlassTrainingData* ktd) {
    TrainingDataLocker::assert_locked();
    ktd->add_comp_dep(this);
    _init_deps.append_if_missing(ktd);
  }
  void clear_init_deps() {
    TrainingDataLocker::assert_locked();
    for (int i = 0; i < _init_deps.length(); i++) {
      _init_deps.at(i)->remove_comp_dep(this);
    }
    _init_deps.clear();
  }
  void dec_init_deps_left(KlassTrainingData* ktd);
  int init_deps_left() const {
    return Atomic::load(&_init_deps_left);
  }
  uint compute_init_deps_left(bool count_initialized = false);

  void notice_inlined_method(CompileTask* task, const methodHandle& method) NOT_CDS_RETURN;

  // The JIT looks at classes and objects too and can depend on their state.
  // These simple calls just report the *possibility* of an observation.
  void notice_jit_observation(ciEnv* env, ciBaseObject* what) NOT_CDS_RETURN;

  virtual void prepare(Visitor& visitor);
  virtual void cleanup(Visitor& visitor) NOT_CDS_RETURN;

  void print_on(outputStream* st, bool name_only) const;
  virtual void print_on(outputStream* st) const { print_on(st, false); }
  virtual void print_value_on(outputStream* st) const { print_on(st, true); }

#if INCLUDE_CDS
  virtual void remove_unshareable_info();
#endif

  virtual void metaspace_pointers_do(MetaspaceClosure* iter);
  virtual MetaspaceObj::Type type() const { return CompileTrainingDataType; }

  virtual const char* internal_name() const {
    return "{ compile training data }";
  };

  virtual int size() const {
    return (int)align_metadata_size(align_up(sizeof(CompileTrainingData), BytesPerWord)/BytesPerWord);
  }

  void verify();

  static CompileTrainingData* allocate(MethodTrainingData* mtd, int level, int compile_id) {
    return TrainingData::allocate<CompileTrainingData>(mtd, level, compile_id);
  }
};

// Record information about a method at the time compilation is requested.
class MethodTrainingData : public TrainingData {
  friend TrainingData;
  friend CompileTrainingData;

  // Used by CDS. These classes need to access the private default constructor.
  template <class T> friend class CppVtableTesterA;
  template <class T> friend class CppVtableTesterB;
  template <class T> friend class CppVtableCloner;

  KlassTrainingData* _klass;
  Method* _holder;
  CompileTrainingData* _last_toplevel_compiles[CompLevel_count - 1];
  int _highest_top_level;
  int _level_mask;  // bit-set of all possible levels
  bool _was_toplevel;
  // metadata snapshots of final state:
  MethodCounters* _final_counters;
  MethodData*     _final_profile;

  MethodTrainingData();
  MethodTrainingData(Method* method, KlassTrainingData* ktd) : TrainingData(method) {
    _klass = ktd;
    _holder = method;
    for (int i = 0; i < CompLevel_count - 1; i++) {
      _last_toplevel_compiles[i] = nullptr;
    }
    _highest_top_level = CompLevel_none;
    _level_mask = 0;
    _was_toplevel = false;
  }

  static int level_mask(int level) {
    return ((level & 0xF) != level ? 0 : 1 << level);
  }

 public:
  KlassTrainingData* klass()  const { return _klass; }
  bool has_holder()           const { return _holder != nullptr; }
  Method* holder()            const { return _holder; }
  bool only_inlined()         const { return !_was_toplevel; }
  bool saw_level(CompLevel l) const { return (_level_mask & level_mask(l)) != 0; }
  int highest_top_level()     const { return _highest_top_level; }
  MethodData* final_profile() const { return _final_profile; }

  Symbol* name() const {
    precond(has_holder());
    return holder()->name();
  }
  Symbol* signature() const {
    precond(has_holder());
    return holder()->signature();
  }

  CompileTrainingData* last_toplevel_compile(int level) const {
    if (level > CompLevel_none) {
      return _last_toplevel_compiles[level - 1];
    }
    return nullptr;
  }

  void notice_compilation(int level, bool inlined = false) {
    if (!inlined) {
      _was_toplevel = true;
    }
    _level_mask |= level_mask(level);
  }

  void notice_toplevel_compilation(int level) {
    _highest_top_level = MAX2(_highest_top_level, level);
  }

  static MethodTrainingData* make(const methodHandle& method,
                                  bool null_if_not_found = false,
                                  bool use_cache = true) NOT_CDS_RETURN_(nullptr);
  static MethodTrainingData* find_fast(const methodHandle& method) { return make(method, true, true); }
  static MethodTrainingData* find(const methodHandle& method) { return make(method, true, false); }

  virtual MethodTrainingData* as_MethodTrainingData() const {
    return const_cast<MethodTrainingData*>(this);
  };

  void print_on(outputStream* st, bool name_only) const;
  virtual void print_on(outputStream* st) const { print_on(st, false); }
  virtual void print_value_on(outputStream* st) const { print_on(st, true); }

  virtual void prepare(Visitor& visitor);
  virtual void cleanup(Visitor& visitor) NOT_CDS_RETURN;

  template<typename Function>
  void iterate_compiles(Function fn) const { // lambda enabled API
    for (int i = 0; i < CompLevel_count - 1; i++) {
      CompileTrainingData* ctd = _last_toplevel_compiles[i];
      if (ctd != nullptr) {
        fn(ctd);
      }
    }
  }

  virtual void metaspace_pointers_do(MetaspaceClosure* iter);
  virtual MetaspaceObj::Type type() const { return MethodTrainingDataType; }

#if INCLUDE_CDS
  virtual void remove_unshareable_info();
#endif

  virtual int size() const {
    return (int)align_metadata_size(align_up(sizeof(MethodTrainingData), BytesPerWord)/BytesPerWord);
  }

  virtual const char* internal_name() const {
    return "{ method training data }";
  };

  void verify();

  static MethodTrainingData* allocate(Method* m, KlassTrainingData* ktd) {
    return TrainingData::allocate<MethodTrainingData>(m, ktd);
  }
};
#endif // SHARE_OOPS_TRAININGDATA_HPP
