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