// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/inspector/v8-profiler-agent-impl.h"

#include <vector>

#include "src/base/atomicops.h"
#include "src/debug/debug-interface.h"
#include "src/flags.h"  // TODO(jgruber): Remove include and DEPS entry.
#include "src/inspector/protocol/Protocol.h"
#include "src/inspector/string-util.h"
#include "src/inspector/v8-debugger.h"
#include "src/inspector/v8-inspector-impl.h"
#include "src/inspector/v8-inspector-session-impl.h"
#include "src/inspector/v8-stack-trace-impl.h"

#include "include/v8-profiler.h"

namespace v8_inspector {

namespace ProfilerAgentState {
static const char samplingInterval[] = "samplingInterval";
static const char userInitiatedProfiling[] = "userInitiatedProfiling";
static const char profilerEnabled[] = "profilerEnabled";
static const char preciseCoverageStarted[] = "preciseCoverageStarted";
static const char preciseCoverageCallCount[] = "preciseCoverageCallCount";
static const char preciseCoverageDetailed[] = "preciseCoverageDetailed";
static const char typeProfileStarted[] = "typeProfileStarted";
}

namespace {

String16 resourceNameToUrl(V8InspectorImpl* inspector,
                           v8::Local<v8::String> v8Name) {
  String16 name = toProtocolString(inspector->isolate(), v8Name);
  if (!inspector) return name;
  std::unique_ptr<StringBuffer> url =
      inspector->client()->resourceNameToUrl(toStringView(name));
  return url ? toString16(url->string()) : name;
}

std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>>
buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) {
  unsigned lineCount = node->GetHitLineCount();
  if (!lineCount) return nullptr;
  auto array = protocol::Array<protocol::Profiler::PositionTickInfo>::create();
  std::vector<v8::CpuProfileNode::LineTick> entries(lineCount);
  if (node->GetLineTicks(&entries[0], lineCount)) {
    for (unsigned i = 0; i < lineCount; i++) {
      std::unique_ptr<protocol::Profiler::PositionTickInfo> line =
          protocol::Profiler::PositionTickInfo::create()
              .setLine(entries[i].line)
              .setTicks(entries[i].hit_count)
              .build();
      array->addItem(std::move(line));
    }
  }
  return array;
}

std::unique_ptr<protocol::Profiler::ProfileNode> buildInspectorObjectFor(
    V8InspectorImpl* inspector, const v8::CpuProfileNode* node) {
  v8::Isolate* isolate = inspector->isolate();
  v8::HandleScope handleScope(isolate);
  auto callFrame =
      protocol::Runtime::CallFrame::create()
          .setFunctionName(toProtocolString(isolate, node->GetFunctionName()))
          .setScriptId(String16::fromInteger(node->GetScriptId()))
          .setUrl(resourceNameToUrl(inspector, node->GetScriptResourceName()))
          .setLineNumber(node->GetLineNumber() - 1)
          .setColumnNumber(node->GetColumnNumber() - 1)
          .build();
  auto result = protocol::Profiler::ProfileNode::create()
                    .setCallFrame(std::move(callFrame))
                    .setHitCount(node->GetHitCount())
                    .setId(node->GetNodeId())
                    .build();

  const int childrenCount = node->GetChildrenCount();
  if (childrenCount) {
    auto children = protocol::Array<int>::create();
    for (int i = 0; i < childrenCount; i++)
      children->addItem(node->GetChild(i)->GetNodeId());
    result->setChildren(std::move(children));
  }

  const char* deoptReason = node->GetBailoutReason();
  if (deoptReason && deoptReason[0] && strcmp(deoptReason, "no reason"))
    result->setDeoptReason(deoptReason);

  auto positionTicks = buildInspectorObjectForPositionTicks(node);
  if (positionTicks) result->setPositionTicks(std::move(positionTicks));

  return result;
}

std::unique_ptr<protocol::Array<int>> buildInspectorObjectForSamples(
    v8::CpuProfile* v8profile) {
  auto array = protocol::Array<int>::create();
  int count = v8profile->GetSamplesCount();
  for (int i = 0; i < count; i++)
    array->addItem(v8profile->GetSample(i)->GetNodeId());
  return array;
}

std::unique_ptr<protocol::Array<int>> buildInspectorObjectForTimestamps(
    v8::CpuProfile* v8profile) {
  auto array = protocol::Array<int>::create();
  int count = v8profile->GetSamplesCount();
  uint64_t lastTime = v8profile->GetStartTime();
  for (int i = 0; i < count; i++) {
    uint64_t ts = v8profile->GetSampleTimestamp(i);
    array->addItem(static_cast<int>(ts - lastTime));
    lastTime = ts;
  }
  return array;
}

void flattenNodesTree(V8InspectorImpl* inspector,
                      const v8::CpuProfileNode* node,
                      protocol::Array<protocol::Profiler::ProfileNode>* list) {
  list->addItem(buildInspectorObjectFor(inspector, node));
  const int childrenCount = node->GetChildrenCount();
  for (int i = 0; i < childrenCount; i++)
    flattenNodesTree(inspector, node->GetChild(i), list);
}

std::unique_ptr<protocol::Profiler::Profile> createCPUProfile(
    V8InspectorImpl* inspector, v8::CpuProfile* v8profile) {
  auto nodes = protocol::Array<protocol::Profiler::ProfileNode>::create();
  flattenNodesTree(inspector, v8profile->GetTopDownRoot(), nodes.get());
  return protocol::Profiler::Profile::create()
      .setNodes(std::move(nodes))
      .setStartTime(static_cast<double>(v8profile->GetStartTime()))
      .setEndTime(static_cast<double>(v8profile->GetEndTime()))
      .setSamples(buildInspectorObjectForSamples(v8profile))
      .setTimeDeltas(buildInspectorObjectForTimestamps(v8profile))
      .build();
}

std::unique_ptr<protocol::Debugger::Location> currentDebugLocation(
    V8InspectorImpl* inspector) {
  std::unique_ptr<V8StackTraceImpl> callStack =
      inspector->debugger()->captureStackTrace(false /* fullStack */);
  auto location = protocol::Debugger::Location::create()
                      .setScriptId(toString16(callStack->topScriptId()))
                      .setLineNumber(callStack->topLineNumber())
                      .build();
  location->setColumnNumber(callStack->topColumnNumber());
  return location;
}

volatile int s_lastProfileId = 0;

}  // namespace

