/*
 * Copyright (c) 2023, 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/archiveHeapLoader.hpp"
#include "cds/cdsEnumKlass.hpp"
#include "cds/heapShared.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "memory/resourceArea.hpp"
#include "oops/fieldStreams.inline.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/fieldDescriptor.inline.hpp"

#if INCLUDE_CDS_JAVA_HEAP

bool CDSEnumKlass::is_enum_obj(oop orig_obj) {
  Klass* k = orig_obj->klass();
  return k->is_instance_klass() &&
         InstanceKlass::cast(k)->is_enum_subclass();
}

// -- Handling of Enum objects
// Java Enum classes have synthetic <clinit> methods that look like this
//     enum MyEnum {FOO, BAR}
//     MyEnum::<clinint> {
//        /*static final MyEnum*/ MyEnum::FOO = new MyEnum("FOO");
//        /*static final MyEnum*/ MyEnum::BAR = new MyEnum("BAR");
//     }
//
// If MyEnum::FOO object is referenced by any of the archived subgraphs, we must
// ensure the archived value equals (in object address) to the runtime value of
// MyEnum::FOO.
//
// However, since MyEnum::<clinint> is synthetically generated by javac, there's
// no way of programmatically handling this inside the Java code (as you would handle
// ModuleLayer::EMPTY_LAYER, for example).
//
// Instead, we archive all static field of such Enum classes. At runtime,
// HeapShared::initialize_enum_klass() skips the <clinit> method and instead pulls
// the static fields out of the archived heap.
void CDSEnumKlass::handle_enum_obj(int level,
                                   KlassSubGraphInfo* subgraph_info,
                                   oop orig_obj) {
  assert(level > 1, "must never be called at the first (outermost) level");
  assert(is_enum_obj(orig_obj), "must be");

  InstanceKlass* ik = InstanceKlass::cast(orig_obj->klass());
  if (ik->has_archived_enum_objs()) {
    return;
  }

  ik->set_has_archived_enum_objs();

  oop mirror = ik->java_mirror();
  for (JavaFieldStream fs(ik); !fs.done(); fs.next()) {
    if (fs.access_flags().is_static()) {
      archive_static_field(level, subgraph_info, ik, mirror, fs);
    }
  }
}

void CDSEnumKlass::archive_static_field(int level, KlassSubGraphInfo* subgraph_info,
                                        InstanceKlass* ik, oop mirror, JavaFieldStream& fs) {
  ResourceMark rm;
  fieldDescriptor& fd = fs.field_descriptor();
  if (fd.field_type() != T_OBJECT && fd.field_type() != T_ARRAY) {
    guarantee(false, "static field %s::%s must be T_OBJECT or T_ARRAY",
              ik->external_name(), fd.name()->as_C_string());
  }
  oop oop_field = mirror->obj_field(fd.offset());
  if (oop_field == nullptr) {
    guarantee(false, "static field %s::%s must not be null",
              ik->external_name(), fd.name()->as_C_string());
  } else if (oop_field->klass() != ik && oop_field->klass() != ik->array_klass_or_null()) {
    guarantee(false, "static field %s::%s is of the wrong type",
              ik->external_name(), fd.name()->as_C_string());
  }
  bool success = HeapShared::archive_reachable_objects_from(level, subgraph_info, oop_field);
  assert(success, "VM should have exited with unarchivable objects for _level > 1");
  int root_index = HeapShared::append_root(oop_field);
  log_info(aot, heap)("Archived enum obj @%d %s::%s (" INTPTR_FORMAT ")",
                      root_index, ik->external_name(), fd.name()->as_C_string(),
                      p2i((oopDesc*)oop_field));
  SystemDictionaryShared::add_enum_klass_static_field(ik, root_index);
}

bool CDSEnumKlass::initialize_enum_klass(InstanceKlass* k, TRAPS) {
  if (!ArchiveHeapLoader::is_in_use()) {
    return false;
  }

  RunTimeClassInfo* info = RunTimeClassInfo::get_for(k);
  assert(info != nullptr, "sanity");

  if (log_is_enabled(Info, aot, heap)) {
    ResourceMark rm;
    log_info(aot, heap)("Initializing Enum class: %s", k->external_name());
  }

  oop mirror = k->java_mirror();
  int i = 0;
  for (JavaFieldStream fs(k); !fs.done(); fs.next()) {
    if (fs.access_flags().is_static()) {
      int root_index = info->enum_klass_static_field_root_index_at(i++);
      fieldDescriptor& fd = fs.field_descriptor();
      assert(fd.field_type() == T_OBJECT || fd.field_type() == T_ARRAY, "must be");
      mirror->obj_field_put(fd.offset(), HeapShared::get_root(root_index, /*clear=*/true));
    }
  }
  return true;
}
#endif // INCLUDE_CDS_JAVA_HEAP
