/*
 * 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.
 *
 */

#include "cds/aotArtifactFinder.hpp"
#include "cds/aotClassInitializer.hpp"
#include "cds/aotClassLinker.hpp"
#include "cds/aotLogging.hpp"
#include "cds/aotReferenceObjSupport.hpp"
#include "cds/dumpTimeClassInfo.inline.hpp"
#include "cds/heapShared.hpp"
#include "cds/lambdaProxyClassDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "logging/log.hpp"
#include "memory/metaspaceClosure.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/trainingData.hpp"
#include "utilities/resourceHash.hpp"

// All the classes that should be included in the AOT cache (in at least the "allocated" state)
static GrowableArrayCHeap<Klass*, mtClassShared>* _all_cached_classes = nullptr;

// This is a stack that tracks all the AOT-inited classes that are waiting to be passed
// to HeapShared::copy_and_rescan_aot_inited_mirror().
static GrowableArrayCHeap<InstanceKlass*, mtClassShared>* _pending_aot_inited_classes = nullptr;

static const int TABLE_SIZE = 15889; // prime number
using ClassesTable = ResourceHashtable<Klass*, bool, TABLE_SIZE, AnyObj::C_HEAP, mtClassShared>;
static ClassesTable* _seen_classes;       // all classes that have been seen by AOTArtifactFinder
static ClassesTable* _aot_inited_classes; // all classes that need to be AOT-initialized.

void AOTArtifactFinder::initialize() {
  _all_cached_classes = new GrowableArrayCHeap<Klass*, mtClassShared>();
  _pending_aot_inited_classes = new GrowableArrayCHeap<InstanceKlass*, mtClassShared>();
  _seen_classes = new (mtClass)ClassesTable();
  _aot_inited_classes = new (mtClass)ClassesTable();
}

void AOTArtifactFinder::dispose() {
  delete _all_cached_classes;
  delete _seen_classes;
  delete _aot_inited_classes;
  delete _pending_aot_inited_classes;
  _all_cached_classes = nullptr;
  _seen_classes = nullptr;
  _aot_inited_classes = nullptr;
  _pending_aot_inited_classes = nullptr;
}

// Find all Klasses and oops that should be included in the AOT cache. See aotArtifactFinder.hpp
void AOTArtifactFinder::find_artifacts() {
  // Some classes might have been marked as excluded as a side effect of running
  // AOTConstantPoolResolver. Make sure we check all the remaining ones.
  //
  // Note, if a class is not excluded, it does NOT mean it will be automatically included
  // into the AOT cache -- that will be decided by the code below.
  SystemDictionaryShared::finish_exclusion_checks();
  AOTReferenceObjSupport::init_keep_alive_objs_table();

  start_scanning_for_oops();

  // Add the primitive array classes
  for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
    BasicType bt = (BasicType)i;
    if (is_java_primitive(bt)) {
      add_cached_type_array_class(Universe::typeArrayKlass(bt));
    }
  }

#if INCLUDE_CDS_JAVA_HEAP
  // Add the mirrors that aren't associated with a Klass
  //    - primitive mirrors (E.g., "int.class" in Java code)
  //    - mirror of fillerArrayKlass
  if (CDSConfig::is_dumping_heap()) {
    for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
      BasicType bt = (BasicType)i;
      if (!is_reference_type(bt)) {
        oop orig_mirror = Universe::java_mirror(bt);
        oop scratch_mirror = HeapShared::scratch_java_mirror(bt);
        HeapShared::scan_java_mirror(orig_mirror);
        log_trace(aot, heap, mirror)(
            "Archived %s mirror object from " PTR_FORMAT,
            type2name(bt), p2i(scratch_mirror));
        Universe::set_archived_basic_type_mirror_index(bt, HeapShared::append_root(scratch_mirror));
      }
    }

    // Universe::fillerArrayKlass() isn't in the class hierarchy, so handle it specially.
    HeapShared::scan_java_mirror(Universe::fillerArrayKlass()->java_mirror());
  }
#endif

  // Add all the InstanceKlasses (and their array classes) that are always included.
  SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* ik, DumpTimeClassInfo& info) {
    // Skip "AOT tooling classes" in this block. They will be included in the AOT cache only if
    // - One of their subtypes is included
    // - One of their instances is found by HeapShared.
    if (!info.is_excluded() && !info.is_aot_tooling_class()) {
      bool add = false;
      if (!ik->is_hidden()) {
        // All non-hidden classes are always included into the AOT cache
        add = true;
      } else {
        if (CDSConfig::is_dumping_lambdas_in_legacy_mode()) {
          // Legacy support of lambda proxies -- these are always included into the AOT cache
          if (LambdaProxyClassDictionary::is_registered_lambda_proxy_class(ik)) {
            add = true;
          }
        } else {
          assert(!LambdaProxyClassDictionary::is_registered_lambda_proxy_class(ik),
                 "registered lambda proxies are only for legacy lambda proxy support");
        }
      }

      if (add) {
        add_cached_instance_class(ik);
        if (AOTClassInitializer::can_archive_initialized_mirror(ik)) {
          add_aot_inited_class(ik);
        }
      }
    }
  });