class V8ProfilerAgentImpl::ProfileDescriptor {
 public:
  ProfileDescriptor(const String16& id, const String16& title)
      : m_id(id), m_title(title) {}
  String16 m_id;
  String16 m_title;
};

V8ProfilerAgentImpl::V8ProfilerAgentImpl(
    V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel,
    protocol::DictionaryValue* state)
    : m_session(session),
      m_isolate(m_session->inspector()->isolate()),
      m_state(state),
      m_frontend(frontendChannel) {}

V8ProfilerAgentImpl::~V8ProfilerAgentImpl() {
  if (m_profiler) m_profiler->Dispose();
}

void V8ProfilerAgentImpl::consoleProfile(const String16& title) {
  if (!m_enabled) return;
  String16 id = nextProfileId();
  m_startedProfiles.push_back(ProfileDescriptor(id, title));
  startProfiling(id);
  m_frontend.consoleProfileStarted(
      id, currentDebugLocation(m_session->inspector()), title);
}

void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) {
  if (!m_enabled) return;
  String16 id;
  String16 resolvedTitle;
  // Take last started profile if no title was passed.
  if (title.isEmpty()) {
    if (m_startedProfiles.empty()) return;
    id = m_startedProfiles.back().m_id;
    resolvedTitle = m_startedProfiles.back().m_title;
    m_startedProfiles.pop_back();
  } else {
    for (size_t i = 0; i < m_startedProfiles.size(); i++) {
      if (m_startedProfiles[i].m_title == title) {
        resolvedTitle = title;
        id = m_startedProfiles[i].m_id;
        m_startedProfiles.erase(m_startedProfiles.begin() + i);
        break;
      }
    }
    if (id.isEmpty()) return;
  }
  std::unique_ptr<protocol::Profiler::Profile> profile =
      stopProfiling(id, true);
  if (!profile) return;
  std::unique_ptr<protocol::Debugger::Location> location =
      currentDebugLocation(m_session->inspector());
  m_frontend.consoleProfileFinished(id, std::move(location), std::move(profile),
                                    resolvedTitle);
}

