/*
 * Copyright (c) 2017, 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/stringTable.hpp"
#include "gc/shared/gc_globals.hpp"
#include "gc/shared/oopStorage.inline.hpp"
#include "gc/shared/oopStorageParState.inline.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "gc/shared/oopStorageSetParState.inline.hpp"
#include "gc/shared/weakProcessor.inline.hpp"
#include "gc/shared/weakProcessorTimes.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/iterator.hpp"
#include "prims/resolvedMethodTable.hpp"
#include "runtime/globals.hpp"
#include "utilities/macros.hpp"

#if INCLUDE_JVMTI
#include "prims/jvmtiTagMap.hpp"
#endif // INCLUDE_JVMTI

static void notify_jvmti_tagmaps() {
#if INCLUDE_JVMTI
  // Notify JVMTI tagmaps that a STW weak reference processing might be
  // clearing entries, so the tagmaps need cleaning.  Doing this here allows
  // the tagmap's oopstorage notification handler to not care whether it's
  // invoked by STW or concurrent reference processing.
  JvmtiTagMap::set_needs_cleaning();
#endif // INCLUDE_JVMTI
}

void WeakProcessor::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive) {

  notify_jvmti_tagmaps();

  for (OopStorage* storage : OopStorageSet::Range<OopStorageSet::WeakId>()) {
    if (storage->should_report_num_dead()) {
      CountingClosure<BoolObjectClosure, OopClosure> cl(is_alive, keep_alive);
      storage->oops_do(&cl);
      storage->report_num_dead(cl.dead());
    } else {
      storage->weak_oops_do(is_alive, keep_alive);
    }
  }
}

void WeakProcessor::oops_do(OopClosure* closure) {
  for (OopStorage* storage : OopStorageSet::Range<OopStorageSet::WeakId>()) {
    storage->weak_oops_do(closure);
  }
}

uint WeakProcessor::ergo_workers(uint max_workers) {
  // Ignore ParallelRefProcEnabled; that's for j.l.r.Reference processing.
  if (ReferencesPerThread == 0) {
    // Configuration says always use all the threads.
    return max_workers;
  }

  // One thread per ReferencesPerThread references (or fraction thereof)
  // in the various OopStorage objects, bounded by max_threads.
  size_t ref_count = 0;
  for (OopStorage* storage : OopStorageSet::Range<OopStorageSet::WeakId>()) {
    ref_count += storage->allocation_count();
  }

  // +1 to (approx) round up the ref per thread division.
  size_t nworkers = 1 + (ref_count / ReferencesPerThread);
  nworkers = MIN2(nworkers, static_cast<size_t>(max_workers));
  return static_cast<uint>(nworkers);
}

void WeakProcessor::Task::initialize() {
  assert(_nworkers != 0, "must be");
  assert(_times == nullptr || _nworkers <= _times->max_threads(),
         "nworkers (%u) exceeds max threads (%u)",
         _nworkers, _times->max_threads());

  if (_times) {
    _times->set_active_workers(_nworkers);
  }
  notify_jvmti_tagmaps();
}

WeakProcessor::Task::Task(uint nworkers) : Task(nullptr, nworkers) {}

WeakProcessor::Task::Task(WeakProcessorTimes* times, uint nworkers) :
  _times(times),
  _nworkers(nworkers),
  _storage_states()
{
  initialize();
}

void WeakProcessor::Task::report_num_dead() {
  _storage_states.report_num_dead();
}

void WeakProcessor::WeakOopsDoTask::work(uint worker_id) {
  _erased_do_work(this, worker_id);
}
