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