//===-- Statistics.cpp ----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/Statistics.h"

#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/StructuredData.h"

using namespace lldb;
using namespace lldb_private;
using namespace llvm;

static void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
                              const std::string &str) {
  if (str.empty())
    return;
  if (LLVM_LIKELY(llvm::json::isUTF8(str)))
    obj.try_emplace(key, str);
  else
    obj.try_emplace(key, llvm::json::fixUTF8(str));
}

json::Value StatsSuccessFail::ToJSON() const {
  return json::Object{{"successes", successes}, {"failures", failures}};
}

static double elapsed(const StatsTimepoint &start, const StatsTimepoint &end) {
  StatsDuration::Duration elapsed =
      end.time_since_epoch() - start.time_since_epoch();
  return elapsed.count();
}

void TargetStats::CollectStats(Target &target) {
  m_module_identifiers.clear();
  for (ModuleSP module_sp : target.GetImages().Modules())
    m_module_identifiers.emplace_back((intptr_t)module_sp.get());
}

json::Value ModuleStats::ToJSON() const {
  json::Object module;
  EmplaceSafeString(module, "path", path);
  EmplaceSafeString(module, "uuid", uuid);
  EmplaceSafeString(module, "triple", triple);
  module.try_emplace("identifier", identifier);
  module.try_emplace("symbolTableParseTime", symtab_parse_time);
  module.try_emplace("symbolTableIndexTime", symtab_index_time);
  module.try_emplace("symbolTableLoadedFromCache", symtab_loaded_from_cache);
  module.try_emplace("symbolTableSavedToCache", symtab_saved_to_cache);
  module.try_emplace("debugInfoParseTime", debug_parse_time);
  module.try_emplace("debugInfoIndexTime", debug_index_time);
  module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
  module.try_emplace("debugInfoIndexLoadedFromCache",
                     debug_info_index_loaded_from_cache);
  module.try_emplace("debugInfoIndexSavedToCache",
                     debug_info_index_saved_to_cache);
  module.try_emplace("debugInfoEnabled", debug_info_enabled);
  module.try_emplace("debugInfoHadVariableErrors",
                     debug_info_had_variable_errors);
  module.try_emplace("debugInfoHadIncompleteTypes",
                     debug_info_had_incomplete_types);
  module.try_emplace("symbolTableStripped", symtab_stripped);
  module.try_emplace("symbolTableSymbolCount", symtab_symbol_count);

  if (!symbol_locator_time.map.empty()) {
    json::Object obj;
    for (const auto &entry : symbol_locator_time.map)
      obj.try_emplace(entry.first().str(), entry.second);
    module.try_emplace("symbolLocatorTime", std::move(obj));
  }

  if (!symfile_path.empty())
    module.try_emplace("symbolFilePath", symfile_path);

  if (!symfile_modules.empty()) {
    json::Array symfile_ids;
    for (const auto symfile_id: symfile_modules)
      symfile_ids.emplace_back(symfile_id);
    module.try_emplace("symbolFileModuleIdentifiers", std::move(symfile_ids));
  }

  if (!type_system_stats.empty()) {
    json::Array type_systems;
    for (const auto &entry : type_system_stats) {
      json::Object obj;
      obj.try_emplace(entry.first().str(), entry.second);
      type_systems.emplace_back(std::move(obj));
    }
    module.try_emplace("typeSystemInfo", std::move(type_systems));
  }

  return module;
}

llvm::json::Value ConstStringStats::ToJSON() const {
  json::Object obj;
  obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
  obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
  obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
  return obj;
}