Response V8ProfilerAgentImpl::enable() {
  if (m_enabled) return Response::OK();
  m_enabled = true;
  m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
  return Response::OK();
}

Response V8ProfilerAgentImpl::disable() {
  if (!m_enabled) return Response::OK();
  for (size_t i = m_startedProfiles.size(); i > 0; --i)
    stopProfiling(m_startedProfiles[i - 1].m_id, false);
  m_startedProfiles.clear();
  stop(nullptr);
  stopPreciseCoverage();
  DCHECK(!m_profiler);
  m_enabled = false;
  m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
  return Response::OK();
}

Response V8ProfilerAgentImpl::setSamplingInterval(int interval) {
  if (m_profiler) {
    return Response::Error("Cannot change sampling interval when profiling.");
  }
  m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
  return Response::OK();
}

void V8ProfilerAgentImpl::restore() {
  DCHECK(!m_enabled);
  if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false))
    return;
  m_enabled = true;
  DCHECK(!m_profiler);
  if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling,
                               false)) {
    start();
  }
  if (m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
                               false)) {
    bool callCount = m_state->booleanProperty(
        ProfilerAgentState::preciseCoverageCallCount, false);
    bool detailed = m_state->booleanProperty(
        ProfilerAgentState::preciseCoverageDetailed, false);
    startPreciseCoverage(Maybe<bool>(callCount), Maybe<bool>(detailed));
  }
}

Response V8ProfilerAgentImpl::start() {
  if (m_recordingCPUProfile) return Response::OK();
  if (!m_enabled) return Response::Error("Profiler is not enabled");
  m_recordingCPUProfile = true;
  m_frontendInitiatedProfileId = nextProfileId();
  startProfiling(m_frontendInitiatedProfileId);
  m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
  return Response::OK();
}

Response V8ProfilerAgentImpl::stop(
    std::unique_ptr<protocol::Profiler::Profile>* profile) {
  if (!m_recordingCPUProfile) {
    return Response::Error("No recording profiles found");
  }
  m_recordingCPUProfile = false;
  std::unique_ptr<protocol::Profiler::Profile> cpuProfile =
      stopProfiling(m_frontendInitiatedProfileId, !!profile);
  if (profile) {
    *profile = std::move(cpuProfile);
    if (!profile->get()) return Response::Error("Profile is not found");
  }
  m_frontendInitiatedProfileId = String16();
  m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
  return Response::OK();
}

Response V8ProfilerAgentImpl::startPreciseCoverage(Maybe<bool> callCount,
                                                   Maybe<bool> detailed) {
  if (!m_enabled) return Response::Error("Profiler is not enabled");
  bool callCountValue = callCount.fromMaybe(false);
  bool detailedValue = detailed.fromMaybe(false);
  m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, true);
  m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount,
                      callCountValue);
  m_state->setBoolean(ProfilerAgentState::preciseCoverageDetailed,
                      detailedValue);
  // BlockCount is a superset of PreciseCount. It includes block-granularity
  // coverage data if it exists (at the time of writing, that's the case for
  // each function recompiled after the BlockCount mode has been set); and
  // function-granularity coverage data otherwise.
  typedef v8::debug::Coverage C;
  C::Mode mode = callCountValue
                     ? (detailedValue ? C::kBlockCount : C::kPreciseCount)
                     : (detailedValue ? C::kBlockBinary : C::kPreciseBinary);
  C::SelectMode(m_isolate, mode);
  return Response::OK();
}

