/*
 * Copyright (c) 2015, 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/aotConstantPoolResolver.hpp"
#include "cds/aotLogging.hpp"
#include "cds/archiveUtils.hpp"
#include "cds/classListParser.hpp"
#include "cds/lambdaFormInvokers.hpp"
#include "cds/lambdaProxyClassDictionary.hpp"
#include "cds/metaspaceShared.hpp"
#include "cds/unregisteredClasses.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/linkResolver.hpp"
#include "jimage.hpp"
#include "jvm.h"
#include "logging/log.hpp"
#include "logging/logTag.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/constantPool.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/macros.hpp"
#include "utilities/utf8.hpp"

const char* ClassListParser::CONSTANT_POOL_TAG = "@cp";
const char* ClassListParser::LAMBDA_FORM_TAG = "@lambda-form-invoker";
const char* ClassListParser::LAMBDA_PROXY_TAG = "@lambda-proxy";

volatile Thread* ClassListParser::_parsing_thread = nullptr;
ClassListParser* ClassListParser::_instance = nullptr;

ClassListParser::ClassListParser(const char* file, ParseMode parse_mode) :
    _classlist_file(file),
    _id2klass_table(INITIAL_TABLE_SIZE, MAX_TABLE_SIZE),
    _file_input(do_open(file), /* need_close=*/true),
    _input_stream(&_file_input),
    _parse_mode(parse_mode) {
  aot_log_info(aot)("Parsing %s%s", file,
                parse_lambda_forms_invokers_only() ? " (lambda form invokers only)" : "");
  if (!_file_input.is_open()) {
    char reason[JVM_MAXPATHLEN];
    os::lasterror(reason, JVM_MAXPATHLEN);
    vm_exit_during_initialization(err_msg("Loading %s %s failed",
                                          FLAG_IS_DEFAULT(AOTConfiguration) ?
                                          "classlist" : "AOTConfiguration file",
                                          file),
                                  reason);
  }
  _token = _line = nullptr;
  _interfaces = new (mtClass) GrowableArray<int>(10, mtClass);
  _indy_items = new (mtClass) GrowableArray<const char*>(9, mtClass);

  // _instance should only be accessed by the thread that created _instance.
  assert(_instance == nullptr, "must be singleton");
  _instance = this;
  Atomic::store(&_parsing_thread, Thread::current());
}

FILE* ClassListParser::do_open(const char* file) {
  // Use os::open() because neither fopen() nor os::fopen()
  // can handle long path name on Windows. (See JDK-8216184)
  int fd = os::open(file, O_RDONLY, S_IREAD);
  FILE* fp = nullptr;
  if (fd != -1) {
    // Obtain a FILE* from the file descriptor so that _input_stream
    // can be used in ClassListParser::parse()
    fp = os::fdopen(fd, "r");
  }
  return fp;
}

bool ClassListParser::is_parsing_thread() {
  return Atomic::load(&_parsing_thread) == Thread::current();
}

ClassListParser::~ClassListParser() {
  Atomic::store(&_parsing_thread, (Thread*)nullptr);
  delete _indy_items;
  delete _interfaces;
  _instance = nullptr;
}

void ClassListParser::parse_classlist(const char* classlist_path, ParseMode parse_mode, TRAPS) {
  UnregisteredClasses::initialize(CHECK);
  ClassListParser parser(classlist_path, parse_mode);
  parser.parse(THREAD);
}

void ClassListParser::parse(TRAPS) {
  for (; !_input_stream.done(); _input_stream.next()) {
    _line = _input_stream.current_line();
    clean_up_input_line();

    // Each line in the classlist can be one of three forms:
    if (_line[0] == '#') {
      // A comment; ignore it
    } else if (_line[0] == '@') {
      // @xxx - a tag like @lambda-proxy, to be parsed by parse_at_tags()
      parse_at_tags(CHECK);
    } else {
      // A class name, followed by optional attributes. E.g.
      //   java/lang/String
      //   java/lang/Object id: 1
      //   my/pkg/TestClass id: 5 super: 1 interfaces: 3 4 source: foo.jar
      parse_class_name_and_attributes(CHECK);
    }
  }
}