json::Value
TargetStats::ToJSON(Target &target,
                    const lldb_private::StatisticsOptions &options) {
  json::Object target_metrics_json;
  ProcessSP process_sp = target.GetProcessSP();
  const bool summary_only = options.GetSummaryOnly();
  const bool include_modules = options.GetIncludeModules();
  if (!summary_only) {
    CollectStats(target);

    json::Array json_module_uuid_array;
    for (auto module_identifier : m_module_identifiers)
      json_module_uuid_array.emplace_back(module_identifier);

    target_metrics_json.try_emplace(m_expr_eval.name, m_expr_eval.ToJSON());
    target_metrics_json.try_emplace(m_frame_var.name, m_frame_var.ToJSON());
    if (include_modules)
      target_metrics_json.try_emplace("moduleIdentifiers",
                                      std::move(json_module_uuid_array));

    if (m_launch_or_attach_time && m_first_private_stop_time) {
      double elapsed_time =
          elapsed(*m_launch_or_attach_time, *m_first_private_stop_time);
      target_metrics_json.try_emplace("launchOrAttachTime", elapsed_time);
    }
    if (m_launch_or_attach_time && m_first_public_stop_time) {
      double elapsed_time =
          elapsed(*m_launch_or_attach_time, *m_first_public_stop_time);
      target_metrics_json.try_emplace("firstStopTime", elapsed_time);
    }
    target_metrics_json.try_emplace("targetCreateTime",
                                    m_create_time.get().count());

    json::Array breakpoints_array;
    double totalBreakpointResolveTime = 0.0;
    // Report both the normal breakpoint list and the internal breakpoint list.
    for (int i = 0; i < 2; ++i) {
      BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
      std::unique_lock<std::recursive_mutex> lock;
      breakpoints.GetListMutex(lock);
      size_t num_breakpoints = breakpoints.GetSize();
      for (size_t i = 0; i < num_breakpoints; i++) {
        Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
        breakpoints_array.push_back(bp->GetStatistics());
        totalBreakpointResolveTime += bp->GetResolveTime().count();
      }
    }
    target_metrics_json.try_emplace("breakpoints",
                                    std::move(breakpoints_array));
    target_metrics_json.try_emplace("totalBreakpointResolveTime",
                                    totalBreakpointResolveTime);

    if (process_sp) {
      UnixSignalsSP unix_signals_sp = process_sp->GetUnixSignals();
      if (unix_signals_sp)
        target_metrics_json.try_emplace(
            "signals", unix_signals_sp->GetHitCountStatistics());
    }
  }

  // Counting "totalSharedLibraryEventHitCount" from breakpoints of kind
  // "shared-library-event".
  {
    uint32_t shared_library_event_breakpoint_hit_count = 0;
    // The "shared-library-event" is only found in the internal breakpoint list.
    BreakpointList &breakpoints = target.GetBreakpointList(/* internal */ true);
    std::unique_lock<std::recursive_mutex> lock;
    breakpoints.GetListMutex(lock);
    size_t num_breakpoints = breakpoints.GetSize();
    for (size_t i = 0; i < num_breakpoints; i++) {
      Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
      if (strcmp(bp->GetBreakpointKind(), "shared-library-event") == 0)
        shared_library_event_breakpoint_hit_count += bp->GetHitCount();
    }

    target_metrics_json.try_emplace("totalSharedLibraryEventHitCount",
                                    shared_library_event_breakpoint_hit_count);
  }

  if (process_sp) {
    uint32_t stop_id = process_sp->GetStopID();
    target_metrics_json.try_emplace("stopCount", stop_id);

    llvm::StringRef dyld_plugin_name;
    if (process_sp->GetDynamicLoader())
      dyld_plugin_name = process_sp->GetDynamicLoader()->GetPluginName();
    target_metrics_json.try_emplace("dyldPluginName", dyld_plugin_name);
  }
  target_metrics_json.try_emplace("sourceMapDeduceCount",
                                  m_source_map_deduce_count);
  target_metrics_json.try_emplace("sourceRealpathAttemptCount",
                                  m_source_realpath_attempt_count);
  target_metrics_json.try_emplace("sourceRealpathCompatibleCount",
                                  m_source_realpath_compatible_count);
  target_metrics_json.try_emplace("summaryProviderStatistics",
                                  target.GetSummaryStatisticsCache().ToJSON());
  return target_metrics_json;
}

void TargetStats::Reset(Target &target) {
  m_launch_or_attach_time.reset();
  m_first_private_stop_time.reset();
  m_first_public_stop_time.reset();
  // Report both the normal breakpoint list and the internal breakpoint list.
  for (int i = 0; i < 2; ++i) {
    BreakpointList &breakpoints = target.GetBreakpointList(i == 1);
    std::unique_lock<std::recursive_mutex> lock;
    breakpoints.GetListMutex(lock);
    size_t num_breakpoints = breakpoints.GetSize();
    for (size_t i = 0; i < num_breakpoints; i++) {
      Breakpoint *bp = breakpoints.GetBreakpointAtIndex(i).get();
      bp->ResetStatistics();
    }
  }
  target.GetSummaryStatisticsCache().Reset();
}

