/*
 * 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 "memory/resourceArea.hpp"
#include "cds/cdsConfig.hpp"
#include "oops/fieldInfo.inline.hpp"
#include "runtime/atomic.hpp"
#include "utilities/packedTable.hpp"

void FieldInfo::print(outputStream* os, ConstantPool* cp) {
  os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d "
               "AccessFlags=%d FieldFlags=%d "
               "initval_index=%d gen_signature_index=%d, gen_signature=%s contended_group=%d",
                index(),
                name_index(), name(cp)->as_utf8(),
                signature_index(), signature(cp)->as_utf8(),
                offset(),
                access_flags().as_field_flags(),
                field_flags().as_uint(),
                initializer_index(),
                generic_signature_index(),
                _field_flags.is_generic() ? (_field_flags.is_injected() ?
                  lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8()
                  ) : "",
                is_contended() ? contended_group() : 0);
}

void FieldInfo::print_from_growable_array(outputStream* os, GrowableArray<FieldInfo>* array, ConstantPool* cp) {
  for (int i = 0; i < array->length(); i++) {
    array->adr_at(i)->print(os, cp);
  }
}

Array<u1>* FieldInfoStream::create_FieldInfoStream(GrowableArray<FieldInfo>* fields, int java_fields, int injected_fields,
                                                          ClassLoaderData* loader_data, TRAPS) {
  // The stream format described in fieldInfo.hpp is:
  //   FieldInfoStream := j=num_java_fields k=num_injected_fields Field[j+k] End
  //   Field := name sig offset access flags Optionals(flags)
  //   Optionals(i) := initval?[i&is_init]     // ConstantValue attr
  //                   gsig?[i&is_generic]     // signature attr
  //                   group?[i&is_contended]  // Contended anno (group)
  //   End = 0

  using StreamSizer = UNSIGNED5::Sizer<>;
  using StreamFieldSizer = Mapper<StreamSizer>;
  StreamSizer s;
  StreamFieldSizer sizer(&s);

  assert(fields->length() == java_fields + injected_fields, "must be");

  sizer.consumer()->accept_uint(java_fields);
  sizer.consumer()->accept_uint(injected_fields);
  for (int i = 0; i < fields->length(); i++) {
    FieldInfo* fi = fields->adr_at(i);
    sizer.map_field_info(*fi);
  }
  // Originally there was an extra byte with 0 terminating the reading;
  // now we check limits instead.
  int storage_size = sizer.consumer()->position();
  Array<u1>* const fis = MetadataFactory::new_array<u1>(loader_data, storage_size, CHECK_NULL);

  using StreamWriter = UNSIGNED5::Writer<Array<u1>*, int, ArrayHelper<Array<u1>*, int>>;
  using StreamFieldWriter = Mapper<StreamWriter>;
  StreamWriter w(fis);
  StreamFieldWriter writer(&w);

  writer.consumer()->accept_uint(java_fields);
  writer.consumer()->accept_uint(injected_fields);
  for (int i = 0; i < fields->length(); i++) {
    writer.map_field_info(fields->at(i));
  }

#ifdef ASSERT
  FieldInfoReader r(fis);
  int jfc, ifc;
  r.read_field_counts(&jfc, &ifc);
  assert(jfc == java_fields, "Must be");
  assert(ifc == injected_fields, "Must be");
  for (int i = 0; i < jfc + ifc; i++) {
    FieldInfo fi;
    r.read_field_info(fi);
    FieldInfo* fi_ref = fields->adr_at(i);
    assert(fi_ref->name_index() == fi.name_index(), "Must be");
    assert(fi_ref->signature_index() == fi.signature_index(), "Must be");
    assert(fi_ref->offset() == fi.offset(), "Must be");
    assert(fi_ref->access_flags().as_field_flags() == fi.access_flags().as_field_flags(), "Must be");
    assert(fi_ref->field_flags().as_uint() == fi.field_flags().as_uint(), " Must be");
    if(fi_ref->field_flags().is_initialized()) {
      assert(fi_ref->initializer_index() == fi.initializer_index(), "Must be");
    }
    if (fi_ref->field_flags().is_generic()) {
      assert(fi_ref->generic_signature_index() == fi.generic_signature_index(), "Must be");
    }
    if (fi_ref->field_flags().is_contended()) {
      assert(fi_ref->contended_group() == fi.contended_group(), "Must be");
    }
  }
#endif // ASSERT

  return fis;
}

int FieldInfoStream::compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2) {
  int cmp = n1->fast_compare(n2);
  return cmp != 0 ? cmp : s1->fast_compare(s2);
}


// We use both name and signature during the comparison; while JLS require unique
// names for fields, JVMS requires only unique name + signature combination.
struct field_pos {
  Symbol* _name;
  Symbol* _signature;
  int _index;
  int _position;
};

class FieldInfoSupplier: public PackedTableBuilder::Supplier {
  const field_pos* _positions;
  size_t _elements;

public:
  FieldInfoSupplier(const field_pos* positions, size_t elements): _positions(positions), _elements(elements) {}

  bool next(uint32_t* key, uint32_t* value) override {
    if (_elements == 0) {
      return false;
    }
    *key = _positions->_position;
    *value = _positions->_index;
    ++_positions;
    --_elements;
    return true;
  }
};

Array<u1>* FieldInfoStream::create_search_table(ConstantPool* cp, const Array<u1>* fis, ClassLoaderData* loader_data, TRAPS) {
  if (CDSConfig::is_dumping_dynamic_archive()) {
    // We cannot use search table; in case of dynamic archives it should be sorted by "requested" addresses,
    // but Symbol* addresses are coming from _constants, which has "buffered" addresses.
    // For background, see new comments inside allocate_node_impl in symbolTable.cpp
    return nullptr;
  }

  FieldInfoReader r(fis);
  int java_fields;
  int injected_fields;
  r.read_field_counts(&java_fields, &injected_fields);
  assert(java_fields >= 0, "must be");
  if (java_fields == 0 || fis->length() == 0 || static_cast<uint>(java_fields) < BinarySearchThreshold) {
    return nullptr;
  }

  ResourceMark rm;
  field_pos* positions = NEW_RESOURCE_ARRAY(field_pos, java_fields);
  for (int i = 0; i < java_fields; ++i) {
    assert(r.has_next(), "number of fields must match");

    positions[i]._position = r.position();
    FieldInfo fi;
    r.read_field_info(fi);

    positions[i]._name = fi.name(cp);
    positions[i]._signature = fi.signature(cp);
    positions[i]._index = i;
  }
  auto compare_pair = [](const void* v1, const void* v2) {
    const field_pos* p1 = reinterpret_cast<const field_pos*>(v1);
    const field_pos* p2 = reinterpret_cast<const field_pos*>(v2);
    return compare_name_and_sig(p1->_name, p1->_signature, p2->_name, p2->_signature);
  };
  qsort(positions, java_fields, sizeof(field_pos), compare_pair);

  PackedTableBuilder builder(fis->length() - 1, java_fields - 1);
  Array<u1>* table = MetadataFactory::new_array<u1>(loader_data, java_fields * builder.element_bytes(), CHECK_NULL);
  FieldInfoSupplier supplier(positions, java_fields);
  builder.fill(table->data(), static_cast<size_t>(table->length()), supplier);
  return table;
}

GrowableArray<FieldInfo>* FieldInfoStream::create_FieldInfoArray(const Array<u1>* fis, int* java_fields_count, int* injected_fields_count) {
  FieldInfoReader r(fis);
  r.read_field_counts(java_fields_count, injected_fields_count);
  int length = *java_fields_count + *injected_fields_count;

  GrowableArray<FieldInfo>* array = new GrowableArray<FieldInfo>(length);
  while (r.has_next()) {
    FieldInfo fi;
    r.read_field_info(fi);
    array->append(fi);
  }
  assert(array->length() == length, "Must be");
  return array;
}

void FieldInfoStream::print_from_fieldinfo_stream(Array<u1>* fis, outputStream* os, ConstantPool* cp) {
  FieldInfoReader r(fis);
  int java_fields_count;
  int injected_fields_count;
  r.read_field_counts(&java_fields_count, &injected_fields_count);
  while (r.has_next()) {
    FieldInfo fi;
    r.read_field_info(fi);
    fi.print(os, cp);
  }
}

class FieldInfoComparator: public PackedTableLookup::Comparator {
  const FieldInfoReader* _reader;
  ConstantPool* _cp;
  const Symbol* _name;
  const Symbol* _signature;

public:
  FieldInfoComparator(const FieldInfoReader* reader, ConstantPool* cp, const Symbol* name, const Symbol* signature):
    _reader(reader), _cp(cp), _name(name), _signature(signature) {}

  int compare_to(uint32_t position) override {
    FieldInfoReader r2(*_reader);
    r2.set_position_and_next_index(position, -1);
    u2 name_index, sig_index;
    r2.read_name_and_signature(&name_index, &sig_index);
    Symbol* mid_name = _cp->symbol_at(name_index);
    Symbol* mid_sig = _cp->symbol_at(sig_index);

    return FieldInfoStream::compare_name_and_sig(_name, _signature, mid_name, mid_sig);
  }

#ifdef ASSERT
  void reset(uint32_t position) override {
    FieldInfoReader r2(*_reader);
    r2.set_position_and_next_index(position, -1);
    u2 name_index, signature_index;
    r2.read_name_and_signature(&name_index, &signature_index);
    _name = _cp->symbol_at(name_index);
    _signature = _cp->symbol_at(signature_index);
  }
#endif // ASSERT
};

#ifdef ASSERT
void FieldInfoStream::validate_search_table(ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
  if (search_table == nullptr) {
    return;
  }
  FieldInfoReader reader(fis);
  int java_fields, injected_fields;
  reader.read_field_counts(&java_fields, &injected_fields);
  assert(java_fields > 0, "must be");

  PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table);
  assert(lookup.element_bytes() * java_fields == static_cast<unsigned int>(search_table->length()), "size does not match");

  FieldInfoComparator comparator(&reader, cp, nullptr, nullptr);
  // Check 1: assert that elements have the correct order based on the comparison function
  lookup.validate_order(comparator);

  // Check 2: Iterate through the original stream (not just search_table) and try if lookup works as expected
  reader.set_position_and_next_index(0, 0);
  reader.read_field_counts(&java_fields, &injected_fields);
  while (reader.has_next()) {
    int field_start = reader.position();
    FieldInfo fi;
    reader.read_field_info(fi);
    if (fi.field_flags().is_injected()) {
      // checking only java fields that precede injected ones
      break;
    }

    FieldInfoReader r2(fis);
    int index = r2.search_table_lookup(search_table, fi.name(cp), fi.signature(cp), cp, java_fields);
    assert(index == static_cast<int>(fi.index()), "wrong index: %d != %u", index, fi.index());
    assert(index == r2.next_index(), "index should match");
    assert(field_start == r2.position(), "must find the same position");
  }
}
#endif // ASSERT

void FieldInfoStream::print_search_table(outputStream* st, ConstantPool* cp, const Array<u1>* fis, const Array<u1>* search_table) {
  if (search_table == nullptr) {
    return;
  }
  FieldInfoReader reader(fis);
  int java_fields, injected_fields;
  reader.read_field_counts(&java_fields, &injected_fields);
  assert(java_fields > 0, "must be");
  PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table);
  auto printer = [&] (size_t offset, uint32_t position, uint32_t index) {
    reader.set_position_and_next_index(position, -1);
    u2 name_index, sig_index;
    reader.read_name_and_signature(&name_index, &sig_index);
    Symbol* name = cp->symbol_at(name_index);
    Symbol* sig = cp->symbol_at(sig_index);
    st->print("   [%zu] #%d,#%d = ", offset, name_index, sig_index);
    name->print_symbol_on(st);
    st->print(":");
    sig->print_symbol_on(st);
    st->print(" @ %p,%p", name, sig);
    st->cr();
  };

  lookup.iterate(printer);
}

int FieldInfoReader::search_table_lookup(const Array<u1>* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields) {
  assert(java_fields >= 0, "must be");
  if (java_fields == 0) {
    return -1;
  }
  FieldInfoComparator comp(this, cp, name, signature);
  PackedTableLookup lookup(_r.limit() - 1, java_fields - 1, search_table);
  uint32_t position;
  static_assert(sizeof(uint32_t) == sizeof(_next_index), "field size assert");
  if (lookup.search(comp, &position, reinterpret_cast<uint32_t*>(&_next_index))) {
    _r.set_position(static_cast<int>(position));
    return _next_index;
  } else {
    return -1;
  }
}
