LCOV - code coverage report
Current view: top level - src/inspector - v8-profiler-agent-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 253 270 93.7 %
Date: 2019-04-19 Functions: 34 35 97.1 %

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

Generated by: LCOV version 1.10