void TargetStats::SetLaunchOrAttachTime() {
  m_launch_or_attach_time = StatsClock::now();
  m_first_private_stop_time = std::nullopt;
}

void TargetStats::SetFirstPrivateStopTime() {
  // Launching and attaching has many paths depending on if synchronous mode
  // was used or if we are stopping at the entry point or not. Only set the
  // first stop time if it hasn't already been set.
  if (!m_first_private_stop_time)
    m_first_private_stop_time = StatsClock::now();
}

void TargetStats::SetFirstPublicStopTime() {
  // Launching and attaching has many paths depending on if synchronous mode
  // was used or if we are stopping at the entry point or not. Only set the
  // first stop time if it hasn't already been set.
  if (!m_first_public_stop_time)
    m_first_public_stop_time = StatsClock::now();
}

void TargetStats::IncreaseSourceMapDeduceCount() {
  ++m_source_map_deduce_count;
}

void TargetStats::IncreaseSourceRealpathAttemptCount(uint32_t count) {
  m_source_realpath_attempt_count += count;
}

void TargetStats::IncreaseSourceRealpathCompatibleCount(uint32_t count) {
  m_source_realpath_compatible_count += count;
}

bool DebuggerStats::g_collecting_stats = false;

void DebuggerStats::ResetStatistics(Debugger &debugger, Target *target) {
  std::lock_guard<std::recursive_mutex> guard(
      Module::GetAllocationModuleCollectionMutex());
  const uint64_t num_modules = target != nullptr
                                   ? target->GetImages().GetSize()
                                   : Module::GetNumberAllocatedModules();
  for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
    Module *module = target != nullptr
                         ? target->GetImages().GetModuleAtIndex(image_idx).get()
                         : Module::GetAllocatedModuleAtIndex(image_idx);
    if (module == nullptr)
      continue;
    module->ResetStatistics();
  }
  if (target)
    target->ResetStatistics();
  else {
    for (const auto &target : debugger.GetTargetList().Targets())
      target->ResetStatistics();
  }
}