void ClassListParser::parse_class_name_and_attributes(TRAPS) {
  read_class_name_and_attributes();

  if (parse_lambda_forms_invokers_only()) {
    return;
  }

  check_class_name(_class_name);
  TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
  Klass* klass = load_current_class(class_name_symbol, THREAD);
  if (HAS_PENDING_EXCEPTION) {
    if (PENDING_EXCEPTION->is_a(vmClasses::OutOfMemoryError_klass())) {
      // If we have run out of memory, don't try to load the rest of the classes in
      // the classlist. Throw an exception, which will terminate the dumping process.
      return; // THROW
    }

    ResourceMark rm(THREAD);
    char* ex_msg = (char*)"";
    oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
    if (message != nullptr) {
      ex_msg = java_lang_String::as_utf8_string(message);
    }
    aot_log_warning(aot)("%s: %s", PENDING_EXCEPTION->klass()->external_name(), ex_msg);
    // We might have an invalid class name or an bad class. Warn about it
    // and keep going to the next line.
    CLEAR_PENDING_EXCEPTION;
    aot_log_warning(aot)("Preload Warning: Cannot find %s", _class_name);
    return;
  }

  assert(klass != nullptr, "sanity");
  if (aot_log_is_enabled(Trace, aot)) {
    ResourceMark rm(THREAD);
    log_trace(aot)("Shared spaces preloaded: %s", klass->external_name());
  }

  if (klass->is_instance_klass()) {
    InstanceKlass* ik = InstanceKlass::cast(klass);

    // Link the class to cause the bytecodes to be rewritten and the
    // cpcache to be created. The linking is done as soon as classes
    // are loaded in order that the related data structures (klass and
    // cpCache) are located together.
    MetaspaceShared::try_link_class(THREAD, ik);
  }
}

void ClassListParser::clean_up_input_line() {
  int len = (int)strlen(_line);
  int i;
  // Replace \t\r\n\f with ' '
  for (i=0; i<len; i++) {
    if (_line[i] == '\t' || _line[i] == '\r' || _line[i] == '\n' || _line[i] == '\f') {
      _line[i] = ' ';
    }
  }

  // Remove trailing newline/space
  while (len > 0) {
    if (_line[len-1] == ' ') {
      _line[len-1] = '\0';
      len --;
    } else {
      break;
    }
  }
  _line_len = len;
}

void ClassListParser::read_class_name_and_attributes() {
  _class_name = _line;
  _id = _unspecified;
  _super = _unspecified;
  _interfaces->clear();
  _source = nullptr;
  _interfaces_specified = false;

  if ((_token = strchr(_line, ' ')) == nullptr) {
    // No optional attributes are specified.
    return;
  }

  // Mark the end of the name, and go to the next input char
  *_token++ = '\0';

  while (*_token) {
    skip_whitespaces();

    if (parse_uint_option("id:", &_id)) {
      continue;
    } else if (parse_uint_option("super:", &_super)) {
      check_already_loaded("Super class", _super);
      continue;
    } else if (skip_token("interfaces:")) {
      int i;
      while (try_parse_uint(&i)) {
        check_already_loaded("Interface", i);
        _interfaces->append(i);
      }
    } else if (skip_token("source:")) {
      skip_whitespaces();
      _source = _token;
      char* s = strchr(_token, ' ');
      if (s == nullptr) {
        break; // end of input line
      } else {
        *s = '\0'; // mark the end of _source
        _token = s+1;
      }
    } else {
      error("Unknown input");
    }
  }

  // if src is specified
  //     id super interfaces must all be specified
  //     loader may be specified
  // else
  //     # the class is loaded from classpath
  //     id may be specified
  //     super, interfaces, loader must not be specified
}

