/*
 * Copyright (c) 2015, 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.
 */

#include "precompiled.hpp"
#include "gc/shared/gc_globals.hpp"
#include "gc/shared/gcCause.hpp"
#include "gc/shared/gcId.hpp"
#include "gc/z/zAbort.inline.hpp"
#include "gc/z/zBreakpoint.hpp"
#include "gc/z/zCollectedHeap.hpp"
#include "gc/z/zDirector.hpp"
#include "gc/z/zDriver.hpp"
#include "gc/z/zGCIdPrinter.hpp"
#include "gc/z/zGeneration.inline.hpp"
#include "gc/z/zHeap.inline.hpp"
#include "gc/z/zLock.inline.hpp"
#include "gc/z/zServiceability.hpp"
#include "gc/z/zStat.hpp"

static const ZStatPhaseCollection ZPhaseCollectionMinor("Minor Collection", true /* minor */);
static const ZStatPhaseCollection ZPhaseCollectionMajor("Major Collection", false /* minor */);

template <typename DriverT>
class ZGCCauseSetter : public GCCauseSetter {
private:
  DriverT* _driver;

public:
  ZGCCauseSetter(DriverT* driver, GCCause::Cause cause)
    : GCCauseSetter(ZCollectedHeap::heap(), cause),
      _driver(driver) {
    _driver->set_gc_cause(cause);
  }

  ~ZGCCauseSetter() {
    _driver->set_gc_cause(GCCause::_no_gc);
  }
};

ZLock*        ZDriver::_lock;
ZDriverMinor* ZDriver::_minor;
ZDriverMajor* ZDriver::_major;

void ZDriver::initialize() {
  _lock = new ZLock();
}

void ZDriver::lock() {
  _lock->lock();
}

void ZDriver::unlock() {
  _lock->unlock();
}

void ZDriver::set_minor(ZDriverMinor* minor) {
  _minor = minor;
}

void ZDriver::set_major(ZDriverMajor* major) {
  _major = major;
}

ZDriverMinor* ZDriver::minor() {
  return _minor;
}

ZDriverMajor* ZDriver::major() {
  return _major;
}

ZDriverLocker::ZDriverLocker() {
  ZDriver::lock();
}

ZDriverLocker::~ZDriverLocker() {
  ZDriver::unlock();
}

ZDriverUnlocker::ZDriverUnlocker() {
  ZDriver::unlock();
}

ZDriverUnlocker::~ZDriverUnlocker() {
  ZDriver::lock();
}

ZDriver::ZDriver()
  : _gc_cause(GCCause::_no_gc) {}

void ZDriver::set_gc_cause(GCCause::Cause cause) {
  _gc_cause = cause;
}

GCCause::Cause ZDriver::gc_cause() {
  return _gc_cause;
}

ZDriverMinor::ZDriverMinor()
  : ZDriver(),
    _port(),
    _gc_timer(),
    _jfr_tracer(),
    _used_at_start() {
  ZDriver::set_minor(this);
  set_name("ZDriverMinor");
  create_and_start();
}

bool ZDriverMinor::is_busy() const {
  return _port.is_busy();
}

void ZDriverMinor::collect(const ZDriverRequest& request) {
  switch (request.cause()) {
  case GCCause::_wb_young_gc:
    // Start synchronous GC
    _port.send_sync(request);
    break;

  case GCCause::_scavenge_alot:
  case GCCause::_z_timer:
  case GCCause::_z_allocation_rate:
  case GCCause::_z_allocation_stall:
  case GCCause::_z_high_usage:
    // Start asynchronous GC
    _port.send_async(request);
    break;

  default:
    fatal("Unsupported GC cause (%s)", GCCause::to_string(request.cause()));
    break;
  }
};

GCTracer* ZDriverMinor::jfr_tracer() {
  return &_jfr_tracer;
}

void ZDriverMinor::set_used_at_start(size_t used) {
  _used_at_start = used;
}

size_t ZDriverMinor::used_at_start() const {
  return _used_at_start;
}

class ZDriverScopeMinor : public StackObj {
private:
  GCIdMark                     _gc_id;
  GCCause::Cause               _gc_cause;
  ZGCCauseSetter<ZDriverMinor> _gc_cause_setter;
  ZStatTimer                   _stat_timer;
  ZServiceabilityCycleTracer   _tracer;

public:
  ZDriverScopeMinor(const ZDriverRequest& request, ConcurrentGCTimer* gc_timer)
    : _gc_id(),
      _gc_cause(request.cause()),
      _gc_cause_setter(ZDriver::minor(), _gc_cause),
      _stat_timer(ZPhaseCollectionMinor, gc_timer),
      _tracer(true /* minor */) {
    // Select number of worker threads to use
    ZGeneration::young()->set_active_workers(request.young_nworkers());
  }
};