Response V8ProfilerAgentImpl::stopPreciseCoverage() {
  if (!m_enabled) return Response::Error("Profiler is not enabled");
  m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, false);
  m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount, false);
  m_state->setBoolean(ProfilerAgentState::preciseCoverageDetailed, false);
  v8::debug::Coverage::SelectMode(m_isolate, v8::debug::Coverage::kBestEffort);
  return Response::OK();
}

namespace {
std::unique_ptr<protocol::Profiler::CoverageRange> createCoverageRange(
    int start, int end, int count) {
  return protocol::Profiler::CoverageRange::create()
      .setStartOffset(start)
      .setEndOffset(end)
      .setCount(count)
      .build();
}

Response coverageToProtocol(
    V8InspectorImpl* inspector, const v8::debug::Coverage& coverage,
    std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
        out_result) {
  std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>> result =
      protocol::Array<protocol::Profiler::ScriptCoverage>::create();
  v8::Isolate* isolate = inspector->isolate();
  for (size_t i = 0; i < coverage.ScriptCount(); i++) {
    v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(i);
    v8::Local<v8::debug::Script> script = script_data.GetScript();
    std::unique_ptr<protocol::Array<protocol::Profiler::FunctionCoverage>>
        functions =
            protocol::Array<protocol::Profiler::FunctionCoverage>::create();
    for (size_t j = 0; j < script_data.FunctionCount(); j++) {
      v8::debug::Coverage::FunctionData function_data =
          script_data.GetFunctionData(j);
      std::unique_ptr<protocol::Array<protocol::Profiler::CoverageRange>>
          ranges = protocol::Array<protocol::Profiler::CoverageRange>::create();

      // Add function range.
      ranges->addItem(createCoverageRange(function_data.StartOffset(),
                                          function_data.EndOffset(),
                                          function_data.Count()));

      // Process inner blocks.
      for (size_t k = 0; k < function_data.BlockCount(); k++) {
        v8::debug::Coverage::BlockData block_data =
            function_data.GetBlockData(k);
        ranges->addItem(createCoverageRange(block_data.StartOffset(),
                                            block_data.EndOffset(),
                                            block_data.Count()));
      }

      functions->addItem(
          protocol::Profiler::FunctionCoverage::create()
              .setFunctionName(toProtocolString(
                  isolate,
                  function_data.Name().FromMaybe(v8::Local<v8::String>())))
              .setRanges(std::move(ranges))
              .setIsBlockCoverage(function_data.HasBlockCoverage())
              .build());
    }
    String16 url;
    v8::Local<v8::String> name;
    if (script->SourceURL().ToLocal(&name) && name->Length()) {
      url = toProtocolString(isolate, name);
    } else if (script->Name().ToLocal(&name) && name->Length()) {
      url = resourceNameToUrl(inspector, name);
    }
    result->addItem(protocol::Profiler::ScriptCoverage::create()
                        .setScriptId(String16::fromInteger(script->Id()))
                        .setUrl(url)
                        .setFunctions(std::move(functions))
                        .build());
  }
  *out_result = std::move(result);
  return Response::OK();
}
}  // anonymous namespace

Response V8ProfilerAgentImpl::takePreciseCoverage(
    std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
        out_result) {
  if (!m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
                                false)) {
    return Response::Error("Precise coverage has not been started.");
  }
  v8::HandleScope handle_scope(m_isolate);
  v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(m_isolate);
  return coverageToProtocol(m_session->inspector(), coverage, out_result);
}

Response V8ProfilerAgentImpl::getBestEffortCoverage(
    std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
        out_result) {
  v8::HandleScope handle_scope(m_isolate);
  v8::debug::Coverage coverage =
      v8::debug::Coverage::CollectBestEffort(m_isolate);
  return coverageToProtocol(m_session->inspector(), coverage, out_result);
}

