/*
 * Copyright (c) 2023, 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_FIELDINFO_INLINE_HPP
#define SHARE_OOPS_FIELDINFO_INLINE_HPP

#include "oops/fieldInfo.hpp"

#include "memory/metadataFactory.hpp"
#include "oops/constantPool.hpp"
#include "oops/symbol.hpp"
#include "runtime/atomic.hpp"

inline Symbol* FieldInfo::name(ConstantPool* cp) const {
  int index = _name_index;
  if (_field_flags.is_injected()) {
    return lookup_symbol(index);
  }
  return cp->symbol_at(index);
}

inline Symbol* FieldInfo::signature(ConstantPool* cp) const {
  int index = _signature_index;
  if (_field_flags.is_injected()) {
    return lookup_symbol(index);
  }
  return cp->symbol_at(index);
}

inline Symbol* FieldInfo::lookup_symbol(int symbol_index) const {
  assert(_field_flags.is_injected(), "only injected fields");
  return Symbol::vm_symbol_at(static_cast<vmSymbolID>(symbol_index));
}

inline int FieldInfoStream::num_injected_java_fields(const Array<u1>* fis) {
  FieldInfoReader fir(fis);
  fir.skip(1);
  return fir.next_uint();
}

inline int FieldInfoStream::num_total_fields(const Array<u1>* fis) {
  FieldInfoReader fir(fis);
  return fir.next_uint() + fir.next_uint();
}

inline int FieldInfoStream::num_java_fields(const Array<u1>* fis) { return FieldInfoReader(fis).next_uint(); }

template<typename CON>
inline void Mapper<CON>::map_field_info(const FieldInfo& fi) {
  _next_index++;  // pre-increment
  _consumer->accept_uint(fi.name_index());
  _consumer->accept_uint(fi.signature_index());
  _consumer->accept_uint(fi.offset());
  _consumer->accept_uint(fi.access_flags().as_int());
  _consumer->accept_uint(fi.field_flags().as_uint());
  if(fi.field_flags().has_any_optionals()) {
    if (fi.field_flags().is_initialized()) {
      _consumer->accept_uint(fi.initializer_index());
    }
    if (fi.field_flags().is_generic()) {
      _consumer->accept_uint(fi.generic_signature_index());
    }
    if (fi.field_flags().is_contended()) {
      _consumer->accept_uint(fi.contention_group());
    }
  } else {
    assert(fi.initializer_index() == 0, "");
    assert(fi.generic_signature_index() == 0, "");
    assert(fi.contention_group() == 0, "");
  }
}


inline FieldInfoReader::FieldInfoReader(const Array<u1>* fi)
  : _r(fi->data(), 0),
    _next_index(0) { }

inline void FieldInfoReader::read_field_info(FieldInfo& fi) {
  fi._index = _next_index++;
  fi._name_index = checked_cast<u2>(next_uint());
  fi._signature_index = checked_cast<u2>(next_uint());
  fi._offset = next_uint();
  fi._access_flags = AccessFlags(next_uint());
  fi._field_flags = FieldInfo::FieldFlags(next_uint());
  if (fi._field_flags.is_initialized()) {
    fi._initializer_index = checked_cast<u2>(next_uint());
  } else {
    fi._initializer_index = 0;
  }
  if (fi._field_flags.is_generic()) {
    fi._generic_signature_index = checked_cast<u2>(next_uint());
  } else {
    fi._generic_signature_index = 0;
  }
  if (fi._field_flags.is_contended()) {
    fi._contention_group = checked_cast<u2>(next_uint());
  } else {
    fi._contention_group = 0;
  }
}

inline FieldInfoReader&  FieldInfoReader::skip_field_info() {
  _next_index++;
  const int name_sig_af_off = 4;  // four items
  skip(name_sig_af_off);
  FieldInfo::FieldFlags ff(next_uint());
  if (ff.has_any_optionals()) {
    const int init_gen_cont = (ff.is_initialized() +
                                ff.is_generic() +
                                ff.is_contended());
    skip(init_gen_cont);  // up to three items
  }
  return *this;
}

// Skip to the nth field.  If the reader is freshly initialized to
// the zero index, this will call skip_field_info() n times.
inline FieldInfoReader& FieldInfoReader::skip_to_field_info(int n) {
  assert(n >= _next_index, "already past that index");
  const int count = n - _next_index;
  for (int i = 0; i < count; i++)  skip_field_info();
  assert(_next_index == n, "");
  return *this;
}

// for random access, if you know where to go up front:
inline FieldInfoReader& FieldInfoReader::set_position_and_next_index(int position, int next_index) {
  _r.set_position(position);
  _next_index = next_index;
  return *this;
}

inline void FieldStatus::atomic_set_bits(u1& flags, u1 mask) {
  Atomic::fetch_then_or(&flags, mask);
}

inline void FieldStatus::atomic_clear_bits(u1& flags, u1 mask) {
  Atomic::fetch_then_and(&flags, (u1)(~mask));
}

inline void FieldStatus::update_flag(FieldStatusBitPosition pos, bool z) {
  if (z) atomic_set_bits(_flags, flag_mask(pos));
  else atomic_clear_bits(_flags, flag_mask(pos));
}

inline void FieldStatus::update_access_watched(bool z) { update_flag(_fs_access_watched, z); }
inline void FieldStatus::update_modification_watched(bool z) { update_flag(_fs_modification_watched, z); }
inline void FieldStatus::update_initialized_final_update(bool z) { update_flag(_initialized_final_update, z); }

#endif // SHARE_OOPS_FIELDINFO_INLINE_HPP