#if INCLUDE_CDS_JAVA_HEAP
  // Keep scanning until we discover no more class that need to be AOT-initialized.
  if (CDSConfig::is_initing_classes_at_dump_time()) {
    while (_pending_aot_inited_classes->length() > 0) {
      InstanceKlass* ik = _pending_aot_inited_classes->pop();
      HeapShared::copy_and_rescan_aot_inited_mirror(ik);
    }
  }
#endif

  // Exclude all the (hidden) classes that have not been discovered by the code above.
  SystemDictionaryShared::dumptime_table()->iterate_all_live_classes([&] (InstanceKlass* k, DumpTimeClassInfo& info) {
    if (!info.is_excluded() && _seen_classes->get(k) == nullptr) {
      info.set_excluded();
      info.set_has_checked_exclusion();
      if (aot_log_is_enabled(Debug, aot)) {
        ResourceMark rm;
        aot_log_debug(aot)("Skipping %s: %s class", k->name()->as_C_string(),
                      k->is_hidden() ? "Unreferenced hidden" : "AOT tooling");
      }
    }
  });

  end_scanning_for_oops();

  TrainingData::cleanup_training_data();
}

void AOTArtifactFinder::start_scanning_for_oops() {
#if INCLUDE_CDS_JAVA_HEAP
  if (CDSConfig::is_dumping_heap()) {
    HeapShared::start_scanning_for_oops();
  }
#endif
}

void AOTArtifactFinder::end_scanning_for_oops() {
#if INCLUDE_CDS_JAVA_HEAP
  if (CDSConfig::is_dumping_heap()) {
    HeapShared::end_scanning_for_oops();
  }
#endif
}

void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) {
  if (CDSConfig::is_initing_classes_at_dump_time()) {
    assert(ik->is_initialized(), "must be");
    add_cached_instance_class(ik);

    bool created;
    _aot_inited_classes->put_if_absent(ik, &created);
    if (created) {
      _pending_aot_inited_classes->push(ik);

      InstanceKlass* s = ik->java_super();
      if (s != nullptr) {
        add_aot_inited_class(s);
      }

      Array<InstanceKlass*>* interfaces = ik->local_interfaces();
      int len = interfaces->length();
      for (int i = 0; i < len; i++) {
        InstanceKlass* intf = interfaces->at(i);
        if (intf->is_initialized()) {
          add_aot_inited_class(intf);
        }
      }
    }
  }
}

void AOTArtifactFinder::append_to_all_cached_classes(Klass* k) {
  precond(!SystemDictionaryShared::should_be_excluded(k));
  _all_cached_classes->append(k);
}

void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) {
  if (CDSConfig::is_dumping_dynamic_archive() && ik->is_shared()) {
    // This class is already included in the base archive. No need to cache
    // it again in the dynamic archive.
    return;
  }

  bool created;
  _seen_classes->put_if_absent(ik, &created);
  if (created) {
    append_to_all_cached_classes(ik);

    // All super types must be added.
    InstanceKlass* s = ik->java_super();
    if (s != nullptr) {
      add_cached_instance_class(s);
    }

    Array<InstanceKlass*>* interfaces = ik->local_interfaces();
    int len = interfaces->length();
    for (int i = 0; i < len; i++) {
      InstanceKlass* intf = interfaces->at(i);
      add_cached_instance_class(intf);
    }

    if (CDSConfig::is_dumping_final_static_archive() && ik->defined_by_other_loaders()) {
      // The following are not appliable to unregistered classes
      return;
    }
    scan_oops_in_instance_class(ik);
    if (ik->is_hidden() && CDSConfig::is_initing_classes_at_dump_time()) {
      bool succeed = AOTClassLinker::try_add_candidate(ik);
      guarantee(succeed, "All cached hidden classes must be aot-linkable");
      add_aot_inited_class(ik);
    }
  }
}

void AOTArtifactFinder::add_cached_type_array_class(TypeArrayKlass* tak) {
  bool created;
  _seen_classes->put_if_absent(tak, &created);
  if (created) {
    append_to_all_cached_classes(tak);
    scan_oops_in_array_class(tak);
  }
}

void AOTArtifactFinder::add_cached_class(Klass* k) {
  if (k->is_typeArray_klass()) {
    add_cached_type_array_class(TypeArrayKlass::cast(k));
  } else if (k->is_objArray_klass()) {
    add_cached_class(ObjArrayKlass::cast(k)->element_klass());
  } else {
    add_cached_instance_class(InstanceKlass::cast(k));
  }
}

void AOTArtifactFinder::scan_oops_in_instance_class(InstanceKlass* ik) {
#if INCLUDE_CDS_JAVA_HEAP
  if (CDSConfig::is_dumping_heap()) {
    HeapShared::scan_java_class(ik);
    scan_oops_in_array_class(ik->array_klasses());
  }
#endif
}

void AOTArtifactFinder::scan_oops_in_array_class(ArrayKlass* ak) {
#if INCLUDE_CDS_JAVA_HEAP
  if (CDSConfig::is_dumping_heap()) {
    while (ak != nullptr) {
      HeapShared::scan_java_class(ak);
      ak = ak->array_klass_or_null();
    }
  }
#endif
}

void AOTArtifactFinder::all_cached_classes_do(MetaspaceClosure* it) {
  for (int i = 0; i < _all_cached_classes->length(); i++) {
    it->push(_all_cached_classes->adr_at(i));
  }
}