namespace {
std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
typeProfileToProtocol(V8InspectorImpl* inspector,
                      const v8::debug::TypeProfile& type_profile) {
  std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
      result = protocol::Array<protocol::Profiler::ScriptTypeProfile>::create();
  v8::Isolate* isolate = inspector->isolate();
  for (size_t i = 0; i < type_profile.ScriptCount(); i++) {
    v8::debug::TypeProfile::ScriptData script_data =
        type_profile.GetScriptData(i);
    v8::Local<v8::debug::Script> script = script_data.GetScript();
    std::unique_ptr<protocol::Array<protocol::Profiler::TypeProfileEntry>>
        entries =
            protocol::Array<protocol::Profiler::TypeProfileEntry>::create();

    for (const auto& entry : script_data.Entries()) {
      std::unique_ptr<protocol::Array<protocol::Profiler::TypeObject>> types =
          protocol::Array<protocol::Profiler::TypeObject>::create();
      for (const auto& type : entry.Types()) {
        types->addItem(
            protocol::Profiler::TypeObject::create()
                .setName(toProtocolString(
                    isolate, type.FromMaybe(v8::Local<v8::String>())))
                .build());
      }
      entries->addItem(protocol::Profiler::TypeProfileEntry::create()
                           .setOffset(entry.SourcePosition())
                           .setTypes(std::move(types))
                           .build());
    }
    String16 url;
    v8::Local<v8::String> name;
    if (script->SourceURL().ToLocal(&name) && name->Length()) {
      url = toProtocolString(isolate, name);
    } else if (script->Name().ToLocal(&name) && name->Length()) {
      url = resourceNameToUrl(inspector, name);
    }
    result->addItem(protocol::Profiler::ScriptTypeProfile::create()
                        .setScriptId(String16::fromInteger(script->Id()))
                        .setUrl(url)
                        .setEntries(std::move(entries))
                        .build());
  }
  return result;
}
}  // anonymous namespace

Response V8ProfilerAgentImpl::startTypeProfile() {
  m_state->setBoolean(ProfilerAgentState::typeProfileStarted, true);
  v8::debug::TypeProfile::SelectMode(m_isolate,
                                     v8::debug::TypeProfile::kCollect);
  return Response::OK();
}

Response V8ProfilerAgentImpl::stopTypeProfile() {
  m_state->setBoolean(ProfilerAgentState::typeProfileStarted, false);
  v8::debug::TypeProfile::SelectMode(m_isolate, v8::debug::TypeProfile::kNone);
  return Response::OK();
}

Response V8ProfilerAgentImpl::takeTypeProfile(
    std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>*
        out_result) {
  if (!m_state->booleanProperty(ProfilerAgentState::typeProfileStarted,
                                false)) {
    return Response::Error("Type profile has not been started.");
  }
  v8::HandleScope handle_scope(m_isolate);
  v8::debug::TypeProfile type_profile =
      v8::debug::TypeProfile::Collect(m_isolate);
  *out_result = typeProfileToProtocol(m_session->inspector(), type_profile);
  return Response::OK();
}

String16 V8ProfilerAgentImpl::nextProfileId() {
  return String16::fromInteger(
      v8::base::Relaxed_AtomicIncrement(&s_lastProfileId, 1));
}

void V8ProfilerAgentImpl::startProfiling(const String16& title) {
  v8::HandleScope handleScope(m_isolate);
  if (!m_startedProfilesCount) {
    DCHECK(!m_profiler);
    m_profiler = v8::CpuProfiler::New(m_isolate);
    int interval =
        m_state->integerProperty(ProfilerAgentState::samplingInterval, 0);
    if (interval) m_profiler->SetSamplingInterval(interval);
  }
  ++m_startedProfilesCount;
  m_profiler->StartProfiling(toV8String(m_isolate, title), true);
}

std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling(
    const String16& title, bool serialize) {
  v8::HandleScope handleScope(m_isolate);
  v8::CpuProfile* profile =
      m_profiler->StopProfiling(toV8String(m_isolate, title));
  std::unique_ptr<protocol::Profiler::Profile> result;
  if (profile) {
    if (serialize) result = createCPUProfile(m_session->inspector(), profile);
    profile->Delete();
  }
  --m_startedProfilesCount;
  if (!m_startedProfilesCount) {
    m_profiler->Dispose();
    m_profiler = nullptr;
  }
  return result;
}

}  // namespace v8_inspector
