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 <vector>
9 #include "v8.h"  // NOLINT(build/include)
10 
11 /**
12  * Profiler support for the V8 JavaScript engine.
13  */
14 namespace v8 {
15 
16 class HeapGraphNode;
17 struct HeapStatsUpdate;
18 
19 typedef uint32_t SnapshotObjectId;
20 
21 
22 struct CpuProfileDeoptFrame {
23   int script_id;
24   size_t position;
25 };
26 
27 }  // namespace v8
28 
29 #ifdef V8_OS_WIN
30 template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
31 #endif
32 
33 namespace v8 {
34 
35 struct 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
44 template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
45 #endif
46 
47 namespace v8 {
48 
49 /**
50  * TracingCpuProfiler monitors tracing being enabled/disabled
51  * and emits CpuProfile trace events once v8.cpu_profiler tracing category
52  * is enabled. It has no overhead unless the category is enabled.
53  */
54 class V8_EXPORT TracingCpuProfiler {
55  public:
56   static std::unique_ptr<TracingCpuProfiler> Create(Isolate*);
57   virtual ~TracingCpuProfiler() = default;
58 
59  protected:
60   TracingCpuProfiler() = default;
61 };
62 
63 // TickSample captures the information collected for each sample.
64 struct TickSample {
65   // Internal profiling (with --prof + tools/$OS-tick-processor) wants to
66   // include the runtime function we're calling. Externally exposed tick
67   // samples don't care.
68   enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame };
69 
TickSampleTickSample70   TickSample()
71       : state(OTHER),
72         pc(nullptr),
73         external_callback_entry(nullptr),
74         frames_count(0),
75         has_external_callback(false),
76         update_stats(true) {}
77 
78   /**
79    * Initialize a tick sample from the isolate.
80    * \param isolate The isolate.
81    * \param state Execution state.
82    * \param record_c_entry_frame Include or skip the runtime function.
83    * \param update_stats Whether update the sample to the aggregated stats.
84    * \param use_simulator_reg_state When set to true and V8 is running under a
85    *                                simulator, the method will use the simulator
86    *                                register state rather than the one provided
87    *                                with |state| argument. Otherwise the method
88    *                                will use provided register |state| as is.
89    */
90   void Init(Isolate* isolate, const v8::RegisterState& state,
91             RecordCEntryFrame record_c_entry_frame, bool update_stats,
92             bool use_simulator_reg_state = true);
93   /**
94    * Get a call stack sample from the isolate.
95    * \param isolate The isolate.
96    * \param state Register state.
97    * \param record_c_entry_frame Include or skip the runtime function.
98    * \param frames Caller allocated buffer to store stack frames.
99    * \param frames_limit Maximum number of frames to capture. The buffer must
100    *                     be large enough to hold the number of frames.
101    * \param sample_info The sample info is filled up by the function
102    *                    provides number of actual captured stack frames and
103    *                    the current VM state.
104    * \param use_simulator_reg_state When set to true and V8 is running under a
105    *                                simulator, the method will use the simulator
106    *                                register state rather than the one provided
107    *                                with |state| argument. Otherwise the method
108    *                                will use provided register |state| as is.
109    * \note GetStackSample is thread and signal safe and should only be called
110    *                      when the JS thread is paused or interrupted.
111    *                      Otherwise the behavior is undefined.
112    */
113   static bool GetStackSample(Isolate* isolate, v8::RegisterState* state,
114                              RecordCEntryFrame record_c_entry_frame,
115                              void** frames, size_t frames_limit,
116                              v8::SampleInfo* sample_info,
117                              bool use_simulator_reg_state = true);
118   StateTag state;  // The state of the VM.
119   void* pc;        // Instruction pointer.
120   union {
121     void* tos;  // Top stack value (*sp).
122     void* external_callback_entry;
123   };
124   static const unsigned kMaxFramesCountLog2 = 8;
125   static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1;
126   void* stack[kMaxFramesCount];                 // Call stack.
127   unsigned frames_count : kMaxFramesCountLog2;  // Number of captured frames.
128   bool has_external_callback : 1;
129   bool update_stats : 1;  // Whether the sample should update aggregated stats.
130 };
131 
132 /**
133  * CpuProfileNode represents a node in a call graph.
134  */
135 class V8_EXPORT CpuProfileNode {
136  public:
137   struct LineTick {
138     /** The 1-based number of the source line where the function originates. */
139     int line;
140 
141     /** The count of samples associated with the source line. */
142     unsigned int hit_count;
143   };
144 
145   /** Returns function name (empty string for anonymous functions.) */
146   Local<String> GetFunctionName() const;
147 
148   /**
149    * Returns function name (empty string for anonymous functions.)
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* GetFunctionNameStr() const;
154 
155   /** Returns id of the script where function is located. */
156   int GetScriptId() const;
157 
158   /** Returns resource name for script from where the function originates. */
159   Local<String> GetScriptResourceName() const;
160 
161   /**
162    * Returns resource name for script from where the function originates.
163    * The string ownership is *not* passed to the caller. It stays valid until
164    * profile is deleted. The function is thread safe.
165    */
166   const char* GetScriptResourceNameStr() const;
167 
168   /**
169    * Returns the number, 1-based, of the line where the function originates.
170    * kNoLineNumberInfo if no line number information is available.
171    */
172   int GetLineNumber() const;
173 
174   /**
175    * Returns 1-based number of the column where the function originates.
176    * kNoColumnNumberInfo if no column number information is available.
177    */
178   int GetColumnNumber() const;
179 
180   /**
181    * Returns the number of the function's source lines that collect the samples.
182    */
183   unsigned int GetHitLineCount() const;
184 
185   /** Returns the set of source lines that collect the samples.
186    *  The caller allocates buffer and responsible for releasing it.
187    *  True if all available entries are copied, otherwise false.
188    *  The function copies nothing if buffer is not large enough.
189    */
190   bool GetLineTicks(LineTick* entries, unsigned int length) const;
191 
192   /** Returns bailout reason for the function
193     * if the optimization was disabled for it.
194     */
195   const char* GetBailoutReason() const;
196 
197   /**
198     * Returns the count of samples where the function was currently executing.
199     */
200   unsigned GetHitCount() const;
201 
202   /** Returns function entry UID. */
203   V8_DEPRECATE_SOON(
204       "Use GetScriptId, GetLineNumber, and GetColumnNumber instead.",
205       unsigned GetCallUid() const);
206 
207   /** Returns id of the node. The id is unique within the tree */
208   unsigned GetNodeId() const;
209 
210   /** Returns child nodes count of the node. */
211   int GetChildrenCount() const;
212 
213   /** Retrieves a child node by index. */
214   const CpuProfileNode* GetChild(int index) const;
215 
216   /** Retrieves deopt infos for the node. */
217   const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
218 
219   static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
220   static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
221 };
222 
223 
224 /**
225  * CpuProfile contains a CPU profile in a form of top-down call tree
226  * (from main() down to functions that do all the work).
227  */
228 class V8_EXPORT CpuProfile {
229  public:
230   /** Returns CPU profile title. */
231   Local<String> GetTitle() const;
232 
233   /** Returns the root node of the top down call tree. */
234   const CpuProfileNode* GetTopDownRoot() const;
235 
236   /**
237    * Returns number of samples recorded. The samples are not recorded unless
238    * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
239    */
240   int GetSamplesCount() const;
241 
242   /**
243    * Returns profile node corresponding to the top frame the sample at
244    * the given index.
245    */
246   const CpuProfileNode* GetSample(int index) const;
247 
248   /**
249    * Returns the timestamp of the sample. The timestamp is the number of
250    * microseconds since some unspecified starting point.
251    * The point is equal to the starting point used by GetStartTime.
252    */
253   int64_t GetSampleTimestamp(int index) const;
254 
255   /**
256    * Returns time when the profile recording was started (in microseconds)
257    * since some unspecified starting point.
258    */
259   int64_t GetStartTime() const;
260 
261   /**
262    * Returns time when the profile recording was stopped (in microseconds)
263    * since some unspecified starting point.
264    * The point is equal to the starting point used by GetStartTime.
265    */
266   int64_t GetEndTime() const;
267 
268   /**
269    * Deletes the profile and removes it from CpuProfiler's list.
270    * All pointers to nodes previously returned become invalid.
271    */
272   void Delete();
273 };
274 
275 /**
276  * Interface for controlling CPU profiling. Instance of the
277  * profiler can be created using v8::CpuProfiler::New method.
278  */
279 class V8_EXPORT CpuProfiler {
280  public:
281   /**
282    * Creates a new CPU profiler for the |isolate|. The isolate must be
283    * initialized. The profiler object must be disposed after use by calling
284    * |Dispose| method.
285    */
286   static CpuProfiler* New(Isolate* isolate);
287 
288   /**
289    * Disposes the CPU profiler object.
290    */
291   void Dispose();
292 
293   /**
294    * Changes default CPU profiler sampling interval to the specified number
295    * of microseconds. Default interval is 1000us. This method must be called
296    * when there are no profiles being recorded.
297    */
298   void SetSamplingInterval(int us);
299 
300   /**
301    * Starts collecting CPU profile. Title may be an empty string. It
302    * is allowed to have several profiles being collected at
303    * once. Attempts to start collecting several profiles with the same
304    * title are silently ignored. While collecting a profile, functions
305    * from all security contexts are included in it. The token-based
306    * filtering is only performed when querying for a profile.
307    *
308    * |record_samples| parameter controls whether individual samples should
309    * be recorded in addition to the aggregated tree.
310    */
311   void StartProfiling(Local<String> title, bool record_samples = false);
312 
313   /**
314    * Stops collecting CPU profile with a given title and returns it.
315    * If the title given is empty, finishes the last profile started.
316    */
317   CpuProfile* StopProfiling(Local<String> title);
318 
319   /**
320    * Force collection of a sample. Must be called on the VM thread.
321    * Recording the forced sample does not contribute to the aggregated
322    * profile statistics.
323    */
324   void CollectSample();
325 
326   /**
327    * Tells the profiler whether the embedder is idle.
328    */
329   void SetIdle(bool is_idle);
330 
331  private:
332   CpuProfiler();
333   ~CpuProfiler();
334   CpuProfiler(const CpuProfiler&);
335   CpuProfiler& operator=(const CpuProfiler&);
336 };
337 
338 
339 /**
340  * HeapSnapshotEdge represents a directed connection between heap
341  * graph nodes: from retainers to retained nodes.
342  */
343 class V8_EXPORT HeapGraphEdge {
344  public:
345   enum Type {
346     kContextVariable = 0,  // A variable from a function context.
347     kElement = 1,          // An element of an array.
348     kProperty = 2,         // A named object property.
349     kInternal = 3,         // A link that can't be accessed from JS,
350                            // thus, its name isn't a real property name
351                            // (e.g. parts of a ConsString).
352     kHidden = 4,           // A link that is needed for proper sizes
353                            // calculation, but may be hidden from user.
354     kShortcut = 5,         // A link that must not be followed during
355                            // sizes calculation.
356     kWeak = 6              // A weak reference (ignored by the GC).
357   };
358 
359   /** Returns edge type (see HeapGraphEdge::Type). */
360   Type GetType() const;
361 
362   /**
363    * Returns edge name. This can be a variable name, an element index, or
364    * a property name.
365    */
366   Local<Value> GetName() const;
367 
368   /** Returns origin node. */
369   const HeapGraphNode* GetFromNode() const;
370 
371   /** Returns destination node. */
372   const HeapGraphNode* GetToNode() const;
373 };
374 
375 
376 /**
377  * HeapGraphNode represents a node in a heap graph.
378  */
379 class V8_EXPORT HeapGraphNode {
380  public:
381   enum Type {
382     kHidden = 0,         // Hidden node, may be filtered when shown to user.
383     kArray = 1,          // An array of elements.
384     kString = 2,         // A string.
385     kObject = 3,         // A JS object (except for arrays and strings).
386     kCode = 4,           // Compiled code.
387     kClosure = 5,        // Function closure.
388     kRegExp = 6,         // RegExp.
389     kHeapNumber = 7,     // Number stored in the heap.
390     kNative = 8,         // Native object (not from V8 heap).
391     kSynthetic = 9,      // Synthetic object, usualy used for grouping
392                          // snapshot items together.
393     kConsString = 10,    // Concatenated string. A pair of pointers to strings.
394     kSlicedString = 11,  // Sliced string. A fragment of another string.
395     kSymbol = 12,        // A Symbol (ES6).
396     kSimdValue = 13      // A SIMD value stored in the heap (Proposed ES7).
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   /**
634    * Callback function invoked for obtaining RetainedObjectInfo for
635    * the given JavaScript wrapper object. It is prohibited to enter V8
636    * while the callback is running: only getters on the handle and
637    * GetPointerFromInternalField on the objects are allowed.
638    */
639   typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id,
640                                                      Local<Value> wrapper);
641 
642   /** Returns the number of snapshots taken. */
643   int GetSnapshotCount();
644 
645   /** Returns a snapshot by index. */
646   const HeapSnapshot* GetHeapSnapshot(int index);
647 
648   /**
649    * Returns SnapshotObjectId for a heap object referenced by |value| if
650    * it has been seen by the heap profiler, kUnknownObjectId otherwise.
651    */
652   SnapshotObjectId GetObjectId(Local<Value> value);
653 
654   /**
655    * Returns heap object with given SnapshotObjectId if the object is alive,
656    * otherwise empty handle is returned.
657    */
658   Local<Value> FindObjectById(SnapshotObjectId id);
659 
660   /**
661    * Clears internal map from SnapshotObjectId to heap object. The new objects
662    * will not be added into it unless a heap snapshot is taken or heap object
663    * tracking is kicked off.
664    */
665   void ClearObjectIds();
666 
667   /**
668    * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
669    * it in case heap profiler cannot find id  for the object passed as
670    * parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
671    */
672   static const SnapshotObjectId kUnknownObjectId = 0;
673 
674   /**
675    * Callback interface for retrieving user friendly names of global objects.
676    */
677   class ObjectNameResolver {
678    public:
679     /**
680      * Returns name to be used in the heap snapshot for given node. Returned
681      * string must stay alive until snapshot collection is completed.
682      */
683     virtual const char* GetName(Local<Object> object) = 0;
684 
685    protected:
~ObjectNameResolver()686     virtual ~ObjectNameResolver() {}
687   };
688 
689   /**
690    * Takes a heap snapshot and returns it.
691    */
692   const HeapSnapshot* TakeHeapSnapshot(
693       ActivityControl* control = NULL,
694       ObjectNameResolver* global_object_name_resolver = NULL);
695 
696   /**
697    * Starts tracking of heap objects population statistics. After calling
698    * this method, all heap objects relocations done by the garbage collector
699    * are being registered.
700    *
701    * |track_allocations| parameter controls whether stack trace of each
702    * allocation in the heap will be recorded and reported as part of
703    * HeapSnapshot.
704    */
705   void StartTrackingHeapObjects(bool track_allocations = false);
706 
707   /**
708    * Adds a new time interval entry to the aggregated statistics array. The
709    * time interval entry contains information on the current heap objects
710    * population size. The method also updates aggregated statistics and
711    * reports updates for all previous time intervals via the OutputStream
712    * object. Updates on each time interval are provided as a stream of the
713    * HeapStatsUpdate structure instances.
714    * If |timestamp_us| is supplied, timestamp of the new entry will be written
715    * into it. The return value of the function is the last seen heap object Id.
716    *
717    * StartTrackingHeapObjects must be called before the first call to this
718    * method.
719    */
720   SnapshotObjectId GetHeapStats(OutputStream* stream,
721                                 int64_t* timestamp_us = NULL);
722 
723   /**
724    * Stops tracking of heap objects population statistics, cleans up all
725    * collected data. StartHeapObjectsTracking must be called again prior to
726    * calling GetHeapStats next time.
727    */
728   void StopTrackingHeapObjects();
729 
730   /**
731    * Starts gathering a sampling heap profile. A sampling heap profile is
732    * similar to tcmalloc's heap profiler and Go's mprof. It samples object
733    * allocations and builds an online 'sampling' heap profile. At any point in
734    * time, this profile is expected to be a representative sample of objects
735    * currently live in the system. Each sampled allocation includes the stack
736    * trace at the time of allocation, which makes this really useful for memory
737    * leak detection.
738    *
739    * This mechanism is intended to be cheap enough that it can be used in
740    * production with minimal performance overhead.
741    *
742    * Allocations are sampled using a randomized Poisson process. On average, one
743    * allocation will be sampled every |sample_interval| bytes allocated. The
744    * |stack_depth| parameter controls the maximum number of stack frames to be
745    * captured on each allocation.
746    *
747    * NOTE: This is a proof-of-concept at this point. Right now we only sample
748    * newspace allocations. Support for paged space allocation (e.g. pre-tenured
749    * objects, large objects, code objects, etc.) and native allocations
750    * doesn't exist yet, but is anticipated in the future.
751    *
752    * Objects allocated before the sampling is started will not be included in
753    * the profile.
754    *
755    * Returns false if a sampling heap profiler is already running.
756    */
757   bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
758                                  int stack_depth = 16,
759                                  SamplingFlags flags = kSamplingNoFlags);
760 
761   /**
762    * Stops the sampling heap profile and discards the current profile.
763    */
764   void StopSamplingHeapProfiler();
765 
766   /**
767    * Returns the sampled profile of allocations allocated (and still live) since
768    * StartSamplingHeapProfiler was called. The ownership of the pointer is
769    * transfered to the caller. Returns nullptr if sampling heap profiler is not
770    * active.
771    */
772   AllocationProfile* GetAllocationProfile();
773 
774   /**
775    * Deletes all snapshots taken. All previously returned pointers to
776    * snapshots and their contents become invalid after this call.
777    */
778   void DeleteAllHeapSnapshots();
779 
780   /** Binds a callback to embedder's class ID. */
781   void SetWrapperClassInfoProvider(
782       uint16_t class_id,
783       WrapperInfoCallback callback);
784 
785   /**
786    * Default value of persistent handle class ID. Must not be used to
787    * define a class. Can be used to reset a class of a persistent
788    * handle.
789    */
790   static const uint16_t kPersistentHandleNoClassId = 0;
791 
792   /** Returns memory used for profiler internal data and snapshots. */
793   size_t GetProfilerMemorySize();
794 
795   /**
796    * Sets a RetainedObjectInfo for an object group (see V8::SetObjectGroupId).
797    */
798   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
799 
800  private:
801   HeapProfiler();
802   ~HeapProfiler();
803   HeapProfiler(const HeapProfiler&);
804   HeapProfiler& operator=(const HeapProfiler&);
805 };
806 
807 /**
808  * Interface for providing information about embedder's objects
809  * held by global handles. This information is reported in two ways:
810  *
811  *  1. When calling AddObjectGroup, an embedder may pass
812  *     RetainedObjectInfo instance describing the group.  To collect
813  *     this information while taking a heap snapshot, V8 calls GC
814  *     prologue and epilogue callbacks.
815  *
816  *  2. When a heap snapshot is collected, V8 additionally
817  *     requests RetainedObjectInfos for persistent handles that
818  *     were not previously reported via AddObjectGroup.
819  *
820  * Thus, if an embedder wants to provide information about native
821  * objects for heap snapshots, it can do it in a GC prologue
822  * handler, and / or by assigning wrapper class ids in the following way:
823  *
824  *  1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
825  *  2. Call SetWrapperClassId on certain persistent handles.
826  *
827  * V8 takes ownership of RetainedObjectInfo instances passed to it and
828  * keeps them alive only during snapshot collection. Afterwards, they
829  * are freed by calling the Dispose class function.
830  */
831 class V8_EXPORT RetainedObjectInfo {  // NOLINT
832  public:
833   /** Called by V8 when it no longer needs an instance. */
834   virtual void Dispose() = 0;
835 
836   /** Returns whether two instances are equivalent. */
837   virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
838 
839   /**
840    * Returns hash value for the instance. Equivalent instances
841    * must have the same hash value.
842    */
843   virtual intptr_t GetHash() = 0;
844 
845   /**
846    * Returns human-readable label. It must be a null-terminated UTF-8
847    * encoded string. V8 copies its contents during a call to GetLabel.
848    */
849   virtual const char* GetLabel() = 0;
850 
851   /**
852    * Returns human-readable group label. It must be a null-terminated UTF-8
853    * encoded string. V8 copies its contents during a call to GetGroupLabel.
854    * Heap snapshot generator will collect all the group names, create
855    * top level entries with these names and attach the objects to the
856    * corresponding top level group objects. There is a default
857    * implementation which is required because embedders don't have their
858    * own implementation yet.
859    */
GetGroupLabel()860   virtual const char* GetGroupLabel() { return GetLabel(); }
861 
862   /**
863    * Returns element count in case if a global handle retains
864    * a subgraph by holding one of its nodes.
865    */
GetElementCount()866   virtual intptr_t GetElementCount() { return -1; }
867 
868   /** Returns embedder's object size in bytes. */
GetSizeInBytes()869   virtual intptr_t GetSizeInBytes() { return -1; }
870 
871  protected:
RetainedObjectInfo()872   RetainedObjectInfo() {}
~RetainedObjectInfo()873   virtual ~RetainedObjectInfo() {}
874 
875  private:
876   RetainedObjectInfo(const RetainedObjectInfo&);
877   RetainedObjectInfo& operator=(const RetainedObjectInfo&);
878 };
879 
880 
881 /**
882  * A struct for exporting HeapStats data from V8, using "push" model.
883  * See HeapProfiler::GetHeapStats.
884  */
885 struct HeapStatsUpdate {
HeapStatsUpdateHeapStatsUpdate886   HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
887     : index(index), count(count), size(size) { }
888   uint32_t index;  // Index of the time interval that was changed.
889   uint32_t count;  // New value of count field for the interval with this index.
890   uint32_t size;  // New value of size field for the interval with this index.
891 };
892 
893 
894 }  // namespace v8
895 
896 
897 #endif  // V8_V8_PROFILER_H_
898