void ClassListParser::split_tokens_by_whitespace(int offset, GrowableArray<const char*>* items) {
  int start = offset;
  int end;
  bool done = false;
  while (!done) {
    while (_line[start] == ' ' || _line[start] == '\t') start++;
    end = start;
    while (_line[end] && _line[end] != ' ' && _line[end] != '\t') end++;
    if (_line[end] == '\0') {
      done = true;
    } else {
      _line[end] = '\0';
    }
    items->append(_line + start);
    start = ++end;
  }
}

int ClassListParser::split_at_tag_from_line() {
  _token = _line;
  char* ptr;
  if ((ptr = strchr(_line, ' ')) == nullptr) {
    error("Too few items following the @ tag \"%s\" line #%zu", _line, lineno());
    return 0;
  }
  *ptr++ = '\0';
  while (*ptr == ' ' || *ptr == '\t') ptr++;
  return (int)(ptr - _line);
}

void ClassListParser::parse_at_tags(TRAPS) {
  assert(_line[0] == '@', "must be");
  int offset = split_at_tag_from_line();
  assert(offset > 0, "would have exited VM");

  if (strcmp(_token, LAMBDA_PROXY_TAG) == 0) {
    _indy_items->clear();
    split_tokens_by_whitespace(offset, _indy_items);
    if (_indy_items->length() < 2) {
      error("Line with @ tag has too few items \"%s\" line #%zu", _token, lineno());
    }
    if (!parse_lambda_forms_invokers_only()) {
      _class_name = _indy_items->at(0);
      check_class_name(_class_name);
      TempNewSymbol class_name_symbol = SymbolTable::new_symbol(_class_name);
      if (_indy_items->length() > 0) {
        // The current line is "@lambda-proxy class_name". Load the proxy class.
        resolve_indy(THREAD, class_name_symbol);
      }
    }
  } else if (strcmp(_token, LAMBDA_FORM_TAG) == 0) {
    LambdaFormInvokers::append(os::strdup((const char*)(_line + offset), mtInternal));
  } else if (strcmp(_token, CONSTANT_POOL_TAG) == 0) {
    _token = _line + offset;
    parse_constant_pool_tag();
  } else {
    error("Invalid @ tag at the beginning of line \"%s\" line #%zu", _token, lineno());
  }
}

void ClassListParser::skip_whitespaces() {
  while (*_token == ' ' || *_token == '\t') {
    _token ++;
  }
}

void ClassListParser::skip_non_whitespaces() {
  while (*_token && *_token != ' ' && *_token != '\t') {
    _token ++;
  }
}

void ClassListParser::parse_int(int* value) {
  skip_whitespaces();
  if (sscanf(_token, "%i", value) == 1) {
    skip_non_whitespaces();
  } else {
    error("Error: expected integer");
  }
}

void ClassListParser::parse_uint(int* value) {
  parse_int(value);
  if (*value < 0) {
    error("Error: negative integers not allowed (%d)", *value);
  }
}

bool ClassListParser::try_parse_uint(int* value) {
  skip_whitespaces();
  if (sscanf(_token, "%i", value) == 1) {
    skip_non_whitespaces();
    return true;
  }
  return false;
}

bool ClassListParser::skip_token(const char* option_name) {
  size_t len = strlen(option_name);
  if (strncmp(_token, option_name, len) == 0) {
    _token += len;
    return true;
  } else {
    return false;
  }
}

bool ClassListParser::parse_int_option(const char* option_name, int* value) {
  if (skip_token(option_name)) {
    if (*value != _unspecified) {
      error("%s specified twice", option_name);
    } else {
      parse_int(value);
      return true;
    }
  }
  return false;
}

bool ClassListParser::parse_uint_option(const char* option_name, int* value) {
  if (skip_token(option_name)) {
    if (*value != _unspecified) {
      error("%s specified twice", option_name);
    } else {
      parse_uint(value);
      return true;
    }
  }
  return false;
}

