/*
 * 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 "classfile/classLoaderData.inline.hpp"
#include "code/nmethod.hpp"
#include "gc/shared/classUnloadingContext.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/growableArray.hpp"

ClassUnloadingContext* ClassUnloadingContext::_context = nullptr;

ClassUnloadingContext::ClassUnloadingContext(uint num_workers,
                                             bool unregister_nmethods_during_purge,
                                             bool lock_nmethod_free_separately) :
  _cld_head(nullptr),
  _num_nmethod_unlink_workers(num_workers),
  _unlinked_nmethods(nullptr),
  _unregister_nmethods_during_purge(unregister_nmethods_during_purge),
  _lock_nmethod_free_separately(lock_nmethod_free_separately) {

  assert(_context == nullptr, "context already set");
  _context = this;

  assert(num_workers > 0, "must be");

  _unlinked_nmethods = NEW_C_HEAP_ARRAY(NMethodSet*, num_workers, mtGC);
  for (uint i = 0; i < num_workers; ++i) {
    _unlinked_nmethods[i] = new NMethodSet();
  }
}

ClassUnloadingContext::~ClassUnloadingContext() {
  for (uint i = 0; i < _num_nmethod_unlink_workers; ++i) {
    delete _unlinked_nmethods[i];
  }
  FREE_C_HEAP_ARRAY(NMethodSet*, _unlinked_nmethods);

  assert(_context == this, "context not set correctly");
  _context = nullptr;
}

bool ClassUnloadingContext::has_unloaded_classes() const {
  return _cld_head != nullptr;
}

void ClassUnloadingContext::register_unloading_class_loader_data(ClassLoaderData* cld) {
  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);

  cld->unload();

  cld->set_unloading_next(_cld_head);
  _cld_head = cld;
}

void ClassUnloadingContext::purge_class_loader_data() {
  for (ClassLoaderData* cld = _cld_head; cld != nullptr;) {
    assert(cld->is_unloading(), "invariant");

    ClassLoaderData* next = cld->unloading_next();
    delete cld;
    cld = next;
  }
}

void ClassUnloadingContext::classes_unloading_do(void f(Klass* const)) {
  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
  for (ClassLoaderData* cld = _cld_head; cld != nullptr; cld = cld->unloading_next()) {
    assert(cld->is_unloading(), "invariant");
    cld->classes_do(f);
  }
}

void ClassUnloadingContext::register_unlinked_nmethod(nmethod* nm) {
  assert(_context != nullptr, "no context set");

  assert(!nm->is_unlinked(), "Only register for unloading once");
  assert(_num_nmethod_unlink_workers == 1 || Thread::current()->is_Worker_thread(), "must be worker thread if parallel");

  uint worker_id = _num_nmethod_unlink_workers == 1 ? 0 : WorkerThread::worker_id();
  assert(worker_id < _num_nmethod_unlink_workers, "larger than expected worker id %u", worker_id);

  _unlinked_nmethods[worker_id]->append(nm);

  nm->set_is_unlinked();
}

void ClassUnloadingContext::purge_nmethods() {
  assert(_context != nullptr, "no context set");

  size_t freed_memory = 0;

  for (uint i = 0; i < _num_nmethod_unlink_workers; ++i) {
    NMethodSet* set = _unlinked_nmethods[i];
    for (nmethod* nm : *set) {
      freed_memory += nm->size();
      nm->purge(_unregister_nmethods_during_purge);
    }
  }

  CodeCache::maybe_restart_compiler(freed_memory);
}

void ClassUnloadingContext::free_nmethods() {
  assert(_context != nullptr, "no context set");

  // Sort nmethods before freeing to benefit from optimizations. If Nmethods were
  // collected in parallel, use a new temporary buffer for the result, otherwise
  // sort in-place.
  NMethodSet* nmethod_set = nullptr;

  bool is_parallel = _num_nmethod_unlink_workers > 1;

  // Merge all collected nmethods into a huge array.
  if (is_parallel) {
    int num_nmethods = 0;

    for (uint i = 0; i < _num_nmethod_unlink_workers; ++i) {
      num_nmethods += _unlinked_nmethods[i]->length();
    }
    nmethod_set = new NMethodSet(num_nmethods);
    for (uint i = 0; i < _num_nmethod_unlink_workers; ++i) {
      nmethod_set->appendAll(_unlinked_nmethods[i]);
    }
  } else {
    nmethod_set = _unlinked_nmethods[0];
  }

  // Sort by ascending address.
  auto sort_nmethods = [] (nmethod** a, nmethod** b) -> int {
    uintptr_t u_a = (uintptr_t)*a;
    uintptr_t u_b = (uintptr_t)*b;
    if (u_a == u_b) return 0;
    if (u_a < u_b) return -1;
    return 1;
  };
  nmethod_set->sort(sort_nmethods);

  // And free. Duplicate loop for clarity depending on where we want the locking.
  if (_lock_nmethod_free_separately) {
    for (nmethod* nm : *nmethod_set) {
      MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag);
      CodeCache::free(nm);
    }
  } else {
    MutexLocker ml(CodeCache_lock, Mutex::_no_safepoint_check_flag);
    for (nmethod* nm : *nmethod_set) {
      CodeCache::free(nm);
    }
  }

  if (is_parallel) {
    delete nmethod_set;
  }
}