void ZDriverMinor::gc(const ZDriverRequest& request) {
  ZDriverScopeMinor scope(request, &_gc_timer);
  ZGCIdMinor minor_id(gc_id());
  ZGeneration::young()->collect(ZYoungType::minor, &_gc_timer);
}

static void handle_alloc_stalling_for_young() {
  ZHeap::heap()->handle_alloc_stalling_for_young();
}

void ZDriverMinor::handle_alloc_stalls() const {
  handle_alloc_stalling_for_young();
}

void ZDriverMinor::run_thread() {
  // Main loop
  for (;;) {
    // Wait for GC request
    const ZDriverRequest request = _port.receive();

    ZDriverLocker locker;

    abortpoint();

    // Run GC
    gc(request);

    abortpoint();

    // Notify GC completed
    _port.ack();

    // Handle allocation stalls
    handle_alloc_stalls();

    // Good point to consider back-to-back GC
    ZDirector::evaluate_rules();
  }
}

void ZDriverMinor::terminate() {
  const ZDriverRequest request(GCCause::_no_gc, 0, 0);
  _port.send_async(request);
}

static bool should_clear_soft_references(GCCause::Cause cause) {
  // Clear soft references if implied by the GC cause
  switch (cause) {
  case GCCause::_wb_full_gc:
  case GCCause::_metadata_GC_clear_soft_refs:
  case GCCause::_z_allocation_stall:
    return true;

  case GCCause::_heap_dump:
  case GCCause::_heap_inspection:
  case GCCause::_wb_breakpoint:
  case GCCause::_dcmd_gc_run:
  case GCCause::_java_lang_system_gc:
  case GCCause::_full_gc_alot:
  case GCCause::_jvmti_force_gc:
  case GCCause::_z_timer:
  case GCCause::_z_warmup:
  case GCCause::_z_allocation_rate:
  case GCCause::_z_proactive:
  case GCCause::_metadata_GC_threshold:
  case GCCause::_codecache_GC_threshold:
  case GCCause::_codecache_GC_aggressive:
    break;

  default:
    fatal("Unsupported GC cause (%s)", GCCause::to_string(cause));
    break;
  }

  // Clear soft references if threads are stalled waiting for an old collection
  if (ZHeap::heap()->is_alloc_stalling_for_old()) {
    return true;
  }

  // Don't clear
  return false;
}

static bool should_preclean_young(GCCause::Cause cause) {
  // Preclean young if implied by the GC cause
  switch (cause) {
  case GCCause::_heap_dump:
  case GCCause::_heap_inspection:
  case GCCause::_wb_full_gc:
  case GCCause::_wb_breakpoint:
  case GCCause::_dcmd_gc_run:
  case GCCause::_java_lang_system_gc:
  case GCCause::_full_gc_alot:
  case GCCause::_jvmti_force_gc:
  case GCCause::_metadata_GC_clear_soft_refs:
  case GCCause::_z_allocation_stall:
    return true;

  case GCCause::_z_timer:
  case GCCause::_z_warmup:
  case GCCause::_z_allocation_rate:
  case GCCause::_z_proactive:
  case GCCause::_metadata_GC_threshold:
  case GCCause::_codecache_GC_threshold:
  case GCCause::_codecache_GC_aggressive:
    break;

  default:
    fatal("Unsupported GC cause (%s)", GCCause::to_string(cause));
    break;
  }

  // Preclean young if threads are stalled waiting for an old collection
  if (ZHeap::heap()->is_alloc_stalling_for_old()) {
    return true;
  }

  // It is important that when soft references are cleared, we also pre-clean the young
  // generation, as we might otherwise throw premature OOM. Therefore, all causes that
  // trigger soft ref cleaning must also trigger pre-cleaning of young gen. If allocations
  // stalled when checking for soft ref cleaning, then since we hold the driver locker all
  // the way until we check for young gen pre-cleaning, we can be certain that we should
  // catch that above and perform young gen pre-cleaning.
  assert(!should_clear_soft_references(cause), "Clearing soft references without pre-cleaning young gen");

  // Preclean young if implied by configuration
  return ScavengeBeforeFullGC;
}

ZDriverMajor::ZDriverMajor()
  : ZDriver(),
    _port(),
    _gc_timer(),
    _jfr_tracer(),
    _used_at_start() {
  ZDriver::set_major(this);
  set_name("ZDriverMajor");
  create_and_start();
}

bool ZDriverMajor::is_busy() const {
  return _port.is_busy();
}

