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