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 249 93.2 %
Date: 2019-02-19 Functions: 32 33 97.0 %

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

Generated by: LCOV version 1.10