LCOV - code coverage report
Current view: top level - src/inspector - v8-profiler-agent-impl.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 240 257 93.4 %
Date: 2019-01-20 Functions: 30 31 96.8 %

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

Generated by: LCOV version 1.10