/src/node/deps/v8/include/v8-profiler.h
Line | Count | Source |
1 | | // Copyright 2010 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 | | #ifndef V8_V8_PROFILER_H_ |
6 | | #define V8_V8_PROFILER_H_ |
7 | | |
8 | | #include <limits.h> |
9 | | |
10 | | #include <memory> |
11 | | #include <unordered_set> |
12 | | #include <vector> |
13 | | |
14 | | #include "cppgc/common.h" // NOLINT(build/include_directory) |
15 | | #include "v8-local-handle.h" // NOLINT(build/include_directory) |
16 | | #include "v8-message.h" // NOLINT(build/include_directory) |
17 | | #include "v8-persistent-handle.h" // NOLINT(build/include_directory) |
18 | | |
19 | | /** |
20 | | * Profiler support for the V8 JavaScript engine. |
21 | | */ |
22 | | namespace v8 { |
23 | | |
24 | | enum class EmbedderStateTag : uint8_t; |
25 | | class HeapGraphNode; |
26 | | struct HeapStatsUpdate; |
27 | | class Object; |
28 | | enum StateTag : uint16_t; |
29 | | |
30 | | using NativeObject = void*; |
31 | | using SnapshotObjectId = uint32_t; |
32 | | using ProfilerId = uint32_t; |
33 | | |
34 | | struct CpuProfileDeoptFrame { |
35 | | int script_id; |
36 | | size_t position; |
37 | | }; |
38 | | |
39 | | namespace internal { |
40 | | class CpuProfile; |
41 | | } // namespace internal |
42 | | |
43 | | } // namespace v8 |
44 | | |
45 | | #ifdef V8_OS_WIN |
46 | | template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>; |
47 | | #endif |
48 | | |
49 | | namespace v8 { |
50 | | |
51 | | struct V8_EXPORT CpuProfileDeoptInfo { |
52 | | /** A pointer to a static string owned by v8. */ |
53 | | const char* deopt_reason; |
54 | | std::vector<CpuProfileDeoptFrame> stack; |
55 | | }; |
56 | | |
57 | | } // namespace v8 |
58 | | |
59 | | #ifdef V8_OS_WIN |
60 | | template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>; |
61 | | #endif |
62 | | |
63 | | namespace v8 { |
64 | | |
65 | | /** |
66 | | * CpuProfileNode represents a node in a call graph. |
67 | | */ |
68 | | class V8_EXPORT CpuProfileNode { |
69 | | public: |
70 | | struct LineTick { |
71 | | /** The 1-based number of the source line where the function originates. */ |
72 | | int line; |
73 | | |
74 | | /** The 1-based number of the source column where the function originates. |
75 | | */ |
76 | | int column; |
77 | | |
78 | | /** The count of samples associated with the source line. */ |
79 | | unsigned int hit_count; |
80 | | }; |
81 | | |
82 | | // An annotation hinting at the source of a CpuProfileNode. |
83 | | enum SourceType { |
84 | | // User-supplied script with associated resource information. |
85 | | kScript = 0, |
86 | | // Native scripts and provided builtins. |
87 | | kBuiltin = 1, |
88 | | // Callbacks into native code. |
89 | | kCallback = 2, |
90 | | // VM-internal functions or state. |
91 | | kInternal = 3, |
92 | | // A node that failed to symbolize. |
93 | | kUnresolved = 4, |
94 | | }; |
95 | | |
96 | | /** Returns function name (empty string for anonymous functions.) */ |
97 | | Local<String> GetFunctionName() const; |
98 | | |
99 | | /** |
100 | | * Returns function name (empty string for anonymous functions.) |
101 | | * The string ownership is *not* passed to the caller. It stays valid until |
102 | | * profile is deleted. The function is thread safe. |
103 | | */ |
104 | | const char* GetFunctionNameStr() const; |
105 | | |
106 | | /** Returns id of the script where function is located. */ |
107 | | int GetScriptId() const; |
108 | | |
109 | | /** Returns resource name for script from where the function originates. */ |
110 | | Local<String> GetScriptResourceName() const; |
111 | | |
112 | | /** |
113 | | * Returns resource name for script from where the function originates. |
114 | | * The string ownership is *not* passed to the caller. It stays valid until |
115 | | * profile is deleted. The function is thread safe. |
116 | | */ |
117 | | const char* GetScriptResourceNameStr() const; |
118 | | |
119 | | /** |
120 | | * Return true if the script from where the function originates is flagged as |
121 | | * being shared cross-origin. |
122 | | */ |
123 | | bool IsScriptSharedCrossOrigin() const; |
124 | | |
125 | | /** |
126 | | * Returns the number, 1-based, of the line where the function originates. |
127 | | * kNoLineNumberInfo if no line number information is available. |
128 | | */ |
129 | | int GetLineNumber() const; |
130 | | |
131 | | /** |
132 | | * Returns 1-based number of the column where the function originates. |
133 | | * kNoColumnNumberInfo if no column number information is available. |
134 | | */ |
135 | | int GetColumnNumber() const; |
136 | | |
137 | | /** |
138 | | * Returns the number of the function's source lines that collect the samples. |
139 | | */ |
140 | | unsigned int GetHitLineCount() const; |
141 | | |
142 | | /** Returns the set of source lines that collect the samples. |
143 | | * The caller allocates buffer and responsible for releasing it. |
144 | | * True if all available entries are copied, otherwise false. |
145 | | * The function copies nothing if buffer is not large enough. |
146 | | */ |
147 | | bool GetLineTicks(LineTick* entries, unsigned int length) const; |
148 | | |
149 | | /** Returns bailout reason for the function |
150 | | * if the optimization was disabled for it. |
151 | | */ |
152 | | const char* GetBailoutReason() const; |
153 | | |
154 | | /** |
155 | | * Returns the count of samples where the function was currently executing. |
156 | | */ |
157 | | unsigned GetHitCount() const; |
158 | | |
159 | | /** Returns id of the node. The id is unique within the tree */ |
160 | | unsigned GetNodeId() const; |
161 | | |
162 | | /** |
163 | | * Gets the type of the source which the node was captured from. |
164 | | */ |
165 | | SourceType GetSourceType() const; |
166 | | |
167 | | /** Returns child nodes count of the node. */ |
168 | | int GetChildrenCount() const; |
169 | | |
170 | | /** Retrieves a child node by index. */ |
171 | | const CpuProfileNode* GetChild(int index) const; |
172 | | |
173 | | /** Retrieves the ancestor node, or null if the root. */ |
174 | | const CpuProfileNode* GetParent() const; |
175 | | |
176 | | /** Retrieves deopt infos for the node. */ |
177 | | const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const; |
178 | | |
179 | | static const int kNoLineNumberInfo = Message::kNoLineNumberInfo; |
180 | | static const int kNoColumnNumberInfo = Message::kNoColumnInfo; |
181 | | }; |
182 | | |
183 | | /** |
184 | | * An interface for exporting data from V8, using "push" model. |
185 | | */ |
186 | | class V8_EXPORT OutputStream { |
187 | | public: |
188 | | enum WriteResult { kContinue = 0, kAbort = 1 }; |
189 | 0 | virtual ~OutputStream() = default; |
190 | | /** Notify about the end of stream. */ |
191 | | virtual void EndOfStream() = 0; |
192 | | /** Get preferred output chunk size. Called only once. */ |
193 | 0 | virtual int GetChunkSize() { return 1024; } |
194 | | /** |
195 | | * Writes the next chunk of snapshot data into the stream. Writing |
196 | | * can be stopped by returning kAbort as function result. EndOfStream |
197 | | * will not be called in case writing was aborted. |
198 | | */ |
199 | | virtual WriteResult WriteAsciiChunk(char* data, int size) = 0; |
200 | | /** |
201 | | * Writes the next chunk of heap stats data into the stream. Writing |
202 | | * can be stopped by returning kAbort as function result. EndOfStream |
203 | | * will not be called in case writing was aborted. |
204 | | */ |
205 | 0 | virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) { |
206 | 0 | return kAbort; |
207 | 0 | } |
208 | | }; |
209 | | |
210 | | /** |
211 | | * CpuProfile contains a CPU profile in a form of top-down call tree |
212 | | * (from main() down to functions that do all the work). |
213 | | */ |
214 | | class V8_EXPORT CpuProfile { |
215 | | public: |
216 | | enum SerializationFormat { |
217 | | kJSON = 0 // See format description near 'Serialize' method. |
218 | | }; |
219 | | /** Returns CPU profile title. */ |
220 | | Local<String> GetTitle() const; |
221 | | |
222 | | /** Returns the root node of the top down call tree. */ |
223 | | const CpuProfileNode* GetTopDownRoot() const; |
224 | | |
225 | | /** |
226 | | * Returns number of samples recorded. The samples are not recorded unless |
227 | | * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true. |
228 | | */ |
229 | | int GetSamplesCount() const; |
230 | | |
231 | | /** |
232 | | * Returns profile node corresponding to the top frame the sample at |
233 | | * the given index. |
234 | | */ |
235 | | const CpuProfileNode* GetSample(int index) const; |
236 | | |
237 | | /** |
238 | | * Returns the timestamp of the sample. The timestamp is the number of |
239 | | * microseconds since some unspecified starting point. |
240 | | * The point is equal to the starting point used by GetStartTime. |
241 | | */ |
242 | | int64_t GetSampleTimestamp(int index) const; |
243 | | |
244 | | /** |
245 | | * Returns time when the profile recording was started (in microseconds) |
246 | | * since some unspecified starting point. |
247 | | */ |
248 | | int64_t GetStartTime() const; |
249 | | |
250 | | /** |
251 | | * Returns state of the vm when sample was captured. |
252 | | */ |
253 | | StateTag GetSampleState(int index) const; |
254 | | |
255 | | /** |
256 | | * Returns state of the embedder when sample was captured. |
257 | | */ |
258 | | EmbedderStateTag GetSampleEmbedderState(int index) const; |
259 | | |
260 | | /** |
261 | | * Returns time when the profile recording was stopped (in microseconds) |
262 | | * since some unspecified starting point. |
263 | | * The point is equal to the starting point used by GetStartTime. |
264 | | */ |
265 | | int64_t GetEndTime() const; |
266 | | |
267 | | /** |
268 | | * Deletes the profile and removes it from CpuProfiler's list. |
269 | | * All pointers to nodes previously returned become invalid. |
270 | | */ |
271 | | void Delete(); |
272 | | |
273 | | /** |
274 | | * Prepare a serialized representation of the profile. The result |
275 | | * is written into the stream provided in chunks of specified size. |
276 | | * |
277 | | * For the JSON format, heap contents are represented as an object |
278 | | * with the following structure: |
279 | | * |
280 | | * { |
281 | | * nodes: [nodes array], |
282 | | * startTime: number, |
283 | | * endTime: number |
284 | | * samples: [strings array] |
285 | | * timeDeltas: [numbers array] |
286 | | * } |
287 | | * |
288 | | */ |
289 | | void Serialize(OutputStream* stream, |
290 | | SerializationFormat format = kJSON) const; |
291 | | }; |
292 | | |
293 | | enum CpuProfilingMode { |
294 | | // In the resulting CpuProfile tree, intermediate nodes in a stack trace |
295 | | // (from the root to a leaf) will have line numbers that point to the start |
296 | | // line of the function, rather than the line of the callsite of the child. |
297 | | kLeafNodeLineNumbers, |
298 | | // In the resulting CpuProfile tree, nodes are separated based on the line |
299 | | // number of their callsite in their parent. |
300 | | kCallerLineNumbers, |
301 | | }; |
302 | | |
303 | | // Determines how names are derived for functions sampled. |
304 | | enum CpuProfilingNamingMode { |
305 | | // Use the immediate name of functions at compilation time. |
306 | | kStandardNaming, |
307 | | // Use more verbose naming for functions without names, inferred from scope |
308 | | // where possible. |
309 | | kDebugNaming, |
310 | | }; |
311 | | |
312 | | enum CpuProfilingLoggingMode { |
313 | | // Enables logging when a profile is active, and disables logging when all |
314 | | // profiles are detached. |
315 | | kLazyLogging, |
316 | | // Enables logging for the lifetime of the CpuProfiler. Calls to |
317 | | // StartRecording are faster, at the expense of runtime overhead. |
318 | | kEagerLogging, |
319 | | }; |
320 | | |
321 | | // Enum for returning profiling status. Once StartProfiling is called, |
322 | | // we want to return to clients whether the profiling was able to start |
323 | | // correctly, or return a descriptive error. |
324 | | enum class CpuProfilingStatus { |
325 | | kStarted, |
326 | | kAlreadyStarted, |
327 | | kErrorTooManyProfilers |
328 | | }; |
329 | | |
330 | | /** |
331 | | * Result from StartProfiling returning the Profiling Status, and |
332 | | * id of the started profiler, or 0 if profiler is not started |
333 | | */ |
334 | | struct CpuProfilingResult { |
335 | | const ProfilerId id; |
336 | | const CpuProfilingStatus status; |
337 | | }; |
338 | | |
339 | | /** |
340 | | * Delegate for when max samples reached and samples are discarded. |
341 | | */ |
342 | | class V8_EXPORT DiscardedSamplesDelegate { |
343 | | public: |
344 | | DiscardedSamplesDelegate() = default; |
345 | | |
346 | | virtual ~DiscardedSamplesDelegate() = default; |
347 | | virtual void Notify() = 0; |
348 | | |
349 | 0 | ProfilerId GetId() const { return profiler_id_; } |
350 | | |
351 | | private: |
352 | | friend internal::CpuProfile; |
353 | | |
354 | 0 | void SetId(ProfilerId id) { profiler_id_ = id; } |
355 | | |
356 | | ProfilerId profiler_id_; |
357 | | }; |
358 | | |
359 | | /** |
360 | | * Optional profiling attributes. |
361 | | */ |
362 | | class V8_EXPORT CpuProfilingOptions { |
363 | | public: |
364 | | // Indicates that the sample buffer size should not be explicitly limited. |
365 | | static const unsigned kNoSampleLimit = UINT_MAX; |
366 | | |
367 | | /** |
368 | | * \param mode Type of computation of stack frame line numbers. |
369 | | * \param max_samples The maximum number of samples that should be recorded by |
370 | | * the profiler. Samples obtained after this limit will be |
371 | | * discarded. |
372 | | * \param sampling_interval_us controls the profile-specific target |
373 | | * sampling interval. The provided sampling |
374 | | * interval will be snapped to the next lowest |
375 | | * non-zero multiple of the profiler's sampling |
376 | | * interval, set via SetSamplingInterval(). If |
377 | | * zero, the sampling interval will be equal to |
378 | | * the profiler's sampling interval. |
379 | | * \param filter_context If specified, profiles will only contain frames |
380 | | * using this context. Other frames will be elided. |
381 | | */ |
382 | | CpuProfilingOptions( |
383 | | CpuProfilingMode mode = kLeafNodeLineNumbers, |
384 | | unsigned max_samples = kNoSampleLimit, int sampling_interval_us = 0, |
385 | | MaybeLocal<Context> filter_context = MaybeLocal<Context>()); |
386 | | |
387 | | CpuProfilingOptions(CpuProfilingOptions&&) = default; |
388 | | CpuProfilingOptions& operator=(CpuProfilingOptions&&) = default; |
389 | | |
390 | 0 | CpuProfilingMode mode() const { return mode_; } |
391 | 0 | unsigned max_samples() const { return max_samples_; } |
392 | 0 | int sampling_interval_us() const { return sampling_interval_us_; } |
393 | | |
394 | | private: |
395 | | friend class internal::CpuProfile; |
396 | | |
397 | 0 | bool has_filter_context() const { return !filter_context_.IsEmpty(); } |
398 | | void* raw_filter_context() const; |
399 | | |
400 | | CpuProfilingMode mode_; |
401 | | unsigned max_samples_; |
402 | | int sampling_interval_us_; |
403 | | Global<Context> filter_context_; |
404 | | }; |
405 | | |
406 | | /** |
407 | | * Interface for controlling CPU profiling. Instance of the |
408 | | * profiler can be created using v8::CpuProfiler::New method. |
409 | | */ |
410 | | class V8_EXPORT CpuProfiler { |
411 | | public: |
412 | | /** |
413 | | * Creates a new CPU profiler for the |isolate|. The isolate must be |
414 | | * initialized. The profiler object must be disposed after use by calling |
415 | | * |Dispose| method. |
416 | | */ |
417 | | static CpuProfiler* New(Isolate* isolate, |
418 | | CpuProfilingNamingMode = kDebugNaming, |
419 | | CpuProfilingLoggingMode = kLazyLogging); |
420 | | |
421 | | /** |
422 | | * Synchronously collect current stack sample in all profilers attached to |
423 | | * the |isolate|. The call does not affect number of ticks recorded for |
424 | | * the current top node. |
425 | | * |trace_id| is an optional identifier set to the collected sample. |
426 | | * this is useful to associate the sample with a trace event. |
427 | | */ |
428 | | static void CollectSample( |
429 | | Isolate* isolate, const std::optional<uint64_t> trace_id = std::nullopt); |
430 | | |
431 | | /** |
432 | | * Disposes the CPU profiler object. |
433 | | */ |
434 | | void Dispose(); |
435 | | |
436 | | /** |
437 | | * Changes default CPU profiler sampling interval to the specified number |
438 | | * of microseconds. Default interval is 1000us. This method must be called |
439 | | * when there are no profiles being recorded. |
440 | | */ |
441 | | void SetSamplingInterval(int us); |
442 | | |
443 | | /** |
444 | | * Sets whether or not the profiler should prioritize consistency of sample |
445 | | * periodicity on Windows. Disabling this can greatly reduce CPU usage, but |
446 | | * may result in greater variance in sample timings from the platform's |
447 | | * scheduler. Defaults to enabled. This method must be called when there are |
448 | | * no profiles being recorded. |
449 | | */ |
450 | | void SetUsePreciseSampling(bool); |
451 | | |
452 | | /** |
453 | | * Starts collecting a CPU profile. Several profiles may be collected at once. |
454 | | * Generates an anonymous profiler, without a String identifier. |
455 | | */ |
456 | | CpuProfilingResult Start( |
457 | | CpuProfilingOptions options, |
458 | | std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr); |
459 | | |
460 | | /** |
461 | | * Starts collecting a CPU profile. Title may be an empty string. Several |
462 | | * profiles may be collected at once. Attempts to start collecting several |
463 | | * profiles with the same title are silently ignored. |
464 | | */ |
465 | | CpuProfilingResult Start( |
466 | | Local<String> title, CpuProfilingOptions options, |
467 | | std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr); |
468 | | |
469 | | /** |
470 | | * Starts profiling with the same semantics as above, except with expanded |
471 | | * parameters. |
472 | | * |
473 | | * |record_samples| parameter controls whether individual samples should |
474 | | * be recorded in addition to the aggregated tree. |
475 | | * |
476 | | * |max_samples| controls the maximum number of samples that should be |
477 | | * recorded by the profiler. Samples obtained after this limit will be |
478 | | * discarded. |
479 | | */ |
480 | | CpuProfilingResult Start( |
481 | | Local<String> title, CpuProfilingMode mode, bool record_samples = false, |
482 | | unsigned max_samples = CpuProfilingOptions::kNoSampleLimit); |
483 | | |
484 | | /** |
485 | | * The same as StartProfiling above, but the CpuProfilingMode defaults to |
486 | | * kLeafNodeLineNumbers mode, which was the previous default behavior of the |
487 | | * profiler. |
488 | | */ |
489 | | CpuProfilingResult Start(Local<String> title, bool record_samples = false); |
490 | | |
491 | | /** |
492 | | * Starts collecting a CPU profile. Title may be an empty string. Several |
493 | | * profiles may be collected at once. Attempts to start collecting several |
494 | | * profiles with the same title are silently ignored. |
495 | | */ |
496 | | CpuProfilingStatus StartProfiling( |
497 | | Local<String> title, CpuProfilingOptions options, |
498 | | std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr); |
499 | | |
500 | | /** |
501 | | * Starts profiling with the same semantics as above, except with expanded |
502 | | * parameters. |
503 | | * |
504 | | * |record_samples| parameter controls whether individual samples should |
505 | | * be recorded in addition to the aggregated tree. |
506 | | * |
507 | | * |max_samples| controls the maximum number of samples that should be |
508 | | * recorded by the profiler. Samples obtained after this limit will be |
509 | | * discarded. |
510 | | */ |
511 | | CpuProfilingStatus StartProfiling( |
512 | | Local<String> title, CpuProfilingMode mode, bool record_samples = false, |
513 | | unsigned max_samples = CpuProfilingOptions::kNoSampleLimit); |
514 | | |
515 | | /** |
516 | | * The same as StartProfiling above, but the CpuProfilingMode defaults to |
517 | | * kLeafNodeLineNumbers mode, which was the previous default behavior of the |
518 | | * profiler. |
519 | | */ |
520 | | CpuProfilingStatus StartProfiling(Local<String> title, |
521 | | bool record_samples = false); |
522 | | |
523 | | /** |
524 | | * Stops collecting CPU profile with a given id and returns it. |
525 | | */ |
526 | | CpuProfile* Stop(ProfilerId id); |
527 | | |
528 | | /** |
529 | | * Stops collecting CPU profile with a given title and returns it. |
530 | | * If the title given is empty, finishes the last profile started. |
531 | | */ |
532 | | CpuProfile* StopProfiling(Local<String> title); |
533 | | |
534 | | /** |
535 | | * Generate more detailed source positions to code objects. This results in |
536 | | * better results when mapping profiling samples to script source. |
537 | | */ |
538 | | static void UseDetailedSourcePositionsForProfiling(Isolate* isolate); |
539 | | |
540 | | private: |
541 | | CpuProfiler(); |
542 | | ~CpuProfiler(); |
543 | | CpuProfiler(const CpuProfiler&); |
544 | | CpuProfiler& operator=(const CpuProfiler&); |
545 | | }; |
546 | | |
547 | | /** |
548 | | * HeapSnapshotEdge represents a directed connection between heap |
549 | | * graph nodes: from retainers to retained nodes. |
550 | | */ |
551 | | class V8_EXPORT HeapGraphEdge { |
552 | | public: |
553 | | enum Type { |
554 | | kContextVariable = 0, // A variable from a function context. |
555 | | kElement = 1, // An element of an array. |
556 | | kProperty = 2, // A named object property. |
557 | | kInternal = 3, // A link that can't be accessed from JS, |
558 | | // thus, its name isn't a real property name |
559 | | // (e.g. parts of a ConsString). |
560 | | kHidden = 4, // A link that is needed for proper sizes |
561 | | // calculation, but may be hidden from user. |
562 | | kShortcut = 5, // A link that must not be followed during |
563 | | // sizes calculation. |
564 | | kWeak = 6 // A weak reference (ignored by the GC). |
565 | | }; |
566 | | |
567 | | /** Returns edge type (see HeapGraphEdge::Type). */ |
568 | | Type GetType() const; |
569 | | |
570 | | /** |
571 | | * Returns edge name. This can be a variable name, an element index, or |
572 | | * a property name. |
573 | | */ |
574 | | Local<Value> GetName() const; |
575 | | |
576 | | /** Returns origin node. */ |
577 | | const HeapGraphNode* GetFromNode() const; |
578 | | |
579 | | /** Returns destination node. */ |
580 | | const HeapGraphNode* GetToNode() const; |
581 | | }; |
582 | | |
583 | | |
584 | | /** |
585 | | * HeapGraphNode represents a node in a heap graph. |
586 | | */ |
587 | | class V8_EXPORT HeapGraphNode { |
588 | | public: |
589 | | enum Type { |
590 | | kHidden = 0, // Hidden node, may be filtered when shown to user. |
591 | | kArray = 1, // An array of elements. |
592 | | kString = 2, // A string. |
593 | | kObject = 3, // A JS object (except for arrays and strings). |
594 | | kCode = 4, // Compiled code. |
595 | | kClosure = 5, // Function closure. |
596 | | kRegExp = 6, // RegExp. |
597 | | kHeapNumber = 7, // Number stored in the heap. |
598 | | kNative = 8, // Native object (not from V8 heap). |
599 | | kSynthetic = 9, // Synthetic object, usually used for grouping |
600 | | // snapshot items together. |
601 | | kConsString = 10, // Concatenated string. A pair of pointers to strings. |
602 | | kSlicedString = 11, // Sliced string. A fragment of another string. |
603 | | kSymbol = 12, // A Symbol (ES6). |
604 | | kBigInt = 13, // BigInt. |
605 | | kObjectShape = 14, // Internal data used for tracking the shapes (or |
606 | | // "hidden classes") of JS objects. |
607 | | }; |
608 | | |
609 | | /** Returns node type (see HeapGraphNode::Type). */ |
610 | | Type GetType() const; |
611 | | |
612 | | /** |
613 | | * Returns node name. Depending on node's type this can be the name |
614 | | * of the constructor (for objects), the name of the function (for |
615 | | * closures), string value, or an empty string (for compiled code). |
616 | | */ |
617 | | Local<String> GetName() const; |
618 | | |
619 | | /** |
620 | | * Returns node id. For the same heap object, the id remains the same |
621 | | * across all snapshots. |
622 | | */ |
623 | | SnapshotObjectId GetId() const; |
624 | | |
625 | | /** Returns node's own size, in bytes. */ |
626 | | size_t GetShallowSize() const; |
627 | | |
628 | | /** Returns child nodes count of the node. */ |
629 | | int GetChildrenCount() const; |
630 | | |
631 | | /** Retrieves a child by index. */ |
632 | | const HeapGraphEdge* GetChild(int index) const; |
633 | | }; |
634 | | |
635 | | /** |
636 | | * HeapSnapshots record the state of the JS heap at some moment. |
637 | | */ |
638 | | class V8_EXPORT HeapSnapshot { |
639 | | public: |
640 | | enum SerializationFormat { |
641 | | kJSON = 0 // See format description near 'Serialize' method. |
642 | | }; |
643 | | |
644 | | /** Returns the root node of the heap graph. */ |
645 | | const HeapGraphNode* GetRoot() const; |
646 | | |
647 | | /** Returns a node by its id. */ |
648 | | const HeapGraphNode* GetNodeById(SnapshotObjectId id) const; |
649 | | |
650 | | /** Returns total nodes count in the snapshot. */ |
651 | | int GetNodesCount() const; |
652 | | |
653 | | /** Returns a node by index. */ |
654 | | const HeapGraphNode* GetNode(int index) const; |
655 | | |
656 | | /** Returns a max seen JS object Id. */ |
657 | | SnapshotObjectId GetMaxSnapshotJSObjectId() const; |
658 | | |
659 | | /** |
660 | | * Deletes the snapshot and removes it from HeapProfiler's list. |
661 | | * All pointers to nodes, edges and paths previously returned become |
662 | | * invalid. |
663 | | */ |
664 | | void Delete(); |
665 | | |
666 | | /** |
667 | | * Prepare a serialized representation of the snapshot. The result |
668 | | * is written into the stream provided in chunks of specified size. |
669 | | * The total length of the serialized snapshot is unknown in |
670 | | * advance, it can be roughly equal to JS heap size (that means, |
671 | | * it can be really big - tens of megabytes). |
672 | | * |
673 | | * For the JSON format, heap contents are represented as an object |
674 | | * with the following structure: |
675 | | * |
676 | | * { |
677 | | * snapshot: { |
678 | | * title: "...", |
679 | | * uid: nnn, |
680 | | * meta: { meta-info }, |
681 | | * node_count: nnn, |
682 | | * edge_count: nnn |
683 | | * }, |
684 | | * nodes: [nodes array], |
685 | | * edges: [edges array], |
686 | | * strings: [strings array] |
687 | | * } |
688 | | * |
689 | | * Nodes reference strings, other nodes, and edges by their indexes |
690 | | * in corresponding arrays. |
691 | | */ |
692 | | void Serialize(OutputStream* stream, |
693 | | SerializationFormat format = kJSON) const; |
694 | | }; |
695 | | |
696 | | |
697 | | /** |
698 | | * An interface for reporting progress and controlling long-running |
699 | | * activities. |
700 | | */ |
701 | | class V8_EXPORT ActivityControl { |
702 | | public: |
703 | | enum ControlOption { |
704 | | kContinue = 0, |
705 | | kAbort = 1 |
706 | | }; |
707 | | virtual ~ActivityControl() = default; |
708 | | /** |
709 | | * Notify about current progress. The activity can be stopped by |
710 | | * returning kAbort as the callback result. |
711 | | */ |
712 | | virtual ControlOption ReportProgressValue(uint32_t done, uint32_t total) = 0; |
713 | | }; |
714 | | |
715 | | /** |
716 | | * AllocationProfile is a sampled profile of allocations done by the program. |
717 | | * This is structured as a call-graph. |
718 | | */ |
719 | | class V8_EXPORT AllocationProfile { |
720 | | public: |
721 | | struct Allocation { |
722 | | /** |
723 | | * Size of the sampled allocation object. |
724 | | */ |
725 | | size_t size; |
726 | | |
727 | | /** |
728 | | * The number of objects of such size that were sampled. |
729 | | */ |
730 | | unsigned int count; |
731 | | }; |
732 | | |
733 | | /** |
734 | | * Represents a node in the call-graph. |
735 | | */ |
736 | | struct Node { |
737 | | /** |
738 | | * Name of the function. May be empty for anonymous functions or if the |
739 | | * script corresponding to this function has been unloaded. |
740 | | */ |
741 | | Local<String> name; |
742 | | |
743 | | /** |
744 | | * Name of the script containing the function. May be empty if the script |
745 | | * name is not available, or if the script has been unloaded. |
746 | | */ |
747 | | Local<String> script_name; |
748 | | |
749 | | /** |
750 | | * id of the script where the function is located. May be equal to |
751 | | * v8::UnboundScript::kNoScriptId in cases where the script doesn't exist. |
752 | | */ |
753 | | int script_id; |
754 | | |
755 | | /** |
756 | | * Start position of the function in the script. |
757 | | */ |
758 | | int start_position; |
759 | | |
760 | | /** |
761 | | * 1-indexed line number where the function starts. May be |
762 | | * kNoLineNumberInfo if no line number information is available. |
763 | | */ |
764 | | int line_number; |
765 | | |
766 | | /** |
767 | | * 1-indexed column number where the function starts. May be |
768 | | * kNoColumnNumberInfo if no line number information is available. |
769 | | */ |
770 | | int column_number; |
771 | | |
772 | | /** |
773 | | * Unique id of the node. |
774 | | */ |
775 | | uint32_t node_id; |
776 | | |
777 | | /** |
778 | | * List of callees called from this node for which we have sampled |
779 | | * allocations. The lifetime of the children is scoped to the containing |
780 | | * AllocationProfile. |
781 | | */ |
782 | | std::vector<Node*> children; |
783 | | |
784 | | /** |
785 | | * List of self allocations done by this node in the call-graph. |
786 | | */ |
787 | | std::vector<Allocation> allocations; |
788 | | }; |
789 | | |
790 | | /** |
791 | | * Represent a single sample recorded for an allocation. |
792 | | */ |
793 | | struct Sample { |
794 | | /** |
795 | | * id of the node in the profile tree. |
796 | | */ |
797 | | uint32_t node_id; |
798 | | |
799 | | /** |
800 | | * Size of the sampled allocation object. |
801 | | */ |
802 | | size_t size; |
803 | | |
804 | | /** |
805 | | * The number of objects of such size that were sampled. |
806 | | */ |
807 | | unsigned int count; |
808 | | |
809 | | /** |
810 | | * Unique time-ordered id of the allocation sample. Can be used to track |
811 | | * what samples were added or removed between two snapshots. |
812 | | */ |
813 | | uint64_t sample_id; |
814 | | }; |
815 | | |
816 | | /** |
817 | | * Returns the root node of the call-graph. The root node corresponds to an |
818 | | * empty JS call-stack. The lifetime of the returned Node* is scoped to the |
819 | | * containing AllocationProfile. |
820 | | */ |
821 | | virtual Node* GetRootNode() = 0; |
822 | | virtual const std::vector<Sample>& GetSamples() = 0; |
823 | | |
824 | | virtual ~AllocationProfile() = default; |
825 | | |
826 | | static const int kNoLineNumberInfo = Message::kNoLineNumberInfo; |
827 | | static const int kNoColumnNumberInfo = Message::kNoColumnInfo; |
828 | | }; |
829 | | |
830 | | /** |
831 | | * An object graph consisting of embedder objects and V8 objects. |
832 | | * Edges of the graph are strong references between the objects. |
833 | | * The embedder can build this graph during heap snapshot generation |
834 | | * to include the embedder objects in the heap snapshot. |
835 | | * Usage: |
836 | | * 1) Define derived class of EmbedderGraph::Node for embedder objects. |
837 | | * 2) Set the build embedder graph callback on the heap profiler using |
838 | | * HeapProfiler::AddBuildEmbedderGraphCallback. |
839 | | * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from |
840 | | * node1 to node2. |
841 | | * 4) To represent references from/to V8 object, construct V8 nodes using |
842 | | * graph->V8Node(value). |
843 | | */ |
844 | | class V8_EXPORT EmbedderGraph { |
845 | | public: |
846 | | class Node { |
847 | | public: |
848 | | /** |
849 | | * Detachedness specifies whether an object is attached or detached from the |
850 | | * main application state. While unkown in general, there may be objects |
851 | | * that specifically know their state. V8 passes this information along in |
852 | | * the snapshot. Users of the snapshot may use it to annotate the object |
853 | | * graph. |
854 | | */ |
855 | | enum class Detachedness : uint8_t { |
856 | | kUnknown = 0, |
857 | | kAttached = 1, |
858 | | kDetached = 2, |
859 | | }; |
860 | | |
861 | 0 | Node() = default; |
862 | 0 | virtual ~Node() = default; |
863 | | virtual const char* Name() = 0; |
864 | | virtual size_t SizeInBytes() = 0; |
865 | | /** |
866 | | * The corresponding V8 wrapper node if not null. |
867 | | * During heap snapshot generation the embedder node and the V8 wrapper |
868 | | * node will be merged into one node to simplify retaining paths. |
869 | | */ |
870 | 0 | virtual Node* WrapperNode() { return nullptr; } |
871 | 0 | virtual bool IsRootNode() { return false; } |
872 | | /** Must return true for non-V8 nodes. */ |
873 | 0 | virtual bool IsEmbedderNode() { return true; } |
874 | | /** |
875 | | * Optional name prefix. It is used in Chrome for tagging detached nodes. |
876 | | */ |
877 | 0 | virtual const char* NamePrefix() { return nullptr; } |
878 | | |
879 | | /** |
880 | | * Returns the NativeObject that can be used for querying the |
881 | | * |HeapSnapshot|. |
882 | | */ |
883 | 0 | virtual NativeObject GetNativeObject() { return nullptr; } |
884 | | |
885 | | /** |
886 | | * Detachedness state of a given object. While unkown in general, there may |
887 | | * be objects that specifically know their state. V8 passes this information |
888 | | * along in the snapshot. Users of the snapshot may use it to annotate the |
889 | | * object graph. |
890 | | */ |
891 | 0 | virtual Detachedness GetDetachedness() { return Detachedness::kUnknown; } |
892 | | |
893 | | /** |
894 | | * Returns the address of the object in the embedder heap, or nullptr to not |
895 | | * specify the address. If this address is provided, then V8 can generate |
896 | | * consistent IDs for objects across subsequent heap snapshots, which allows |
897 | | * devtools to determine which objects were retained from one snapshot to |
898 | | * the next. This value is used only if GetNativeObject returns nullptr. |
899 | | */ |
900 | 0 | virtual const void* GetAddress() { return nullptr; } |
901 | | |
902 | | Node(const Node&) = delete; |
903 | | Node& operator=(const Node&) = delete; |
904 | | }; |
905 | | |
906 | | /** |
907 | | * Returns a node corresponding to the given V8 value. Ownership is not |
908 | | * transferred. The result pointer is valid while the graph is alive. |
909 | | * |
910 | | * For now the variant that takes v8::Data is not marked as abstract for |
911 | | * compatibility, but embedders who subclass EmbedderGraph are expected to |
912 | | * implement it. Then in the implementation of the variant that takes |
913 | | * v8::Value, they can simply forward the call to the one that takes |
914 | | * v8::Local<v8::Data>. |
915 | | */ |
916 | | virtual Node* V8Node(const v8::Local<v8::Value>& value) = 0; |
917 | | |
918 | | /** |
919 | | * Returns a node corresponding to the given V8 value. Ownership is not |
920 | | * transferred. The result pointer is valid while the graph is alive. |
921 | | * |
922 | | * For API compatibility, this default implementation just checks that the |
923 | | * data is a v8::Value and forward it to the variant that takes v8::Value, |
924 | | * which is currently required to be implemented. In the future we'll remove |
925 | | * the v8::Value variant, and make this variant that takes v8::Data abstract |
926 | | * instead. If the embedder subclasses v8::EmbedderGraph and also use |
927 | | * v8::TracedReference<v8::Data>, they must override this variant. |
928 | | */ |
929 | | virtual Node* V8Node(const v8::Local<v8::Data>& value); |
930 | | |
931 | | /** |
932 | | * Adds the given node to the graph and takes ownership of the node. |
933 | | * Returns a raw pointer to the node that is valid while the graph is alive. |
934 | | */ |
935 | | virtual Node* AddNode(std::unique_ptr<Node> node) = 0; |
936 | | |
937 | | /** |
938 | | * Adds an edge that represents a strong reference from the given |
939 | | * node |from| to the given node |to|. The nodes must be added to the graph |
940 | | * before calling this function. |
941 | | * |
942 | | * If name is nullptr, the edge will have auto-increment indexes, otherwise |
943 | | * it will be named accordingly. |
944 | | */ |
945 | | virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0; |
946 | | |
947 | | /** |
948 | | * Adds a count of bytes that are not associated with any particular Node. |
949 | | * An embedder may use this to represent the size of nodes which were omitted |
950 | | * from this EmbedderGraph despite being retained by the graph, or other |
951 | | * overhead costs. This number will contribute to the total size in a heap |
952 | | * snapshot, without being represented in the object graph. |
953 | | */ |
954 | 0 | virtual void AddNativeSize(size_t size) {} |
955 | | |
956 | 0 | virtual ~EmbedderGraph() = default; |
957 | | }; |
958 | | |
959 | | class QueryObjectPredicate { |
960 | | public: |
961 | 0 | virtual ~QueryObjectPredicate() = default; |
962 | | virtual bool Filter(v8::Local<v8::Object> object) = 0; |
963 | | }; |
964 | | |
965 | | /** |
966 | | * Interface for controlling heap profiling. Instance of the |
967 | | * profiler can be retrieved using v8::Isolate::GetHeapProfiler. |
968 | | */ |
969 | | class V8_EXPORT HeapProfiler { |
970 | | public: |
971 | | void QueryObjects(v8::Local<v8::Context> context, |
972 | | QueryObjectPredicate* predicate, |
973 | | std::vector<v8::Global<v8::Object>>* objects); |
974 | | |
975 | | enum SamplingFlags { |
976 | | kSamplingNoFlags = 0, |
977 | | kSamplingForceGC = 1 << 0, |
978 | | kSamplingIncludeObjectsCollectedByMajorGC = 1 << 1, |
979 | | kSamplingIncludeObjectsCollectedByMinorGC = 1 << 2, |
980 | | }; |
981 | | |
982 | | /** |
983 | | * Callback function invoked during heap snapshot generation to retrieve |
984 | | * the embedder object graph. The callback should use graph->AddEdge(..) to |
985 | | * add references between the objects. |
986 | | * The callback must not trigger garbage collection in V8. |
987 | | */ |
988 | | typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate, |
989 | | v8::EmbedderGraph* graph, |
990 | | void* data); |
991 | | |
992 | | /** |
993 | | * Callback function invoked during heap snapshot generation to retrieve |
994 | | * the detachedness state of a JS object referenced by a TracedReference. |
995 | | * |
996 | | * The callback takes Local<Value> as parameter to allow the embedder to |
997 | | * unpack the TracedReference into a Local and reuse that Local for different |
998 | | * purposes. |
999 | | */ |
1000 | | using GetDetachednessCallback = EmbedderGraph::Node::Detachedness (*)( |
1001 | | v8::Isolate* isolate, const v8::Local<v8::Value>& v8_value, |
1002 | | uint16_t class_id, void* data); |
1003 | | |
1004 | | /** Returns the number of snapshots taken. */ |
1005 | | int GetSnapshotCount(); |
1006 | | |
1007 | | /** Returns a snapshot by index. */ |
1008 | | const HeapSnapshot* GetHeapSnapshot(int index); |
1009 | | |
1010 | | /** |
1011 | | * Returns SnapshotObjectId for a heap object referenced by |value| if |
1012 | | * it has been seen by the heap profiler, kUnknownObjectId otherwise. |
1013 | | */ |
1014 | | SnapshotObjectId GetObjectId(Local<Value> value); |
1015 | | |
1016 | | /** |
1017 | | * Returns SnapshotObjectId for a native object referenced by |value| if it |
1018 | | * has been seen by the heap profiler, kUnknownObjectId otherwise. |
1019 | | */ |
1020 | | SnapshotObjectId GetObjectId(NativeObject value); |
1021 | | |
1022 | | /** |
1023 | | * Returns heap object with given SnapshotObjectId if the object is alive, |
1024 | | * otherwise empty handle is returned. |
1025 | | */ |
1026 | | Local<Value> FindObjectById(SnapshotObjectId id); |
1027 | | |
1028 | | /** |
1029 | | * Clears internal map from SnapshotObjectId to heap object. The new objects |
1030 | | * will not be added into it unless a heap snapshot is taken or heap object |
1031 | | * tracking is kicked off. |
1032 | | */ |
1033 | | void ClearObjectIds(); |
1034 | | |
1035 | | /** |
1036 | | * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return |
1037 | | * it in case heap profiler cannot find id for the object passed as |
1038 | | * parameter. HeapSnapshot::GetNodeById will always return NULL for such id. |
1039 | | */ |
1040 | | static const SnapshotObjectId kUnknownObjectId = 0; |
1041 | | |
1042 | | /** |
1043 | | * Callback interface for retrieving user friendly names of global objects. |
1044 | | * |
1045 | | * This interface will soon be deprecated in favour of ContextNameResolver. |
1046 | | */ |
1047 | | class ObjectNameResolver { |
1048 | | public: |
1049 | | /** |
1050 | | * Returns name to be used in the heap snapshot for given node. Returned |
1051 | | * string must stay alive until snapshot collection is completed. |
1052 | | */ |
1053 | | virtual const char* GetName(Local<Object> object) = 0; |
1054 | | |
1055 | | protected: |
1056 | | virtual ~ObjectNameResolver() = default; |
1057 | | }; |
1058 | | |
1059 | | /** |
1060 | | * Callback interface for retrieving user friendly names of a V8::Context |
1061 | | * objects. |
1062 | | */ |
1063 | | class ContextNameResolver { |
1064 | | public: |
1065 | | /** |
1066 | | * Returns name to be used in the heap snapshot for given node. Returned |
1067 | | * string must stay alive until snapshot collection is completed. |
1068 | | * If no user friendly name is available return nullptr. |
1069 | | */ |
1070 | | virtual const char* GetName(Local<Context> context) = 0; |
1071 | | |
1072 | | protected: |
1073 | | virtual ~ContextNameResolver() = default; |
1074 | | }; |
1075 | | |
1076 | | enum class HeapSnapshotMode { |
1077 | | /** |
1078 | | * Heap snapshot for regular developers. |
1079 | | */ |
1080 | | kRegular, |
1081 | | /** |
1082 | | * Heap snapshot is exposing internals that may be useful for experts. |
1083 | | */ |
1084 | | kExposeInternals, |
1085 | | }; |
1086 | | |
1087 | | enum class NumericsMode { |
1088 | | /** |
1089 | | * Numeric values are hidden as they are values of the corresponding |
1090 | | * objects. |
1091 | | */ |
1092 | | kHideNumericValues, |
1093 | | /** |
1094 | | * Numeric values are exposed in artificial fields. |
1095 | | */ |
1096 | | kExposeNumericValues |
1097 | | }; |
1098 | | |
1099 | | struct HeapSnapshotOptions final { |
1100 | | // Manually define default constructor here to be able to use it in |
1101 | | // `TakeSnapshot()` below. |
1102 | | // NOLINTNEXTLINE |
1103 | 0 | HeapSnapshotOptions() {} |
1104 | | |
1105 | | // TODO(https://crbug.com/333672197): remove once ObjectNameResolver is |
1106 | | // removed. |
1107 | | ALLOW_COPY_AND_MOVE_WITH_DEPRECATED_FIELDS(HeapSnapshotOptions) |
1108 | | |
1109 | | /** |
1110 | | * The control used to report intermediate progress to. |
1111 | | */ |
1112 | | ActivityControl* control = nullptr; |
1113 | | /** |
1114 | | * The resolver used by the snapshot generator to get names for V8 objects. |
1115 | | */ |
1116 | | V8_DEPRECATE_SOON("Use context_name_resolver callback instead.") |
1117 | | ObjectNameResolver* global_object_name_resolver = nullptr; |
1118 | | /** |
1119 | | * The resolver used by the snapshot generator to get names for v8::Context |
1120 | | * objects. |
1121 | | * In case both this and |global_object_name_resolver| callbacks are |
1122 | | * provided, this one will be used. |
1123 | | */ |
1124 | | ContextNameResolver* context_name_resolver = nullptr; |
1125 | | /** |
1126 | | * Mode for taking the snapshot, see `HeapSnapshotMode`. |
1127 | | */ |
1128 | | HeapSnapshotMode snapshot_mode = HeapSnapshotMode::kRegular; |
1129 | | /** |
1130 | | * Mode for dealing with numeric values, see `NumericsMode`. |
1131 | | */ |
1132 | | NumericsMode numerics_mode = NumericsMode::kHideNumericValues; |
1133 | | /** |
1134 | | * Whether stack is considered as a root set. |
1135 | | */ |
1136 | | cppgc::EmbedderStackState stack_state = |
1137 | | cppgc::EmbedderStackState::kMayContainHeapPointers; |
1138 | | }; |
1139 | | |
1140 | | /** |
1141 | | * Takes a heap snapshot. |
1142 | | * |
1143 | | * \returns the snapshot. |
1144 | | */ |
1145 | | const HeapSnapshot* TakeHeapSnapshot( |
1146 | | const HeapSnapshotOptions& options = HeapSnapshotOptions()); |
1147 | | |
1148 | | /** |
1149 | | * Takes a heap snapshot. See `HeapSnapshotOptions` for details on the |
1150 | | * parameters. |
1151 | | * |
1152 | | * \returns the snapshot. |
1153 | | */ |
1154 | | V8_DEPRECATE_SOON("Use overload with ContextNameResolver* resolver instead.") |
1155 | | const HeapSnapshot* TakeHeapSnapshot( |
1156 | | ActivityControl* control, ObjectNameResolver* global_object_name_resolver, |
1157 | | bool hide_internals = true, bool capture_numeric_value = false); |
1158 | | const HeapSnapshot* TakeHeapSnapshot(ActivityControl* control, |
1159 | | ContextNameResolver* resolver, |
1160 | | bool hide_internals = true, |
1161 | | bool capture_numeric_value = false); |
1162 | | // TODO(333672197): remove this version once ObjectNameResolver* overload |
1163 | | // is removed. |
1164 | | const HeapSnapshot* TakeHeapSnapshot(ActivityControl* control, |
1165 | | std::nullptr_t resolver = nullptr, |
1166 | | bool hide_internals = true, |
1167 | | bool capture_numeric_value = false); |
1168 | | |
1169 | | /** |
1170 | | * Obtains list of Detached JS Wrapper Objects. This functon calls garbage |
1171 | | * collection, then iterates over traced handles in the isolate |
1172 | | */ |
1173 | | std::vector<v8::Local<v8::Value>> GetDetachedJSWrapperObjects(); |
1174 | | |
1175 | | /** |
1176 | | * Starts tracking of heap objects population statistics. After calling |
1177 | | * this method, all heap objects relocations done by the garbage collector |
1178 | | * are being registered. |
1179 | | * |
1180 | | * |track_allocations| parameter controls whether stack trace of each |
1181 | | * allocation in the heap will be recorded and reported as part of |
1182 | | * HeapSnapshot. |
1183 | | */ |
1184 | | void StartTrackingHeapObjects(bool track_allocations = false); |
1185 | | |
1186 | | /** |
1187 | | * Adds a new time interval entry to the aggregated statistics array. The |
1188 | | * time interval entry contains information on the current heap objects |
1189 | | * population size. The method also updates aggregated statistics and |
1190 | | * reports updates for all previous time intervals via the OutputStream |
1191 | | * object. Updates on each time interval are provided as a stream of the |
1192 | | * HeapStatsUpdate structure instances. |
1193 | | * If |timestamp_us| is supplied, timestamp of the new entry will be written |
1194 | | * into it. The return value of the function is the last seen heap object Id. |
1195 | | * |
1196 | | * StartTrackingHeapObjects must be called before the first call to this |
1197 | | * method. |
1198 | | */ |
1199 | | SnapshotObjectId GetHeapStats(OutputStream* stream, |
1200 | | int64_t* timestamp_us = nullptr); |
1201 | | |
1202 | | /** |
1203 | | * Stops tracking of heap objects population statistics, cleans up all |
1204 | | * collected data. StartHeapObjectsTracking must be called again prior to |
1205 | | * calling GetHeapStats next time. |
1206 | | */ |
1207 | | void StopTrackingHeapObjects(); |
1208 | | |
1209 | | /** |
1210 | | * Starts gathering a sampling heap profile. A sampling heap profile is |
1211 | | * similar to tcmalloc's heap profiler and Go's mprof. It samples object |
1212 | | * allocations and builds an online 'sampling' heap profile. At any point in |
1213 | | * time, this profile is expected to be a representative sample of objects |
1214 | | * currently live in the system. Each sampled allocation includes the stack |
1215 | | * trace at the time of allocation, which makes this really useful for memory |
1216 | | * leak detection. |
1217 | | * |
1218 | | * This mechanism is intended to be cheap enough that it can be used in |
1219 | | * production with minimal performance overhead. |
1220 | | * |
1221 | | * Allocations are sampled using a randomized Poisson process. On average, one |
1222 | | * allocation will be sampled every |sample_interval| bytes allocated. The |
1223 | | * |stack_depth| parameter controls the maximum number of stack frames to be |
1224 | | * captured on each allocation. |
1225 | | * |
1226 | | * NOTE: Support for native allocations doesn't exist yet, but is anticipated |
1227 | | * in the future. |
1228 | | * |
1229 | | * Objects allocated before the sampling is started will not be included in |
1230 | | * the profile. |
1231 | | * |
1232 | | * Returns false if a sampling heap profiler is already running. |
1233 | | */ |
1234 | | bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024, |
1235 | | int stack_depth = 16, |
1236 | | SamplingFlags flags = kSamplingNoFlags); |
1237 | | |
1238 | | /** |
1239 | | * Stops the sampling heap profile and discards the current profile. |
1240 | | */ |
1241 | | void StopSamplingHeapProfiler(); |
1242 | | |
1243 | | /** |
1244 | | * Returns the sampled profile of allocations allocated (and still live) since |
1245 | | * StartSamplingHeapProfiler was called. The ownership of the pointer is |
1246 | | * transferred to the caller. Returns nullptr if sampling heap profiler is not |
1247 | | * active. |
1248 | | */ |
1249 | | AllocationProfile* GetAllocationProfile(); |
1250 | | |
1251 | | /** |
1252 | | * Deletes all snapshots taken. All previously returned pointers to |
1253 | | * snapshots and their contents become invalid after this call. |
1254 | | */ |
1255 | | void DeleteAllHeapSnapshots(); |
1256 | | |
1257 | | void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, |
1258 | | void* data); |
1259 | | void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, |
1260 | | void* data); |
1261 | | |
1262 | | void SetGetDetachednessCallback(GetDetachednessCallback callback, void* data); |
1263 | | |
1264 | | /** |
1265 | | * Returns whether the heap profiler is currently taking a snapshot. |
1266 | | */ |
1267 | | bool IsTakingSnapshot(); |
1268 | | |
1269 | | /** |
1270 | | * Allocates a copy of the provided string within the heap snapshot generator |
1271 | | * and returns a pointer to the copy. May only be called during heap snapshot |
1272 | | * generation. |
1273 | | */ |
1274 | | const char* CopyNameForHeapSnapshot(const char* name); |
1275 | | |
1276 | | /** |
1277 | | * Default value of persistent handle class ID. Must not be used to |
1278 | | * define a class. Can be used to reset a class of a persistent |
1279 | | * handle. |
1280 | | */ |
1281 | | static const uint16_t kPersistentHandleNoClassId = 0; |
1282 | | |
1283 | | private: |
1284 | | HeapProfiler(); |
1285 | | ~HeapProfiler(); |
1286 | | HeapProfiler(const HeapProfiler&); |
1287 | | HeapProfiler& operator=(const HeapProfiler&); |
1288 | | }; |
1289 | | |
1290 | | /** |
1291 | | * A struct for exporting HeapStats data from V8, using "push" model. |
1292 | | * See HeapProfiler::GetHeapStats. |
1293 | | */ |
1294 | | struct HeapStatsUpdate { |
1295 | | HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size) |
1296 | 0 | : index(index), count(count), size(size) { } |
1297 | | uint32_t index; // Index of the time interval that was changed. |
1298 | | uint32_t count; // New value of count field for the interval with this index. |
1299 | | uint32_t size; // New value of size field for the interval with this index. |
1300 | | }; |
1301 | | |
1302 | | #define CODE_EVENTS_LIST(V) \ |
1303 | | V(Builtin) \ |
1304 | | V(Callback) \ |
1305 | | V(Eval) \ |
1306 | | V(Function) \ |
1307 | | V(InterpretedFunction) \ |
1308 | | V(Handler) \ |
1309 | | V(BytecodeHandler) \ |
1310 | | V(LazyCompile) /* Unused, use kFunction instead */ \ |
1311 | | V(RegExp) \ |
1312 | | V(Script) \ |
1313 | | V(Stub) \ |
1314 | | V(Relocation) |
1315 | | |
1316 | | /** |
1317 | | * Note that this enum may be extended in the future. Please include a default |
1318 | | * case if this enum is used in a switch statement. |
1319 | | */ |
1320 | | enum CodeEventType { |
1321 | | kUnknownType = 0 |
1322 | | #define V(Name) , k##Name##Type |
1323 | | CODE_EVENTS_LIST(V) |
1324 | | #undef V |
1325 | | }; |
1326 | | |
1327 | | /** |
1328 | | * Representation of a code creation event |
1329 | | */ |
1330 | | class V8_EXPORT CodeEvent { |
1331 | | public: |
1332 | | uintptr_t GetCodeStartAddress(); |
1333 | | size_t GetCodeSize(); |
1334 | | Local<String> GetFunctionName(); |
1335 | | Local<String> GetScriptName(); |
1336 | | int GetScriptLine(); |
1337 | | int GetScriptColumn(); |
1338 | | /** |
1339 | | * NOTE (mmarchini): We can't allocate objects in the heap when we collect |
1340 | | * existing code, and both the code type and the comment are not stored in the |
1341 | | * heap, so we return those as const char*. |
1342 | | */ |
1343 | | CodeEventType GetCodeType(); |
1344 | | const char* GetComment(); |
1345 | | |
1346 | | static const char* GetCodeEventTypeName(CodeEventType code_event_type); |
1347 | | |
1348 | | uintptr_t GetPreviousCodeStartAddress(); |
1349 | | }; |
1350 | | |
1351 | | /** |
1352 | | * Interface to listen to code creation and code relocation events. |
1353 | | */ |
1354 | | class V8_EXPORT CodeEventHandler { |
1355 | | public: |
1356 | | /** |
1357 | | * Creates a new listener for the |isolate|. The isolate must be initialized. |
1358 | | * The listener object must be disposed after use by calling |Dispose| method. |
1359 | | * Multiple listeners can be created for the same isolate. |
1360 | | */ |
1361 | | explicit CodeEventHandler(Isolate* isolate); |
1362 | | virtual ~CodeEventHandler(); |
1363 | | |
1364 | | /** |
1365 | | * Handle is called every time a code object is created or moved. Information |
1366 | | * about each code event will be available through the `code_event` |
1367 | | * parameter. |
1368 | | * |
1369 | | * When the CodeEventType is kRelocationType, the code for this CodeEvent has |
1370 | | * moved from `GetPreviousCodeStartAddress()` to `GetCodeStartAddress()`. |
1371 | | */ |
1372 | | virtual void Handle(CodeEvent* code_event) = 0; |
1373 | | |
1374 | | /** |
1375 | | * Call `Enable()` to starts listening to code creation and code relocation |
1376 | | * events. These events will be handled by `Handle()`. |
1377 | | */ |
1378 | | void Enable(); |
1379 | | |
1380 | | /** |
1381 | | * Call `Disable()` to stop listening to code creation and code relocation |
1382 | | * events. |
1383 | | */ |
1384 | | void Disable(); |
1385 | | |
1386 | | private: |
1387 | | CodeEventHandler(); |
1388 | | CodeEventHandler(const CodeEventHandler&); |
1389 | | CodeEventHandler& operator=(const CodeEventHandler&); |
1390 | | void* internal_listener_; |
1391 | | }; |
1392 | | |
1393 | | } // namespace v8 |
1394 | | |
1395 | | |
1396 | | #endif // V8_V8_PROFILER_H_ |