GrowableArray<InstanceKlass *> ClassListParser::get_specified_interfaces() {
  const int n = _interfaces->length();
  GrowableArray<InstanceKlass *> specified_interfaces(n);
  for (int i = 0; i < n; i++) {
    specified_interfaces.append(lookup_class_by_id(_interfaces->at(i)));
  }
  return specified_interfaces;
}

void ClassListParser::print_specified_interfaces() {
  const int n = _interfaces->length();
  jio_fprintf(defaultStream::error_stream(), "Currently specified interfaces[%d] = {\n", n);
  for (int i=0; i<n; i++) {
    InstanceKlass* k = lookup_class_by_id(_interfaces->at(i));
    jio_fprintf(defaultStream::error_stream(), "  %4d = %s\n", _interfaces->at(i), k->name()->as_klass_external_name());
  }
  jio_fprintf(defaultStream::error_stream(), "}\n");
}

void ClassListParser::print_actual_interfaces(InstanceKlass* ik) {
  int n = ik->local_interfaces()->length();
  jio_fprintf(defaultStream::error_stream(), "Actual interfaces[%d] = {\n", n);
  for (int i = 0; i < n; i++) {
    InstanceKlass* e = ik->local_interfaces()->at(i);
    jio_fprintf(defaultStream::error_stream(), "  %s\n", e->name()->as_klass_external_name());
  }
  jio_fprintf(defaultStream::error_stream(), "}\n");
}

void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, ...) {
  va_list ap;
  va_start(ap, msg);
  print_diagnostic_info(st, msg, ap);
  va_end(ap);
}

void ClassListParser::print_diagnostic_info(outputStream* st, const char* msg, va_list ap) {
  int error_index = pointer_delta_as_int(_token, _line);
  if (error_index >= _line_len) {
    error_index = _line_len - 1;
  }
  if (error_index < 0) {
    error_index = 0;
  }

  st->print("An error has occurred while processing class list file %s %zu:%d.\n",
            _classlist_file, lineno(), (error_index + 1));
  st->vprint(msg, ap);

  if (_line_len <= 0) {
    st->print("\n");
  } else {
    st->print(":\n");
    for (int i=0; i<_line_len; i++) {
      char c = _line[i];
      if (c == '\0') {
        st->print("%s", " ");
      } else {
        st->print("%c", c);
      }
    }
    st->print("\n");
    for (int i=0; i<error_index; i++) {
      st->print("%s", " ");
    }
    st->print("^\n");
  }
}

void ClassListParser::error(const char* msg, ...) {
  va_list ap;
  va_start(ap, msg);
  fileStream fs(defaultStream::error_stream());
  //TODO: we should write to UL/error instead, but that requires fixing some tests cases.
  //LogTarget(Error, cds) lt;
  //LogStream ls(lt);
  print_diagnostic_info(&fs, msg, ap);
  va_end(ap);
  vm_exit_during_initialization("class list format error.", nullptr);
}

void ClassListParser::check_class_name(const char* class_name) {
  const char* err = nullptr;
  size_t len = strlen(class_name);
  if (len > (size_t)Symbol::max_length()) {
    err = "class name too long";
  } else {
    assert(Symbol::max_length() < INT_MAX && len < INT_MAX, "must be");
    if (!UTF8::is_legal_utf8((const unsigned char*)class_name, len, /*version_leq_47*/false)) {
      err = "class name is not valid UTF8";
    }
  }
  if (err != nullptr) {
    jio_fprintf(defaultStream::error_stream(),
              "An error has occurred while processing class list file %s:%zu %s\n",
              _classlist_file, lineno(), err);
    vm_exit_during_initialization("class list format error.", nullptr);
  }
}

void ClassListParser::constant_pool_resolution_warning(const char* msg, ...) {
  va_list ap;
  va_start(ap, msg);
  LogTarget(Warning, aot, resolve) lt;
  LogStream ls(lt);
  print_diagnostic_info(&ls, msg, ap);
  ls.print("Your classlist may be out of sync with the JDK or the application.");
  va_end(ap);
}

