/*
 * Copyright (c) 2012, 2023, 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 "precompiled.hpp"
#include "jvm.h"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/metaspaceUtils.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vmOperations.hpp"
#include "services/memBaseline.hpp"
#include "services/memReporter.hpp"
#include "services/mallocLimit.hpp"
#include "services/mallocTracker.hpp"
#include "services/memTracker.hpp"
#include "services/nmtCommon.hpp"
#include "services/nmtPreInit.hpp"
#include "services/threadStackTracker.hpp"
#include "utilities/debug.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/vmError.hpp"

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

NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;

MemBaseline MemTracker::_baseline;

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 type is encoded into tracking header as a byte field,
  // make sure that we don't overflow it.
  STATIC_ASSERT(mt_number_of_types <= max_jubyte);

  if (level > NMT_off) {
    if (!MallocTracker::initialize(level) ||
        !VirtualMemoryTracker::initialize(level) ||
        !ThreadStackTracker::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);
  }
}

void Tracker::record(address addr, size_t size) {
  if (MemTracker::tracking_level() < NMT_summary) return;
  switch(_type) {
    case uncommit:
      VirtualMemoryTracker::remove_uncommitted_region(addr, size);
      break;
    case release:
      VirtualMemoryTracker::remove_released_region(addr, size);
        break;
    default:
      ShouldNotReachHere();
  }
}

// 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));
  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();
}
