/*
 * Copyright (c) 2019, 2022, Red Hat, Inc. 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 "precompiled.hpp"

#include "gc/shenandoah/shenandoahClosures.inline.hpp"
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahNMethod.inline.hpp"
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/continuation.hpp"

ShenandoahNMethod::ShenandoahNMethod(nmethod* nm, GrowableArray<oop*>& oops, bool non_immediate_oops) :
  _nm(nm), _oops(nullptr), _oops_count(0), _unregistered(false) {

  if (!oops.is_empty()) {
    _oops_count = oops.length();
    _oops = NEW_C_HEAP_ARRAY(oop*, _oops_count, mtGC);
    for (int c = 0; c < _oops_count; c++) {
      _oops[c] = oops.at(c);
    }
  }
  _has_non_immed_oops = non_immediate_oops;

  assert_same_oops();
}

ShenandoahNMethod::~ShenandoahNMethod() {
  if (_oops != nullptr) {
    FREE_C_HEAP_ARRAY(oop*, _oops);
  }
}

void ShenandoahNMethod::update() {
  ResourceMark rm;
  bool non_immediate_oops = false;
  GrowableArray<oop*> oops;

  detect_reloc_oops(nm(), oops, non_immediate_oops);
  if (oops.length() != _oops_count) {
    if (_oops != nullptr) {
      FREE_C_HEAP_ARRAY(oop*, _oops);
      _oops = nullptr;
    }

    _oops_count = oops.length();
    if (_oops_count > 0) {
      _oops = NEW_C_HEAP_ARRAY(oop*, _oops_count, mtGC);
    }
  }

  for (int index = 0; index < _oops_count; index ++) {
    _oops[index] = oops.at(index);
  }
  _has_non_immed_oops = non_immediate_oops;

  assert_same_oops();
}

void ShenandoahNMethod::detect_reloc_oops(nmethod* nm, GrowableArray<oop*>& oops, bool& has_non_immed_oops) {
  has_non_immed_oops = false;
  // Find all oops relocations
  RelocIterator iter(nm);
  while (iter.next()) {
    if (iter.type() != relocInfo::oop_type) {
      // Not an oop
      continue;
    }

    oop_Relocation* r = iter.oop_reloc();
    if (!r->oop_is_immediate()) {
      // Non-immediate oop found
      has_non_immed_oops = true;
      continue;
    }

    oop value = r->oop_value();
    if (value != nullptr) {
      oop* addr = r->oop_addr();
      shenandoah_assert_correct(addr, value);
      shenandoah_assert_not_in_cset_except(addr, value, ShenandoahHeap::heap()->cancelled_gc());
      shenandoah_assert_not_forwarded(addr, value);
      // Non-null immediate oop found. null oops can safely be
      // ignored since the method will be re-registered if they
      // are later patched to be non-null.
      oops.push(addr);
    }
  }
}

ShenandoahNMethod* ShenandoahNMethod::for_nmethod(nmethod* nm) {
  ResourceMark rm;
  bool non_immediate_oops = false;
  GrowableArray<oop*> oops;

  detect_reloc_oops(nm, oops, non_immediate_oops);
  return new ShenandoahNMethod(nm, oops, non_immediate_oops);
}

void ShenandoahNMethod::heal_nmethod(nmethod* nm) {
  ShenandoahNMethod* data = gc_data(nm);
  assert(data != nullptr, "Sanity");
  assert(data->lock()->owned_by_self(), "Must hold the lock");

  ShenandoahHeap* const heap = ShenandoahHeap::heap();
  if (heap->is_concurrent_mark_in_progress()) {
    ShenandoahKeepAliveClosure cl;
    data->oops_do(&cl);
  } else if (heap->is_concurrent_weak_root_in_progress() ||
             heap->is_concurrent_strong_root_in_progress() ) {
    ShenandoahEvacOOMScope evac_scope;
    heal_nmethod_metadata(data);
  } else {
    // There is possibility that GC is cancelled when it arrives final mark.
    // In this case, concurrent root phase is skipped and degenerated GC should be
    // followed, where nmethods are disarmed.
  }
}

#ifdef ASSERT
void ShenandoahNMethod::assert_correct() {
  ShenandoahHeap* heap = ShenandoahHeap::heap();
  for (int c = 0; c < _oops_count; c++) {
    oop *loc = _oops[c];
    assert(_nm->code_contains((address) loc) || _nm->oops_contains(loc), "nmethod should contain the oop*");
    oop o = RawAccess<>::oop_load(loc);
    shenandoah_assert_correct_except(loc, o, o == nullptr || heap->is_full_gc_move_in_progress());
  }

  oop* const begin = _nm->oops_begin();
  oop* const end = _nm->oops_end();
  for (oop* p = begin; p < end; p++) {
    if (*p != Universe::non_oop_word()) {
      oop o = RawAccess<>::oop_load(p);
      shenandoah_assert_correct_except(p, o, o == nullptr || heap->is_full_gc_move_in_progress());
    }
  }
}

class ShenandoahNMethodOopDetector : public OopClosure {
private:
  ResourceMark rm; // For growable array allocation below.
  GrowableArray<oop*> _oops;

public:
  ShenandoahNMethodOopDetector() : _oops(10) {};

  void do_oop(oop* o) {
    _oops.append(o);
  }
  void do_oop(narrowOop* o) {
    fatal("NMethods should not have compressed oops embedded.");
  }

  GrowableArray<oop*>* oops() {
    return &_oops;
  }
};

void ShenandoahNMethod::assert_same_oops(bool allow_dead) {
  ShenandoahNMethodOopDetector detector;
  nm()->oops_do(&detector, allow_dead);

  GrowableArray<oop*>* oops = detector.oops();

  int count = _oops_count;
  for (int index = 0; index < _oops_count; index ++) {
    assert(oops->contains(_oops[index]), "Must contain this oop");
  }

  for (oop* p = nm()->oops_begin(); p < nm()->oops_end(); p ++) {
    if (*p == Universe::non_oop_word()) continue;
    count++;
    assert(oops->contains(p), "Must contain this oop");
  }

  if (oops->length() < count) {
    stringStream debug_stream;
    debug_stream.print_cr("detected locs: %d", oops->length());
    for (int i = 0; i < oops->length(); i++) {
      debug_stream.print_cr("-> " PTR_FORMAT, p2i(oops->at(i)));
    }
    debug_stream.print_cr("recorded oops: %d", _oops_count);
    for (int i = 0; i < _oops_count; i++) {
      debug_stream.print_cr("-> " PTR_FORMAT, p2i(_oops[i]));
    }
    GrowableArray<oop*> check;
    bool non_immed;
    detect_reloc_oops(nm(), check, non_immed);
    debug_stream.print_cr("check oops: %d", check.length());
    for (int i = 0; i < check.length(); i++) {
      debug_stream.print_cr("-> " PTR_FORMAT, p2i(check.at(i)));
    }
    fatal("Must match #detected: %d, #recorded: %d, #total: %d, begin: " PTR_FORMAT ", end: " PTR_FORMAT "\n%s",
          oops->length(), _oops_count, count, p2i(nm()->oops_begin()), p2i(nm()->oops_end()), debug_stream.freeze());
  }
}
#endif

ShenandoahNMethodTable::ShenandoahNMethodTable() :
  _heap(ShenandoahHeap::heap()),
  _index(0),
  _itr_cnt(0) {
  _list = new ShenandoahNMethodList(minSize);
}

ShenandoahNMethodTable::~ShenandoahNMethodTable() {
  assert(_list != nullptr, "Sanity");
  _list->release();
}

void ShenandoahNMethodTable::register_nmethod(nmethod* nm) {
  assert(CodeCache_lock->owned_by_self(), "Must have CodeCache_lock held");
  assert(_index >= 0 && _index <= _list->size(), "Sanity");

  ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);

  if (data != nullptr) {
    assert(contain(nm), "Must have been registered");
    assert(nm == data->nm(), "Must be same nmethod");
    // Prevent updating a nmethod while concurrent iteration is in progress.
    wait_until_concurrent_iteration_done();
    ShenandoahReentrantLocker data_locker(data->lock());
    data->update();
  } else {
    // For a new nmethod, we can safely append it to the list, because
    // concurrent iteration will not touch it.
    data = ShenandoahNMethod::for_nmethod(nm);
    assert(data != nullptr, "Sanity");
    ShenandoahNMethod::attach_gc_data(nm, data);
    ShenandoahLocker locker(&_lock);
    log_register_nmethod(nm);
    append(data);
  }
  // Disarm new nmethod
  ShenandoahNMethod::disarm_nmethod(nm);
}

void ShenandoahNMethodTable::unregister_nmethod(nmethod* nm) {
  assert_locked_or_safepoint(CodeCache_lock);

  ShenandoahNMethod* data = ShenandoahNMethod::gc_data(nm);
  assert(data != nullptr, "Sanity");
  log_unregister_nmethod(nm);
  ShenandoahLocker locker(&_lock);
  assert(contain(nm), "Must have been registered");

  int idx = index_of(nm);
  assert(idx >= 0 && idx < _index, "Invalid index");
  ShenandoahNMethod::attach_gc_data(nm, nullptr);
  remove(idx);
}

bool ShenandoahNMethodTable::contain(nmethod* nm) const {
  return index_of(nm) != -1;
}

ShenandoahNMethod* ShenandoahNMethodTable::at(int index) const {
  assert(index >= 0 && index < _index, "Out of bound");
  return _list->at(index);
}

int ShenandoahNMethodTable::index_of(nmethod* nm) const {
  for (int index = 0; index < length(); index ++) {
    if (at(index)->nm() == nm) {
      return index;
    }
  }
  return -1;
}

void ShenandoahNMethodTable::remove(int idx) {
  shenandoah_assert_locked_or_safepoint(CodeCache_lock);
  assert(_index >= 0 && _index <= _list->size(), "Sanity");

  assert(idx >= 0 && idx < _index, "Out of bound");
  ShenandoahNMethod* snm = _list->at(idx);
  ShenandoahNMethod* tmp = _list->at(_index - 1);
  _list->set(idx, tmp);
  _index --;

  delete snm;
}

void ShenandoahNMethodTable::wait_until_concurrent_iteration_done() {
  assert(CodeCache_lock->owned_by_self(), "Lock must be held");
  while (iteration_in_progress()) {
    CodeCache_lock->wait_without_safepoint_check();
  }
}

void ShenandoahNMethodTable::append(ShenandoahNMethod* snm) {
  if (is_full()) {
    int new_size = 2 * _list->size();
    // Rebuild table and replace current one
    rebuild(new_size);
  }

  _list->set(_index++,  snm);
  assert(_index >= 0 && _index <= _list->size(), "Sanity");
}

void ShenandoahNMethodTable::rebuild(int size) {
  ShenandoahNMethodList* new_list = new ShenandoahNMethodList(size);
  new_list->transfer(_list, _index);

  // Release old list
  _list->release();
  _list = new_list;
}

ShenandoahNMethodTableSnapshot* ShenandoahNMethodTable::snapshot_for_iteration() {
  assert(CodeCache_lock->owned_by_self(), "Must have CodeCache_lock held");
  _itr_cnt++;
  return new ShenandoahNMethodTableSnapshot(this);
}

void ShenandoahNMethodTable::finish_iteration(ShenandoahNMethodTableSnapshot* snapshot) {
  assert(CodeCache_lock->owned_by_self(), "Must have CodeCache_lock held");
  assert(iteration_in_progress(), "Why we here?");
  assert(snapshot != nullptr, "No snapshot");
  _itr_cnt--;

  delete snapshot;
}

void ShenandoahNMethodTable::log_register_nmethod(nmethod* nm) {
  LogTarget(Debug, gc, nmethod) log;
  if (!log.is_enabled()) {
    return;
  }

  ResourceMark rm;
  log.print("Register NMethod: %s.%s [" PTR_FORMAT "] (%s)",
            nm->method()->method_holder()->external_name(),
            nm->method()->name()->as_C_string(),
            p2i(nm),
            nm->compiler_name());
}

void ShenandoahNMethodTable::log_unregister_nmethod(nmethod* nm) {
  LogTarget(Debug, gc, nmethod) log;
  if (!log.is_enabled()) {
    return;
  }

  ResourceMark rm;
  log.print("Unregister NMethod: %s.%s [" PTR_FORMAT "]",
            nm->method()->method_holder()->external_name(),
            nm->method()->name()->as_C_string(),
            p2i(nm));
}

#ifdef ASSERT
void ShenandoahNMethodTable::assert_nmethods_correct() {
  assert_locked_or_safepoint(CodeCache_lock);

  for (int index = 0; index < length(); index ++) {
    ShenandoahNMethod* m = _list->at(index);
    // Concurrent unloading may have dead nmethods to be cleaned by sweeper
    if (m->is_unregistered()) continue;
    m->assert_correct();
  }
}
#endif


ShenandoahNMethodList::ShenandoahNMethodList(int size) :
  _size(size), _ref_count(1) {
  _list = NEW_C_HEAP_ARRAY(ShenandoahNMethod*, size, mtGC);
}

ShenandoahNMethodList::~ShenandoahNMethodList() {
  assert(_list != nullptr, "Sanity");
  assert(_ref_count == 0, "Must be");
  FREE_C_HEAP_ARRAY(ShenandoahNMethod*, _list);
}

void ShenandoahNMethodList::transfer(ShenandoahNMethodList* const list, int limit) {
  assert(limit <= size(), "Sanity");
  ShenandoahNMethod** old_list = list->list();
  for (int index = 0; index < limit; index++) {
    _list[index] = old_list[index];
  }
}

ShenandoahNMethodList* ShenandoahNMethodList::acquire() {
  assert_locked_or_safepoint(CodeCache_lock);
  _ref_count++;
  return this;
}

void ShenandoahNMethodList::release() {
  assert_locked_or_safepoint(CodeCache_lock);
  _ref_count--;
  if (_ref_count == 0) {
    delete this;
  }
}

ShenandoahNMethodTableSnapshot::ShenandoahNMethodTableSnapshot(ShenandoahNMethodTable* table) :
  _heap(ShenandoahHeap::heap()), _list(table->_list->acquire()), _limit(table->_index), _claimed(0) {
}

ShenandoahNMethodTableSnapshot::~ShenandoahNMethodTableSnapshot() {
  _list->release();
}

void ShenandoahNMethodTableSnapshot::parallel_blobs_do(CodeBlobClosure *f) {
  size_t stride = 256; // educated guess

  ShenandoahNMethod** const list = _list->list();

  size_t max = (size_t)_limit;
  while (_claimed < max) {
    size_t cur = Atomic::fetch_then_add(&_claimed, stride, memory_order_relaxed);
    size_t start = cur;
    size_t end = MIN2(cur + stride, max);
    if (start >= max) break;

    for (size_t idx = start; idx < end; idx++) {
      ShenandoahNMethod* nmr = list[idx];
      assert(nmr != nullptr, "Sanity");
      if (nmr->is_unregistered()) {
        continue;
      }

      nmr->assert_correct();
      f->do_code_blob(nmr->nm());
    }
  }
}

void ShenandoahNMethodTableSnapshot::concurrent_nmethods_do(NMethodClosure* cl) {
  size_t stride = 256; // educated guess

  ShenandoahNMethod** list = _list->list();
  size_t max = (size_t)_limit;
  while (_claimed < max) {
    size_t cur = Atomic::fetch_then_add(&_claimed, stride, memory_order_relaxed);
    size_t start = cur;
    size_t end = MIN2(cur + stride, max);
    if (start >= max) break;

    for (size_t idx = start; idx < end; idx++) {
      ShenandoahNMethod* data = list[idx];
      assert(data != nullptr, "Should not be null");
      if (!data->is_unregistered()) {
        cl->do_nmethod(data->nm());
      }
    }
  }
}

ShenandoahConcurrentNMethodIterator::ShenandoahConcurrentNMethodIterator(ShenandoahNMethodTable* table) :
  _table(table), _table_snapshot(nullptr) {
}

void ShenandoahConcurrentNMethodIterator::nmethods_do_begin() {
  assert(CodeCache_lock->owned_by_self(), "Lock must be held");
  _table_snapshot = _table->snapshot_for_iteration();
}

void ShenandoahConcurrentNMethodIterator::nmethods_do(NMethodClosure* cl) {
  assert(_table_snapshot != nullptr, "Must first call nmethod_do_begin()");
  _table_snapshot->concurrent_nmethods_do(cl);
}

void ShenandoahConcurrentNMethodIterator::nmethods_do_end() {
  assert(CodeCache_lock->owned_by_self(), "Lock must be held");
  _table->finish_iteration(_table_snapshot);
  CodeCache_lock->notify_all();
}