// If an unregistered class U is specified to have a registered supertype S1
// named SN but an unregistered class S2 also named SN has already been loaded
// S2 will be incorrectly used as the supertype of U instead of S1 due to
// limitations in the loading mechanism of unregistered classes.
void ClassListParser::check_supertype_obstruction(int specified_supertype_id, const InstanceKlass* specified_supertype, TRAPS) {
  if (specified_supertype->defined_by_other_loaders()) {
    return; // Only registered supertypes can be obstructed
  }
  const InstanceKlass* obstructor = SystemDictionaryShared::get_unregistered_class(specified_supertype->name());
  if (obstructor == nullptr) {
    return; // No unregistered types with the same name have been loaded, i.e. no obstruction
  }
  // 'specified_supertype' is S1, 'obstructor' is S2 from the explanation above
  ResourceMark rm;
  THROW_MSG(vmSymbols::java_lang_UnsupportedOperationException(),
            err_msg("%s (id %d) has super-type %s (id %d) obstructed by another class with the same name",
                    _class_name, _id, specified_supertype->external_name(), specified_supertype_id));
}

// This function is used for loading classes for customized class loaders
// during archive dumping.
InstanceKlass* ClassListParser::load_class_from_source(Symbol* class_name, TRAPS) {
#if !(defined(_LP64) && (defined(LINUX) || defined(__APPLE__) || defined(_WINDOWS)))
  // The only supported platforms are: (1) Linux/64-bit and (2) Solaris/64-bit and
  // (3) MacOSX/64-bit and (4) Windowss/64-bit
  // This #if condition should be in sync with the areCustomLoadersSupportedForCDS
  // method in test/lib/jdk/test/lib/Platform.java.
  error("AppCDS custom class loaders not supported on this platform");
#endif

  if (!is_super_specified()) {
    error("If source location is specified, super class must be also specified");
  }
  if (!is_id_specified()) {
    error("If source location is specified, id must be also specified");
  }
  if (strncmp(_class_name, "java/", 5) == 0) {
    aot_log_info(aot)("Prohibited package for non-bootstrap classes: %s.class from %s",
          _class_name, _source);
    THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
  }

  ResourceMark rm;
  InstanceKlass* specified_super = lookup_class_by_id(_super);
  GrowableArray<InstanceKlass*> specified_interfaces = get_specified_interfaces();
  // Obstruction must be checked before the class loading attempt because it may
  // cause class loading errors (JVMS 5.3.5.3-5.3.5.4)
  check_supertype_obstruction(_super, specified_super, CHECK_NULL);
  for (int i = 0; i < _interfaces->length(); i++) {
    check_supertype_obstruction(_interfaces->at(i), specified_interfaces.at(i), CHECK_NULL);
  }

  const char* source_path = ClassLoader::uri_to_path(_source);
  InstanceKlass* k = UnregisteredClasses::load_class(class_name, source_path, CHECK_NULL);

  if (k->java_super() != specified_super) {
    error("The specified super class %s (id %d) does not match actual super class %s",
          specified_super->external_name(), _super,
          k->java_super()->external_name());
  }
  if (k->local_interfaces()->length() != _interfaces->length()) {
    print_specified_interfaces();
    print_actual_interfaces(k);
    error("The number of interfaces (%d) specified in class list does not match the class file (%d)",
          _interfaces->length(), k->local_interfaces()->length());
  }
  for (int i = 0; i < _interfaces->length(); i++) {
    InstanceKlass* specified_interface = specified_interfaces.at(i);
    if (!k->local_interfaces()->contains(specified_interface)) {
      print_specified_interfaces();
      print_actual_interfaces(k);
      error("Specified interface %s (id %d) is not directly implemented",
            specified_interface->external_name(), _interfaces->at(i));
      }
  }

  assert(k->defined_by_other_loaders(), "must be");

  bool added = SystemDictionaryShared::add_unregistered_class(THREAD, k);
  if (!added) {
    // We allow only a single unregistered class for each unique name.
    error("Duplicated class %s", _class_name);
  }

  return k;
}

