• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_V8_PROFILER_H_
29 #define V8_V8_PROFILER_H_
30 
31 #include "v8.h"
32 
33 /**
34  * Profiler support for the V8 JavaScript engine.
35  */
36 namespace v8 {
37 
38 typedef uint32_t SnapshotObjectId;
39 
40 /**
41  * CpuProfileNode represents a node in a call graph.
42  */
43 class V8_EXPORT CpuProfileNode {
44  public:
45   /** Returns function name (empty string for anonymous functions.) */
46   Handle<String> GetFunctionName() const;
47 
48   /** Returns id of the script where function is located. */
49   int GetScriptId() const;
50 
51   /** Returns resource name for script from where the function originates. */
52   Handle<String> GetScriptResourceName() const;
53 
54   /**
55    * Returns the number, 1-based, of the line where the function originates.
56    * kNoLineNumberInfo if no line number information is available.
57    */
58   int GetLineNumber() const;
59 
60   /**
61    * Returns 1-based number of the column where the function originates.
62    * kNoColumnNumberInfo if no column number information is available.
63    */
64   int GetColumnNumber() const;
65 
66   /** Returns bailout reason for the function
67     * if the optimization was disabled for it.
68     */
69   const char* GetBailoutReason() const;
70 
71   /**
72     * Returns the count of samples where the function was currently executing.
73     */
74   unsigned GetHitCount() const;
75 
76   /** Returns function entry UID. */
77   unsigned GetCallUid() const;
78 
79   /** Returns id of the node. The id is unique within the tree */
80   unsigned GetNodeId() const;
81 
82   /** Returns child nodes count of the node. */
83   int GetChildrenCount() const;
84 
85   /** Retrieves a child node by index. */
86   const CpuProfileNode* GetChild(int index) const;
87 
88   static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
89   static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
90 };
91 
92 
93 /**
94  * CpuProfile contains a CPU profile in a form of top-down call tree
95  * (from main() down to functions that do all the work).
96  */
97 class V8_EXPORT CpuProfile {
98  public:
99   /** Returns CPU profile UID (assigned by the profiler.) */
100   unsigned GetUid() const;
101 
102   /** Returns CPU profile title. */
103   Handle<String> GetTitle() const;
104 
105   /** Returns the root node of the top down call tree. */
106   const CpuProfileNode* GetTopDownRoot() const;
107 
108   /**
109     * Returns number of samples recorded. The samples are not recorded unless
110     * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
111     */
112   int GetSamplesCount() const;
113 
114   /**
115     * Returns profile node corresponding to the top frame the sample at
116     * the given index.
117     */
118   const CpuProfileNode* GetSample(int index) const;
119 
120   /**
121     * Returns time when the profile recording started (in microseconds
122     * since the Epoch).
123     */
124   int64_t GetStartTime() const;
125 
126   /**
127     * Returns time when the profile recording was stopped (in microseconds
128     * since the Epoch).
129     */
130   int64_t GetEndTime() const;
131 
132   /**
133    * Deletes the profile and removes it from CpuProfiler's list.
134    * All pointers to nodes previously returned become invalid.
135    * Profiles with the same uid but obtained using different
136    * security token are not deleted, but become inaccessible
137    * using FindProfile method. It is embedder's responsibility
138    * to call Delete on these profiles.
139    */
140   void Delete();
141 };
142 
143 
144 /**
145  * Interface for controlling CPU profiling. Instance of the
146  * profiler can be retrieved using v8::Isolate::GetCpuProfiler.
147  */
148 class V8_EXPORT CpuProfiler {
149  public:
150   /**
151    * Changes default CPU profiler sampling interval to the specified number
152    * of microseconds. Default interval is 1000us. This method must be called
153    * when there are no profiles being recorded.
154    */
155   void SetSamplingInterval(int us);
156 
157   /**
158    * Returns the number of profiles collected (doesn't include
159    * profiles that are being collected at the moment of call.)
160    */
161   int GetProfileCount();
162 
163   /** Returns a profile by index. */
164   const CpuProfile* GetCpuProfile(int index);
165 
166   /**
167    * Starts collecting CPU profile. Title may be an empty string. It
168    * is allowed to have several profiles being collected at
169    * once. Attempts to start collecting several profiles with the same
170    * title are silently ignored. While collecting a profile, functions
171    * from all security contexts are included in it. The token-based
172    * filtering is only performed when querying for a profile.
173    *
174    * |record_samples| parameter controls whether individual samples should
175    * be recorded in addition to the aggregated tree.
176    */
177   void StartCpuProfiling(Handle<String> title, bool record_samples = false);
178 
179   /**
180    * Stops collecting CPU profile with a given title and returns it.
181    * If the title given is empty, finishes the last profile started.
182    */
183   const CpuProfile* StopCpuProfiling(Handle<String> title);
184 
185   /**
186    * Deletes all existing profiles, also cancelling all profiling
187    * activity.  All previously returned pointers to profiles and their
188    * contents become invalid after this call.
189    */
190   void DeleteAllCpuProfiles();
191 
192   /**
193    * Tells the profiler whether the embedder is idle.
194    */
195   void SetIdle(bool is_idle);
196 
197  private:
198   CpuProfiler();
199   ~CpuProfiler();
200   CpuProfiler(const CpuProfiler&);
201   CpuProfiler& operator=(const CpuProfiler&);
202 };
203 
204 
205 class HeapGraphNode;
206 
207 
208 /**
209  * HeapSnapshotEdge represents a directed connection between heap
210  * graph nodes: from retainers to retained nodes.
211  */
212 class V8_EXPORT HeapGraphEdge {
213  public:
214   enum Type {
215     kContextVariable = 0,  // A variable from a function context.
216     kElement = 1,          // An element of an array.
217     kProperty = 2,         // A named object property.
218     kInternal = 3,         // A link that can't be accessed from JS,
219                            // thus, its name isn't a real property name
220                            // (e.g. parts of a ConsString).
221     kHidden = 4,           // A link that is needed for proper sizes
222                            // calculation, but may be hidden from user.
223     kShortcut = 5,         // A link that must not be followed during
224                            // sizes calculation.
225     kWeak = 6              // A weak reference (ignored by the GC).
226   };
227 
228   /** Returns edge type (see HeapGraphEdge::Type). */
229   Type GetType() const;
230 
231   /**
232    * Returns edge name. This can be a variable name, an element index, or
233    * a property name.
234    */
235   Handle<Value> GetName() const;
236 
237   /** Returns origin node. */
238   const HeapGraphNode* GetFromNode() const;
239 
240   /** Returns destination node. */
241   const HeapGraphNode* GetToNode() const;
242 };
243 
244 
245 /**
246  * HeapGraphNode represents a node in a heap graph.
247  */
248 class V8_EXPORT HeapGraphNode {
249  public:
250   enum Type {
251     kHidden = 0,        // Hidden node, may be filtered when shown to user.
252     kArray = 1,         // An array of elements.
253     kString = 2,        // A string.
254     kObject = 3,        // A JS object (except for arrays and strings).
255     kCode = 4,          // Compiled code.
256     kClosure = 5,       // Function closure.
257     kRegExp = 6,        // RegExp.
258     kHeapNumber = 7,    // Number stored in the heap.
259     kNative = 8,        // Native object (not from V8 heap).
260     kSynthetic = 9,     // Synthetic object, usualy used for grouping
261                         // snapshot items together.
262     kConsString = 10,   // Concatenated string. A pair of pointers to strings.
263     kSlicedString = 11  // Sliced string. A fragment of another string.
264   };
265 
266   /** Returns node type (see HeapGraphNode::Type). */
267   Type GetType() const;
268 
269   /**
270    * Returns node name. Depending on node's type this can be the name
271    * of the constructor (for objects), the name of the function (for
272    * closures), string value, or an empty string (for compiled code).
273    */
274   Handle<String> GetName() const;
275 
276   /**
277    * Returns node id. For the same heap object, the id remains the same
278    * across all snapshots.
279    */
280   SnapshotObjectId GetId() const;
281 
282   /** Returns node's own size, in bytes. */
283   int GetSelfSize() const;
284 
285   /** Returns child nodes count of the node. */
286   int GetChildrenCount() const;
287 
288   /** Retrieves a child by index. */
289   const HeapGraphEdge* GetChild(int index) const;
290 
291   /**
292    * Finds and returns a value from the heap corresponding to this node,
293    * if the value is still reachable.
294    */
295   Handle<Value> GetHeapValue() const;
296 };
297 
298 
299 /**
300  * HeapSnapshots record the state of the JS heap at some moment.
301  */
302 class V8_EXPORT HeapSnapshot {
303  public:
304   enum SerializationFormat {
305     kJSON = 0  // See format description near 'Serialize' method.
306   };
307 
308   /** Returns heap snapshot UID (assigned by the profiler.) */
309   unsigned GetUid() const;
310 
311   /** Returns heap snapshot title. */
312   Handle<String> GetTitle() const;
313 
314   /** Returns the root node of the heap graph. */
315   const HeapGraphNode* GetRoot() const;
316 
317   /** Returns a node by its id. */
318   const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
319 
320   /** Returns total nodes count in the snapshot. */
321   int GetNodesCount() const;
322 
323   /** Returns a node by index. */
324   const HeapGraphNode* GetNode(int index) const;
325 
326   /** Returns a max seen JS object Id. */
327   SnapshotObjectId GetMaxSnapshotJSObjectId() const;
328 
329   /**
330    * Deletes the snapshot and removes it from HeapProfiler's list.
331    * All pointers to nodes, edges and paths previously returned become
332    * invalid.
333    */
334   void Delete();
335 
336   /**
337    * Prepare a serialized representation of the snapshot. The result
338    * is written into the stream provided in chunks of specified size.
339    * The total length of the serialized snapshot is unknown in
340    * advance, it can be roughly equal to JS heap size (that means,
341    * it can be really big - tens of megabytes).
342    *
343    * For the JSON format, heap contents are represented as an object
344    * with the following structure:
345    *
346    *  {
347    *    snapshot: {
348    *      title: "...",
349    *      uid: nnn,
350    *      meta: { meta-info },
351    *      node_count: nnn,
352    *      edge_count: nnn
353    *    },
354    *    nodes: [nodes array],
355    *    edges: [edges array],
356    *    strings: [strings array]
357    *  }
358    *
359    * Nodes reference strings, other nodes, and edges by their indexes
360    * in corresponding arrays.
361    */
362   void Serialize(OutputStream* stream, SerializationFormat format) const;
363 };
364 
365 
366 class RetainedObjectInfo;
367 
368 /**
369  * Interface for controlling heap profiling. Instance of the
370  * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
371  */
372 class V8_EXPORT HeapProfiler {
373  public:
374   /**
375    * Callback function invoked for obtaining RetainedObjectInfo for
376    * the given JavaScript wrapper object. It is prohibited to enter V8
377    * while the callback is running: only getters on the handle and
378    * GetPointerFromInternalField on the objects are allowed.
379    */
380   typedef RetainedObjectInfo* (*WrapperInfoCallback)
381       (uint16_t class_id, Handle<Value> wrapper);
382 
383   /** Returns the number of snapshots taken. */
384   int GetSnapshotCount();
385 
386   /** Returns a snapshot by index. */
387   const HeapSnapshot* GetHeapSnapshot(int index);
388 
389   /**
390    * Returns SnapshotObjectId for a heap object referenced by |value| if
391    * it has been seen by the heap profiler, kUnknownObjectId otherwise.
392    */
393   SnapshotObjectId GetObjectId(Handle<Value> value);
394 
395   /**
396    * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
397    * it in case heap profiler cannot find id  for the object passed as
398    * parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
399    */
400   static const SnapshotObjectId kUnknownObjectId = 0;
401 
402   /**
403    * Callback interface for retrieving user friendly names of global objects.
404    */
405   class ObjectNameResolver {
406    public:
407     /**
408      * Returns name to be used in the heap snapshot for given node. Returned
409      * string must stay alive until snapshot collection is completed.
410      */
411     virtual const char* GetName(Handle<Object> object) = 0;
412    protected:
~ObjectNameResolver()413     virtual ~ObjectNameResolver() {}
414   };
415 
416   /**
417    * Takes a heap snapshot and returns it. Title may be an empty string.
418    */
419   const HeapSnapshot* TakeHeapSnapshot(
420       Handle<String> title,
421       ActivityControl* control = NULL,
422       ObjectNameResolver* global_object_name_resolver = NULL);
423 
424   /**
425    * Starts tracking of heap objects population statistics. After calling
426    * this method, all heap objects relocations done by the garbage collector
427    * are being registered.
428    *
429    * |track_allocations| parameter controls whether stack trace of each
430    * allocation in the heap will be recorded and reported as part of
431    * HeapSnapshot.
432    */
433   void StartTrackingHeapObjects(bool track_allocations = false);
434 
435   /**
436    * Adds a new time interval entry to the aggregated statistics array. The
437    * time interval entry contains information on the current heap objects
438    * population size. The method also updates aggregated statistics and
439    * reports updates for all previous time intervals via the OutputStream
440    * object. Updates on each time interval are provided as a stream of the
441    * HeapStatsUpdate structure instances.
442    * The return value of the function is the last seen heap object Id.
443    *
444    * StartTrackingHeapObjects must be called before the first call to this
445    * method.
446    */
447   SnapshotObjectId GetHeapStats(OutputStream* stream);
448 
449   /**
450    * Stops tracking of heap objects population statistics, cleans up all
451    * collected data. StartHeapObjectsTracking must be called again prior to
452    * calling PushHeapObjectsStats next time.
453    */
454   void StopTrackingHeapObjects();
455 
456   /**
457    * Deletes all snapshots taken. All previously returned pointers to
458    * snapshots and their contents become invalid after this call.
459    */
460   void DeleteAllHeapSnapshots();
461 
462   /** Binds a callback to embedder's class ID. */
463   void SetWrapperClassInfoProvider(
464       uint16_t class_id,
465       WrapperInfoCallback callback);
466 
467   /**
468    * Default value of persistent handle class ID. Must not be used to
469    * define a class. Can be used to reset a class of a persistent
470    * handle.
471    */
472   static const uint16_t kPersistentHandleNoClassId = 0;
473 
474   /** Returns memory used for profiler internal data and snapshots. */
475   size_t GetProfilerMemorySize();
476 
477   /**
478    * Sets a RetainedObjectInfo for an object group (see V8::SetObjectGroupId).
479    */
480   void SetRetainedObjectInfo(UniqueId id, RetainedObjectInfo* info);
481 
482   /**
483    * Starts recording JS allocations immediately as they arrive and tracking of
484    * heap objects population statistics.
485    */
486   V8_DEPRECATED("Use StartTrackingHeapObjects instead",
487                 void StartRecordingHeapAllocations());
488 
489   /**
490    * Stops recording JS allocations and tracking of heap objects population
491    * statistics, cleans all collected heap objects population statistics data.
492    */
493   V8_DEPRECATED("Use StopTrackingHeapObjects instead",
494                 void StopRecordingHeapAllocations());
495 
496 
497  private:
498   HeapProfiler();
499   ~HeapProfiler();
500   HeapProfiler(const HeapProfiler&);
501   HeapProfiler& operator=(const HeapProfiler&);
502 };
503 
504 
505 /**
506  * Interface for providing information about embedder's objects
507  * held by global handles. This information is reported in two ways:
508  *
509  *  1. When calling AddObjectGroup, an embedder may pass
510  *     RetainedObjectInfo instance describing the group.  To collect
511  *     this information while taking a heap snapshot, V8 calls GC
512  *     prologue and epilogue callbacks.
513  *
514  *  2. When a heap snapshot is collected, V8 additionally
515  *     requests RetainedObjectInfos for persistent handles that
516  *     were not previously reported via AddObjectGroup.
517  *
518  * Thus, if an embedder wants to provide information about native
519  * objects for heap snapshots, he can do it in a GC prologue
520  * handler, and / or by assigning wrapper class ids in the following way:
521  *
522  *  1. Bind a callback to class id by calling SetWrapperClassInfoProvider.
523  *  2. Call SetWrapperClassId on certain persistent handles.
524  *
525  * V8 takes ownership of RetainedObjectInfo instances passed to it and
526  * keeps them alive only during snapshot collection. Afterwards, they
527  * are freed by calling the Dispose class function.
528  */
529 class V8_EXPORT RetainedObjectInfo {  // NOLINT
530  public:
531   /** Called by V8 when it no longer needs an instance. */
532   virtual void Dispose() = 0;
533 
534   /** Returns whether two instances are equivalent. */
535   virtual bool IsEquivalent(RetainedObjectInfo* other) = 0;
536 
537   /**
538    * Returns hash value for the instance. Equivalent instances
539    * must have the same hash value.
540    */
541   virtual intptr_t GetHash() = 0;
542 
543   /**
544    * Returns human-readable label. It must be a null-terminated UTF-8
545    * encoded string. V8 copies its contents during a call to GetLabel.
546    */
547   virtual const char* GetLabel() = 0;
548 
549   /**
550    * Returns human-readable group label. It must be a null-terminated UTF-8
551    * encoded string. V8 copies its contents during a call to GetGroupLabel.
552    * Heap snapshot generator will collect all the group names, create
553    * top level entries with these names and attach the objects to the
554    * corresponding top level group objects. There is a default
555    * implementation which is required because embedders don't have their
556    * own implementation yet.
557    */
GetGroupLabel()558   virtual const char* GetGroupLabel() { return GetLabel(); }
559 
560   /**
561    * Returns element count in case if a global handle retains
562    * a subgraph by holding one of its nodes.
563    */
GetElementCount()564   virtual intptr_t GetElementCount() { return -1; }
565 
566   /** Returns embedder's object size in bytes. */
GetSizeInBytes()567   virtual intptr_t GetSizeInBytes() { return -1; }
568 
569  protected:
RetainedObjectInfo()570   RetainedObjectInfo() {}
~RetainedObjectInfo()571   virtual ~RetainedObjectInfo() {}
572 
573  private:
574   RetainedObjectInfo(const RetainedObjectInfo&);
575   RetainedObjectInfo& operator=(const RetainedObjectInfo&);
576 };
577 
578 
579 /**
580  * A struct for exporting HeapStats data from V8, using "push" model.
581  * See HeapProfiler::GetHeapStats.
582  */
583 struct HeapStatsUpdate {
HeapStatsUpdateHeapStatsUpdate584   HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
585     : index(index), count(count), size(size) { }
586   uint32_t index;  // Index of the time interval that was changed.
587   uint32_t count;  // New value of count field for the interval with this index.
588   uint32_t size;  // New value of size field for the interval with this index.
589 };
590 
591 
592 }  // namespace v8
593 
594 
595 #endif  // V8_V8_PROFILER_H_
596