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: 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 */ 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 */ 564 virtual intptr_t GetElementCount() { return -1; } 565 566 /** Returns embedder's object size in bytes. */ 567 virtual intptr_t GetSizeInBytes() { return -1; } 568 569 protected: 570 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 { 584 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