LCOV - code coverage report
Current view: top level - src/inspector - v8-profiler-agent-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 232 255 91.0 %
Date: 2017-10-20 Functions: 29 32 90.6 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/inspector/v8-profiler-agent-impl.h"
       6             : 
       7             : #include <vector>
       8             : 
       9             : #include "src/base/atomicops.h"
      10             : #include "src/flags.h"  // TODO(jgruber): Remove include and DEPS entry.
      11             : #include "src/inspector/protocol/Protocol.h"
      12             : #include "src/inspector/string-util.h"
      13             : #include "src/inspector/v8-debugger.h"
      14             : #include "src/inspector/v8-inspector-impl.h"
      15             : #include "src/inspector/v8-inspector-session-impl.h"
      16             : #include "src/inspector/v8-stack-trace-impl.h"
      17             : 
      18             : #include "include/v8-profiler.h"
      19             : 
      20             : namespace v8_inspector {
      21             : 
      22             : namespace ProfilerAgentState {
      23             : static const char samplingInterval[] = "samplingInterval";
      24             : static const char userInitiatedProfiling[] = "userInitiatedProfiling";
      25             : static const char profilerEnabled[] = "profilerEnabled";
      26             : static const char preciseCoverageStarted[] = "preciseCoverageStarted";
      27             : static const char preciseCoverageCallCount[] = "preciseCoverageCallCount";
      28             : static const char preciseCoverageDetailed[] = "preciseCoverageDetailed";
      29             : static const char typeProfileStarted[] = "typeProfileStarted";
      30             : }
      31             : 
      32             : namespace {
      33             : 
      34             : std::unique_ptr<protocol::Array<protocol::Profiler::PositionTickInfo>>
      35          93 : buildInspectorObjectForPositionTicks(const v8::CpuProfileNode* node) {
      36          93 :   unsigned lineCount = node->GetHitLineCount();
      37          93 :   if (!lineCount) return nullptr;
      38             :   auto array = protocol::Array<protocol::Profiler::PositionTickInfo>::create();
      39          16 :   std::vector<v8::CpuProfileNode::LineTick> entries(lineCount);
      40          16 :   if (node->GetLineTicks(&entries[0], lineCount)) {
      41          19 :     for (unsigned i = 0; i < lineCount; i++) {
      42             :       std::unique_ptr<protocol::Profiler::PositionTickInfo> line =
      43             :           protocol::Profiler::PositionTickInfo::create()
      44          38 :               .setLine(entries[i].line)
      45          38 :               .setTicks(entries[i].hit_count)
      46             :               .build();
      47          19 :       array->addItem(std::move(line));
      48             :     }
      49             :   }
      50             :   return array;
      51             : }
      52             : 
      53          93 : std::unique_ptr<protocol::Profiler::ProfileNode> buildInspectorObjectFor(
      54             :     v8::Isolate* isolate, const v8::CpuProfileNode* node) {
      55          93 :   v8::HandleScope handleScope(isolate);
      56             :   auto callFrame =
      57             :       protocol::Runtime::CallFrame::create()
      58         279 :           .setFunctionName(toProtocolString(node->GetFunctionName()))
      59         186 :           .setScriptId(String16::fromInteger(node->GetScriptId()))
      60         186 :           .setUrl(toProtocolString(node->GetScriptResourceName()))
      61          93 :           .setLineNumber(node->GetLineNumber() - 1)
      62          93 :           .setColumnNumber(node->GetColumnNumber() - 1)
      63             :           .build();
      64             :   auto result = protocol::Profiler::ProfileNode::create()
      65          93 :                     .setCallFrame(std::move(callFrame))
      66          93 :                     .setHitCount(node->GetHitCount())
      67          93 :                     .setId(node->GetNodeId())
      68             :                     .build();
      69             : 
      70          93 :   const int childrenCount = node->GetChildrenCount();
      71          93 :   if (childrenCount) {
      72             :     auto children = protocol::Array<int>::create();
      73         110 :     for (int i = 0; i < childrenCount; i++)
      74         128 :       children->addItem(node->GetChild(i)->GetNodeId());
      75             :     result->setChildren(std::move(children));
      76             :   }
      77             : 
      78          93 :   const char* deoptReason = node->GetBailoutReason();
      79          93 :   if (deoptReason && deoptReason[0] && strcmp(deoptReason, "no reason"))
      80           0 :     result->setDeoptReason(deoptReason);
      81             : 
      82          93 :   auto positionTicks = buildInspectorObjectForPositionTicks(node);
      83          93 :   if (positionTicks) result->setPositionTicks(std::move(positionTicks));
      84             : 
      85          93 :   return result;
      86             : }
      87             : 
      88          29 : std::unique_ptr<protocol::Array<int>> buildInspectorObjectForSamples(
      89             :     v8::CpuProfile* v8profile) {
      90             :   auto array = protocol::Array<int>::create();
      91          29 :   int count = v8profile->GetSamplesCount();
      92          95 :   for (int i = 0; i < count; i++)
      93         132 :     array->addItem(v8profile->GetSample(i)->GetNodeId());
      94          29 :   return array;
      95             : }
      96             : 
      97          29 : std::unique_ptr<protocol::Array<int>> buildInspectorObjectForTimestamps(
      98             :     v8::CpuProfile* v8profile) {
      99             :   auto array = protocol::Array<int>::create();
     100          29 :   int count = v8profile->GetSamplesCount();
     101          29 :   uint64_t lastTime = v8profile->GetStartTime();
     102          95 :   for (int i = 0; i < count; i++) {
     103          66 :     uint64_t ts = v8profile->GetSampleTimestamp(i);
     104         132 :     array->addItem(static_cast<int>(ts - lastTime));
     105             :     lastTime = ts;
     106             :   }
     107          29 :   return array;
     108             : }
     109             : 
     110          93 : void flattenNodesTree(v8::Isolate* isolate, const v8::CpuProfileNode* node,
     111             :                       protocol::Array<protocol::Profiler::ProfileNode>* list) {
     112         186 :   list->addItem(buildInspectorObjectFor(isolate, node));
     113          93 :   const int childrenCount = node->GetChildrenCount();
     114         157 :   for (int i = 0; i < childrenCount; i++)
     115          64 :     flattenNodesTree(isolate, node->GetChild(i), list);
     116          93 : }
     117             : 
     118          29 : std::unique_ptr<protocol::Profiler::Profile> createCPUProfile(
     119             :     v8::Isolate* isolate, v8::CpuProfile* v8profile) {
     120             :   auto nodes = protocol::Array<protocol::Profiler::ProfileNode>::create();
     121          29 :   flattenNodesTree(isolate, v8profile->GetTopDownRoot(), nodes.get());
     122             :   return protocol::Profiler::Profile::create()
     123          29 :       .setNodes(std::move(nodes))
     124          29 :       .setStartTime(static_cast<double>(v8profile->GetStartTime()))
     125          29 :       .setEndTime(static_cast<double>(v8profile->GetEndTime()))
     126          58 :       .setSamples(buildInspectorObjectForSamples(v8profile))
     127          58 :       .setTimeDeltas(buildInspectorObjectForTimestamps(v8profile))
     128          29 :       .build();
     129             : }
     130             : 
     131          43 : std::unique_ptr<protocol::Debugger::Location> currentDebugLocation(
     132             :     V8InspectorImpl* inspector) {
     133             :   std::unique_ptr<V8StackTraceImpl> callStack =
     134          43 :       inspector->debugger()->captureStackTrace(false /* fullStack */);
     135             :   auto location = protocol::Debugger::Location::create()
     136         129 :                       .setScriptId(toString16(callStack->topScriptId()))
     137          43 :                       .setLineNumber(callStack->topLineNumber())
     138             :                       .build();
     139          43 :   location->setColumnNumber(callStack->topColumnNumber());
     140          43 :   return location;
     141             : }
     142             : 
     143             : volatile int s_lastProfileId = 0;
     144             : 
     145             : }  // namespace
     146             : 
     147          27 : class V8ProfilerAgentImpl::ProfileDescriptor {
     148             :  public:
     149             :   ProfileDescriptor(const String16& id, const String16& title)
     150          24 :       : m_id(id), m_title(title) {}
     151             :   String16 m_id;
     152             :   String16 m_title;
     153             : };
     154             : 
     155        3406 : V8ProfilerAgentImpl::V8ProfilerAgentImpl(
     156             :     V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel,
     157             :     protocol::DictionaryValue* state)
     158             :     : m_session(session),
     159        3406 :       m_isolate(m_session->inspector()->isolate()),
     160             :       m_state(state),
     161       13624 :       m_frontend(frontendChannel) {}
     162             : 
     163       10218 : V8ProfilerAgentImpl::~V8ProfilerAgentImpl() {
     164        3406 :   if (m_profiler) m_profiler->Dispose();
     165        6812 : }
     166             : 
     167          24 : void V8ProfilerAgentImpl::consoleProfile(const String16& title) {
     168          24 :   if (!m_enabled) return;
     169          24 :   String16 id = nextProfileId();
     170          48 :   m_startedProfiles.push_back(ProfileDescriptor(id, title));
     171          24 :   startProfiling(id);
     172             :   m_frontend.consoleProfileStarted(
     173          72 :       id, currentDebugLocation(m_session->inspector()), title);
     174             : }
     175             : 
     176          24 : void V8ProfilerAgentImpl::consoleProfileEnd(const String16& title) {
     177          29 :   if (!m_enabled) return;
     178          24 :   String16 id;
     179          24 :   String16 resolvedTitle;
     180             :   // Take last started profile if no title was passed.
     181          24 :   if (title.isEmpty()) {
     182          41 :     if (m_startedProfiles.empty()) return;
     183           2 :     id = m_startedProfiles.back().m_id;
     184           2 :     resolvedTitle = m_startedProfiles.back().m_title;
     185           2 :     m_startedProfiles.pop_back();
     186             :   } else {
     187          17 :     for (size_t i = 0; i < m_startedProfiles.size(); i++) {
     188          17 :       if (m_startedProfiles[i].m_title == title) {
     189          17 :         resolvedTitle = title;
     190          17 :         id = m_startedProfiles[i].m_id;
     191          17 :         m_startedProfiles.erase(m_startedProfiles.begin() + i);
     192          17 :         break;
     193             :       }
     194             :     }
     195          17 :     if (id.isEmpty()) return;
     196             :   }
     197             :   std::unique_ptr<protocol::Profiler::Profile> profile =
     198          19 :       stopProfiling(id, true);
     199          19 :   if (!profile) return;
     200             :   std::unique_ptr<protocol::Debugger::Location> location =
     201          19 :       currentDebugLocation(m_session->inspector());
     202             :   m_frontend.consoleProfileFinished(id, std::move(location), std::move(profile),
     203          95 :                                     resolvedTitle);
     204             : }
     205             : 
     206         177 : Response V8ProfilerAgentImpl::enable() {
     207         177 :   if (m_enabled) return Response::OK();
     208         177 :   m_enabled = true;
     209         354 :   m_state->setBoolean(ProfilerAgentState::profilerEnabled, true);
     210         177 :   return Response::OK();
     211             : }
     212             : 
     213        3571 : Response V8ProfilerAgentImpl::disable() {
     214        3571 :   if (!m_enabled) return Response::OK();
     215         541 :   for (size_t i = m_startedProfiles.size(); i > 0; --i)
     216          15 :     stopProfiling(m_startedProfiles[i - 1].m_id, false);
     217             :   m_startedProfiles.clear();
     218         354 :   stop(nullptr);
     219         354 :   stopPreciseCoverage();
     220             :   DCHECK(!m_profiler);
     221         177 :   m_enabled = false;
     222         354 :   m_state->setBoolean(ProfilerAgentState::profilerEnabled, false);
     223         177 :   return Response::OK();
     224             : }
     225             : 
     226           0 : Response V8ProfilerAgentImpl::setSamplingInterval(int interval) {
     227           0 :   if (m_profiler) {
     228           0 :     return Response::Error("Cannot change sampling interval when profiling.");
     229             :   }
     230           0 :   m_state->setInteger(ProfilerAgentState::samplingInterval, interval);
     231           0 :   return Response::OK();
     232             : }
     233             : 
     234          40 : void V8ProfilerAgentImpl::restore() {
     235             :   DCHECK(!m_enabled);
     236          80 :   if (!m_state->booleanProperty(ProfilerAgentState::profilerEnabled, false))
     237          40 :     return;
     238           0 :   m_enabled = true;
     239             :   DCHECK(!m_profiler);
     240           0 :   if (m_state->booleanProperty(ProfilerAgentState::userInitiatedProfiling,
     241           0 :                                false)) {
     242           0 :     start();
     243             :   }
     244           0 :   if (m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
     245           0 :                                false)) {
     246             :     bool callCount = m_state->booleanProperty(
     247           0 :         ProfilerAgentState::preciseCoverageCallCount, false);
     248             :     bool detailed = m_state->booleanProperty(
     249           0 :         ProfilerAgentState::preciseCoverageDetailed, false);
     250           0 :     startPreciseCoverage(Maybe<bool>(callCount), Maybe<bool>(detailed));
     251             :   }
     252             : }
     253             : 
     254          20 : Response V8ProfilerAgentImpl::start() {
     255          20 :   if (m_recordingCPUProfile) return Response::OK();
     256          25 :   if (!m_enabled) return Response::Error("Profiler is not enabled");
     257          15 :   m_recordingCPUProfile = true;
     258          30 :   m_frontendInitiatedProfileId = nextProfileId();
     259          15 :   startProfiling(m_frontendInitiatedProfileId);
     260          30 :   m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, true);
     261          15 :   return Response::OK();
     262             : }
     263             : 
     264         197 : Response V8ProfilerAgentImpl::stop(
     265             :     std::unique_ptr<protocol::Profiler::Profile>* profile) {
     266         197 :   if (!m_recordingCPUProfile) {
     267         364 :     return Response::Error("No recording profiles found");
     268             :   }
     269          15 :   m_recordingCPUProfile = false;
     270             :   std::unique_ptr<protocol::Profiler::Profile> cpuProfile =
     271          15 :       stopProfiling(m_frontendInitiatedProfileId, !!profile);
     272          15 :   if (profile) {
     273             :     *profile = std::move(cpuProfile);
     274          10 :     if (!profile->get()) return Response::Error("Profile is not found");
     275             :   }
     276          30 :   m_frontendInitiatedProfileId = String16();
     277          30 :   m_state->setBoolean(ProfilerAgentState::userInitiatedProfiling, false);
     278          15 :   return Response::OK();
     279             : }
     280             : 
     281          85 : Response V8ProfilerAgentImpl::startPreciseCoverage(Maybe<bool> callCount,
     282             :                                                    Maybe<bool> detailed) {
     283          85 :   if (!m_enabled) return Response::Error("Profiler is not enabled");
     284             :   bool callCountValue = callCount.fromMaybe(false);
     285             :   bool detailedValue = detailed.fromMaybe(false);
     286         170 :   m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, true);
     287             :   m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount,
     288         170 :                       callCountValue);
     289             :   m_state->setBoolean(ProfilerAgentState::preciseCoverageDetailed,
     290         170 :                       detailedValue);
     291             :   // BlockCount is a superset of PreciseCount. It includes block-granularity
     292             :   // coverage data if it exists (at the time of writing, that's the case for
     293             :   // each function recompiled after the BlockCount mode has been set); and
     294             :   // function-granularity coverage data otherwise.
     295             :   typedef v8::debug::Coverage C;
     296             :   C::Mode mode = callCountValue
     297             :                      ? (detailedValue ? C::kBlockCount : C::kPreciseCount)
     298          85 :                      : (detailedValue ? C::kBlockBinary : C::kPreciseBinary);
     299          85 :   C::SelectMode(m_isolate, mode);
     300          85 :   return Response::OK();
     301             : }
     302             : 
     303         262 : Response V8ProfilerAgentImpl::stopPreciseCoverage() {
     304         262 :   if (!m_enabled) return Response::Error("Profiler is not enabled");
     305         524 :   m_state->setBoolean(ProfilerAgentState::preciseCoverageStarted, false);
     306         524 :   m_state->setBoolean(ProfilerAgentState::preciseCoverageCallCount, false);
     307         524 :   m_state->setBoolean(ProfilerAgentState::preciseCoverageDetailed, false);
     308         262 :   v8::debug::Coverage::SelectMode(m_isolate, v8::debug::Coverage::kBestEffort);
     309         262 :   return Response::OK();
     310             : }
     311             : 
     312             : namespace {
     313             : std::unique_ptr<protocol::Profiler::CoverageRange> createCoverageRange(
     314             :     int start, int end, int count) {
     315             :   return protocol::Profiler::CoverageRange::create()
     316         585 :       .setStartOffset(start)
     317             :       .setEndOffset(end)
     318             :       .setCount(count)
     319             :       .build();
     320             : }
     321             : 
     322         170 : Response coverageToProtocol(
     323             :     v8::Isolate* isolate, const v8::debug::Coverage& coverage,
     324             :     std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
     325             :         out_result) {
     326             :   std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>> result =
     327             :       protocol::Array<protocol::Profiler::ScriptCoverage>::create();
     328         200 :   for (size_t i = 0; i < coverage.ScriptCount(); i++) {
     329         200 :     v8::debug::Coverage::ScriptData script_data = coverage.GetScriptData(i);
     330         200 :     v8::Local<v8::debug::Script> script = script_data.GetScript();
     331             :     std::unique_ptr<protocol::Array<protocol::Profiler::FunctionCoverage>>
     332             :         functions =
     333             :             protocol::Array<protocol::Profiler::FunctionCoverage>::create();
     334         475 :     for (size_t j = 0; j < script_data.FunctionCount(); j++) {
     335             :       v8::debug::Coverage::FunctionData function_data =
     336         475 :           script_data.GetFunctionData(j);
     337             :       std::unique_ptr<protocol::Array<protocol::Profiler::CoverageRange>>
     338             :           ranges = protocol::Array<protocol::Profiler::CoverageRange>::create();
     339             : 
     340             :       // Add function range.
     341             :       ranges->addItem(createCoverageRange(function_data.StartOffset(),
     342             :                                           function_data.EndOffset(),
     343         950 :                                           function_data.Count()));
     344             : 
     345             :       // Process inner blocks.
     346         110 :       for (size_t k = 0; k < function_data.BlockCount(); k++) {
     347             :         v8::debug::Coverage::BlockData block_data =
     348         110 :             function_data.GetBlockData(k);
     349             :         ranges->addItem(createCoverageRange(block_data.StartOffset(),
     350             :                                             block_data.EndOffset(),
     351         220 :                                             block_data.Count()));
     352             :       }
     353             : 
     354             :       functions->addItem(
     355             :           protocol::Profiler::FunctionCoverage::create()
     356             :               .setFunctionName(toProtocolString(
     357        1900 :                   function_data.Name().FromMaybe(v8::Local<v8::String>())))
     358             :               .setRanges(std::move(ranges))
     359         475 :               .setIsBlockCoverage(function_data.HasBlockCoverage())
     360         475 :               .build());
     361             :     }
     362         200 :     String16 url;
     363             :     v8::Local<v8::String> name;
     364         400 :     if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) {
     365         400 :       url = toProtocolString(name);
     366             :     }
     367             :     result->addItem(protocol::Profiler::ScriptCoverage::create()
     368         600 :                         .setScriptId(String16::fromInteger(script->Id()))
     369             :                         .setUrl(url)
     370             :                         .setFunctions(std::move(functions))
     371         200 :                         .build());
     372             :   }
     373             :   *out_result = std::move(result);
     374         170 :   return Response::OK();
     375             : }
     376             : }  // anonymous namespace
     377             : 
     378         120 : Response V8ProfilerAgentImpl::takePreciseCoverage(
     379             :     std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
     380             :         out_result) {
     381         120 :   if (!m_state->booleanProperty(ProfilerAgentState::preciseCoverageStarted,
     382         240 :                                 false)) {
     383          20 :     return Response::Error("Precise coverage has not been started.");
     384             :   }
     385         110 :   v8::HandleScope handle_scope(m_isolate);
     386         110 :   v8::debug::Coverage coverage = v8::debug::Coverage::CollectPrecise(m_isolate);
     387         220 :   return coverageToProtocol(m_isolate, coverage, out_result);
     388             : }
     389             : 
     390          60 : Response V8ProfilerAgentImpl::getBestEffortCoverage(
     391             :     std::unique_ptr<protocol::Array<protocol::Profiler::ScriptCoverage>>*
     392             :         out_result) {
     393          60 :   v8::HandleScope handle_scope(m_isolate);
     394             :   v8::debug::Coverage coverage =
     395          60 :       v8::debug::Coverage::CollectBestEffort(m_isolate);
     396         120 :   return coverageToProtocol(m_isolate, coverage, out_result);
     397             : }
     398             : 
     399             : namespace {
     400             : std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
     401          50 : typeProfileToProtocol(v8::Isolate* isolate,
     402             :                       const v8::debug::TypeProfile& type_profile) {
     403             :   std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>
     404             :       result = protocol::Array<protocol::Profiler::ScriptTypeProfile>::create();
     405          40 :   for (size_t i = 0; i < type_profile.ScriptCount(); i++) {
     406             :     v8::debug::TypeProfile::ScriptData script_data =
     407          40 :         type_profile.GetScriptData(i);
     408          40 :     v8::Local<v8::debug::Script> script = script_data.GetScript();
     409             :     std::unique_ptr<protocol::Array<protocol::Profiler::TypeProfileEntry>>
     410             :         entries =
     411             :             protocol::Array<protocol::Profiler::TypeProfileEntry>::create();
     412             : 
     413         265 :     for (const auto& entry : script_data.Entries()) {
     414             :       std::unique_ptr<protocol::Array<protocol::Profiler::TypeObject>> types =
     415             :           protocol::Array<protocol::Profiler::TypeObject>::create();
     416         615 :       for (const auto& type : entry.Types()) {
     417             :         types->addItem(protocol::Profiler::TypeObject::create()
     418             :                            .setName(toProtocolString(
     419         735 :                                type.FromMaybe(v8::Local<v8::String>())))
     420         245 :                            .build());
     421             :       }
     422             :       entries->addItem(protocol::Profiler::TypeProfileEntry::create()
     423         370 :                            .setOffset(entry.SourcePosition())
     424             :                            .setTypes(std::move(types))
     425         185 :                            .build());
     426          40 :     }
     427          40 :     String16 url;
     428             :     v8::Local<v8::String> name;
     429          80 :     if (script->Name().ToLocal(&name) || script->SourceURL().ToLocal(&name)) {
     430          80 :       url = toProtocolString(name);
     431             :     }
     432             :     result->addItem(protocol::Profiler::ScriptTypeProfile::create()
     433         120 :                         .setScriptId(String16::fromInteger(script->Id()))
     434             :                         .setUrl(url)
     435             :                         .setEntries(std::move(entries))
     436          40 :                         .build());
     437             :   }
     438          50 :   return result;
     439             : }
     440             : }  // anonymous namespace
     441             : 
     442          65 : Response V8ProfilerAgentImpl::startTypeProfile() {
     443         130 :   m_state->setBoolean(ProfilerAgentState::typeProfileStarted, true);
     444             :   v8::debug::TypeProfile::SelectMode(m_isolate,
     445          65 :                                      v8::debug::TypeProfile::kCollect);
     446          65 :   return Response::OK();
     447             : }
     448             : 
     449          60 : Response V8ProfilerAgentImpl::stopTypeProfile() {
     450         120 :   m_state->setBoolean(ProfilerAgentState::typeProfileStarted, false);
     451          60 :   v8::debug::TypeProfile::SelectMode(m_isolate, v8::debug::TypeProfile::kNone);
     452          60 :   return Response::OK();
     453             : }
     454             : 
     455          60 : Response V8ProfilerAgentImpl::takeTypeProfile(
     456             :     std::unique_ptr<protocol::Array<protocol::Profiler::ScriptTypeProfile>>*
     457             :         out_result) {
     458          60 :   if (!m_state->booleanProperty(ProfilerAgentState::typeProfileStarted,
     459         120 :                                 false)) {
     460          20 :     return Response::Error("Type profile has not been started.");
     461             :   }
     462          50 :   v8::HandleScope handle_scope(m_isolate);
     463             :   v8::debug::TypeProfile type_profile =
     464          50 :       v8::debug::TypeProfile::Collect(m_isolate);
     465         100 :   *out_result = typeProfileToProtocol(m_isolate, type_profile);
     466         100 :   return Response::OK();
     467             : }
     468             : 
     469          39 : String16 V8ProfilerAgentImpl::nextProfileId() {
     470             :   return String16::fromInteger(
     471          39 :       v8::base::Relaxed_AtomicIncrement(&s_lastProfileId, 1));
     472             : }
     473             : 
     474          39 : void V8ProfilerAgentImpl::startProfiling(const String16& title) {
     475          39 :   v8::HandleScope handleScope(m_isolate);
     476          39 :   if (!m_startedProfilesCount) {
     477             :     DCHECK(!m_profiler);
     478          27 :     m_profiler = v8::CpuProfiler::New(m_isolate);
     479          27 :     m_profiler->SetIdle(m_idle);
     480             :     int interval =
     481          54 :         m_state->integerProperty(ProfilerAgentState::samplingInterval, 0);
     482          27 :     if (interval) m_profiler->SetSamplingInterval(interval);
     483             :   }
     484          39 :   ++m_startedProfilesCount;
     485          39 :   m_profiler->StartProfiling(toV8String(m_isolate, title), true);
     486          39 : }
     487             : 
     488          39 : std::unique_ptr<protocol::Profiler::Profile> V8ProfilerAgentImpl::stopProfiling(
     489             :     const String16& title, bool serialize) {
     490          39 :   v8::HandleScope handleScope(m_isolate);
     491             :   v8::CpuProfile* profile =
     492          39 :       m_profiler->StopProfiling(toV8String(m_isolate, title));
     493          39 :   std::unique_ptr<protocol::Profiler::Profile> result;
     494          39 :   if (profile) {
     495          68 :     if (serialize) result = createCPUProfile(m_isolate, profile);
     496          39 :     profile->Delete();
     497             :   }
     498          39 :   --m_startedProfilesCount;
     499          39 :   if (!m_startedProfilesCount) {
     500          27 :     m_profiler->Dispose();
     501          27 :     m_profiler = nullptr;
     502             :   }
     503          39 :   return result;
     504             : }
     505             : 
     506           0 : bool V8ProfilerAgentImpl::idleStarted() {
     507           0 :   m_idle = true;
     508           0 :   if (m_profiler) m_profiler->SetIdle(m_idle);
     509           0 :   return m_profiler;
     510             : }
     511             : 
     512           0 : bool V8ProfilerAgentImpl::idleFinished() {
     513           0 :   m_idle = false;
     514           0 :   if (m_profiler) m_profiler->SetIdle(m_idle);
     515           0 :   return m_profiler;
     516             : }
     517             : 
     518             : }  // namespace v8_inspector

Generated by: LCOV version 1.10