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 <unordered_set> 9 #include <vector> 10 #include "v8.h" // NOLINT(build/include) 11 12 /** 13 * Profiler support for the V8 JavaScript engine. 14 */ 15 namespace v8 { 16 17 class HeapGraphNode; 18 struct HeapStatsUpdate; 19 20 typedef uint32_t SnapshotObjectId; 21 22 23 struct CpuProfileDeoptFrame { 24 int script_id; 25 size_t position; 26 }; 27 28 } // namespace v8 29 30 #ifdef V8_OS_WIN 31 template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>; 32 #endif 33 34 namespace v8 { 35 36 struct V8_EXPORT CpuProfileDeoptInfo { 37 /** A pointer to a static string owned by v8. */ 38 const char* deopt_reason; 39 std::vector<CpuProfileDeoptFrame> stack; 40 }; 41 42 } // namespace v8 43 44 #ifdef V8_OS_WIN 45 template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>; 46 #endif 47 48 namespace v8 { 49 50 // TickSample captures the information collected for each sample. 51 struct TickSample { 52 // Internal profiling (with --prof + tools/$OS-tick-processor) wants to 53 // include the runtime function we're calling. Externally exposed tick 54 // samples don't care. 55 enum RecordCEntryFrame { kIncludeCEntryFrame, kSkipCEntryFrame }; 56 57 TickSample() 58 : state(OTHER), 59 pc(nullptr), 60 external_callback_entry(nullptr), 61 frames_count(0), 62 has_external_callback(false), 63 update_stats(true) {} 64 65 /** 66 * Initialize a tick sample from the isolate. 67 * \param isolate The isolate. 68 * \param state Execution state. 69 * \param record_c_entry_frame Include or skip the runtime function. 70 * \param update_stats Whether update the sample to the aggregated stats. 71 * \param use_simulator_reg_state When set to true and V8 is running under a 72 * simulator, the method will use the simulator 73 * register state rather than the one provided 74 * with |state| argument. Otherwise the method 75 * will use provided register |state| as is. 76 */ 77 void Init(Isolate* isolate, const v8::RegisterState& state, 78 RecordCEntryFrame record_c_entry_frame, bool update_stats, 79 bool use_simulator_reg_state = true); 80 /** 81 * Get a call stack sample from the isolate. 82 * \param isolate The isolate. 83 * \param state Register state. 84 * \param record_c_entry_frame Include or skip the runtime function. 85 * \param frames Caller allocated buffer to store stack frames. 86 * \param frames_limit Maximum number of frames to capture. The buffer must 87 * be large enough to hold the number of frames. 88 * \param sample_info The sample info is filled up by the function 89 * provides number of actual captured stack frames and 90 * the current VM state. 91 * \param use_simulator_reg_state When set to true and V8 is running under a 92 * simulator, the method will use the simulator 93 * register state rather than the one provided 94 * with |state| argument. Otherwise the method 95 * will use provided register |state| as is. 96 * \note GetStackSample is thread and signal safe and should only be called 97 * when the JS thread is paused or interrupted. 98 * Otherwise the behavior is undefined. 99 */ 100 static bool GetStackSample(Isolate* isolate, v8::RegisterState* state, 101 RecordCEntryFrame record_c_entry_frame, 102 void** frames, size_t frames_limit, 103 v8::SampleInfo* sample_info, 104 bool use_simulator_reg_state = true); 105 StateTag state; // The state of the VM. 106 void* pc; // Instruction pointer. 107 union { 108 void* tos; // Top stack value (*sp). 109 void* external_callback_entry; 110 }; 111 static const unsigned kMaxFramesCountLog2 = 8; 112 static const unsigned kMaxFramesCount = (1 << kMaxFramesCountLog2) - 1; 113 void* stack[kMaxFramesCount]; // Call stack. 114 unsigned frames_count : kMaxFramesCountLog2; // Number of captured frames. 115 bool has_external_callback : 1; 116 bool update_stats : 1; // Whether the sample should update aggregated stats. 117 }; 118 119 /** 120 * CpuProfileNode represents a node in a call graph. 121 */ 122 class V8_EXPORT CpuProfileNode { 123 public: 124 struct LineTick { 125 /** The 1-based number of the source line where the function originates. */ 126 int line; 127 128 /** The count of samples associated with the source line. */ 129 unsigned int hit_count; 130 }; 131 132 /** Returns function name (empty string for anonymous functions.) */ 133 Local<String> GetFunctionName() const; 134 135 /** 136 * Returns function name (empty string for anonymous functions.) 137 * The string ownership is *not* passed to the caller. It stays valid until 138 * profile is deleted. The function is thread safe. 139 */ 140 const char* GetFunctionNameStr() const; 141 142 /** Returns id of the script where function is located. */ 143 int GetScriptId() const; 144 145 /** Returns resource name for script from where the function originates. */ 146 Local<String> GetScriptResourceName() const; 147 148 /** 149 * Returns resource name for script from where the function originates. 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* GetScriptResourceNameStr() const; 154 155 /** 156 * Returns the number, 1-based, of the line where the function originates. 157 * kNoLineNumberInfo if no line number information is available. 158 */ 159 int GetLineNumber() const; 160 161 /** 162 * Returns 1-based number of the column where the function originates. 163 * kNoColumnNumberInfo if no column number information is available. 164 */ 165 int GetColumnNumber() const; 166 167 /** 168 * Returns the number of the function's source lines that collect the samples. 169 */ 170 unsigned int GetHitLineCount() const; 171 172 /** Returns the set of source lines that collect the samples. 173 * The caller allocates buffer and responsible for releasing it. 174 * True if all available entries are copied, otherwise false. 175 * The function copies nothing if buffer is not large enough. 176 */ 177 bool GetLineTicks(LineTick* entries, unsigned int length) const; 178 179 /** Returns bailout reason for the function 180 * if the optimization was disabled for it. 181 */ 182 const char* GetBailoutReason() const; 183 184 /** 185 * Returns the count of samples where the function was currently executing. 186 */ 187 unsigned GetHitCount() const; 188 189 /** Returns function entry UID. */ 190 V8_DEPRECATE_SOON( 191 "Use GetScriptId, GetLineNumber, and GetColumnNumber instead.", 192 unsigned GetCallUid() const); 193 194 /** Returns id of the node. The id is unique within the tree */ 195 unsigned GetNodeId() const; 196 197 /** Returns child nodes count of the node. */ 198 int GetChildrenCount() const; 199 200 /** Retrieves a child node by index. */ 201 const CpuProfileNode* GetChild(int index) const; 202 203 /** Retrieves deopt infos for the node. */ 204 const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const; 205 206 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo; 207 static const int kNoColumnNumberInfo = Message::kNoColumnInfo; 208 }; 209 210 211 /** 212 * CpuProfile contains a CPU profile in a form of top-down call tree 213 * (from main() down to functions that do all the work). 214 */ 215 class V8_EXPORT CpuProfile { 216 public: 217 /** Returns CPU profile title. */ 218 Local<String> GetTitle() const; 219 220 /** Returns the root node of the top down call tree. */ 221 const CpuProfileNode* GetTopDownRoot() const; 222 223 /** 224 * Returns number of samples recorded. The samples are not recorded unless 225 * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true. 226 */ 227 int GetSamplesCount() const; 228 229 /** 230 * Returns profile node corresponding to the top frame the sample at 231 * the given index. 232 */ 233 const CpuProfileNode* GetSample(int index) const; 234 235 /** 236 * Returns the timestamp of the sample. The timestamp is the number of 237 * microseconds since some unspecified starting point. 238 * The point is equal to the starting point used by GetStartTime. 239 */ 240 int64_t GetSampleTimestamp(int index) const; 241 242 /** 243 * Returns time when the profile recording was started (in microseconds) 244 * since some unspecified starting point. 245 */ 246 int64_t GetStartTime() const; 247 248 /** 249 * Returns time when the profile recording was stopped (in microseconds) 250 * since some unspecified starting point. 251 * The point is equal to the starting point used by GetStartTime. 252 */ 253 int64_t GetEndTime() const; 254 255 /** 256 * Deletes the profile and removes it from CpuProfiler's list. 257 * All pointers to nodes previously returned become invalid. 258 */ 259 void Delete(); 260 }; 261 262 enum CpuProfilingMode { 263 // In the resulting CpuProfile tree, intermediate nodes in a stack trace 264 // (from the root to a leaf) will have line numbers that point to the start 265 // line of the function, rather than the line of the callsite of the child. 266 kLeafNodeLineNumbers, 267 // In the resulting CpuProfile tree, nodes are separated based on the line 268 // number of their callsite in their parent. 269 kCallerLineNumbers, 270 }; 271 272 /** 273 * Interface for controlling CPU profiling. Instance of the 274 * profiler can be created using v8::CpuProfiler::New method. 275 */ 276 class V8_EXPORT CpuProfiler { 277 public: 278 /** 279 * Creates a new CPU profiler for the |isolate|. The isolate must be 280 * initialized. The profiler object must be disposed after use by calling 281 * |Dispose| method. 282 */ 283 static CpuProfiler* New(Isolate* isolate); 284 285 /** 286 * Synchronously collect current stack sample in all profilers attached to 287 * the |isolate|. The call does not affect number of ticks recorded for 288 * the current top node. 289 */ 290 static void CollectSample(Isolate* isolate); 291 292 /** 293 * Disposes the CPU profiler object. 294 */ 295 void Dispose(); 296 297 /** 298 * Changes default CPU profiler sampling interval to the specified number 299 * of microseconds. Default interval is 1000us. This method must be called 300 * when there are no profiles being recorded. 301 */ 302 void SetSamplingInterval(int us); 303 304 /** 305 * Starts collecting CPU profile. Title may be an empty string. It 306 * is allowed to have several profiles being collected at 307 * once. Attempts to start collecting several profiles with the same 308 * title are silently ignored. While collecting a profile, functions 309 * from all security contexts are included in it. The token-based 310 * filtering is only performed when querying for a profile. 311 * 312 * |record_samples| parameter controls whether individual samples should 313 * be recorded in addition to the aggregated tree. 314 */ 315 void StartProfiling(Local<String> title, CpuProfilingMode mode, 316 bool record_samples = false); 317 /** 318 * The same as StartProfiling above, but the CpuProfilingMode defaults to 319 * kLeafNodeLineNumbers mode, which was the previous default behavior of the 320 * profiler. 321 */ 322 void StartProfiling(Local<String> title, bool record_samples = false); 323 324 /** 325 * Stops collecting CPU profile with a given title and returns it. 326 * If the title given is empty, finishes the last profile started. 327 */ 328 CpuProfile* StopProfiling(Local<String> title); 329 330 /** 331 * Force collection of a sample. Must be called on the VM thread. 332 * Recording the forced sample does not contribute to the aggregated 333 * profile statistics. 334 */ 335 V8_DEPRECATED("Use static CollectSample(Isolate*) instead.", 336 void CollectSample()); 337 338 /** 339 * Tells the profiler whether the embedder is idle. 340 */ 341 V8_DEPRECATED("Use Isolate::SetIdle(bool) instead.", 342 void SetIdle(bool is_idle)); 343 344 private: 345 CpuProfiler(); 346 ~CpuProfiler(); 347 CpuProfiler(const CpuProfiler&); 348 CpuProfiler& operator=(const CpuProfiler&); 349 }; 350 351 352 /** 353 * HeapSnapshotEdge represents a directed connection between heap 354 * graph nodes: from retainers to retained nodes. 355 */ 356 class V8_EXPORT HeapGraphEdge { 357 public: 358 enum Type { 359 kContextVariable = 0, // A variable from a function context. 360 kElement = 1, // An element of an array. 361 kProperty = 2, // A named object property. 362 kInternal = 3, // A link that can't be accessed from JS, 363 // thus, its name isn't a real property name 364 // (e.g. parts of a ConsString). 365 kHidden = 4, // A link that is needed for proper sizes 366 // calculation, but may be hidden from user. 367 kShortcut = 5, // A link that must not be followed during 368 // sizes calculation. 369 kWeak = 6 // A weak reference (ignored by the GC). 370 }; 371 372 /** Returns edge type (see HeapGraphEdge::Type). */ 373 Type GetType() const; 374 375 /** 376 * Returns edge name. This can be a variable name, an element index, or 377 * a property name. 378 */ 379 Local<Value> GetName() const; 380 381 /** Returns origin node. */ 382 const HeapGraphNode* GetFromNode() const; 383 384 /** Returns destination node. */ 385 const HeapGraphNode* GetToNode() const; 386 }; 387 388 389 /** 390 * HeapGraphNode represents a node in a heap graph. 391 */ 392 class V8_EXPORT HeapGraphNode { 393 public: 394 enum Type { 395 kHidden = 0, // Hidden node, may be filtered when shown to user. 396 kArray = 1, // An array of elements. 397 kString = 2, // A string. 398 kObject = 3, // A JS object (except for arrays and strings). 399 kCode = 4, // Compiled code. 400 kClosure = 5, // Function closure. 401 kRegExp = 6, // RegExp. 402 kHeapNumber = 7, // Number stored in the heap. 403 kNative = 8, // Native object (not from V8 heap). 404 kSynthetic = 9, // Synthetic object, usually used for grouping 405 // snapshot items together. 406 kConsString = 10, // Concatenated string. A pair of pointers to strings. 407 kSlicedString = 11, // Sliced string. A fragment of another string. 408 kSymbol = 12, // A Symbol (ES6). 409 kBigInt = 13 // BigInt. 410 }; 411 412 /** Returns node type (see HeapGraphNode::Type). */ 413 Type GetType() const; 414 415 /** 416 * Returns node name. Depending on node's type this can be the name 417 * of the constructor (for objects), the name of the function (for 418 * closures), string value, or an empty string (for compiled code). 419 */ 420 Local<String> GetName() const; 421 422 /** 423 * Returns node id. For the same heap object, the id remains the same 424 * across all snapshots. 425 */ 426 SnapshotObjectId GetId() const; 427 428 /** Returns node's own size, in bytes. */ 429 size_t GetShallowSize() const; 430 431 /** Returns child nodes count of the node. */ 432 int GetChildrenCount() const; 433 434 /** Retrieves a child by index. */ 435 const HeapGraphEdge* GetChild(int index) const; 436 }; 437 438 439 /** 440 * An interface for exporting data from V8, using "push" model. 441 */ 442 class V8_EXPORT OutputStream { // NOLINT 443 public: 444 enum WriteResult { 445 kContinue = 0, 446 kAbort = 1 447 }; 448 virtual ~OutputStream() {} 449 /** Notify about the end of stream. */ 450 virtual void EndOfStream() = 0; 451 /** Get preferred output chunk size. Called only once. */ 452 virtual int GetChunkSize() { return 1024; } 453 /** 454 * Writes the next chunk of snapshot data into the stream. Writing 455 * can be stopped by returning kAbort as function result. EndOfStream 456 * will not be called in case writing was aborted. 457 */ 458 virtual WriteResult WriteAsciiChunk(char* data, int size) = 0; 459 /** 460 * Writes the next chunk of heap stats data into the stream. Writing 461 * can be stopped by returning kAbort as function result. EndOfStream 462 * will not be called in case writing was aborted. 463 */ 464 virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) { 465 return kAbort; 466 } 467 }; 468 469 470 /** 471 * HeapSnapshots record the state of the JS heap at some moment. 472 */ 473 class V8_EXPORT HeapSnapshot { 474 public: 475 enum SerializationFormat { 476 kJSON = 0 // See format description near 'Serialize' method. 477 }; 478 479 /** Returns the root node of the heap graph. */ 480 const HeapGraphNode* GetRoot() const; 481 482 /** Returns a node by its id. */ 483 const HeapGraphNode* GetNodeById(SnapshotObjectId id) const; 484 485 /** Returns total nodes count in the snapshot. */ 486 int GetNodesCount() const; 487 488 /** Returns a node by index. */ 489 const HeapGraphNode* GetNode(int index) const; 490 491 /** Returns a max seen JS object Id. */ 492 SnapshotObjectId GetMaxSnapshotJSObjectId() const; 493 494 /** 495 * Deletes the snapshot and removes it from HeapProfiler's list. 496 * All pointers to nodes, edges and paths previously returned become 497 * invalid. 498 */ 499 void Delete(); 500 501 /** 502 * Prepare a serialized representation of the snapshot. The result 503 * is written into the stream provided in chunks of specified size. 504 * The total length of the serialized snapshot is unknown in 505 * advance, it can be roughly equal to JS heap size (that means, 506 * it can be really big - tens of megabytes). 507 * 508 * For the JSON format, heap contents are represented as an object 509 * with the following structure: 510 * 511 * { 512 * snapshot: { 513 * title: "...", 514 * uid: nnn, 515 * meta: { meta-info }, 516 * node_count: nnn, 517 * edge_count: nnn 518 * }, 519 * nodes: [nodes array], 520 * edges: [edges array], 521 * strings: [strings array] 522 * } 523 * 524 * Nodes reference strings, other nodes, and edges by their indexes 525 * in corresponding arrays. 526 */ 527 void Serialize(OutputStream* stream, 528 SerializationFormat format = kJSON) const; 529 }; 530 531 532 /** 533 * An interface for reporting progress and controlling long-running 534 * activities. 535 */ 536 class V8_EXPORT ActivityControl { // NOLINT 537 public: 538 enum ControlOption { 539 kContinue = 0, 540 kAbort = 1 541 }; 542 virtual ~ActivityControl() {} 543 /** 544 * Notify about current progress. The activity can be stopped by 545 * returning kAbort as the callback result. 546 */ 547 virtual ControlOption ReportProgressValue(int done, int total) = 0; 548 }; 549 550 551 /** 552 * AllocationProfile is a sampled profile of allocations done by the program. 553 * This is structured as a call-graph. 554 */ 555 class V8_EXPORT AllocationProfile { 556 public: 557 struct Allocation { 558 /** 559 * Size of the sampled allocation object. 560 */ 561 size_t size; 562 563 /** 564 * The number of objects of such size that were sampled. 565 */ 566 unsigned int count; 567 }; 568 569 /** 570 * Represents a node in the call-graph. 571 */ 572 struct Node { 573 /** 574 * Name of the function. May be empty for anonymous functions or if the 575 * script corresponding to this function has been unloaded. 576 */ 577 Local<String> name; 578 579 /** 580 * Name of the script containing the function. May be empty if the script 581 * name is not available, or if the script has been unloaded. 582 */ 583 Local<String> script_name; 584 585 /** 586 * id of the script where the function is located. May be equal to 587 * v8::UnboundScript::kNoScriptId in cases where the script doesn't exist. 588 */ 589 int script_id; 590 591 /** 592 * Start position of the function in the script. 593 */ 594 int start_position; 595 596 /** 597 * 1-indexed line number where the function starts. May be 598 * kNoLineNumberInfo if no line number information is available. 599 */ 600 int line_number; 601 602 /** 603 * 1-indexed column number where the function starts. May be 604 * kNoColumnNumberInfo if no line number information is available. 605 */ 606 int column_number; 607 608 /** 609 * List of callees called from this node for which we have sampled 610 * allocations. The lifetime of the children is scoped to the containing 611 * AllocationProfile. 612 */ 613 std::vector<Node*> children; 614 615 /** 616 * List of self allocations done by this node in the call-graph. 617 */ 618 std::vector<Allocation> allocations; 619 }; 620 621 /** 622 * Returns the root node of the call-graph. The root node corresponds to an 623 * empty JS call-stack. The lifetime of the returned Node* is scoped to the 624 * containing AllocationProfile. 625 */ 626 virtual Node* GetRootNode() = 0; 627 628 virtual ~AllocationProfile() {} 629 630 static const int kNoLineNumberInfo = Message::kNoLineNumberInfo; 631 static const int kNoColumnNumberInfo = Message::kNoColumnInfo; 632 }; 633 634 /** 635 * An object graph consisting of embedder objects and V8 objects. 636 * Edges of the graph are strong references between the objects. 637 * The embedder can build this graph during heap snapshot generation 638 * to include the embedder objects in the heap snapshot. 639 * Usage: 640 * 1) Define derived class of EmbedderGraph::Node for embedder objects. 641 * 2) Set the build embedder graph callback on the heap profiler using 642 * HeapProfiler::AddBuildEmbedderGraphCallback. 643 * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from 644 * node1 to node2. 645 * 4) To represent references from/to V8 object, construct V8 nodes using 646 * graph->V8Node(value). 647 */ 648 class V8_EXPORT EmbedderGraph { 649 public: 650 class Node { 651 public: 652 Node() = default; 653 virtual ~Node() = default; 654 virtual const char* Name() = 0; 655 virtual size_t SizeInBytes() = 0; 656 /** 657 * The corresponding V8 wrapper node if not null. 658 * During heap snapshot generation the embedder node and the V8 wrapper 659 * node will be merged into one node to simplify retaining paths. 660 */ 661 virtual Node* WrapperNode() { return nullptr; } 662 virtual bool IsRootNode() { return false; } 663 /** Must return true for non-V8 nodes. */ 664 virtual bool IsEmbedderNode() { return true; } 665 /** 666 * Optional name prefix. It is used in Chrome for tagging detached nodes. 667 */ 668 virtual const char* NamePrefix() { return nullptr; } 669 670 private: 671 Node(const Node&) = delete; 672 Node& operator=(const Node&) = delete; 673 }; 674 675 /** 676 * Returns a node corresponding to the given V8 value. Ownership is not 677 * transferred. The result pointer is valid while the graph is alive. 678 */ 679 virtual Node* V8Node(const v8::Local<v8::Value>& value) = 0; 680 681 /** 682 * Adds the given node to the graph and takes ownership of the node. 683 * Returns a raw pointer to the node that is valid while the graph is alive. 684 */ 685 virtual Node* AddNode(std::unique_ptr<Node> node) = 0; 686 687 /** 688 * Adds an edge that represents a strong reference from the given 689 * node |from| to the given node |to|. The nodes must be added to the graph 690 * before calling this function. 691 * 692 * If name is nullptr, the edge will have auto-increment indexes, otherwise 693 * it will be named accordingly. 694 */ 695 virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0; 696 697 virtual ~EmbedderGraph() = default; 698 }; 699 700 /** 701 * Interface for controlling heap profiling. Instance of the 702 * profiler can be retrieved using v8::Isolate::GetHeapProfiler. 703 */ 704 class V8_EXPORT HeapProfiler { 705 public: 706 enum SamplingFlags { 707 kSamplingNoFlags = 0, 708 kSamplingForceGC = 1 << 0, 709 }; 710 711 typedef std::unordered_set<const v8::PersistentBase<v8::Value>*> 712 RetainerChildren; 713 typedef std::vector<std::pair<v8::RetainedObjectInfo*, RetainerChildren>> 714 RetainerGroups; 715 typedef std::vector<std::pair<const v8::PersistentBase<v8::Value>*, 716 const v8::PersistentBase<v8::Value>*>> 717 RetainerEdges; 718 719 struct RetainerInfos { 720 RetainerGroups groups; 721 RetainerEdges edges; 722 }; 723 724 /** 725 * Callback function invoked to retrieve all RetainerInfos from the embedder. 726 */ 727 typedef RetainerInfos (*GetRetainerInfosCallback)(v8::Isolate* isolate); 728 729 /** 730 * Callback function invoked for obtaining RetainedObjectInfo for 731 * the given JavaScript wrapper object. It is prohibited to enter V8 732 * while the callback is running: only getters on the handle and 733 * GetPointerFromInternalField on the objects are allowed. 734 */ 735 typedef RetainedObjectInfo* (*WrapperInfoCallback)(uint16_t class_id, 736 Local<Value> wrapper); 737 738 /** 739 * Callback function invoked during heap snapshot generation to retrieve 740 * the embedder object graph. The callback should use graph->AddEdge(..) to 741 * add references between the objects. 742 * The callback must not trigger garbage collection in V8. 743 */ 744 typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate, 745 v8::EmbedderGraph* graph, 746 void* data); 747 748 /** TODO(addaleax): Remove */ 749 typedef void (*LegacyBuildEmbedderGraphCallback)(v8::Isolate* isolate, 750 v8::EmbedderGraph* graph); 751 752 /** Returns the number of snapshots taken. */ 753 int GetSnapshotCount(); 754 755 /** Returns a snapshot by index. */ 756 const HeapSnapshot* GetHeapSnapshot(int index); 757 758 /** 759 * Returns SnapshotObjectId for a heap object referenced by |value| if 760 * it has been seen by the heap profiler, kUnknownObjectId otherwise. 761 */ 762 SnapshotObjectId GetObjectId(Local<Value> value); 763 764 /** 765 * Returns heap object with given SnapshotObjectId if the object is alive, 766 * otherwise empty handle is returned. 767 */ 768 Local<Value> FindObjectById(SnapshotObjectId id); 769 770 /** 771 * Clears internal map from SnapshotObjectId to heap object. The new objects 772 * will not be added into it unless a heap snapshot is taken or heap object 773 * tracking is kicked off. 774 */ 775 void ClearObjectIds(); 776 777 /** 778 * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return 779 * it in case heap profiler cannot find id for the object passed as 780 * parameter. HeapSnapshot::GetNodeById will always return NULL for such id. 781 */ 782 static const SnapshotObjectId kUnknownObjectId = 0; 783 784 /** 785 * Callback interface for retrieving user friendly names of global objects. 786 */ 787 class ObjectNameResolver { 788 public: 789 /** 790 * Returns name to be used in the heap snapshot for given node. Returned 791 * string must stay alive until snapshot collection is completed. 792 */ 793 virtual const char* GetName(Local<Object> object) = 0; 794 795 protected: 796 virtual ~ObjectNameResolver() {} 797 }; 798 799 /** 800 * Takes a heap snapshot and returns it. 801 */ 802 const HeapSnapshot* TakeHeapSnapshot( 803 ActivityControl* control = NULL, 804 ObjectNameResolver* global_object_name_resolver = NULL); 805 806 /** 807 * Starts tracking of heap objects population statistics. After calling 808 * this method, all heap objects relocations done by the garbage collector 809 * are being registered. 810 * 811 * |track_allocations| parameter controls whether stack trace of each 812 * allocation in the heap will be recorded and reported as part of 813 * HeapSnapshot. 814 */ 815 void StartTrackingHeapObjects(bool track_allocations = false); 816 817 /** 818 * Adds a new time interval entry to the aggregated statistics array. The 819 * time interval entry contains information on the current heap objects 820 * population size. The method also updates aggregated statistics and 821 * reports updates for all previous time intervals via the OutputStream 822 * object. Updates on each time interval are provided as a stream of the 823 * HeapStatsUpdate structure instances. 824 * If |timestamp_us| is supplied, timestamp of the new entry will be written 825 * into it. The return value of the function is the last seen heap object Id. 826 * 827 * StartTrackingHeapObjects must be called before the first call to this 828 * method. 829 */ 830 SnapshotObjectId GetHeapStats(OutputStream* stream, 831 int64_t* timestamp_us = NULL); 832 833 /** 834 * Stops tracking of heap objects population statistics, cleans up all 835 * collected data. StartHeapObjectsTracking must be called again prior to 836 * calling GetHeapStats next time. 837 */ 838 void StopTrackingHeapObjects(); 839 840 /** 841 * Starts gathering a sampling heap profile. A sampling heap profile is 842 * similar to tcmalloc's heap profiler and Go's mprof. It samples object 843 * allocations and builds an online 'sampling' heap profile. At any point in 844 * time, this profile is expected to be a representative sample of objects 845 * currently live in the system. Each sampled allocation includes the stack 846 * trace at the time of allocation, which makes this really useful for memory 847 * leak detection. 848 * 849 * This mechanism is intended to be cheap enough that it can be used in 850 * production with minimal performance overhead. 851 * 852 * Allocations are sampled using a randomized Poisson process. On average, one 853 * allocation will be sampled every |sample_interval| bytes allocated. The 854 * |stack_depth| parameter controls the maximum number of stack frames to be 855 * captured on each allocation. 856 * 857 * NOTE: This is a proof-of-concept at this point. Right now we only sample 858 * newspace allocations. Support for paged space allocation (e.g. pre-tenured 859 * objects, large objects, code objects, etc.) and native allocations 860 * doesn't exist yet, but is anticipated in the future. 861 * 862 * Objects allocated before the sampling is started will not be included in 863 * the profile. 864 * 865 * Returns false if a sampling heap profiler is already running. 866 */ 867 bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024, 868 int stack_depth = 16, 869 SamplingFlags flags = kSamplingNoFlags); 870 871 /** 872 * Stops the sampling heap profile and discards the current profile. 873 */ 874 void StopSamplingHeapProfiler(); 875 876 /** 877 * Returns the sampled profile of allocations allocated (and still live) since 878 * StartSamplingHeapProfiler was called. The ownership of the pointer is 879 * transferred to the caller. Returns nullptr if sampling heap profiler is not 880 * active. 881 */ 882 AllocationProfile* GetAllocationProfile(); 883 884 /** 885 * Deletes all snapshots taken. All previously returned pointers to 886 * snapshots and their contents become invalid after this call. 887 */ 888 void DeleteAllHeapSnapshots(); 889 890 /** Binds a callback to embedder's class ID. */ 891 V8_DEPRECATED( 892 "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", 893 void SetWrapperClassInfoProvider(uint16_t class_id, 894 WrapperInfoCallback callback)); 895 896 V8_DEPRECATED( 897 "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", 898 void SetGetRetainerInfosCallback(GetRetainerInfosCallback callback)); 899 900 V8_DEPRECATED( 901 "Use AddBuildEmbedderGraphCallback to provide info about embedder nodes", 902 void SetBuildEmbedderGraphCallback( 903 LegacyBuildEmbedderGraphCallback callback)); 904 void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, 905 void* data); 906 void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback, 907 void* data); 908 909 /** 910 * Default value of persistent handle class ID. Must not be used to 911 * define a class. Can be used to reset a class of a persistent 912 * handle. 913 */ 914 static const uint16_t kPersistentHandleNoClassId = 0; 915 916 private: 917 HeapProfiler(); 918 ~HeapProfiler(); 919 HeapProfiler(const HeapProfiler&); 920 HeapProfiler& operator=(const HeapProfiler&); 921 }; 922 923 /** 924 * Interface for providing information about embedder's objects 925 * held by global handles. This information is reported in two ways: 926 * 927 * 1. When calling AddObjectGroup, an embedder may pass 928 * RetainedObjectInfo instance describing the group. To collect 929 * this information while taking a heap snapshot, V8 calls GC 930 * prologue and epilogue callbacks. 931 * 932 * 2. When a heap snapshot is collected, V8 additionally 933 * requests RetainedObjectInfos for persistent handles that 934 * were not previously reported via AddObjectGroup. 935 * 936 * Thus, if an embedder wants to provide information about native 937 * objects for heap snapshots, it can do it in a GC prologue 938 * handler, and / or by assigning wrapper class ids in the following way: 939 * 940 * 1. Bind a callback to class id by calling SetWrapperClassInfoProvider. 941 * 2. Call SetWrapperClassId on certain persistent handles. 942 * 943 * V8 takes ownership of RetainedObjectInfo instances passed to it and 944 * keeps them alive only during snapshot collection. Afterwards, they 945 * are freed by calling the Dispose class function. 946 */ 947 class V8_EXPORT RetainedObjectInfo { // NOLINT 948 public: 949 /** Called by V8 when it no longer needs an instance. */ 950 virtual void Dispose() = 0; 951 952 /** Returns whether two instances are equivalent. */ 953 virtual bool IsEquivalent(RetainedObjectInfo* other) = 0; 954 955 /** 956 * Returns hash value for the instance. Equivalent instances 957 * must have the same hash value. 958 */ 959 virtual intptr_t GetHash() = 0; 960 961 /** 962 * Returns human-readable label. It must be a null-terminated UTF-8 963 * encoded string. V8 copies its contents during a call to GetLabel. 964 */ 965 virtual const char* GetLabel() = 0; 966 967 /** 968 * Returns human-readable group label. It must be a null-terminated UTF-8 969 * encoded string. V8 copies its contents during a call to GetGroupLabel. 970 * Heap snapshot generator will collect all the group names, create 971 * top level entries with these names and attach the objects to the 972 * corresponding top level group objects. There is a default 973 * implementation which is required because embedders don't have their 974 * own implementation yet. 975 */ 976 virtual const char* GetGroupLabel() { return GetLabel(); } 977 978 /** 979 * Returns element count in case if a global handle retains 980 * a subgraph by holding one of its nodes. 981 */ 982 virtual intptr_t GetElementCount() { return -1; } 983 984 /** Returns embedder's object size in bytes. */ 985 virtual intptr_t GetSizeInBytes() { return -1; } 986 987 protected: 988 RetainedObjectInfo() {} 989 virtual ~RetainedObjectInfo() {} 990 991 private: 992 RetainedObjectInfo(const RetainedObjectInfo&); 993 RetainedObjectInfo& operator=(const RetainedObjectInfo&); 994 }; 995 996 997 /** 998 * A struct for exporting HeapStats data from V8, using "push" model. 999 * See HeapProfiler::GetHeapStats. 1000 */ 1001 struct HeapStatsUpdate { 1002 HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size) 1003 : index(index), count(count), size(size) { } 1004 uint32_t index; // Index of the time interval that was changed. 1005 uint32_t count; // New value of count field for the interval with this index. 1006 uint32_t size; // New value of size field for the interval with this index. 1007 }; 1008 1009 #define CODE_EVENTS_LIST(V) \ 1010 V(Builtin) \ 1011 V(Callback) \ 1012 V(Eval) \ 1013 V(Function) \ 1014 V(InterpretedFunction) \ 1015 V(Handler) \ 1016 V(BytecodeHandler) \ 1017 V(LazyCompile) \ 1018 V(RegExp) \ 1019 V(Script) \ 1020 V(Stub) 1021 1022 /** 1023 * Note that this enum may be extended in the future. Please include a default 1024 * case if this enum is used in a switch statement. 1025 */ 1026 enum CodeEventType { 1027 kUnknownType = 0 1028 #define V(Name) , k##Name##Type 1029 CODE_EVENTS_LIST(V) 1030 #undef V 1031 }; 1032 1033 /** 1034 * Representation of a code creation event 1035 */ 1036 class V8_EXPORT CodeEvent { 1037 public: 1038 uintptr_t GetCodeStartAddress(); 1039 size_t GetCodeSize(); 1040 Local<String> GetFunctionName(); 1041 Local<String> GetScriptName(); 1042 int GetScriptLine(); 1043 int GetScriptColumn(); 1044 /** 1045 * NOTE (mmarchini): We can't allocate objects in the heap when we collect 1046 * existing code, and both the code type and the comment are not stored in the 1047 * heap, so we return those as const char*. 1048 */ 1049 CodeEventType GetCodeType(); 1050 const char* GetComment(); 1051 1052 static const char* GetCodeEventTypeName(CodeEventType code_event_type); 1053 }; 1054 1055 /** 1056 * Interface to listen to code creation events. 1057 */ 1058 class V8_EXPORT CodeEventHandler { 1059 public: 1060 /** 1061 * Creates a new listener for the |isolate|. The isolate must be initialized. 1062 * The listener object must be disposed after use by calling |Dispose| method. 1063 * Multiple listeners can be created for the same isolate. 1064 */ 1065 explicit CodeEventHandler(Isolate* isolate); 1066 virtual ~CodeEventHandler(); 1067 1068 virtual void Handle(CodeEvent* code_event) = 0; 1069 1070 void Enable(); 1071 void Disable(); 1072 1073 private: 1074 CodeEventHandler(); 1075 CodeEventHandler(const CodeEventHandler&); 1076 CodeEventHandler& operator=(const CodeEventHandler&); 1077 void* internal_listener_; 1078 }; 1079 1080 } // namespace v8 1081 1082 1083 #endif // V8_V8_PROFILER_H_ 1084