void ClassListParser::populate_cds_indy_info(const constantPoolHandle &pool, int cp_index, CDSIndyInfo* cii, TRAPS) {
  // Caller needs to allocate ResourceMark.
  int type_index = pool->bootstrap_name_and_type_ref_index_at(cp_index);
  int name_index = pool->name_ref_index_at(type_index);
  cii->add_item(pool->symbol_at(name_index)->as_C_string());
  int sig_index = pool->signature_ref_index_at(type_index);
  cii->add_item(pool->symbol_at(sig_index)->as_C_string());
  int argc = pool->bootstrap_argument_count_at(cp_index);
  if (argc > 0) {
    for (int arg_i = 0; arg_i < argc; arg_i++) {
      int arg = pool->bootstrap_argument_index_at(cp_index, arg_i);
      jbyte tag = pool->tag_at(arg).value();
      if (tag == JVM_CONSTANT_MethodType) {
        cii->add_item(pool->method_type_signature_at(arg)->as_C_string());
      } else if (tag == JVM_CONSTANT_MethodHandle) {
        cii->add_ref_kind(pool->method_handle_ref_kind_at(arg));
        int callee_index = pool->method_handle_klass_index_at(arg);
        Klass* callee = pool->klass_at(callee_index, CHECK);
        cii->add_item(callee->name()->as_C_string());
        cii->add_item(pool->method_handle_name_ref_at(arg)->as_C_string());
        cii->add_item(pool->method_handle_signature_ref_at(arg)->as_C_string());
      } else {
        ShouldNotReachHere();
      }
    }
  }
}

bool ClassListParser::is_matching_cp_entry(const constantPoolHandle &pool, int cp_index, TRAPS) {
  ResourceMark rm(THREAD);
  CDSIndyInfo cii;
  populate_cds_indy_info(pool, cp_index, &cii, CHECK_0);
  GrowableArray<const char*>* items = cii.items();
  int indy_info_offset = 1;
  if (_indy_items->length() - indy_info_offset != items->length()) {
    return false;
  }
  for (int i = 0; i < items->length(); i++) {
    if (strcmp(_indy_items->at(i + indy_info_offset), items->at(i)) != 0) {
      return false;
    }
  }
  return true;
}

void ClassListParser::resolve_indy(JavaThread* current, Symbol* class_name_symbol) {
  ExceptionMark em(current);
  JavaThread* THREAD = current; // For exception macros.
  ClassListParser::resolve_indy_impl(class_name_symbol, THREAD);
  if (HAS_PENDING_EXCEPTION) {
    ResourceMark rm(current);
    char* ex_msg = (char*)"";
    oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
    if (message != nullptr) {
      ex_msg = java_lang_String::as_utf8_string(message);
    }
    aot_log_warning(aot)("resolve_indy for class %s has encountered exception: %s %s",
                     class_name_symbol->as_C_string(),
                     PENDING_EXCEPTION->klass()->external_name(),
                     ex_msg);
    CLEAR_PENDING_EXCEPTION;
  }
}

