//===-- 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);
  module.try_emplace("dwoFileCount", dwo_stats.dwo_file_count);
  module.try_emplace("loadedDwoFileCount", dwo_stats.loaded_dwo_file_count);
  module.try_emplace("dwoErrorCount", dwo_stats.dwo_error_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());

    if (m_load_core_time.get().count() > 0) {
      target_metrics_json.try_emplace("loadCoreTime",
                                      m_load_core_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);

    if (process_sp->GetCoreFile())
      target_metrics_json.try_emplace("coreFile",
                                      process_sp->GetCoreFile().GetFilename());
  }
  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;
  DWOStats total_dwo_stats;
  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());
      }
      DWOStats current_dwo_stats = sym_file->GetDwoStats();
      module_stat.dwo_stats += current_dwo_stats;
      total_dwo_stats += current_dwo_stats;
      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},
      {"totalLoadedDwoFileCount", total_dwo_stats.loaded_dwo_file_count},
      {"totalDwoFileCount", total_dwo_stats.dwo_file_count},
      {"totalDwoErrorCount", total_dwo_stats.dwo_error_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();
}
