blob: b2c1dc9818ac8e4f78660e48d6a0992815495fb5 [file] [log] [blame]
Steve Block6ded16b2010-05-10 14:33:55 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Block6ded16b2010-05-10 14:33:55 +01004
5#ifndef V8_V8_PROFILER_H_
6#define V8_V8_PROFILER_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include <vector>
9#include "v8.h" // NOLINT(build/include)
Steve Block6ded16b2010-05-10 14:33:55 +010010
Steve Block6ded16b2010-05-10 14:33:55 +010011/**
12 * Profiler support for the V8 JavaScript engine.
13 */
14namespace v8 {
15
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016class HeapGraphNode;
17struct HeapStatsUpdate;
18
19typedef uint32_t SnapshotObjectId;
Steve Block6ded16b2010-05-10 14:33:55 +010020
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021
22struct CpuProfileDeoptFrame {
23 int script_id;
24 size_t position;
25};
26
27} // namespace v8
28
29#ifdef V8_OS_WIN
30template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
31#endif
32
33namespace v8 {
34
35struct V8_EXPORT CpuProfileDeoptInfo {
36 /** A pointer to a static string owned by v8. */
37 const char* deopt_reason;
38 std::vector<CpuProfileDeoptFrame> stack;
39};
40
41} // namespace v8
42
43#ifdef V8_OS_WIN
44template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
45#endif
46
47namespace v8 {
48
Steve Block6ded16b2010-05-10 14:33:55 +010049/**
50 * CpuProfileNode represents a node in a call graph.
51 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +000052class V8_EXPORT CpuProfileNode {
Steve Block6ded16b2010-05-10 14:33:55 +010053 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040054 struct LineTick {
55 /** The 1-based number of the source line where the function originates. */
56 int line;
57
58 /** The count of samples associated with the source line. */
59 unsigned int hit_count;
60 };
61
Steve Block6ded16b2010-05-10 14:33:55 +010062 /** Returns function name (empty string for anonymous functions.) */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000063 Local<String> GetFunctionName() const;
Steve Block6ded16b2010-05-10 14:33:55 +010064
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 /** Returns id of the script where function is located. */
66 int GetScriptId() const;
67
Steve Block6ded16b2010-05-10 14:33:55 +010068 /** Returns resource name for script from where the function originates. */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069 Local<String> GetScriptResourceName() const;
Steve Block6ded16b2010-05-10 14:33:55 +010070
71 /**
72 * Returns the number, 1-based, of the line where the function originates.
73 * kNoLineNumberInfo if no line number information is available.
74 */
75 int GetLineNumber() const;
76
77 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 * Returns 1-based number of the column where the function originates.
79 * kNoColumnNumberInfo if no column number information is available.
Steve Block6ded16b2010-05-10 14:33:55 +010080 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 int GetColumnNumber() const;
82
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083 /**
84 * Returns the number of the function's source lines that collect the samples.
85 */
86 unsigned int GetHitLineCount() const;
87
88 /** Returns the set of source lines that collect the samples.
89 * The caller allocates buffer and responsible for releasing it.
90 * True if all available entries are copied, otherwise false.
91 * The function copies nothing if buffer is not large enough.
92 */
93 bool GetLineTicks(LineTick* entries, unsigned int length) const;
94
Ben Murdochb8a8cc12014-11-26 15:28:44 +000095 /** Returns bailout reason for the function
96 * if the optimization was disabled for it.
97 */
98 const char* GetBailoutReason() const;
Steve Block6ded16b2010-05-10 14:33:55 +010099
100 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 * Returns the count of samples where the function was currently executing.
102 */
103 unsigned GetHitCount() const;
Steve Block6ded16b2010-05-10 14:33:55 +0100104
105 /** Returns function entry UID. */
106 unsigned GetCallUid() const;
107
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 /** Returns id of the node. The id is unique within the tree */
109 unsigned GetNodeId() const;
110
Steve Block6ded16b2010-05-10 14:33:55 +0100111 /** Returns child nodes count of the node. */
112 int GetChildrenCount() const;
113
114 /** Retrieves a child node by index. */
115 const CpuProfileNode* GetChild(int index) const;
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 /** Retrieves deopt infos for the node. */
118 const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
119
Kristian Monsen25f61362010-05-21 11:50:48 +0100120 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
Steve Block6ded16b2010-05-10 14:33:55 +0100122};
123
124
125/**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 * CpuProfile contains a CPU profile in a form of top-down call tree
127 * (from main() down to functions that do all the work).
Steve Block6ded16b2010-05-10 14:33:55 +0100128 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000129class V8_EXPORT CpuProfile {
Steve Block6ded16b2010-05-10 14:33:55 +0100130 public:
Steve Block6ded16b2010-05-10 14:33:55 +0100131 /** Returns CPU profile title. */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 Local<String> GetTitle() const;
Steve Block6ded16b2010-05-10 14:33:55 +0100133
Steve Block6ded16b2010-05-10 14:33:55 +0100134 /** Returns the root node of the top down call tree. */
135 const CpuProfileNode* GetTopDownRoot() const;
Steve Block44f0eee2011-05-26 01:26:41 +0100136
137 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 * Returns number of samples recorded. The samples are not recorded unless
139 * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
140 */
141 int GetSamplesCount() const;
142
143 /**
144 * Returns profile node corresponding to the top frame the sample at
145 * the given index.
146 */
147 const CpuProfileNode* GetSample(int index) const;
148
149 /**
150 * Returns the timestamp of the sample. The timestamp is the number of
151 * microseconds since some unspecified starting point.
152 * The point is equal to the starting point used by GetStartTime.
153 */
154 int64_t GetSampleTimestamp(int index) const;
155
156 /**
157 * Returns time when the profile recording was started (in microseconds)
158 * since some unspecified starting point.
159 */
160 int64_t GetStartTime() const;
161
162 /**
163 * Returns time when the profile recording was stopped (in microseconds)
164 * since some unspecified starting point.
165 * The point is equal to the starting point used by GetStartTime.
166 */
167 int64_t GetEndTime() const;
168
169 /**
Steve Block44f0eee2011-05-26 01:26:41 +0100170 * Deletes the profile and removes it from CpuProfiler's list.
171 * All pointers to nodes previously returned become invalid.
Steve Block44f0eee2011-05-26 01:26:41 +0100172 */
173 void Delete();
Steve Block6ded16b2010-05-10 14:33:55 +0100174};
175
176
177/**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000178 * Interface for controlling CPU profiling. Instance of the
179 * profiler can be retrieved using v8::Isolate::GetCpuProfiler.
Steve Block6ded16b2010-05-10 14:33:55 +0100180 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000181class V8_EXPORT CpuProfiler {
Steve Block6ded16b2010-05-10 14:33:55 +0100182 public:
183 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 * Changes default CPU profiler sampling interval to the specified number
185 * of microseconds. Default interval is 1000us. This method must be called
186 * when there are no profiles being recorded.
Leon Clarkef7060e22010-06-03 12:02:55 +0100187 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188 void SetSamplingInterval(int us);
Steve Block6ded16b2010-05-10 14:33:55 +0100189
190 /**
191 * Starts collecting CPU profile. Title may be an empty string. It
192 * is allowed to have several profiles being collected at
193 * once. Attempts to start collecting several profiles with the same
Leon Clarkef7060e22010-06-03 12:02:55 +0100194 * title are silently ignored. While collecting a profile, functions
195 * from all security contexts are included in it. The token-based
196 * filtering is only performed when querying for a profile.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000197 *
198 * |record_samples| parameter controls whether individual samples should
199 * be recorded in addition to the aggregated tree.
Steve Block6ded16b2010-05-10 14:33:55 +0100200 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 void StartProfiling(Local<String> title, bool record_samples = false);
Steve Block6ded16b2010-05-10 14:33:55 +0100202
203 /**
204 * Stops collecting CPU profile with a given title and returns it.
205 * If the title given is empty, finishes the last profile started.
206 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 CpuProfile* StopProfiling(Local<String> title);
Steve Block44f0eee2011-05-26 01:26:41 +0100208
209 /**
Ben Murdoch097c5b22016-05-18 11:27:45 +0100210 * Force collection of a sample. Must be called on the VM thread.
211 * Recording the forced sample does not contribute to the aggregated
212 * profile statistics.
213 */
214 void CollectSample();
215
216 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 * Tells the profiler whether the embedder is idle.
Steve Block44f0eee2011-05-26 01:26:41 +0100218 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 void SetIdle(bool is_idle);
220
221 private:
222 CpuProfiler();
223 ~CpuProfiler();
224 CpuProfiler(const CpuProfiler&);
225 CpuProfiler& operator=(const CpuProfiler&);
Steve Block6ded16b2010-05-10 14:33:55 +0100226};
227
228
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100229/**
230 * HeapSnapshotEdge represents a directed connection between heap
Ben Murdoch257744e2011-11-30 15:57:28 +0000231 * graph nodes: from retainers to retained nodes.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100232 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233class V8_EXPORT HeapGraphEdge {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100234 public:
235 enum Type {
Iain Merrick75681382010-08-19 15:07:18 +0100236 kContextVariable = 0, // A variable from a function context.
237 kElement = 1, // An element of an array.
238 kProperty = 2, // A named object property.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800239 kInternal = 3, // A link that can't be accessed from JS,
240 // thus, its name isn't a real property name
241 // (e.g. parts of a ConsString).
242 kHidden = 4, // A link that is needed for proper sizes
243 // calculation, but may be hidden from user.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100244 kShortcut = 5, // A link that must not be followed during
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800245 // sizes calculation.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100246 kWeak = 6 // A weak reference (ignored by the GC).
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100247 };
248
249 /** Returns edge type (see HeapGraphEdge::Type). */
250 Type GetType() const;
251
252 /**
253 * Returns edge name. This can be a variable name, an element index, or
254 * a property name.
255 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 Local<Value> GetName() const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100257
258 /** Returns origin node. */
259 const HeapGraphNode* GetFromNode() const;
260
261 /** Returns destination node. */
262 const HeapGraphNode* GetToNode() const;
263};
264
265
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100266/**
267 * HeapGraphNode represents a node in a heap graph.
268 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269class V8_EXPORT HeapGraphNode {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100270 public:
271 enum Type {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000272 kHidden = 0, // Hidden node, may be filtered when shown to user.
273 kArray = 1, // An array of elements.
274 kString = 2, // A string.
275 kObject = 3, // A JS object (except for arrays and strings).
276 kCode = 4, // Compiled code.
277 kClosure = 5, // Function closure.
278 kRegExp = 6, // RegExp.
279 kHeapNumber = 7, // Number stored in the heap.
280 kNative = 8, // Native object (not from V8 heap).
281 kSynthetic = 9, // Synthetic object, usualy used for grouping
282 // snapshot items together.
283 kConsString = 10, // Concatenated string. A pair of pointers to strings.
284 kSlicedString = 11, // Sliced string. A fragment of another string.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 kSymbol = 12, // A Symbol (ES6).
286 kSimdValue = 13 // A SIMD value stored in the heap (Proposed ES7).
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100287 };
288
289 /** Returns node type (see HeapGraphNode::Type). */
290 Type GetType() const;
291
292 /**
293 * Returns node name. Depending on node's type this can be the name
294 * of the constructor (for objects), the name of the function (for
295 * closures), string value, or an empty string (for compiled code).
296 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 Local<String> GetName() const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100298
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100299 /**
300 * Returns node id. For the same heap object, the id remains the same
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000301 * across all snapshots.
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100302 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 SnapshotObjectId GetId() const;
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100304
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100305 /** Returns node's own size, in bytes. */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 size_t GetShallowSize() const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100307
308 /** Returns child nodes count of the node. */
309 int GetChildrenCount() const;
310
311 /** Retrieves a child by index. */
312 const HeapGraphEdge* GetChild(int index) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000313};
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100314
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100315
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316/**
317 * An interface for exporting data from V8, using "push" model.
318 */
319class V8_EXPORT OutputStream { // NOLINT
320 public:
321 enum WriteResult {
322 kContinue = 0,
323 kAbort = 1
324 };
325 virtual ~OutputStream() {}
326 /** Notify about the end of stream. */
327 virtual void EndOfStream() = 0;
328 /** Get preferred output chunk size. Called only once. */
329 virtual int GetChunkSize() { return 1024; }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800330 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000331 * Writes the next chunk of snapshot data into the stream. Writing
332 * can be stopped by returning kAbort as function result. EndOfStream
333 * will not be called in case writing was aborted.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800334 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000336 /**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337 * Writes the next chunk of heap stats data into the stream. Writing
338 * can be stopped by returning kAbort as function result. EndOfStream
339 * will not be called in case writing was aborted.
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000340 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) {
342 return kAbort;
343 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100344};
345
346
347/**
348 * HeapSnapshots record the state of the JS heap at some moment.
349 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350class V8_EXPORT HeapSnapshot {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100351 public:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100352 enum SerializationFormat {
353 kJSON = 0 // See format description near 'Serialize' method.
Steve Block791712a2010-08-27 10:21:07 +0100354 };
355
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100356 /** Returns the root node of the heap graph. */
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100357 const HeapGraphNode* GetRoot() const;
358
Ben Murdochb0fe1622011-05-05 13:52:32 +0100359 /** Returns a node by its id. */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100361
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000362 /** Returns total nodes count in the snapshot. */
363 int GetNodesCount() const;
364
365 /** Returns a node by index. */
366 const HeapGraphNode* GetNode(int index) const;
367
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000368 /** Returns a max seen JS object Id. */
369 SnapshotObjectId GetMaxSnapshotJSObjectId() const;
370
Steve Block791712a2010-08-27 10:21:07 +0100371 /**
Steve Block44f0eee2011-05-26 01:26:41 +0100372 * Deletes the snapshot and removes it from HeapProfiler's list.
373 * All pointers to nodes, edges and paths previously returned become
374 * invalid.
Steve Block791712a2010-08-27 10:21:07 +0100375 */
Steve Block44f0eee2011-05-26 01:26:41 +0100376 void Delete();
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100377
378 /**
379 * Prepare a serialized representation of the snapshot. The result
380 * is written into the stream provided in chunks of specified size.
381 * The total length of the serialized snapshot is unknown in
Ben Murdoch257744e2011-11-30 15:57:28 +0000382 * advance, it can be roughly equal to JS heap size (that means,
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100383 * it can be really big - tens of megabytes).
384 *
385 * For the JSON format, heap contents are represented as an object
386 * with the following structure:
387 *
388 * {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389 * snapshot: {
390 * title: "...",
391 * uid: nnn,
392 * meta: { meta-info },
393 * node_count: nnn,
394 * edge_count: nnn
395 * },
396 * nodes: [nodes array],
397 * edges: [edges array],
398 * strings: [strings array]
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100399 * }
400 *
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000401 * Nodes reference strings, other nodes, and edges by their indexes
402 * in corresponding arrays.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100403 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 void Serialize(OutputStream* stream,
405 SerializationFormat format = kJSON) const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100406};
407
408
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409/**
410 * An interface for reporting progress and controlling long-running
411 * activities.
412 */
413class V8_EXPORT ActivityControl { // NOLINT
414 public:
415 enum ControlOption {
416 kContinue = 0,
417 kAbort = 1
418 };
419 virtual ~ActivityControl() {}
420 /**
421 * Notify about current progress. The activity can be stopped by
422 * returning kAbort as the callback result.
423 */
424 virtual ControlOption ReportProgressValue(int done, int total) = 0;
425};
426
Steve Block44f0eee2011-05-26 01:26:41 +0100427
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100428/**
Ben Murdoch097c5b22016-05-18 11:27:45 +0100429 * AllocationProfile is a sampled profile of allocations done by the program.
430 * This is structured as a call-graph.
431 */
432class V8_EXPORT AllocationProfile {
433 public:
434 struct Allocation {
435 /**
436 * Size of the sampled allocation object.
437 */
438 size_t size;
439
440 /**
441 * The number of objects of such size that were sampled.
442 */
443 unsigned int count;
444 };
445
446 /**
447 * Represents a node in the call-graph.
448 */
449 struct Node {
450 /**
451 * Name of the function. May be empty for anonymous functions or if the
452 * script corresponding to this function has been unloaded.
453 */
454 Local<String> name;
455
456 /**
457 * Name of the script containing the function. May be empty if the script
458 * name is not available, or if the script has been unloaded.
459 */
460 Local<String> script_name;
461
462 /**
463 * id of the script where the function is located. May be equal to
464 * v8::UnboundScript::kNoScriptId in cases where the script doesn't exist.
465 */
466 int script_id;
467
468 /**
469 * Start position of the function in the script.
470 */
471 int start_position;
472
473 /**
474 * 1-indexed line number where the function starts. May be
475 * kNoLineNumberInfo if no line number information is available.
476 */
477 int line_number;
478
479 /**
480 * 1-indexed column number where the function starts. May be
481 * kNoColumnNumberInfo if no line number information is available.
482 */
483 int column_number;
484
485 /**
486 * List of callees called from this node for which we have sampled
487 * allocations. The lifetime of the children is scoped to the containing
488 * AllocationProfile.
489 */
490 std::vector<Node*> children;
491
492 /**
493 * List of self allocations done by this node in the call-graph.
494 */
495 std::vector<Allocation> allocations;
496 };
497
498 /**
499 * Returns the root node of the call-graph. The root node corresponds to an
500 * empty JS call-stack. The lifetime of the returned Node* is scoped to the
501 * containing AllocationProfile.
502 */
503 virtual Node* GetRootNode() = 0;
504
505 virtual ~AllocationProfile() {}
506
507 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
508 static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
509};
510
511
512/**
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513 * Interface for controlling heap profiling. Instance of the
514 * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100515 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516class V8_EXPORT HeapProfiler {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100517 public:
Ben Murdochc5610432016-08-08 18:44:38 +0100518 enum SamplingFlags {
519 kSamplingNoFlags = 0,
520 kSamplingForceGC = 1 << 0,
521 };
522
Steve Block44f0eee2011-05-26 01:26:41 +0100523 /**
524 * Callback function invoked for obtaining RetainedObjectInfo for
525 * the given JavaScript wrapper object. It is prohibited to enter V8
526 * while the callback is running: only getters on the handle and
527 * GetPointerFromInternalField on the objects are allowed.
528 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id,
530 Local<Value> wrapper);
Steve Block44f0eee2011-05-26 01:26:41 +0100531
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100532 /** Returns the number of snapshots taken. */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 int GetSnapshotCount();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100534
535 /** Returns a snapshot by index. */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000536 const HeapSnapshot* GetHeapSnapshot(int index);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100537
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000538 /**
539 * Returns SnapshotObjectId for a heap object referenced by |value| if
540 * it has been seen by the heap profiler, kUnknownObjectId otherwise.
541 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 SnapshotObjectId GetObjectId(Local<Value> value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000543
544 /**
545 * Returns heap object with given SnapshotObjectId if the object is alive,
546 * otherwise empty handle is returned.
547 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000548 Local<Value> FindObjectById(SnapshotObjectId id);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549
550 /**
551 * Clears internal map from SnapshotObjectId to heap object. The new objects
552 * will not be added into it unless a heap snapshot is taken or heap object
553 * tracking is kicked off.
554 */
555 void ClearObjectIds();
556
557 /**
558 * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
559 * it in case heap profiler cannot find id for the object passed as
560 * parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
561 */
562 static const SnapshotObjectId kUnknownObjectId = 0;
563
564 /**
565 * Callback interface for retrieving user friendly names of global objects.
566 */
567 class ObjectNameResolver {
568 public:
569 /**
570 * Returns name to be used in the heap snapshot for given node. Returned
571 * string must stay alive until snapshot collection is completed.
572 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 virtual const char* GetName(Local<Object> object) = 0;
574
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000575 protected:
576 virtual ~ObjectNameResolver() {}
577 };
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100578
Steve Block791712a2010-08-27 10:21:07 +0100579 /**
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 * Takes a heap snapshot and returns it.
Steve Block791712a2010-08-27 10:21:07 +0100581 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000582 const HeapSnapshot* TakeHeapSnapshot(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 ActivityControl* control = NULL,
584 ObjectNameResolver* global_object_name_resolver = NULL);
585
586 /**
587 * Starts tracking of heap objects population statistics. After calling
588 * this method, all heap objects relocations done by the garbage collector
589 * are being registered.
590 *
591 * |track_allocations| parameter controls whether stack trace of each
592 * allocation in the heap will be recorded and reported as part of
593 * HeapSnapshot.
594 */
595 void StartTrackingHeapObjects(bool track_allocations = false);
596
597 /**
598 * Adds a new time interval entry to the aggregated statistics array. The
599 * time interval entry contains information on the current heap objects
600 * population size. The method also updates aggregated statistics and
601 * reports updates for all previous time intervals via the OutputStream
602 * object. Updates on each time interval are provided as a stream of the
603 * HeapStatsUpdate structure instances.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 * If |timestamp_us| is supplied, timestamp of the new entry will be written
605 * into it. The return value of the function is the last seen heap object Id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606 *
607 * StartTrackingHeapObjects must be called before the first call to this
608 * method.
609 */
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 SnapshotObjectId GetHeapStats(OutputStream* stream,
611 int64_t* timestamp_us = NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000612
613 /**
614 * Stops tracking of heap objects population statistics, cleans up all
615 * collected data. StartHeapObjectsTracking must be called again prior to
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 * calling GetHeapStats next time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000617 */
618 void StopTrackingHeapObjects();
Steve Block44f0eee2011-05-26 01:26:41 +0100619
620 /**
Ben Murdoch097c5b22016-05-18 11:27:45 +0100621 * Starts gathering a sampling heap profile. A sampling heap profile is
622 * similar to tcmalloc's heap profiler and Go's mprof. It samples object
623 * allocations and builds an online 'sampling' heap profile. At any point in
624 * time, this profile is expected to be a representative sample of objects
625 * currently live in the system. Each sampled allocation includes the stack
626 * trace at the time of allocation, which makes this really useful for memory
627 * leak detection.
628 *
629 * This mechanism is intended to be cheap enough that it can be used in
630 * production with minimal performance overhead.
631 *
632 * Allocations are sampled using a randomized Poisson process. On average, one
633 * allocation will be sampled every |sample_interval| bytes allocated. The
634 * |stack_depth| parameter controls the maximum number of stack frames to be
635 * captured on each allocation.
636 *
637 * NOTE: This is a proof-of-concept at this point. Right now we only sample
638 * newspace allocations. Support for paged space allocation (e.g. pre-tenured
639 * objects, large objects, code objects, etc.) and native allocations
640 * doesn't exist yet, but is anticipated in the future.
641 *
642 * Objects allocated before the sampling is started will not be included in
643 * the profile.
644 *
645 * Returns false if a sampling heap profiler is already running.
646 */
647 bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
Ben Murdochc5610432016-08-08 18:44:38 +0100648 int stack_depth = 16,
649 SamplingFlags flags = kSamplingNoFlags);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100650
651 /**
652 * Stops the sampling heap profile and discards the current profile.
653 */
654 void StopSamplingHeapProfiler();
655
656 /**
657 * Returns the sampled profile of allocations allocated (and still live) since
658 * StartSamplingHeapProfiler was called. The ownership of the pointer is
659 * transfered to the caller. Returns nullptr if sampling heap profiler is not
660 * active.
661 */
662 AllocationProfile* GetAllocationProfile();
663
664 /**
Steve Block44f0eee2011-05-26 01:26:41 +0100665 * Deletes all snapshots taken. All previously returned pointers to
666 * snapshots and their contents become invalid after this call.
667 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000668 void DeleteAllHeapSnapshots();
Steve Block44f0eee2011-05-26 01:26:41 +0100669
670 /** Binds a callback to embedder's class ID. */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000671 void SetWrapperClassInfoProvider(
Steve Block44f0eee2011-05-26 01:26:41 +0100672 uint16_t class_id,
673 WrapperInfoCallback callback);
674
675 /**
676 * Default value of persistent handle class ID. Must not be used to
677 * define a class. Can be used to reset a class of a persistent
678 * handle.
679 */
680 static const uint16_t kPersistentHandleNoClassId = 0;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100681
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000682 /** Returns memory used for profiler internal data and snapshots. */
683 size_t GetProfilerMemorySize();
684
685 /**
686 * Sets a RetainedObjectInfo for an object group (see V8::SetObjectGroupId).
687 */
688 void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
689
690 private:
691 HeapProfiler();
692 ~HeapProfiler();
693 HeapProfiler(const HeapProfiler&);
694 HeapProfiler& operator=(const HeapProfiler&);
Steve Block44f0eee2011-05-26 01:26:41 +0100695};
696
Steve Block44f0eee2011-05-26 01:26:41 +0100697/**
698 * Interface for providing information about embedder's objects
699 * held by global handles. This information is reported in two ways:
700 *
701 * 1. When calling AddObjectGroup, an embedder may pass
702 * RetainedObjectInfo instance describing the group. To collect
703 * this information while taking a heap snapshot, V8 calls GC
704 * prologue and epilogue callbacks.
705 *
706 * 2. When a heap snapshot is collected, V8 additionally
707 * requests RetainedObjectInfos for persistent handles that
708 * were not previously reported via AddObjectGroup.
709 *
710 * Thus, if an embedder wants to provide information about native
Ben Murdoch61f157c2016-09-16 13:49:30 +0100711 * objects for heap snapshots, it can do it in a GC prologue
Steve Block44f0eee2011-05-26 01:26:41 +0100712 * handler, and / or by assigning wrapper class ids in the following way:
713 *
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000714 * 1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
Steve Block44f0eee2011-05-26 01:26:41 +0100715 * 2. Call SetWrapperClassId on certain persistent handles.
716 *
717 * V8 takes ownership of RetainedObjectInfo instances passed to it and
718 * keeps them alive only during snapshot collection. Afterwards, they
719 * are freed by calling the Dispose class function.
720 */
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000721class V8_EXPORT RetainedObjectInfo { // NOLINT
Steve Block44f0eee2011-05-26 01:26:41 +0100722 public:
723 /** Called by V8 when it no longer needs an instance. */
724 virtual void Dispose() = 0;
725
726 /** Returns whether two instances are equivalent. */
727 virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
728
729 /**
730 * Returns hash value for the instance. Equivalent instances
731 * must have the same hash value.
732 */
733 virtual intptr_t GetHash() = 0;
734
735 /**
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100736 * Returns human-readable label. It must be a null-terminated UTF-8
Steve Block44f0eee2011-05-26 01:26:41 +0100737 * encoded string. V8 copies its contents during a call to GetLabel.
738 */
739 virtual const char* GetLabel() = 0;
740
741 /**
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100742 * Returns human-readable group label. It must be a null-terminated UTF-8
743 * encoded string. V8 copies its contents during a call to GetGroupLabel.
744 * Heap snapshot generator will collect all the group names, create
745 * top level entries with these names and attach the objects to the
746 * corresponding top level group objects. There is a default
747 * implementation which is required because embedders don't have their
748 * own implementation yet.
749 */
750 virtual const char* GetGroupLabel() { return GetLabel(); }
751
752 /**
Steve Block44f0eee2011-05-26 01:26:41 +0100753 * Returns element count in case if a global handle retains
754 * a subgraph by holding one of its nodes.
755 */
756 virtual intptr_t GetElementCount() { return -1; }
757
758 /** Returns embedder's object size in bytes. */
759 virtual intptr_t GetSizeInBytes() { return -1; }
760
761 protected:
762 RetainedObjectInfo() {}
763 virtual ~RetainedObjectInfo() {}
764
765 private:
766 RetainedObjectInfo(const RetainedObjectInfo&);
767 RetainedObjectInfo& operator=(const RetainedObjectInfo&);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100768};
769
770
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771/**
772 * A struct for exporting HeapStats data from V8, using "push" model.
773 * See HeapProfiler::GetHeapStats.
774 */
775struct HeapStatsUpdate {
776 HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
777 : index(index), count(count), size(size) { }
778 uint32_t index; // Index of the time interval that was changed.
779 uint32_t count; // New value of count field for the interval with this index.
780 uint32_t size; // New value of size field for the interval with this index.
781};
782
783
Steve Block6ded16b2010-05-10 14:33:55 +0100784} // namespace v8
785
786
Steve Block6ded16b2010-05-10 14:33:55 +0100787#endif // V8_V8_PROFILER_H_