void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) {
  if (CDSConfig::is_dumping_method_handles()) {
    // The CP entry for the invokedynamic instruction will be resolved.
    // No need to do the following.
    return;
  }

  // This is an older CDS optimization:
  // We store a pre-generated version of the lambda proxy class in the AOT cache,
  // which will be loaded via JVM_LookupLambdaProxyClassFromArchive().
  // This eliminate dynamic class generation of the proxy class, but we still need to
  // resolve the CP entry for the invokedynamic instruction, which may result in
  // generation of LambdaForm classes.
  Handle class_loader(THREAD, SystemDictionary::java_system_loader());
  Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, true, CHECK);
  if (klass->is_instance_klass()) {
    InstanceKlass* ik = InstanceKlass::cast(klass);
    MetaspaceShared::try_link_class(THREAD, ik);
    if (!ik->is_linked()) {
      // Verification of ik has failed
      return;
    }

    ConstantPool* cp = ik->constants();
    ConstantPoolCache* cpcache = cp->cache();
    bool found = false;
    for (int indy_index = 0; indy_index < cpcache->resolved_indy_entries_length(); indy_index++) {
      int pool_index = cpcache->resolved_indy_entry_at(indy_index)->constant_pool_index();
      constantPoolHandle pool(THREAD, cp);
      BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index);
      Handle bsm = bootstrap_specifier.resolve_bsm(CHECK);
      if (!LambdaProxyClassDictionary::is_supported_invokedynamic(&bootstrap_specifier)) {
        log_debug(aot, lambda)("is_supported_invokedynamic check failed for cp_index %d", pool_index);
        continue;
      }
      bool matched = is_matching_cp_entry(pool, pool_index, CHECK);
      if (matched) {
        found = true;
        CallInfo info;
        bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(info, CHECK);
        if (!is_done) {
          // resolve it
          Handle recv;
          LinkResolver::resolve_invoke(info,
                                       recv,
                                       pool,
                                       indy_index,
                                       Bytecodes::_invokedynamic, CHECK);
          break;
        }
        cpcache->set_dynamic_call(info, indy_index);
      }
    }
    if (!found) {
      ResourceMark rm(THREAD);
      aot_log_warning(aot)("No invoke dynamic constant pool entry can be found for class %s. The classlist is probably out-of-date.",
                     class_name_symbol->as_C_string());
    }
  }
}

Klass* ClassListParser::load_current_class(Symbol* class_name_symbol, TRAPS) {
  Klass* klass;
  if (!is_loading_from_source()) {
    // Load classes for the boot/platform/app loaders only.
    if (is_super_specified()) {
      error("If source location is not specified, super class must not be specified");
    }
    if (are_interfaces_specified()) {
      error("If source location is not specified, interface(s) must not be specified");
    }

    if (Signature::is_array(class_name_symbol)) {
      // array classes are not supported in class list.
      THROW_NULL(vmSymbols::java_lang_ClassNotFoundException());
    }

    JavaValue result(T_OBJECT);
    // Call java_system_loader().loadClass() directly, which will
    // delegate to the correct loader (boot, platform or app) depending on
    // the package name.

    // ClassLoader.loadClass() wants external class name format, i.e., convert '/' chars to '.'
    Handle ext_class_name = java_lang_String::externalize_classname(class_name_symbol, CHECK_NULL);
    Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());

    JavaCalls::call_virtual(&result,
                            loader, //SystemDictionary::java_system_loader(),
                            vmClasses::ClassLoader_klass(),
                            vmSymbols::loadClass_name(),
                            vmSymbols::string_class_signature(),
                            ext_class_name,
                            CHECK_NULL);

    assert(result.get_type() == T_OBJECT, "just checking");
    oop obj = result.get_oop();
    assert(obj != nullptr, "jdk.internal.loader.BuiltinClassLoader::loadClass never returns null");
    klass = java_lang_Class::as_Klass(obj);
  } else {
    // If "source:" tag is specified, all super class and super interfaces must be specified in the
    // class list file.
    klass = load_class_from_source(class_name_symbol, CHECK_NULL);
  }

  assert(klass != nullptr, "exception should have been thrown");
  assert(klass->is_instance_klass(), "array classes should have been filtered out");

  if (is_id_specified()) {
    InstanceKlass* ik = InstanceKlass::cast(klass);
    int id = this->id();
    SystemDictionaryShared::update_shared_entry(ik, id);
    bool created;
    id2klass_table()->put_if_absent(id, ik, &created);
    if (!created) {
      error("Duplicated ID %d for class %s", id, _class_name);
    }
    if (id2klass_table()->maybe_grow()) {
      log_info(aot, hashtables)("Expanded id2klass_table() to %d", id2klass_table()->table_size());
    }
  }

  return klass;
}

bool ClassListParser::is_loading_from_source() {
  return (_source != nullptr);
}

