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