llvm::json::Value DebuggerStats::ReportStatistics(
    Debugger &debugger, Target *target,
    const lldb_private::StatisticsOptions &options) {

  const bool summary_only = options.GetSummaryOnly();
  const bool load_all_debug_info = options.GetLoadAllDebugInfo();
  const bool include_targets = options.GetIncludeTargets();
  const bool include_modules = options.GetIncludeModules();
  const bool include_transcript = options.GetIncludeTranscript();
  const bool include_plugins = options.GetIncludePlugins();

  json::Array json_targets;
  json::Array json_modules;
  StatisticsMap symbol_locator_total_time;
  double symtab_parse_time = 0.0;
  double symtab_index_time = 0.0;
  double debug_parse_time = 0.0;
  double debug_index_time = 0.0;
  uint32_t symtabs_loaded = 0;
  uint32_t symtabs_loaded_from_cache = 0;
  uint32_t symtabs_saved_to_cache = 0;
  uint32_t debug_index_loaded = 0;
  uint32_t debug_index_saved = 0;
  uint64_t debug_info_size = 0;

  std::lock_guard<std::recursive_mutex> guard(
      Module::GetAllocationModuleCollectionMutex());
  const uint64_t num_modules = target != nullptr
                                   ? target->GetImages().GetSize()
                                   : Module::GetNumberAllocatedModules();
  uint32_t num_debug_info_enabled_modules = 0;
  uint32_t num_modules_has_debug_info = 0;
  uint32_t num_modules_with_variable_errors = 0;
  uint32_t num_modules_with_incomplete_types = 0;
  uint32_t num_stripped_modules = 0;
  uint32_t symtab_symbol_count = 0;
  for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
    Module *module = target != nullptr
                         ? target->GetImages().GetModuleAtIndex(image_idx).get()
                         : Module::GetAllocatedModuleAtIndex(image_idx);
    ModuleStats module_stat;
    module_stat.symtab_parse_time = module->GetSymtabParseTime().get().count();
    module_stat.symtab_index_time = module->GetSymtabIndexTime().get().count();
    module_stat.symbol_locator_time = module->GetSymbolLocatorStatistics();
    symbol_locator_total_time.merge(module_stat.symbol_locator_time);
    Symtab *symtab = module->GetSymtab(/*can_create=*/false);
    if (symtab) {
      module_stat.symtab_symbol_count = symtab->GetNumSymbols();
      symtab_symbol_count += module_stat.symtab_symbol_count;
      ++symtabs_loaded;
      module_stat.symtab_loaded_from_cache = symtab->GetWasLoadedFromCache();
      if (module_stat.symtab_loaded_from_cache)
        ++symtabs_loaded_from_cache;
      module_stat.symtab_saved_to_cache = symtab->GetWasSavedToCache();
      if (module_stat.symtab_saved_to_cache)
        ++symtabs_saved_to_cache;
    }
    SymbolFile *sym_file = module->GetSymbolFile(/*can_create=*/false);
    if (sym_file) {
      if (!summary_only) {
        if (sym_file->GetObjectFile() != module->GetObjectFile())
          module_stat.symfile_path =
              sym_file->GetObjectFile()->GetFileSpec().GetPath();
        ModuleList symbol_modules = sym_file->GetDebugInfoModules();
        for (const auto &symbol_module : symbol_modules.Modules())
          module_stat.symfile_modules.push_back((intptr_t)symbol_module.get());
      }
      module_stat.debug_info_index_loaded_from_cache =
          sym_file->GetDebugInfoIndexWasLoadedFromCache();
      if (module_stat.debug_info_index_loaded_from_cache)
        ++debug_index_loaded;
      module_stat.debug_info_index_saved_to_cache =
          sym_file->GetDebugInfoIndexWasSavedToCache();
      if (module_stat.debug_info_index_saved_to_cache)
        ++debug_index_saved;
      module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
      module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
      module_stat.debug_info_size =
          sym_file->GetDebugInfoSize(load_all_debug_info);
      module_stat.symtab_stripped = module->GetObjectFile()->IsStripped();
      if (module_stat.symtab_stripped)
        ++num_stripped_modules;
      module_stat.debug_info_enabled = sym_file->GetLoadDebugInfoEnabled() &&
                                       module_stat.debug_info_size > 0;
      module_stat.debug_info_had_variable_errors =
          sym_file->GetDebugInfoHadFrameVariableErrors();
      if (module_stat.debug_info_enabled)
        ++num_debug_info_enabled_modules;
      if (module_stat.debug_info_size > 0)
        ++num_modules_has_debug_info;
      if (module_stat.debug_info_had_variable_errors)
        ++num_modules_with_variable_errors;
    }
    symtab_parse_time += module_stat.symtab_parse_time;
    symtab_index_time += module_stat.symtab_index_time;
    debug_parse_time += module_stat.debug_parse_time;
    debug_index_time += module_stat.debug_index_time;
    debug_info_size += module_stat.debug_info_size;
    module->ForEachTypeSystem([&](lldb::TypeSystemSP ts) {
      if (auto stats = ts->ReportStatistics())
        module_stat.type_system_stats.insert({ts->GetPluginName(), *stats});
      if (ts->GetHasForcefullyCompletedTypes())
        module_stat.debug_info_had_incomplete_types = true;
      return true;
    });
    if (module_stat.debug_info_had_incomplete_types)
      ++num_modules_with_incomplete_types;

    if (include_modules) {
      module_stat.identifier = (intptr_t)module;
      module_stat.path = module->GetFileSpec().GetPath();
      if (ConstString object_name = module->GetObjectName()) {
        module_stat.path.append(1, '(');
        module_stat.path.append(object_name.GetStringRef().str());
        module_stat.path.append(1, ')');
      }
      module_stat.uuid = module->GetUUID().GetAsString();
      module_stat.triple = module->GetArchitecture().GetTriple().str();
      json_modules.emplace_back(module_stat.ToJSON());
    }
  }

  json::Object global_stats{
      {"totalSymbolTableParseTime", symtab_parse_time},
      {"totalSymbolTableIndexTime", symtab_index_time},
      {"totalSymbolTablesLoaded", symtabs_loaded},
      {"totalSymbolTablesLoadedFromCache", symtabs_loaded_from_cache},
      {"totalSymbolTablesSavedToCache", symtabs_saved_to_cache},
      {"totalDebugInfoParseTime", debug_parse_time},
      {"totalDebugInfoIndexTime", debug_index_time},
      {"totalDebugInfoIndexLoadedFromCache", debug_index_loaded},
      {"totalDebugInfoIndexSavedToCache", debug_index_saved},
      {"totalDebugInfoByteSize", debug_info_size},
      {"totalModuleCount", num_modules},
      {"totalModuleCountHasDebugInfo", num_modules_has_debug_info},
      {"totalModuleCountWithVariableErrors", num_modules_with_variable_errors},
      {"totalModuleCountWithIncompleteTypes",
       num_modules_with_incomplete_types},
      {"totalDebugInfoEnabled", num_debug_info_enabled_modules},
      {"totalSymbolTableStripped", num_stripped_modules},
      {"totalSymbolTableSymbolCount", symtab_symbol_count},
  };

  if (include_targets) {
    if (target) {
      json_targets.emplace_back(target->ReportStatistics(options));
    } else {
      for (const auto &target : debugger.GetTargetList().Targets())
        json_targets.emplace_back(target->ReportStatistics(options));
    }
    global_stats.try_emplace("targets", std::move(json_targets));
  }

  if (!symbol_locator_total_time.map.empty()) {
    json::Object obj;
    for (const auto &entry : symbol_locator_total_time.map)
      obj.try_emplace(entry.first().str(), entry.second);
    global_stats.try_emplace("totalSymbolLocatorTime", std::move(obj));
  }

  ConstStringStats const_string_stats;
  json::Object json_memory{
      {"strings", const_string_stats.ToJSON()},
  };
  global_stats.try_emplace("memory", std::move(json_memory));
  if (!summary_only) {
    json::Value cmd_stats = debugger.GetCommandInterpreter().GetStatistics();
    global_stats.try_emplace("commands", std::move(cmd_stats));
  }

  if (include_modules) {
    global_stats.try_emplace("modules", std::move(json_modules));
  }

  if (include_transcript) {
    // When transcript is available, add it to the to-be-returned statistics.
    //
    // NOTE:
    // When the statistics is polled by an LLDB command:
    // - The transcript in the returned statistics *will NOT* contain the
    //   returned statistics itself (otherwise infinite recursion).
    // - The returned statistics *will* be written to the internal transcript
    //   buffer. It *will* appear in the next statistcs or transcript poll.
    //
    // For example, let's say the following commands are run in order:
    // - "version"
    // - "statistics dump"  <- call it "A"
    // - "statistics dump"  <- call it "B"
    // The output of "A" will contain the transcript of "version" and
    // "statistics dump" (A), with the latter having empty output. The output
    // of B will contain the trascnript of "version", "statistics dump" (A),
    // "statistics dump" (B), with A's output populated and B's output empty.
    const StructuredData::Array &transcript =
        debugger.GetCommandInterpreter().GetTranscript();
    if (transcript.GetSize() != 0) {
      std::string buffer;
      llvm::raw_string_ostream ss(buffer);
      json::OStream json_os(ss);
      transcript.Serialize(json_os);
      if (auto json_transcript = llvm::json::parse(buffer))
        global_stats.try_emplace("transcript",
                                 std::move(json_transcript.get()));
    }
  }

  if (include_plugins) {
    global_stats.try_emplace("plugins", PluginManager::GetJSON());
  }

  return std::move(global_stats);
}

llvm::json::Value SummaryStatistics::ToJSON() const {
  return json::Object{{
      {"name", GetName()},
      {"type", GetSummaryKindName()},
      {"count", GetSummaryCount()},
      {"totalTime", GetTotalTime()},
  }};
}

json::Value SummaryStatisticsCache::ToJSON() {
  std::lock_guard<std::mutex> guard(m_map_mutex);
  json::Array json_summary_stats;
  for (const auto &summary_stat : m_summary_stats_map)
    json_summary_stats.emplace_back(summary_stat.second->ToJSON());

  return json_summary_stats;
}

void SummaryStatisticsCache::Reset() {
  for (const auto &summary_stat : m_summary_stats_map)
    summary_stat.second->Reset();
}
