v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8-heap-profiler-agent-impl.cc
Go to the documentation of this file.
1// Copyright 2016 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
6
10#include "include/v8-profiler.h"
15#include "src/inspector/protocol/Protocol.h"
20
21namespace v8_inspector {
22
23namespace {
24
25namespace HeapProfilerAgentState {
26static const char heapProfilerEnabled[] = "heapProfilerEnabled";
27static const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled";
28static const char allocationTrackingEnabled[] = "allocationTrackingEnabled";
29static const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled";
30static const char samplingHeapProfilerInterval[] =
31 "samplingHeapProfilerInterval";
32static const char samplingHeapProfilerFlags[] = "samplingHeapProfilerFlags";
33} // namespace HeapProfilerAgentState
34
35class HeapSnapshotProgress final : public v8::ActivityControl {
36 public:
37 explicit HeapSnapshotProgress(protocol::HeapProfiler::Frontend* frontend)
38 : m_frontend(frontend) {}
39 ControlOption ReportProgressValue(uint32_t done, uint32_t total) override {
40 m_frontend->reportHeapSnapshotProgress(done, total, std::nullopt);
41 if (done >= total) {
42 m_frontend->reportHeapSnapshotProgress(total, total, true);
43 }
44 m_frontend->flush();
45 return kContinue;
46 }
47
48 private:
49 protocol::HeapProfiler::Frontend* m_frontend;
50};
51
52class GlobalObjectNameResolver final
54 public:
55 explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session)
56 : m_offset(0), m_strings(10000), m_session(session) {}
57
58 const char* GetName(v8::Local<v8::Object> object) override {
59 v8::Local<v8::Context> creationContext;
60 if (!object->GetCreationContext(m_session->inspector()->isolate())
61 .ToLocal(&creationContext)) {
62 return "";
63 }
64 InspectedContext* context = m_session->inspector()->getContext(
65 m_session->contextGroupId(),
66 InspectedContext::contextId(creationContext));
67 if (!context) return "";
68 String16 name = context->origin();
69 size_t length = name.length();
70 if (m_offset + length + 1 >= m_strings.size()) return "";
71 for (size_t i = 0; i < length; ++i) {
72 UChar ch = name[i];
73 m_strings[m_offset + i] = ch > 0xFF ? '?' : static_cast<char>(ch);
74 }
75 m_strings[m_offset + length] = '\0';
76 char* result = &*m_strings.begin() + m_offset;
77 m_offset += length + 1;
78 return result;
79 }
80
81 private:
82 size_t m_offset;
83 std::vector<char> m_strings;
84 V8InspectorSessionImpl* m_session;
85};
86
87class HeapSnapshotOutputStream final : public v8::OutputStream {
88 public:
89 explicit HeapSnapshotOutputStream(protocol::HeapProfiler::Frontend* frontend)
90 : m_frontend(frontend) {}
91 void EndOfStream() override {}
92 int GetChunkSize() override { return 1 * v8::internal::MB; }
93 WriteResult WriteAsciiChunk(char* data, int size) override {
94 m_frontend->addHeapSnapshotChunk(String16(data, size));
95 m_frontend->flush();
96 return kContinue;
97 }
98
99 private:
100 protocol::HeapProfiler::Frontend* m_frontend;
101};
102
103v8::Local<v8::Object> objectByHeapObjectId(v8::Isolate* isolate, int id) {
104 v8::HeapProfiler* profiler = isolate->GetHeapProfiler();
105 v8::Local<v8::Value> value = profiler->FindObjectById(id);
106 if (value.IsEmpty() || !value->IsObject()) return v8::Local<v8::Object>();
107 return value.As<v8::Object>();
108}
109
110class InspectableHeapObject final : public V8InspectorSession::Inspectable {
111 public:
112 explicit InspectableHeapObject(int heapObjectId)
113 : m_heapObjectId(heapObjectId) {}
114 v8::Local<v8::Value> get(v8::Local<v8::Context> context) override {
115 return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId);
116 }
117
118 private:
120};
121
122class HeapStatsStream final : public v8::OutputStream {
123 public:
124 explicit HeapStatsStream(protocol::HeapProfiler::Frontend* frontend)
125 : m_frontend(frontend) {}
126
127 void EndOfStream() override {}
128
129 WriteResult WriteAsciiChunk(char* data, int size) override {
130 DCHECK(false);
131 return kAbort;
132 }
133
134 WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData,
135 int count) override {
136 DCHECK_GT(count, 0);
137 auto statsDiff = std::make_unique<protocol::Array<int>>();
138 for (int i = 0; i < count; ++i) {
139 statsDiff->emplace_back(updateData[i].index);
140 statsDiff->emplace_back(updateData[i].count);
141 statsDiff->emplace_back(updateData[i].size);
142 }
143 m_frontend->heapStatsUpdate(std::move(statsDiff));
144 return kContinue;
145 }
146
147 private:
148 protocol::HeapProfiler::Frontend* m_frontend;
149};
150
151} // namespace
152
155 bool m_canceled = false;
156 std::vector<std::unique_ptr<CollectGarbageCallback>> m_gcCallbacks;
157 std::vector<V8HeapProfilerAgentImpl::HeapSnapshotTask*> m_heapSnapshotTasks;
158};
159
161 public:
162 GCTask(v8::Isolate* isolate, std::shared_ptr<AsyncCallbacks> asyncCallbacks)
163 : m_isolate(isolate), m_asyncCallbacks(asyncCallbacks) {}
164
165 void Run() override {
166 std::shared_ptr<AsyncCallbacks> asyncCallbacks = m_asyncCallbacks.lock();
167 if (!asyncCallbacks) return;
168 v8::base::MutexGuard lock(&asyncCallbacks->m_mutex);
169 if (asyncCallbacks->m_canceled) return;
171 v8::StackState::kNoHeapPointers);
172 for (auto& callback : asyncCallbacks->m_gcCallbacks) {
173 callback->sendSuccess();
174 }
175 asyncCallbacks->m_gcCallbacks.clear();
176 }
177
178 private:
180 std::weak_ptr<AsyncCallbacks> m_asyncCallbacks;
181};
182
184 HeapSnapshotProtocolOptions(std::optional<bool> reportProgress,
185 std::optional<bool> treatGlobalObjectsAsRoots,
186 std::optional<bool> captureNumericValue,
187 std::optional<bool> exposeInternals)
188 : m_reportProgress(reportProgress.value_or(false)),
189 m_treatGlobalObjectsAsRoots(treatGlobalObjectsAsRoots.value_or(true)),
190 m_captureNumericValue(captureNumericValue.value_or(false)),
191 m_exposeInternals(exposeInternals.value_or(false)) {}
196};
197
199 public:
201 std::shared_ptr<AsyncCallbacks> asyncCallbacks,
202 HeapSnapshotProtocolOptions protocolOptions,
203 std::unique_ptr<TakeHeapSnapshotCallback> callback)
204 : m_agent(agent),
205 m_asyncCallbacks(asyncCallbacks),
206 m_protocolOptions(protocolOptions),
207 m_callback(std::move(callback)) {}
208
210
212 Response response = Response::Success();
213 {
214 // If the async callbacks object still exists and is not canceled, then
215 // the V8HeapProfilerAgentImpl still exists, so we can safely take a
216 // snapshot.
217 std::shared_ptr<AsyncCallbacks> asyncCallbacks = m_asyncCallbacks.lock();
218 if (!asyncCallbacks) return;
219 v8::base::MutexGuard lock(&asyncCallbacks->m_mutex);
220 if (asyncCallbacks->m_canceled) return;
221
222 auto& heapSnapshotTasks = asyncCallbacks->m_heapSnapshotTasks;
223 auto it =
224 std::find(heapSnapshotTasks.begin(), heapSnapshotTasks.end(), this);
225 if (it == heapSnapshotTasks.end()) {
226 // This task must have already been run. This can happen because the
227 // task was queued with PostNonNestableTask but then got run early by
228 // takePendingHeapSnapshots.
229 return;
230 }
231 heapSnapshotTasks.erase(it);
232
233 response = m_agent->takeHeapSnapshotNow(m_protocolOptions, stackState);
234 }
235
236 // The rest of this function runs without the mutex, because Node expects to
237 // be able to dispose the profiler agent during the callback, which would
238 // deadlock if this function still held the mutex. It's safe to call the
239 // callback without the mutex; the internal implementation of the callback
240 // uses weak pointers to avoid doing anything dangerous if other components
241 // have been disposed (see DomainDispatcher::Callback::sendIfActive).
242 if (response.IsSuccess()) {
243 m_callback->sendSuccess();
244 } else {
245 m_callback->sendFailure(std::move(response));
246 }
247 }
248
249 private:
251 std::weak_ptr<AsyncCallbacks> m_asyncCallbacks;
253 std::unique_ptr<TakeHeapSnapshotCallback> m_callback;
254};
255
257 V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel,
258 protocol::DictionaryValue* state)
259 : m_session(session),
260 m_isolate(session->inspector()->isolate()),
261 m_frontend(frontendChannel),
262 m_state(state),
263 m_hasTimer(false),
264 m_asyncCallbacks(std::make_shared<AsyncCallbacks>()) {}
265
268 m_asyncCallbacks->m_canceled = true;
269 m_asyncCallbacks->m_gcCallbacks.clear();
270 m_asyncCallbacks->m_heapSnapshotTasks.clear();
271}
272
274 if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled,
275 false))
276 m_frontend.resetProfiles();
277 if (m_state->booleanProperty(
278 HeapProfilerAgentState::heapObjectsTrackingEnabled, false))
280 HeapProfilerAgentState::allocationTrackingEnabled, false));
281 if (m_state->booleanProperty(
282 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) {
283 double samplingInterval = m_state->doubleProperty(
284 HeapProfilerAgentState::samplingHeapProfilerInterval, -1);
285 DCHECK_GE(samplingInterval, 0);
286 int flags = m_state->integerProperty(
287 HeapProfilerAgentState::samplingHeapProfilerFlags, 0);
289 samplingInterval,
292 }
293}
294
296 std::unique_ptr<CollectGarbageCallback> callback) {
298 m_asyncCallbacks->m_gcCallbacks.push_back(std::move(callback));
302 std::make_unique<GCTask>(m_isolate, m_asyncCallbacks));
303}
304
306 std::optional<bool> trackAllocations) {
307 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true);
308 bool allocationTrackingEnabled = trackAllocations.value_or(false);
309 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled,
310 allocationTrackingEnabled);
311 startTrackingHeapObjectsInternal(allocationTrackingEnabled);
312 return Response::Success();
313}
314
316 std::optional<bool> reportProgress,
317 std::optional<bool> treatGlobalObjectsAsRoots,
318 std::optional<bool> captureNumericValue,
319 std::optional<bool> exposeInternals) {
323 std::move(reportProgress), std::move(treatGlobalObjectsAsRoots),
324 std::move(captureNumericValue), std::move(exposeInternals)),
327 return Response::Success();
328}
329
331 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true);
332 return Response::Success();
333}
334
338 DCHECK(profiler);
339 if (m_state->booleanProperty(
340 HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) {
341 profiler->StopSamplingHeapProfiler();
342 }
343 profiler->ClearObjectIds();
344 m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false);
345 return Response::Success();
346}
347
349 std::optional<bool> reportProgress,
350 std::optional<bool> treatGlobalObjectsAsRoots,
351 std::optional<bool> captureNumericValue,
352 std::optional<bool> exposeInternals,
353 std::unique_ptr<TakeHeapSnapshotCallback> callback) {
354 HeapSnapshotProtocolOptions protocolOptions(
355 std::move(reportProgress), std::move(treatGlobalObjectsAsRoots),
356 std::move(captureNumericValue), std::move(exposeInternals));
357 std::shared_ptr<v8::TaskRunner> task_runner =
359
360 // Heap snapshots can be more accurate if we wait until the stack is empty and
361 // run the garbage collector without conservative stack scanning, as done in
362 // V8HeapProfilerAgentImpl::collectGarbage. However, heap snapshots can also
363 // be requested while paused in the debugger, in which case the snapshot must
364 // be taken immediately with conservative stack scanning enabled.
365 if (m_session->inspector()->debugger()->isPaused() ||
366 !task_runner->NonNestableTasksEnabled()) {
367 Response response = takeHeapSnapshotNow(
369 if (response.IsSuccess()) {
370 callback->sendSuccess();
371 } else {
372 callback->sendFailure(std::move(response));
373 }
374 return;
375 }
376
377 std::unique_ptr<HeapSnapshotTask> task = std::make_unique<HeapSnapshotTask>(
378 this, m_asyncCallbacks, protocolOptions, std::move(callback));
379 m_asyncCallbacks->m_heapSnapshotTasks.push_back(task.get());
380 task_runner->PostNonNestableTask(std::move(task));
381}
382
384 const HeapSnapshotProtocolOptions& protocolOptions,
385 cppgc::EmbedderStackState stackState) {
387 DCHECK(profiler);
388 std::unique_ptr<HeapSnapshotProgress> progress;
389 if (protocolOptions.m_reportProgress)
390 progress.reset(new HeapSnapshotProgress(&m_frontend));
391
392 GlobalObjectNameResolver resolver(m_session);
394 options.global_object_name_resolver = &resolver;
395 options.control = progress.get();
396 options.snapshot_mode =
397 protocolOptions.m_exposeInternals ||
398 // Not treating global objects as roots results into exposing
399 // internals.
400 !protocolOptions.m_treatGlobalObjectsAsRoots
403 options.numerics_mode =
404 protocolOptions.m_captureNumericValue
407 options.stack_state = stackState;
408 const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(options);
409 if (!snapshot) return Response::ServerError("Failed to take heap snapshot");
410 HeapSnapshotOutputStream stream(&m_frontend);
411 snapshot->Serialize(&stream);
412 const_cast<v8::HeapSnapshot*>(snapshot)->Delete();
413 return Response::Success();
414}
415
417 const String16& heapSnapshotObjectId, std::optional<String16> objectGroup,
418 std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
419 bool ok;
420 int id = heapSnapshotObjectId.toInteger(&ok);
421 if (!ok) return Response::ServerError("Invalid heap snapshot object id");
422
423 v8::HandleScope handles(m_isolate);
424 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
425 if (heapObject.IsEmpty())
426 return Response::ServerError("Object is not available");
427
428 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject))
429 return Response::ServerError("Object is not available");
430
431 v8::Local<v8::Context> creationContext;
432 if (!heapObject->GetCreationContext(m_isolate).ToLocal(&creationContext)) {
433 return Response::ServerError("Object is not available");
434 }
435 *result = m_session->wrapObject(creationContext, heapObject,
436 objectGroup.value_or(""), false);
437 if (!*result) return Response::ServerError("Object is not available");
438 return Response::Success();
439}
440
442 // Each task will remove itself from m_heapSnapshotTasks.
443 while (!m_asyncCallbacks->m_heapSnapshotTasks.empty()) {
444 m_asyncCallbacks->m_heapSnapshotTasks.front()->Run(
446 }
447}
448
450 const String16& inspectedHeapObjectId) {
451 bool ok;
452 int id = inspectedHeapObjectId.toInteger(&ok);
453 if (!ok) return Response::ServerError("Invalid heap snapshot object id");
454
455 v8::HandleScope handles(m_isolate);
456 v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id);
457 if (heapObject.IsEmpty())
458 return Response::ServerError("Object is not available");
459
460 if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject))
461 return Response::ServerError("Object is not available");
463 std::unique_ptr<InspectableHeapObject>(new InspectableHeapObject(id)));
464 return Response::Success();
465}
466
468 const String16& objectId, String16* heapSnapshotObjectId) {
469 v8::HandleScope handles(m_isolate);
472 Response response =
473 m_session->unwrapObject(objectId, &value, &context, nullptr);
474 if (!response.IsSuccess()) return response;
475 if (value->IsUndefined()) return Response::InternalError();
476
478 *heapSnapshotObjectId = String16::fromInteger(static_cast<size_t>(id));
479 return Response::Success();
480}
481
483 HeapStatsStream stream(&m_frontend);
484 v8::SnapshotObjectId lastSeenObjectId =
486 m_frontend.lastSeenObjectId(
487 lastSeenObjectId, m_session->inspector()->client()->currentTimeMS());
488}
489
490// static
492 reinterpret_cast<V8HeapProfilerAgentImpl*>(data)->onTimerImpl();
493}
494
497
502 if (m_hasTimer) {
503 // requestHeapStatsUpdate can take a long time on large heaps. To ensure
504 // that there is still some time for the thread to make progress on running
505 // JavaScript or doing other useful work, we'll adjust the timer delay here.
506 const v8::base::TimeDelta minAcceptableDelay =
507 std::max(elapsed * 2, kDefaultTimerDelay);
508 const v8::base::TimeDelta idealDelay =
509 std::max(elapsed * 3, kDefaultTimerDelay);
510 const v8::base::TimeDelta maxAcceptableDelay =
511 std::max(elapsed * 4, kDefaultTimerDelay);
512 if (m_timerDelayInSeconds < minAcceptableDelay.InSecondsF() ||
513 m_timerDelayInSeconds > maxAcceptableDelay.InSecondsF()) {
514 // The existing timer's speed is not very close to ideal, so cancel it and
515 // start a new timer.
517 reinterpret_cast<void*>(this));
518 m_timerDelayInSeconds = idealDelay.InSecondsF();
521 reinterpret_cast<void*>(this));
522 }
523 }
524}
525
537
539 if (m_hasTimer) {
541 reinterpret_cast<void*>(this));
542 m_hasTimer = false;
543 }
545 m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled,
546 false);
547 m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false);
548}
549
551 std::optional<double> samplingInterval,
552 std::optional<bool> includeObjectsCollectedByMajorGC,
553 std::optional<bool> includeObjectsCollectedByMinorGC) {
555 DCHECK(profiler);
556 const unsigned defaultSamplingInterval = 1 << 15;
557 double samplingIntervalValue =
558 samplingInterval.value_or(defaultSamplingInterval);
559 if (samplingIntervalValue <= 0.0) {
560 return Response::ServerError("Invalid sampling interval");
561 }
562 m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval,
563 samplingIntervalValue);
564 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
565 true);
567 if (includeObjectsCollectedByMajorGC.value_or(false)) {
569 }
570 if (includeObjectsCollectedByMinorGC.value_or(false)) {
572 }
573 m_state->setInteger(HeapProfilerAgentState::samplingHeapProfilerFlags, flags);
574 profiler->StartSamplingHeapProfiler(
575 static_cast<uint64_t>(samplingIntervalValue), 128,
576 static_cast<v8::HeapProfiler::SamplingFlags>(flags));
577 return Response::Success();
578}
579
580namespace {
581std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode>
582buildSampingHeapProfileNode(v8::Isolate* isolate,
583 const v8::AllocationProfile::Node* node) {
584 auto children = std::make_unique<
585 protocol::Array<protocol::HeapProfiler::SamplingHeapProfileNode>>();
586 for (const auto* child : node->children)
587 children->emplace_back(buildSampingHeapProfileNode(isolate, child));
588 size_t selfSize = 0;
589 for (const auto& allocation : node->allocations)
590 selfSize += allocation.size * allocation.count;
591 std::unique_ptr<protocol::Runtime::CallFrame> callFrame =
592 protocol::Runtime::CallFrame::create()
593 .setFunctionName(toProtocolString(isolate, node->name))
594 .setScriptId(String16::fromInteger(node->script_id))
595 .setUrl(toProtocolString(isolate, node->script_name))
596 .setLineNumber(node->line_number - 1)
597 .setColumnNumber(node->column_number - 1)
598 .build();
599 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result =
600 protocol::HeapProfiler::SamplingHeapProfileNode::create()
601 .setCallFrame(std::move(callFrame))
602 .setSelfSize(selfSize)
603 .setChildren(std::move(children))
604 .setId(node->node_id)
605 .build();
606 return result;
607}
608} // namespace
609
611 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
612 Response result = getSamplingProfile(profile);
613 if (result.IsSuccess()) {
615 m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled,
616 false);
617 }
618 return result;
619}
620
622 std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) {
624 // Need a scope as v8::AllocationProfile contains Local handles.
626 std::unique_ptr<v8::AllocationProfile> v8Profile(
627 profiler->GetAllocationProfile());
628 if (!v8Profile)
629 return Response::ServerError("V8 sampling heap profiler was not started.");
630 v8::AllocationProfile::Node* root = v8Profile->GetRootNode();
631 auto samples = std::make_unique<
632 protocol::Array<protocol::HeapProfiler::SamplingHeapProfileSample>>();
633 for (const auto& sample : v8Profile->GetSamples()) {
634 samples->emplace_back(
635 protocol::HeapProfiler::SamplingHeapProfileSample::create()
636 .setSize(sample.size * sample.count)
637 .setNodeId(sample.node_id)
638 .setOrdinal(static_cast<double>(sample.sample_id))
639 .build());
640 }
641 *profile = protocol::HeapProfiler::SamplingHeapProfile::create()
642 .setHead(buildSampingHeapProfileNode(m_isolate, root))
643 .setSamples(std::move(samples))
644 .build();
645 return Response::Success();
646}
647
648} // namespace v8_inspector
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
void StartTrackingHeapObjects(bool track_allocations=false)
Definition api.cc:11766
@ kSamplingIncludeObjectsCollectedByMajorGC
@ kSamplingIncludeObjectsCollectedByMinorGC
SnapshotObjectId GetObjectId(Local< Value > value)
Definition api.cc:11720
void StopSamplingHeapProfiler()
Definition api.cc:11788
SnapshotObjectId GetHeapStats(OutputStream *stream, int64_t *timestamp_us=nullptr)
Definition api.cc:11775
void StopTrackingHeapObjects()
Definition api.cc:11771
HeapProfiler * GetHeapProfiler()
Definition api.cc:9730
std::shared_ptr< v8::TaskRunner > GetForegroundTaskRunner(Isolate *isolate)
void PostNonNestableTask(std::unique_ptr< Task > task, const SourceLocation &location=SourceLocation::Current())
double InSecondsF() const
Definition time.cc:210
static constexpr TimeDelta FromMilliseconds(int64_t milliseconds)
Definition time.h:84
static TimeTicks Now()
Definition time.cc:736
static String16 fromInteger(int)
Definition string-16.cc:71
int toInteger(bool *ok=nullptr) const
Definition string-16.cc:118
GCTask(v8::Isolate *isolate, std::shared_ptr< AsyncCallbacks > asyncCallbacks)
HeapSnapshotTask(V8HeapProfilerAgentImpl *agent, std::shared_ptr< AsyncCallbacks > asyncCallbacks, HeapSnapshotProtocolOptions protocolOptions, std::unique_ptr< TakeHeapSnapshotCallback > callback)
void collectGarbage(std::unique_ptr< CollectGarbageCallback > callback) override
Response takeHeapSnapshotNow(const HeapSnapshotProtocolOptions &protocolOptions, cppgc::EmbedderStackState stackState)
Response getHeapObjectId(const String16 &objectId, String16 *heapSnapshotObjectId) override
Response stopTrackingHeapObjects(std::optional< bool > reportProgress, std::optional< bool > treatGlobalObjectsAsRoots, std::optional< bool > captureNumericValue, std::optional< bool > exposeInternals) override
std::shared_ptr< AsyncCallbacks > m_asyncCallbacks
void takeHeapSnapshot(std::optional< bool > reportProgress, std::optional< bool > treatGlobalObjectsAsRoots, std::optional< bool > captureNumericValue, std::optional< bool > exposeInternals, std::unique_ptr< TakeHeapSnapshotCallback > callback) override
Response addInspectedHeapObject(const String16 &inspectedHeapObjectId) override
V8HeapProfilerAgentImpl(V8InspectorSessionImpl *, protocol::FrontendChannel *, protocol::DictionaryValue *state)
Response startSampling(std::optional< double > samplingInterval, std::optional< bool > includeObjectsCollectedByMajorGC, std::optional< bool > includeObjectsCollectedByMinorGC) override
void startTrackingHeapObjectsInternal(bool trackAllocations)
protocol::HeapProfiler::Frontend m_frontend
Response getSamplingProfile(std::unique_ptr< protocol::HeapProfiler::SamplingHeapProfile > *) override
Response startTrackingHeapObjects(std::optional< bool > trackAllocations) override
Response getObjectByHeapObjectId(const String16 &heapSnapshotObjectId, std::optional< String16 > objectGroup, std::unique_ptr< protocol::Runtime::RemoteObject > *result) override
Response stopSampling(std::unique_ptr< protocol::HeapProfiler::SamplingHeapProfile > *) override
virtual bool isInspectableHeapObject(v8::Local< v8::Object >)
virtual void startRepeatingTimer(double, TimerCallback, void *data)
virtual void cancelTimer(void *data)
void addInspectedObject(std::unique_ptr< V8InspectorSession::Inspectable >) override
std::unique_ptr< protocol::Runtime::RemoteObject > wrapObject(v8::Local< v8::Context >, v8::Local< v8::Value >, const String16 &groupName, bool generatePreview)
Response unwrapObject(const String16 &objectId, v8::Local< v8::Value > *, v8::Local< v8::Context > *, String16 *objectGroup)
int start
uint32_t count
std::vector< std::unique_ptr< InstanceTypeTree > > children
TNode< Context > context
TNode< Object > callback
DirectHandle< JSReceiver > options
ZoneVector< RpoNumber > & result
EmbedderStackState
Definition common.h:15
STL namespace.
void ForceGarbageCollection(Isolate *isolate, StackState embedder_stack_state)
Platform * GetCurrentPlatform()
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage * MB
Definition flags.cc:2197
char16_t UChar
Definition string-16.h:22
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
static constexpr v8::base::TimeDelta kDefaultTimerDelay
uint32_t SnapshotObjectId
Definition v8-profiler.h:31
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_GT(v1, v2)
Definition logging.h:487
ObjectNameResolver * global_object_name_resolver
std::vector< std::unique_ptr< CollectGarbageCallback > > m_gcCallbacks
std::vector< V8HeapProfilerAgentImpl::HeapSnapshotTask * > m_heapSnapshotTasks
HeapSnapshotProtocolOptions(std::optional< bool > reportProgress, std::optional< bool > treatGlobalObjectsAsRoots, std::optional< bool > captureNumericValue, std::optional< bool > exposeInternals)
v8::Isolate * m_isolate
V8InspectorSessionImpl * m_session
protocol::HeapProfiler::Frontend * m_frontend
std::vector< char > m_strings
std::unique_ptr< ValueMirror > value