• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <unordered_set>
9 #include <vector>
10 #include "v8.h"  // NOLINT(build/include)
11 
12 /**
13  * Profiler support for the V8 JavaScript engine.
14  */
15 namespace v8 {
16 
17 class HeapGraphNode;
18 struct HeapStatsUpdate;
19 
20 typedef uint32_t SnapshotObjectId;
21 
22 
23 struct CpuProfileDeoptFrame {
24   int script_id;
25   size_t position;
26 };
27 
28 }  // namespace v8
29 
30 #ifdef V8_OS_WIN
31 template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
32 #endif
33 
34 namespace v8 {
35 
36 struct V8_EXPORT CpuProfileDeoptInfo {
37   /** A pointer to a static string owned by v8. */
38   const char* deopt_reason;
39   std::vector<CpuProfileDeoptFrame> stack;
40 };
41 
42 }  // namespace v8
43 
44 #ifdef V8_OS_WIN
45 template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
46 #endif
47 
48 namespace v8 {
49 
50 // TickSample captures the information collected for each sample.
51 struct TickSample {
52   // Internal profiling (with --prof + tools/$OS-tick-processor) wants to
53   // include the runtime function we're calling. Externally exposed tick
54   // samples don't care.
55   enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame };
56 
TickSampleTickSample57   TickSample()
58       : state(OTHER),
59         pc(nullptr),
60         external_callback_entry(nullptr),
61         frames_count(0),
62         has_external_callback(false),
63         update_stats(true) {}
64 
65   /**
66    * Initialize a tick sample from the isolate.
67    * \param isolate The isolate.
68    * \param state Execution state.
69    * \param record_c_entry_frame Include or skip the runtime function.
70    * \param update_stats Whether update the sample to the aggregated stats.
71    * \param use_simulator_reg_state When set to true and V8 is running under a
72    *                                simulator, the method will use the simulator
73    *                                register state rather than the one provided
74    *                                with |state| argument. Otherwise the method
75    *                                will use provided register |state| as is.
76    */
77   void Init(Isolate* isolate, const v8::RegisterState& state,
78             RecordCEntryFrame record_c_entry_frame, bool update_stats,
79             bool use_simulator_reg_state = true);
80   /**
81    * Get a call stack sample from the isolate.
82    * \param isolate The isolate.
83    * \param state Register state.
84    * \param record_c_entry_frame Include or skip the runtime function.
85    * \param frames Caller allocated buffer to store stack frames.
86    * \param frames_limit Maximum number of frames to capture. The buffer must
87    *                     be large enough to hold the number of frames.
88    * \param sample_info The sample info is filled up by the function
89    *                    provides number of actual captured stack frames and
90    *                    the current VM state.
91    * \param use_simulator_reg_state When set to true and V8 is running under a
92    *                                simulator, the method will use the simulator
93    *                                register state rather than the one provided
94    *                                with |state| argument. Otherwise the method
95    *                                will use provided register |state| as is.
96    * \note GetStackSample is thread and signal safe and should only be called
97    *                      when the JS thread is paused or interrupted.
98    *                      Otherwise the behavior is undefined.
99    */
100   static bool GetStackSample(Isolate* isolate, v8::RegisterState* state,
101                              RecordCEntryFrame record_c_entry_frame,
102                              void** frames, size_t frames_limit,
103                              v8::SampleInfo* sample_info,
104                              bool use_simulator_reg_state = true);
105   StateTag state;  // The state of the VM.
106   void* pc;        // Instruction pointer.
107   union {
108     void* tos;  // Top stack value (*sp).
109     void* external_callback_entry;
110   };
111   static const unsigned kMaxFramesCountLog2 = 8;
112   static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
113   void* stack[kMaxFramesCount];                 // Call stack.
114   unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
115   bool has_external_callback : 1;
116   bool update_stats : 1;  // Whether the sample should update aggregated stats.
117 };
118 
119 /**
120  * CpuProfileNode represents a node in a call graph.
121  */
122 class V8_EXPORT CpuProfileNode {
123  public:
124   struct LineTick {
125     /** The 1-based number of the source line where the function originates. */
126     int line;
127 
128     /** The count of samples associated with the source line. */
129     unsigned int hit_count;
130   };
131 
132   /** Returns function name (empty string for anonymous functions.) */
133   Local<String> GetFunctionName() const;
134 
135   /**
136    * Returns function name (empty string for anonymous functions.)
137    * The string ownership is *not* passed to the caller. It stays valid until
138    * profile is deleted. The function is thread safe.
139    */
140   const char* GetFunctionNameStr() const;
141 
142   /** Returns id of the script where function is located. */
143   int GetScriptId() const;
144 
145   /** Returns resource name for script from where the function originates. */
146   Local<String> GetScriptResourceName() const;
147 
148   /**
149    * Returns resource name for script from where the function originates.
150    * The string ownership is *not* passed to the caller. It stays valid until
151    * profile is deleted. The function is thread safe.
152    */
153   const char* GetScriptResourceNameStr() const;
154 
155   /**
156    * Returns the number, 1-based, of the line where the function originates.
157    * kNoLineNumberInfo if no line number information is available.
158    */
159   int GetLineNumber() const;
160 
161   /**
162    * Returns 1-based number of the column where the function originates.
163    * kNoColumnNumberInfo if no column number information is available.
164    */
165   int GetColumnNumber() const;
166 
167   /**
168    * Returns the number of the function's source lines that collect the samples.
169    */
170   unsigned int GetHitLineCount() const;
171 
172   /** Returns the set of source lines that collect the samples.
173    *  The caller allocates buffer and responsible for releasing it.
174    *  True if all available entries are copied, otherwise false.
175    *  The function copies nothing if buffer is not large enough.
176    */
177   bool GetLineTicks(LineTick* entries, unsigned int length) const;
178 
179   /** Returns bailout reason for the function
180     * if the optimization was disabled for it.
181     */
182   const char* GetBailoutReason() const;
183 
184   /**
185     * Returns the count of samples where the function was currently executing.
186     */
187   unsigned GetHitCount() const;
188 
189   /** Returns function entry UID. */
190   V8_DEPRECATE_SOON(
191       "Use GetScriptId, GetLineNumber, and GetColumnNumber instead.",
192       unsigned GetCallUid() const);
193 
194   /** Returns id of the node. The id is unique within the tree */
195   unsigned GetNodeId() const;
196 
197   /** Returns child nodes count of the node. */
198   int GetChildrenCount() const;
199 
200   /** Retrieves a child node by index. */
201   const CpuProfileNode* GetChild(int index) const;
202 
203   /** Retrieves deopt infos for the node. */
204   const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
205 
206   static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
207   static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
208 };
209 
210 
211 /**
212  * CpuProfile contains a CPU profile in a form of top-down call tree
213  * (from main() down to functions that do all the work).
214  */
215 class V8_EXPORT CpuProfile {
216  public:
217   /** Returns CPU profile title. */
218   Local<String> GetTitle() const;
219 
220   /** Returns the root node of the top down call tree. */
221   const CpuProfileNode* GetTopDownRoot() const;
222 
223   /**
224    * Returns number of samples recorded. The samples are not recorded unless
225    * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
226    */
227   int GetSamplesCount() const;
228 
229   /**
230    * Returns profile node corresponding to the top frame the sample at
231    * the given index.
232    */
233   const CpuProfileNode* GetSample(int index) const;
234 
235   /**
236    * Returns the timestamp of the sample. The timestamp is the number of
237    * microseconds since some unspecified starting point.
238    * The point is equal to the starting point used by GetStartTime.
239    */
240   int64_t GetSampleTimestamp(int index) const;
241 
242   /**
243    * Returns time when the profile recording was started (in microseconds)
244    * since some unspecified starting point.
245    */
246   int64_t GetStartTime() const;
247 
248   /**
249    * Returns time when the profile recording was stopped (in microseconds)
250    * since some unspecified starting point.
251    * The point is equal to the starting point used by GetStartTime.
252    */
253   int64_t GetEndTime() const;
254 
255   /**
256    * Deletes the profile and removes it from CpuProfiler's list.
257    * All pointers to nodes previously returned become invalid.
258    */
259   void Delete();
260 };
261 
262 enum CpuProfilingMode {
263   // In the resulting CpuProfile tree, intermediate nodes in a stack trace
264   // (from the root to a leaf) will have line numbers that point to the start
265   // line of the function, rather than the line of the callsite of the child.
266   kLeafNodeLineNumbers,
267   // In the resulting CpuProfile tree, nodes are separated based on the line
268   // number of their callsite in their parent.
269   kCallerLineNumbers,
270 };
271 
272 /**
273  * Interface for controlling CPU profiling. Instance of the
274  * profiler can be created using v8::CpuProfiler::New method.
275  */
276 class V8_EXPORT CpuProfiler {
277  public:
278   /**
279    * Creates a new CPU profiler for the |isolate|. The isolate must be
280    * initialized. The profiler object must be disposed after use by calling
281    * |Dispose| method.
282    */
283   static CpuProfiler* New(Isolate* isolate);
284 
285   /**
286    * Synchronously collect current stack sample in all profilers attached to
287    * the |isolate|. The call does not affect number of ticks recorded for
288    * the current top node.
289    */
290   static void CollectSample(Isolate* isolate);
291 
292   /**
293    * Disposes the CPU profiler object.
294    */
295   void Dispose();
296 
297   /**
298    * Changes default CPU profiler sampling interval to the specified number
299    * of microseconds. Default interval is 1000us. This method must be called
300    * when there are no profiles being recorded.
301    */
302   void SetSamplingInterval(int us);
303 
304   /**
305    * Starts collecting CPU profile. Title may be an empty string. It
306    * is allowed to have several profiles being collected at
307    * once. Attempts to start collecting several profiles with the same
308    * title are silently ignored. While collecting a profile, functions
309    * from all security contexts are included in it. The token-based
310    * filtering is only performed when querying for a profile.
311    *
312    * |record_samples| parameter controls whether individual samples should
313    * be recorded in addition to the aggregated tree.
314    */
315   void StartProfiling(Local<String> title, CpuProfilingMode mode,
316                       bool record_samples = false);
317   /**
318    * The same as StartProfiling above, but the CpuProfilingMode defaults to
319    * kLeafNodeLineNumbers mode, which was the previous default behavior of the
320    * profiler.
321    */
322   void StartProfiling(Local<String> title, bool record_samples = false);
323 
324   /**
325    * Stops collecting CPU profile with a given title and returns it.
326    * If the title given is empty, finishes the last profile started.
327    */
328   CpuProfile* StopProfiling(Local<String> title);
329 
330   /**
331    * Force collection of a sample. Must be called on the VM thread.
332    * Recording the forced sample does not contribute to the aggregated
333    * profile statistics.
334    */
335   V8_DEPRECATED("Use static CollectSample(Isolate*) instead.",
336                 void CollectSample());
337 
338   /**
339    * Tells the profiler whether the embedder is idle.
340    */
341   V8_DEPRECATED("Use Isolate::SetIdle(bool) instead.",
342                 void SetIdle(bool is_idle));
343 
344  private:
345   CpuProfiler();
346   ~CpuProfiler();
347   CpuProfiler(const CpuProfiler&);
348   CpuProfiler& operator=(const CpuProfiler&);
349 };
350 
351 
352 /**
353  * HeapSnapshotEdge represents a directed connection between heap
354  * graph nodes: from retainers to retained nodes.
355  */
356 class V8_EXPORT HeapGraphEdge {
357  public:
358   enum Type {
359     kContextVariable = 0,  // A variable from a function context.
360     kElement = 1,          // An element of an array.
361     kProperty = 2,         // A named object property.
362     kInternal = 3,         // A link that can't be accessed from JS,
363                            // thus, its name isn't a real property name
364                            // (e.g. parts of a ConsString).
365     kHidden = 4,           // A link that is needed for proper sizes
366                            // calculation, but may be hidden from user.
367     kShortcut = 5,         // A link that must not be followed during
368                            // sizes calculation.
369     kWeak = 6              // A weak reference (ignored by the GC).
370   };
371 
372   /** Returns edge type (see HeapGraphEdge::Type). */
373   Type GetType() const;
374 
375   /**
376    * Returns edge name. This can be a variable name, an element index, or
377    * a property name.
378    */
379   Local<Value> GetName() const;
380 
381   /** Returns origin node. */
382   const HeapGraphNode* GetFromNode() const;
383 
384   /** Returns destination node. */
385   const HeapGraphNode* GetToNode() const;
386 };
387 
388 
389 /**
390  * HeapGraphNode represents a node in a heap graph.
391  */
392 class V8_EXPORT HeapGraphNode {
393  public:
394   enum Type {
395     kHidden = 0,         // Hidden node, may be filtered when shown to user.
396     kArray = 1,          // An array of elements.
397     kString = 2,         // A string.
398     kObject = 3,         // A JS object (except for arrays and strings).
399     kCode = 4,           // Compiled code.
400     kClosure = 5,        // Function closure.
401     kRegExp = 6,         // RegExp.
402     kHeapNumber = 7,     // Number stored in the heap.
403     kNative = 8,         // Native object (not from V8 heap).
404     kSynthetic = 9,      // Synthetic object, usually used for grouping
405                          // snapshot items together.
406     kConsString = 10,    // Concatenated string. A pair of pointers to strings.
407     kSlicedString = 11,  // Sliced string. A fragment of another string.
408     kSymbol = 12,        // A Symbol (ES6).
409     kBigInt = 13         // BigInt.
410   };
411 
412   /** Returns node type (see HeapGraphNode::Type). */
413   Type GetType() const;
414 
415   /**
416    * Returns node name. Depending on node's type this can be the name
417    * of the constructor (for objects), the name of the function (for
418    * closures), string value, or an empty string (for compiled code).
419    */
420   Local<String> GetName() const;
421 
422   /**
423    * Returns node id. For the same heap object, the id remains the same
424    * across all snapshots.
425    */
426   SnapshotObjectId GetId() const;
427 
428   /** Returns node's own size, in bytes. */
429   size_t GetShallowSize() const;
430 
431   /** Returns child nodes count of the node. */
432   int GetChildrenCount() const;
433 
434   /** Retrieves a child by index. */
435   const HeapGraphEdge* GetChild(int index) const;
436 };
437 
438 
439 /**
440  * An interface for exporting data from V8, using "push" model.
441  */
442 class V8_EXPORT OutputStream {  // NOLINT
443  public:
444   enum WriteResult {
445     kContinue = 0,
446     kAbort = 1
447   };
~OutputStream()448   virtual ~OutputStream() {}
449   /** Notify about the end of stream. */
450   virtual void EndOfStream() = 0;
451   /** Get preferred output chunk size. Called only once. */
GetChunkSize()452   virtual int GetChunkSize() { return 1024; }
453   /**
454    * Writes the next chunk of snapshot data into the stream. Writing
455    * can be stopped by returning kAbort as function result. EndOfStream
456    * will not be called in case writing was aborted.
457    */
458   virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
459   /**
460    * Writes the next chunk of heap stats data into the stream. Writing
461    * can be stopped by returning kAbort as function result. EndOfStream
462    * will not be called in case writing was aborted.
463    */
WriteHeapStatsChunk(HeapStatsUpdate * data,int count)464   virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) {
465     return kAbort;
466   }
467 };
468 
469 
470 /**
471  * HeapSnapshots record the state of the JS heap at some moment.
472  */
473 class V8_EXPORT HeapSnapshot {
474  public:
475   enum SerializationFormat {
476     kJSON = 0  // See format description near 'Serialize' method.
477   };
478 
479   /** Returns the root node of the heap graph. */
480   const HeapGraphNode* GetRoot() const;
481 
482   /** Returns a node by its id. */
483   const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
484 
485   /** Returns total nodes count in the snapshot. */
486   int GetNodesCount() const;
487 
488   /** Returns a node by index. */
489   const HeapGraphNode* GetNode(int index) const;
490 
491   /** Returns a max seen JS object Id. */
492   SnapshotObjectId GetMaxSnapshotJSObjectId() const;
493 
494   /**
495    * Deletes the snapshot and removes it from HeapProfiler's list.
496    * All pointers to nodes, edges and paths previously returned become
497    * invalid.
498    */
499   void Delete();
500 
501   /**
502    * Prepare a serialized representation of the snapshot. The result
503    * is written into the stream provided in chunks of specified size.
504    * The total length of the serialized snapshot is unknown in
505    * advance, it can be roughly equal to JS heap size (that means,
506    * it can be really big - tens of megabytes).
507    *
508    * For the JSON format, heap contents are represented as an object
509    * with the following structure:
510    *
511    *  {
512    *    snapshot: {
513    *      title: "...",
514    *      uid: nnn,
515    *      meta: { meta-info },
516    *      node_count: nnn,
517    *      edge_count: nnn
518    *    },
519    *    nodes: [nodes array],
520    *    edges: [edges array],
521    *    strings: [strings array]
522    *  }
523    *
524    * Nodes reference strings, other nodes, and edges by their indexes
525    * in corresponding arrays.
526    */
527   void Serialize(OutputStream* stream,
528                  SerializationFormat format = kJSON) const;
529 };
530 
531 
532 /**
533  * An interface for reporting progress and controlling long-running
534  * activities.
535  */
536 class V8_EXPORT ActivityControl {  // NOLINT
537  public:
538   enum ControlOption {
539     kContinue = 0,
540     kAbort = 1
541   };
~ActivityControl()542   virtual ~ActivityControl() {}
543   /**
544    * Notify about current progress. The activity can be stopped by
545    * returning kAbort as the callback result.
546    */
547   virtual ControlOption ReportProgressValue(int done, int total) = 0;
548 };
549 
550 
551 /**
552  * AllocationProfile is a sampled profile of allocations done by the program.
553  * This is structured as a call-graph.
554  */
555 class V8_EXPORT AllocationProfile {
556  public:
557   struct Allocation {
558     /**
559      * Size of the sampled allocation object.
560      */
561     size_t size;
562 
563     /**
564      * The number of objects of such size that were sampled.
565      */
566     unsigned int count;
567   };
568 
569   /**
570    * Represents a node in the call-graph.
571    */
572   struct Node {
573     /**
574      * Name of the function. May be empty for anonymous functions or if the
575      * script corresponding to this function has been unloaded.
576      */
577     Local<String> name;
578 
579     /**
580      * Name of the script containing the function. May be empty if the script
581      * name is not available, or if the script has been unloaded.
582      */
583     Local<String> script_name;
584 
585     /**
586      * id of the script where the function is located. May be equal to
587      * v8::UnboundScript::kNoScriptId in cases where the script doesn't exist.
588      */
589     int script_id;
590 
591     /**
592      * Start position of the function in the script.
593      */
594     int start_position;
595 
596     /**
597      * 1-indexed line number where the function starts. May be
598      * kNoLineNumberInfo if no line number information is available.
599      */
600     int line_number;
601 
602     /**
603      * 1-indexed column number where the function starts. May be
604      * kNoColumnNumberInfo if no line number information is available.
605      */
606     int column_number;
607 
608     /**
609      * List of callees called from this node for which we have sampled
610      * allocations. The lifetime of the children is scoped to the containing
611      * AllocationProfile.
612      */
613     std::vector<Node*> children;
614 
615     /**
616      * List of self allocations done by this node in the call-graph.
617      */
618     std::vector<Allocation> allocations;
619   };
620 
621   /**
622    * Returns the root node of the call-graph. The root node corresponds to an
623    * empty JS call-stack. The lifetime of the returned Node* is scoped to the
624    * containing AllocationProfile.
625    */
626   virtual Node* GetRootNode() = 0;
627 
~AllocationProfile()628   virtual ~AllocationProfile() {}
629 
630   static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
631   static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
632 };
633 
634 /**
635  * An object graph consisting of embedder objects and V8 objects.
636  * Edges of the graph are strong references between the objects.
637  * The embedder can build this graph during heap snapshot generation
638  * to include the embedder objects in the heap snapshot.
639  * Usage:
640  * 1) Define derived class of EmbedderGraph::Node for embedder objects.
641  * 2) Set the build embedder graph callback on the heap profiler using
642  *    HeapProfiler::AddBuildEmbedderGraphCallback.
643  * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from
644  *    node1 to node2.
645  * 4) To represent references from/to V8 object, construct V8 nodes using
646  *    graph->V8Node(value).
647  */
648 class V8_EXPORT EmbedderGraph {
649  public:
650   class Node {
651    public:
652     Node() = default;
653     virtual ~Node() = default;
654     virtual const char* Name() = 0;
655     virtual size_t SizeInBytes() = 0;
656     /**
657      * The corresponding V8 wrapper node if not null.
658      * During heap snapshot generation the embedder node and the V8 wrapper
659      * node will be merged into one node to simplify retaining paths.
660      */
WrapperNode()661     virtual Node* WrapperNode() { return nullptr; }
IsRootNode()662     virtual bool IsRootNode() { return false; }
663     /** Must return true for non-V8 nodes. */
IsEmbedderNode()664     virtual bool IsEmbedderNode() { return true; }
665     /**
666      * Optional name prefix. It is used in Chrome for tagging detached nodes.
667      */
NamePrefix()668     virtual const char* NamePrefix() { return nullptr; }
669 
670    private:
671     Node(const Node&) = delete;
672     Node& operator=(const Node&) = delete;
673   };
674 
675   /**
676    * Returns a node corresponding to the given V8 value. Ownership is not
677    * transferred. The result pointer is valid while the graph is alive.
678    */
679   virtual Node* V8Node(const v8::Local<v8::Value>& value) = 0;
680 
681   /**
682    * Adds the given node to the graph and takes ownership of the node.
683    * Returns a raw pointer to the node that is valid while the graph is alive.
684    */
685   virtual Node* AddNode(std::unique_ptr<Node> node) = 0;
686 
687   /**
688    * Adds an edge that represents a strong reference from the given
689    * node |from| to the given node |to|. The nodes must be added to the graph
690    * before calling this function.
691    *
692    * If name is nullptr, the edge will have auto-increment indexes, otherwise
693    * it will be named accordingly.
694    */
695   virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0;
696 
697   virtual ~EmbedderGraph() = default;
698 };
699 
700 /**
701  * Interface for controlling heap profiling. Instance of the
702  * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
703  */
704 class V8_EXPORT HeapProfiler {
705  public:
706   enum SamplingFlags {
707     kSamplingNoFlags = 0,
708     kSamplingForceGC = 1 << 0,
709   };
710 
711   typedef std::unordered_set<const v8::PersistentBase<v8::Value>*>
712       RetainerChildren;
713   typedef std::vector<std::pair<v8::RetainedObjectInfo*, RetainerChildren>>
714       RetainerGroups;
715   typedef std::vector<std::pair<const v8::PersistentBase<v8::Value>*,
716                                 const v8::PersistentBase<v8::Value>*>>
717       RetainerEdges;
718 
719   struct RetainerInfos {
720     RetainerGroups groups;
721     RetainerEdges edges;
722   };
723 
724   /**
725    * Callback function invoked to retrieve all RetainerInfos from the embedder.
726    */
727   typedef RetainerInfos (*GetRetainerInfosCallback)(v8::Isolate* isolate);
728 
729   /**
730    * Callback function invoked for obtaining RetainedObjectInfo for
731    * the given JavaScript wrapper object. It is prohibited to enter V8
732    * while the callback is running: only getters on the handle and
733    * GetPointerFromInternalField on the objects are allowed.
734    */
735   typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id,
736                                                      Local<Value> wrapper);
737 
738   /**
739    * Callback function invoked during heap snapshot generation to retrieve
740    * the embedder object graph. The callback should use graph->AddEdge(..) to
741    * add references between the objects.
742    * The callback must not trigger garbage collection in V8.
743    */
744   typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate,
745                                              v8::EmbedderGraph* graph,
746                                              void* data);
747 
748   /** TODO(addaleax): Remove */
749   typedef void (*LegacyBuildEmbedderGraphCallback)(v8::Isolate* isolate,
750                                                    v8::EmbedderGraph* graph);
751 
752   /** Returns the number of snapshots taken. */
753   int GetSnapshotCount();
754 
755   /** Returns a snapshot by index. */
756   const HeapSnapshot* GetHeapSnapshot(int index);
757 
758   /**
759    * Returns SnapshotObjectId for a heap object referenced by |value| if
760    * it has been seen by the heap profiler, kUnknownObjectId otherwise.
761    */
762   SnapshotObjectId GetObjectId(Local<Value> value);
763 
764   /**
765    * Returns heap object with given SnapshotObjectId if the object is alive,
766    * otherwise empty handle is returned.
767    */
768   Local<Value> FindObjectById(SnapshotObjectId id);
769 
770   /**
771    * Clears internal map from SnapshotObjectId to heap object. The new objects
772    * will not be added into it unless a heap snapshot is taken or heap object
773    * tracking is kicked off.
774    */
775   void ClearObjectIds();
776 
777   /**
778    * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
779    * it in case heap profiler cannot find id  for the object passed as
780    * parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
781    */
782   static const SnapshotObjectId kUnknownObjectId = 0;
783 
784   /**
785    * Callback interface for retrieving user friendly names of global objects.
786    */
787   class ObjectNameResolver {
788    public:
789     /**
790      * Returns name to be used in the heap snapshot for given node. Returned
791      * string must stay alive until snapshot collection is completed.
792      */
793     virtual const char* GetName(Local<Object> object) = 0;
794 
795    protected:
~ObjectNameResolver()796     virtual ~ObjectNameResolver() {}
797   };
798 
799   /**
800    * Takes a heap snapshot and returns it.
801    */
802   const HeapSnapshot* TakeHeapSnapshot(
803       ActivityControl* control = NULL,
804       ObjectNameResolver* global_object_name_resolver = NULL);
805 
806   /**
807    * Starts tracking of heap objects population statistics. After calling
808    * this method, all heap objects relocations done by the garbage collector
809    * are being registered.
810    *
811    * |track_allocations| parameter controls whether stack trace of each
812    * allocation in the heap will be recorded and reported as part of
813    * HeapSnapshot.
814    */
815   void StartTrackingHeapObjects(bool track_allocations = false);
816 
817   /**
818    * Adds a new time interval entry to the aggregated statistics array. The
819    * time interval entry contains information on the current heap objects
820    * population size. The method also updates aggregated statistics and
821    * reports updates for all previous time intervals via the OutputStream
822    * object. Updates on each time interval are provided as a stream of the
823    * HeapStatsUpdate structure instances.
824    * If |timestamp_us| is supplied, timestamp of the new entry will be written
825    * into it. The return value of the function is the last seen heap object Id.
826    *
827    * StartTrackingHeapObjects must be called before the first call to this
828    * method.
829    */
830   SnapshotObjectId GetHeapStats(OutputStream* stream,
831                                 int64_t* timestamp_us = NULL);
832 
833   /**
834    * Stops tracking of heap objects population statistics, cleans up all
835    * collected data. StartHeapObjectsTracking must be called again prior to
836    * calling GetHeapStats next time.
837    */
838   void StopTrackingHeapObjects();
839 
840   /**
841    * Starts gathering a sampling heap profile. A sampling heap profile is
842    * similar to tcmalloc's heap profiler and Go's mprof. It samples object
843    * allocations and builds an online 'sampling' heap profile. At any point in
844    * time, this profile is expected to be a representative sample of objects
845    * currently live in the system. Each sampled allocation includes the stack
846    * trace at the time of allocation, which makes this really useful for memory
847    * leak detection.
848    *
849    * This mechanism is intended to be cheap enough that it can be used in
850    * production with minimal performance overhead.
851    *
852    * Allocations are sampled using a randomized Poisson process. On average, one
853    * allocation will be sampled every |sample_interval| bytes allocated. The
854    * |stack_depth| parameter controls the maximum number of stack frames to be
855    * captured on each allocation.
856    *
857    * NOTE: This is a proof-of-concept at this point. Right now we only sample
858    * newspace allocations. Support for paged space allocation (e.g. pre-tenured
859    * objects, large objects, code objects, etc.) and native allocations
860    * doesn't exist yet, but is anticipated in the future.
861    *
862    * Objects allocated before the sampling is started will not be included in
863    * the profile.
864    *
865    * Returns false if a sampling heap profiler is already running.
866    */
867   bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
868                                  int stack_depth = 16,
869                                  SamplingFlags flags = kSamplingNoFlags);
870 
871   /**
872    * Stops the sampling heap profile and discards the current profile.
873    */
874   void StopSamplingHeapProfiler();
875 
876   /**
877    * Returns the sampled profile of allocations allocated (and still live) since
878    * StartSamplingHeapProfiler was called. The ownership of the pointer is
879    * transferred to the caller. Returns nullptr if sampling heap profiler is not
880    * active.
881    */
882   AllocationProfile* GetAllocationProfile();
883 
884   /**
885    * Deletes all snapshots taken. All previously returned pointers to
886    * snapshots and their contents become invalid after this call.
887    */
888   void DeleteAllHeapSnapshots();
889 
890   /** Binds a callback to embedder's class ID. */
891   V8_DEPRECATED(
892       "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes",
893       void SetWrapperClassInfoProvider(uint16_t class_id,
894                                        WrapperInfoCallback callback));
895 
896   V8_DEPRECATED(
897       "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes",
898       void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback));
899 
900   V8_DEPRECATED(
901       "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes",
902       void SetBuildEmbedderGraphCallback(
903           LegacyBuildEmbedderGraphCallback callback));
904   void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,
905                                      void* data);
906   void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,
907                                         void* data);
908 
909   /**
910    * Default value of persistent handle class ID. Must not be used to
911    * define a class. Can be used to reset a class of a persistent
912    * handle.
913    */
914   static const uint16_t kPersistentHandleNoClassId = 0;
915 
916  private:
917   HeapProfiler();
918   ~HeapProfiler();
919   HeapProfiler(const HeapProfiler&);
920   HeapProfiler& operator=(const HeapProfiler&);
921 };
922 
923 /**
924  * Interface for providing information about embedder's objects
925  * held by global handles. This information is reported in two ways:
926  *
927  *  1. When calling AddObjectGroup, an embedder may pass
928  *     RetainedObjectInfo instance describing the group.  To collect
929  *     this information while taking a heap snapshot, V8 calls GC
930  *     prologue and epilogue callbacks.
931  *
932  *  2. When a heap snapshot is collected, V8 additionally
933  *     requests RetainedObjectInfos for persistent handles that
934  *     were not previously reported via AddObjectGroup.
935  *
936  * Thus, if an embedder wants to provide information about native
937  * objects for heap snapshots, it can do it in a GC prologue
938  * handler, and / or by assigning wrapper class ids in the following way:
939  *
940  *  1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
941  *  2. Call SetWrapperClassId on certain persistent handles.
942  *
943  * V8 takes ownership of RetainedObjectInfo instances passed to it and
944  * keeps them alive only during snapshot collection. Afterwards, they
945  * are freed by calling the Dispose class function.
946  */
947 class V8_EXPORT RetainedObjectInfo {  // NOLINT
948  public:
949   /** Called by V8 when it no longer needs an instance. */
950   virtual void Dispose() = 0;
951 
952   /** Returns whether two instances are equivalent. */
953   virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
954 
955   /**
956    * Returns hash value for the instance. Equivalent instances
957    * must have the same hash value.
958    */
959   virtual intptr_t GetHash() = 0;
960 
961   /**
962    * Returns human-readable label. It must be a null-terminated UTF-8
963    * encoded string. V8 copies its contents during a call to GetLabel.
964    */
965   virtual const char* GetLabel() = 0;
966 
967   /**
968    * Returns human-readable group label. It must be a null-terminated UTF-8
969    * encoded string. V8 copies its contents during a call to GetGroupLabel.
970    * Heap snapshot generator will collect all the group names, create
971    * top level entries with these names and attach the objects to the
972    * corresponding top level group objects. There is a default
973    * implementation which is required because embedders don't have their
974    * own implementation yet.
975    */
GetGroupLabel()976   virtual const char* GetGroupLabel() { return GetLabel(); }
977 
978   /**
979    * Returns element count in case if a global handle retains
980    * a subgraph by holding one of its nodes.
981    */
GetElementCount()982   virtual intptr_t GetElementCount() { return -1; }
983 
984   /** Returns embedder's object size in bytes. */
GetSizeInBytes()985   virtual intptr_t GetSizeInBytes() { return -1; }
986 
987  protected:
RetainedObjectInfo()988   RetainedObjectInfo() {}
~RetainedObjectInfo()989   virtual ~RetainedObjectInfo() {}
990 
991  private:
992   RetainedObjectInfo(const RetainedObjectInfo&);
993   RetainedObjectInfo& operator=(const RetainedObjectInfo&);
994 };
995 
996 
997 /**
998  * A struct for exporting HeapStats data from V8, using "push" model.
999  * See HeapProfiler::GetHeapStats.
1000  */
1001 struct HeapStatsUpdate {
HeapStatsUpdateHeapStatsUpdate1002   HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
1003     : index(index), count(count), size(size) { }
1004   uint32_t index;  // Index of the time interval that was changed.
1005   uint32_t count;  // New value of count field for the interval with this index.
1006   uint32_t size;  // New value of size field for the interval with this index.
1007 };
1008 
1009 #define CODE_EVENTS_LIST(V) \
1010   V(Builtin)                \
1011   V(Callback)               \
1012   V(Eval)                   \
1013   V(Function)               \
1014   V(InterpretedFunction)    \
1015   V(Handler)                \
1016   V(BytecodeHandler)        \
1017   V(LazyCompile)            \
1018   V(RegExp)                 \
1019   V(Script)                 \
1020   V(Stub)
1021 
1022 /**
1023  * Note that this enum may be extended in the future. Please include a default
1024  * case if this enum is used in a switch statement.
1025  */
1026 enum CodeEventType {
1027   kUnknownType = 0
1028 #define V(Name) , k##Name##Type
1029   CODE_EVENTS_LIST(V)
1030 #undef V
1031 };
1032 
1033 /**
1034  * Representation of a code creation event
1035  */
1036 class V8_EXPORT CodeEvent {
1037  public:
1038   uintptr_t GetCodeStartAddress();
1039   size_t GetCodeSize();
1040   Local<String> GetFunctionName();
1041   Local<String> GetScriptName();
1042   int GetScriptLine();
1043   int GetScriptColumn();
1044   /**
1045    * NOTE (mmarchini): We can't allocate objects in the heap when we collect
1046    * existing code, and both the code type and the comment are not stored in the
1047    * heap, so we return those as const char*.
1048    */
1049   CodeEventType GetCodeType();
1050   const char* GetComment();
1051 
1052   static const char* GetCodeEventTypeName(CodeEventType code_event_type);
1053 };
1054 
1055 /**
1056  * Interface to listen to code creation events.
1057  */
1058 class V8_EXPORT CodeEventHandler {
1059  public:
1060   /**
1061    * Creates a new listener for the |isolate|. The isolate must be initialized.
1062    * The listener object must be disposed after use by calling |Dispose| method.
1063    * Multiple listeners can be created for the same isolate.
1064    */
1065   explicit CodeEventHandler(Isolate* isolate);
1066   virtual ~CodeEventHandler();
1067 
1068   virtual void Handle(CodeEvent* code_event) = 0;
1069 
1070   void Enable();
1071   void Disable();
1072 
1073  private:
1074   CodeEventHandler();
1075   CodeEventHandler(const CodeEventHandler&);
1076   CodeEventHandler& operator=(const CodeEventHandler&);
1077   void* internal_listener_;
1078 };
1079 
1080 }  // namespace v8
1081 
1082 
1083 #endif  // V8_V8_PROFILER_H_
1084