void ZDriverMajor::collect(const ZDriverRequest& request) {
  switch (request.cause()) {
  case GCCause::_heap_dump:
  case GCCause::_heap_inspection:
  case GCCause::_wb_full_gc:
  case GCCause::_dcmd_gc_run:
  case GCCause::_java_lang_system_gc:
  case GCCause::_full_gc_alot:
  case GCCause::_jvmti_force_gc:
  case GCCause::_metadata_GC_clear_soft_refs:
  case GCCause::_codecache_GC_aggressive:
    // Start synchronous GC
    _port.send_sync(request);
    break;

  case GCCause::_z_timer:
  case GCCause::_z_warmup:
  case GCCause::_z_allocation_rate:
  case GCCause::_z_allocation_stall:
  case GCCause::_z_proactive:
  case GCCause::_codecache_GC_threshold:
  case GCCause::_metadata_GC_threshold:
    // Start asynchronous GC
    _port.send_async(request);
    break;

  case GCCause::_wb_breakpoint:
    ZBreakpoint::start_gc();
    _port.send_async(request);
    break;

  default:
    fatal("Unsupported GC cause (%s)", GCCause::to_string(request.cause()));
    break;
  }
}

GCTracer* ZDriverMajor::jfr_tracer() {
  return &_jfr_tracer;
}

void ZDriverMajor::set_used_at_start(size_t used) {
  _used_at_start = used;
}

size_t ZDriverMajor::used_at_start() const {
  return _used_at_start;
}

class ZDriverScopeMajor : public StackObj {
private:
  GCIdMark                     _gc_id;
  GCCause::Cause               _gc_cause;
  ZGCCauseSetter<ZDriverMajor> _gc_cause_setter;
  ZStatTimer                   _stat_timer;
  ZServiceabilityCycleTracer   _tracer;

public:
  ZDriverScopeMajor(const ZDriverRequest& request, ConcurrentGCTimer* gc_timer)
    : _gc_id(),
      _gc_cause(request.cause()),
      _gc_cause_setter(ZDriver::major(), _gc_cause),
      _stat_timer(ZPhaseCollectionMajor, gc_timer),
      _tracer(false /* minor */) {
    // Select number of worker threads to use
    ZGeneration::young()->set_active_workers(request.young_nworkers());
    ZGeneration::old()->set_active_workers(request.old_nworkers());
  }

  ~ZDriverScopeMajor() {
    // Update data used by soft reference policy
    ZCollectedHeap::heap()->update_capacity_and_used_at_gc();

    // Signal that we have completed a visit to all live objects
    ZCollectedHeap::heap()->record_whole_heap_examined_timestamp();
  }
};

void ZDriverMajor::collect_young(const ZDriverRequest& request) {
  ZGCIdMajor major_id(gc_id(), 'Y');
  if (should_preclean_young(request.cause())) {
    // Collect young generation and promote everything to old generation
    ZGeneration::young()->collect(ZYoungType::major_full_preclean, &_gc_timer);

    abortpoint();

    // Collect young generation and gather roots pointing into old generation
    ZGeneration::young()->collect(ZYoungType::major_full_roots, &_gc_timer);
  } else {
    // Collect young generation and gather roots pointing into old generation
    ZGeneration::young()->collect(ZYoungType::major_partial_roots, &_gc_timer);
  }

  abortpoint();

  // Handle allocations waiting for a young collection
  handle_alloc_stalling_for_young();
}

void ZDriverMajor::collect_old() {
  ZGCIdMajor major_id(gc_id(), 'O');
  ZGeneration::old()->collect(&_gc_timer);
}

void ZDriverMajor::gc(const ZDriverRequest& request) {
  ZDriverScopeMajor scope(request, &_gc_timer);

  // Collect the young generation
  collect_young(request);

  abortpoint();

  // Collect the old generation
  collect_old();
}

static void handle_alloc_stalling_for_old(bool cleared_soft_refs) {
  ZHeap::heap()->handle_alloc_stalling_for_old(cleared_soft_refs);
}

void ZDriverMajor::handle_alloc_stalls(bool cleared_soft_refs) const {
  handle_alloc_stalling_for_old(cleared_soft_refs);
}

void ZDriverMajor::run_thread() {
  // Main loop
  for (;;) {
    // Wait for GC request
    const ZDriverRequest request = _port.receive();

    ZDriverLocker locker;

    ZBreakpoint::at_before_gc();

    abortpoint();

    // Set up soft reference policy
    const bool clear_soft_refs = should_clear_soft_references(request.cause());
    ZGeneration::old()->set_soft_reference_policy(clear_soft_refs);

    // Run GC
    gc(request);

    abortpoint();

    // Notify GC completed
    _port.ack();

    // Handle allocation stalls
    handle_alloc_stalls(clear_soft_refs);

    ZBreakpoint::at_after_gc();
  }
}

void ZDriverMajor::terminate() {
  const ZDriverRequest request(GCCause::_no_gc, 0, 0);
  _port.send_async(request);
}