InstanceKlass* ClassListParser::lookup_class_by_id(int id) {
  InstanceKlass** klass_ptr = id2klass_table()->get(id);
  if (klass_ptr == nullptr) {
    error("Class ID %d has not been defined", id);
  }
  assert(*klass_ptr != nullptr, "must be");
  return *klass_ptr;
}

InstanceKlass* ClassListParser::find_builtin_class_helper(JavaThread* current, Symbol* class_name_symbol, oop class_loader_oop) {
  Handle class_loader(current, class_loader_oop);
  return SystemDictionary::find_instance_klass(current, class_name_symbol, class_loader);
}

InstanceKlass* ClassListParser::find_builtin_class(JavaThread* current, const char* class_name) {
  TempNewSymbol class_name_symbol = SymbolTable::new_symbol(class_name);
  InstanceKlass* ik;

  if ( (ik = find_builtin_class_helper(current, class_name_symbol, nullptr)) != nullptr
    || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_platform_loader())) != nullptr
    || (ik = find_builtin_class_helper(current, class_name_symbol, SystemDictionary::java_system_loader())) != nullptr) {
    return ik;
  } else {
    return nullptr;
  }
}

void ClassListParser::parse_constant_pool_tag() {
  if (parse_lambda_forms_invokers_only()) {
    return;
  }

  JavaThread* THREAD = JavaThread::current();
  skip_whitespaces();
  char* class_name = _token;
  skip_non_whitespaces();
  *_token = '\0';
  _token ++;

  InstanceKlass* ik = find_builtin_class(THREAD, class_name);
  if (ik == nullptr) {
    _token = class_name;
    if (strstr(class_name, "/$Proxy") != nullptr ||
        strstr(class_name, "MethodHandle$Species_") != nullptr) {
      // ignore -- TODO: we should filter these out in classListWriter.cpp
    } else {
      constant_pool_resolution_warning("class %s is not (yet) loaded by one of the built-in loaders", class_name);
    }
    return;
  }

  ResourceMark rm(THREAD);
  constantPoolHandle cp(THREAD, ik->constants());
  GrowableArray<bool> preresolve_list(cp->length(), cp->length(), false);
  bool preresolve_class = false;
  bool preresolve_fmi = false;
  bool preresolve_indy = false;

  while (*_token) {
    int cp_index;
    skip_whitespaces();
    parse_uint(&cp_index);
    if (cp_index < 1 || cp_index >= cp->length()) {
      constant_pool_resolution_warning("Invalid constant pool index %d", cp_index);
      return;
    } else {
      preresolve_list.at_put(cp_index, true);
    }
    constantTag cp_tag = cp->tag_at(cp_index);
    switch (cp_tag.value()) {
    case JVM_CONSTANT_UnresolvedClass:
      preresolve_class = true;
      break;
    case JVM_CONSTANT_UnresolvedClassInError:
    case JVM_CONSTANT_Class:
      // ignore
      break;
    case JVM_CONSTANT_Fieldref:
    case JVM_CONSTANT_Methodref:
    case JVM_CONSTANT_InterfaceMethodref:
      preresolve_fmi = true;
      break;
    case JVM_CONSTANT_InvokeDynamic:
      preresolve_indy = true;
      break;
    default:
      constant_pool_resolution_warning("Unsupported constant pool index %d: %s (type=%d)",
                                       cp_index, cp_tag.internal_name(), cp_tag.value());
      return;
    }
  }

  if (SystemDictionaryShared::should_be_excluded(ik)) {
    if (log_is_enabled(Warning, aot, resolve)) {
      ResourceMark rm;
      log_warning(aot, resolve)("Cannot aot-resolve constants for %s because it is excluded", ik->external_name());
    }
    return;
  }

  if (preresolve_class) {
    AOTConstantPoolResolver::preresolve_class_cp_entries(THREAD, ik, &preresolve_list);
  }
  if (preresolve_fmi) {
    AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(THREAD, ik, &preresolve_list);
  }
  if (preresolve_indy) {
    AOTConstantPoolResolver::preresolve_indy_cp_entries(THREAD, ik, &preresolve_list);
  }
}
