/*
 * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2020, 2023 SAP SE. 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 "jvm.h"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/metaspaceUtils.hpp"
#include "nmt/mallocLimit.hpp"
#include "nmt/mallocTracker.hpp"
#include "nmt/memBaseline.hpp"
#include "nmt/memReporter.hpp"
#include "nmt/memTracker.hpp"
#include "nmt/nmtCommon.hpp"
#include "nmt/nmtPreInit.hpp"
#include "nmt/threadStackTracker.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/vmOperations.hpp"
#include "runtime/vmThread.hpp"
#include "utilities/debug.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/deferred.hpp"
#include "utilities/vmError.hpp"

#ifdef _WINDOWS
#include <windows.h>
#endif

NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;

Deferred<MemBaseline> MemTracker::_baseline;

bool MemTracker::NmtVirtualMemoryLocker::_safe_to_use;

void MemTracker::initialize() {
  bool rc = true;
  assert(_tracking_level == NMT_unknown, "only call once");

  NMT_TrackingLevel level = NMTUtil::parse_tracking_level(NativeMemoryTracking);
  // Should have been validated before in arguments.cpp
  assert(level == NMT_off || level == NMT_summary || level == NMT_detail,
         "Invalid setting for NativeMemoryTracking (%s)", NativeMemoryTracking);

  // Memory tag is encoded into tracking header as a byte field,
  // make sure that we don't overflow it.
  STATIC_ASSERT(mt_number_of_tags <= max_jubyte);

  if (level > NMT_off) {
    _baseline.initialize();
    if (!MallocTracker::initialize(level) ||
        !MemoryFileTracker::Instance::initialize(level) ||
        !VirtualMemoryTracker::initialize(level)) {
      assert(false, "NMT initialization failed");
      level = NMT_off;
      log_warning(nmt)("NMT initialization failed. NMT disabled.");
      return;
    }
  } else {
    if (MallocLimit != nullptr) {
      warning("MallocLimit will be ignored since NMT is disabled.");
    }
  }

  NMTPreInit::pre_to_post(level == NMT_off);

  _tracking_level = level;

  // Log state right after NMT initialization
  if (log_is_enabled(Info, nmt)) {
    LogTarget(Info, nmt) lt;
    LogStream ls(lt);
    ls.print_cr("NMT initialized: %s", NMTUtil::tracking_level_to_string(_tracking_level));
    ls.print_cr("Preinit state: ");
    NMTPreInit::print_state(&ls);
    MallocLimitHandler::print_on(&ls);
  }
}

// Report during error reporting.
void MemTracker::error_report(outputStream* output) {
  if (enabled()) {
    report(true, output, MemReporterBase::default_scale); // just print summary for error case.
    output->print("Preinit state:");
    NMTPreInit::print_state(output);
    MallocLimitHandler::print_on(output);
  }
}

// Report when handling PrintNMTStatistics before VM shutdown.
static volatile bool g_final_report_did_run = false;
void MemTracker::final_report(outputStream* output) {
  // This function is called during both error reporting and normal VM exit.
  // However, it should only ever run once.  E.g. if the VM crashes after
  // printing the final report during normal VM exit, it should not print
  // the final report again. In addition, it should be guarded from
  // recursive calls in case NMT reporting itself crashes.
  if (enabled() && Atomic::cmpxchg(&g_final_report_did_run, false, true) == false) {
    report(tracking_level() == NMT_summary, output, 1);
  }
}

// Given an unknown pointer, check if it points into a known region; print region if found
// and return true; false if not found.
bool MemTracker::print_containing_region(const void* p, outputStream* out) {
  return enabled() &&
      (MallocTracker::print_pointer_information(p, out) ||
       VirtualMemoryTracker::print_containing_region(p, out));
}

void MemTracker::report(bool summary_only, outputStream* output, size_t scale) {
 assert(output != nullptr, "No output stream");
  MemBaseline baseline;
  baseline.baseline(summary_only);
  if (summary_only) {
    MemSummaryReporter rpt(baseline, output, scale);
    rpt.report();
  } else {
    MemDetailReporter rpt(baseline, output, scale);
    rpt.report();
    output->print("Metaspace:");
    // The basic metaspace report avoids any locking and should be safe to
    // be called at any time.
    MetaspaceUtils::print_basic_report(output, scale);
  }
}

void MemTracker::tuning_statistics(outputStream* out) {
  // NMT statistics
  out->print_cr("Native Memory Tracking Statistics:");
  out->print_cr("State: %s",
                NMTUtil::tracking_level_to_string(_tracking_level));
  if (_tracking_level == NMT_detail) {
    out->print_cr("Malloc allocation site table size: %d",
                  MallocSiteTable::hash_buckets());
    out->print_cr("             Tracking stack depth: %d",
                  NMT_TrackingStackDepth);
    out->cr();
    MallocSiteTable::print_tuning_statistics(out);
    out->cr();
  }
  out->print_cr("Preinit state:");
  NMTPreInit::print_state(out);
  MallocLimitHandler::print_on(out);
  out->cr();
}
