Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:05:26

0001 // Copyright 2010 the V8 project authors. All rights reserved.
0002 // Use of this source code is governed by a BSD-style license that can be
0003 // found in the LICENSE file.
0004 
0005 #ifndef V8_V8_PROFILER_H_
0006 #define V8_V8_PROFILER_H_
0007 
0008 #include <limits.h>
0009 
0010 #include <memory>
0011 #include <unordered_set>
0012 #include <vector>
0013 
0014 #include "cppgc/common.h"          // NOLINT(build/include_directory)
0015 #include "v8-local-handle.h"       // NOLINT(build/include_directory)
0016 #include "v8-message.h"            // NOLINT(build/include_directory)
0017 #include "v8-persistent-handle.h"  // NOLINT(build/include_directory)
0018 
0019 /**
0020  * Profiler support for the V8 JavaScript engine.
0021  */
0022 namespace v8 {
0023 
0024 enum class EmbedderStateTag : uint8_t;
0025 class HeapGraphNode;
0026 struct HeapStatsUpdate;
0027 class Object;
0028 enum StateTag : uint16_t;
0029 
0030 using NativeObject = void*;
0031 using SnapshotObjectId = uint32_t;
0032 using ProfilerId = uint32_t;
0033 
0034 struct CpuProfileDeoptFrame {
0035   int script_id;
0036   size_t position;
0037 };
0038 
0039 namespace internal {
0040 class CpuProfile;
0041 }  // namespace internal
0042 
0043 }  // namespace v8
0044 
0045 #ifdef V8_OS_WIN
0046 template class V8_EXPORT std::vector<v8::CpuProfileDeoptFrame>;
0047 #endif
0048 
0049 namespace v8 {
0050 
0051 struct V8_EXPORT CpuProfileDeoptInfo {
0052   /** A pointer to a static string owned by v8. */
0053   const char* deopt_reason;
0054   std::vector<CpuProfileDeoptFrame> stack;
0055 };
0056 
0057 }  // namespace v8
0058 
0059 #ifdef V8_OS_WIN
0060 template class V8_EXPORT std::vector<v8::CpuProfileDeoptInfo>;
0061 #endif
0062 
0063 namespace v8 {
0064 
0065 /**
0066  * CpuProfileNode represents a node in a call graph.
0067  */
0068 class V8_EXPORT CpuProfileNode {
0069  public:
0070   struct LineTick {
0071     /** The 1-based number of the source line where the function originates. */
0072     int line;
0073 
0074     /** The count of samples associated with the source line. */
0075     unsigned int hit_count;
0076   };
0077 
0078   // An annotation hinting at the source of a CpuProfileNode.
0079   enum SourceType {
0080     // User-supplied script with associated resource information.
0081     kScript = 0,
0082     // Native scripts and provided builtins.
0083     kBuiltin = 1,
0084     // Callbacks into native code.
0085     kCallback = 2,
0086     // VM-internal functions or state.
0087     kInternal = 3,
0088     // A node that failed to symbolize.
0089     kUnresolved = 4,
0090   };
0091 
0092   /** Returns function name (empty string for anonymous functions.) */
0093   Local<String> GetFunctionName() const;
0094 
0095   /**
0096    * Returns function name (empty string for anonymous functions.)
0097    * The string ownership is *not* passed to the caller. It stays valid until
0098    * profile is deleted. The function is thread safe.
0099    */
0100   const char* GetFunctionNameStr() const;
0101 
0102   /** Returns id of the script where function is located. */
0103   int GetScriptId() const;
0104 
0105   /** Returns resource name for script from where the function originates. */
0106   Local<String> GetScriptResourceName() const;
0107 
0108   /**
0109    * Returns resource name for script from where the function originates.
0110    * The string ownership is *not* passed to the caller. It stays valid until
0111    * profile is deleted. The function is thread safe.
0112    */
0113   const char* GetScriptResourceNameStr() const;
0114 
0115   /**
0116    * Return true if the script from where the function originates is flagged as
0117    * being shared cross-origin.
0118    */
0119   bool IsScriptSharedCrossOrigin() const;
0120 
0121   /**
0122    * Returns the number, 1-based, of the line where the function originates.
0123    * kNoLineNumberInfo if no line number information is available.
0124    */
0125   int GetLineNumber() const;
0126 
0127   /**
0128    * Returns 1-based number of the column where the function originates.
0129    * kNoColumnNumberInfo if no column number information is available.
0130    */
0131   int GetColumnNumber() const;
0132 
0133   /**
0134    * Returns the number of the function's source lines that collect the samples.
0135    */
0136   unsigned int GetHitLineCount() const;
0137 
0138   /** Returns the set of source lines that collect the samples.
0139    *  The caller allocates buffer and responsible for releasing it.
0140    *  True if all available entries are copied, otherwise false.
0141    *  The function copies nothing if buffer is not large enough.
0142    */
0143   bool GetLineTicks(LineTick* entries, unsigned int length) const;
0144 
0145   /** Returns bailout reason for the function
0146     * if the optimization was disabled for it.
0147     */
0148   const char* GetBailoutReason() const;
0149 
0150   /**
0151     * Returns the count of samples where the function was currently executing.
0152     */
0153   unsigned GetHitCount() const;
0154 
0155   /** Returns id of the node. The id is unique within the tree */
0156   unsigned GetNodeId() const;
0157 
0158   /**
0159    * Gets the type of the source which the node was captured from.
0160    */
0161   SourceType GetSourceType() const;
0162 
0163   /** Returns child nodes count of the node. */
0164   int GetChildrenCount() const;
0165 
0166   /** Retrieves a child node by index. */
0167   const CpuProfileNode* GetChild(int index) const;
0168 
0169   /** Retrieves the ancestor node, or null if the root. */
0170   const CpuProfileNode* GetParent() const;
0171 
0172   /** Retrieves deopt infos for the node. */
0173   const std::vector<CpuProfileDeoptInfo>& GetDeoptInfos() const;
0174 
0175   static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
0176   static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
0177 };
0178 
0179 /**
0180  * An interface for exporting data from V8, using "push" model.
0181  */
0182 class V8_EXPORT OutputStream {
0183  public:
0184   enum WriteResult { kContinue = 0, kAbort = 1 };
0185   virtual ~OutputStream() = default;
0186   /** Notify about the end of stream. */
0187   virtual void EndOfStream() = 0;
0188   /** Get preferred output chunk size. Called only once. */
0189   virtual int GetChunkSize() { return 1024; }
0190   /**
0191    * Writes the next chunk of snapshot data into the stream. Writing
0192    * can be stopped by returning kAbort as function result. EndOfStream
0193    * will not be called in case writing was aborted.
0194    */
0195   virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
0196   /**
0197    * Writes the next chunk of heap stats data into the stream. Writing
0198    * can be stopped by returning kAbort as function result. EndOfStream
0199    * will not be called in case writing was aborted.
0200    */
0201   virtual WriteResult WriteHeapStatsChunk(HeapStatsUpdate* data, int count) {
0202     return kAbort;
0203   }
0204 };
0205 
0206 /**
0207  * CpuProfile contains a CPU profile in a form of top-down call tree
0208  * (from main() down to functions that do all the work).
0209  */
0210 class V8_EXPORT CpuProfile {
0211  public:
0212   enum SerializationFormat {
0213     kJSON = 0  // See format description near 'Serialize' method.
0214   };
0215   /** Returns CPU profile title. */
0216   Local<String> GetTitle() const;
0217 
0218   /** Returns the root node of the top down call tree. */
0219   const CpuProfileNode* GetTopDownRoot() const;
0220 
0221   /**
0222    * Returns number of samples recorded. The samples are not recorded unless
0223    * |record_samples| parameter of CpuProfiler::StartCpuProfiling is true.
0224    */
0225   int GetSamplesCount() const;
0226 
0227   /**
0228    * Returns profile node corresponding to the top frame the sample at
0229    * the given index.
0230    */
0231   const CpuProfileNode* GetSample(int index) const;
0232 
0233   /**
0234    * Returns the timestamp of the sample. The timestamp is the number of
0235    * microseconds since some unspecified starting point.
0236    * The point is equal to the starting point used by GetStartTime.
0237    */
0238   int64_t GetSampleTimestamp(int index) const;
0239 
0240   /**
0241    * Returns time when the profile recording was started (in microseconds)
0242    * since some unspecified starting point.
0243    */
0244   int64_t GetStartTime() const;
0245 
0246   /**
0247    * Returns state of the vm when sample was captured.
0248    */
0249   StateTag GetSampleState(int index) const;
0250 
0251   /**
0252    * Returns state of the embedder when sample was captured.
0253    */
0254   EmbedderStateTag GetSampleEmbedderState(int index) const;
0255 
0256   /**
0257    * Returns time when the profile recording was stopped (in microseconds)
0258    * since some unspecified starting point.
0259    * The point is equal to the starting point used by GetStartTime.
0260    */
0261   int64_t GetEndTime() const;
0262 
0263   /**
0264    * Deletes the profile and removes it from CpuProfiler's list.
0265    * All pointers to nodes previously returned become invalid.
0266    */
0267   void Delete();
0268 
0269   /**
0270    * Prepare a serialized representation of the profile. The result
0271    * is written into the stream provided in chunks of specified size.
0272    *
0273    * For the JSON format, heap contents are represented as an object
0274    * with the following structure:
0275    *
0276    *  {
0277    *    nodes: [nodes array],
0278    *    startTime: number,
0279    *    endTime: number
0280    *    samples: [strings array]
0281    *    timeDeltas: [numbers array]
0282    *  }
0283    *
0284    */
0285   void Serialize(OutputStream* stream,
0286                  SerializationFormat format = kJSON) const;
0287 };
0288 
0289 enum CpuProfilingMode {
0290   // In the resulting CpuProfile tree, intermediate nodes in a stack trace
0291   // (from the root to a leaf) will have line numbers that point to the start
0292   // line of the function, rather than the line of the callsite of the child.
0293   kLeafNodeLineNumbers,
0294   // In the resulting CpuProfile tree, nodes are separated based on the line
0295   // number of their callsite in their parent.
0296   kCallerLineNumbers,
0297 };
0298 
0299 // Determines how names are derived for functions sampled.
0300 enum CpuProfilingNamingMode {
0301   // Use the immediate name of functions at compilation time.
0302   kStandardNaming,
0303   // Use more verbose naming for functions without names, inferred from scope
0304   // where possible.
0305   kDebugNaming,
0306 };
0307 
0308 enum CpuProfilingLoggingMode {
0309   // Enables logging when a profile is active, and disables logging when all
0310   // profiles are detached.
0311   kLazyLogging,
0312   // Enables logging for the lifetime of the CpuProfiler. Calls to
0313   // StartRecording are faster, at the expense of runtime overhead.
0314   kEagerLogging,
0315 };
0316 
0317 // Enum for returning profiling status. Once StartProfiling is called,
0318 // we want to return to clients whether the profiling was able to start
0319 // correctly, or return a descriptive error.
0320 enum class CpuProfilingStatus {
0321   kStarted,
0322   kAlreadyStarted,
0323   kErrorTooManyProfilers
0324 };
0325 
0326 /**
0327  * Result from StartProfiling returning the Profiling Status, and
0328  * id of the started profiler, or 0 if profiler is not started
0329  */
0330 struct CpuProfilingResult {
0331   const ProfilerId id;
0332   const CpuProfilingStatus status;
0333 };
0334 
0335 /**
0336  * Delegate for when max samples reached and samples are discarded.
0337  */
0338 class V8_EXPORT DiscardedSamplesDelegate {
0339  public:
0340   DiscardedSamplesDelegate() = default;
0341 
0342   virtual ~DiscardedSamplesDelegate() = default;
0343   virtual void Notify() = 0;
0344 
0345   ProfilerId GetId() const { return profiler_id_; }
0346 
0347  private:
0348   friend internal::CpuProfile;
0349 
0350   void SetId(ProfilerId id) { profiler_id_ = id; }
0351 
0352   ProfilerId profiler_id_;
0353 };
0354 
0355 /**
0356  * Optional profiling attributes.
0357  */
0358 class V8_EXPORT CpuProfilingOptions {
0359  public:
0360   // Indicates that the sample buffer size should not be explicitly limited.
0361   static const unsigned kNoSampleLimit = UINT_MAX;
0362 
0363   /**
0364    * \param mode Type of computation of stack frame line numbers.
0365    * \param max_samples The maximum number of samples that should be recorded by
0366    *                    the profiler. Samples obtained after this limit will be
0367    *                    discarded.
0368    * \param sampling_interval_us controls the profile-specific target
0369    *                             sampling interval. The provided sampling
0370    *                             interval will be snapped to the next lowest
0371    *                             non-zero multiple of the profiler's sampling
0372    *                             interval, set via SetSamplingInterval(). If
0373    *                             zero, the sampling interval will be equal to
0374    *                             the profiler's sampling interval.
0375    * \param filter_context If specified, profiles will only contain frames
0376    *                       using this context. Other frames will be elided.
0377    */
0378   CpuProfilingOptions(
0379       CpuProfilingMode mode = kLeafNodeLineNumbers,
0380       unsigned max_samples = kNoSampleLimit, int sampling_interval_us = 0,
0381       MaybeLocal<Context> filter_context = MaybeLocal<Context>());
0382 
0383   CpuProfilingOptions(CpuProfilingOptions&&) = default;
0384   CpuProfilingOptions& operator=(CpuProfilingOptions&&) = default;
0385 
0386   CpuProfilingMode mode() const { return mode_; }
0387   unsigned max_samples() const { return max_samples_; }
0388   int sampling_interval_us() const { return sampling_interval_us_; }
0389 
0390  private:
0391   friend class internal::CpuProfile;
0392 
0393   bool has_filter_context() const { return !filter_context_.IsEmpty(); }
0394   void* raw_filter_context() const;
0395 
0396   CpuProfilingMode mode_;
0397   unsigned max_samples_;
0398   int sampling_interval_us_;
0399   Global<Context> filter_context_;
0400 };
0401 
0402 /**
0403  * Interface for controlling CPU profiling. Instance of the
0404  * profiler can be created using v8::CpuProfiler::New method.
0405  */
0406 class V8_EXPORT CpuProfiler {
0407  public:
0408   /**
0409    * Creates a new CPU profiler for the |isolate|. The isolate must be
0410    * initialized. The profiler object must be disposed after use by calling
0411    * |Dispose| method.
0412    */
0413   static CpuProfiler* New(Isolate* isolate,
0414                           CpuProfilingNamingMode = kDebugNaming,
0415                           CpuProfilingLoggingMode = kLazyLogging);
0416 
0417   /**
0418    * Synchronously collect current stack sample in all profilers attached to
0419    * the |isolate|. The call does not affect number of ticks recorded for
0420    * the current top node.
0421    */
0422   static void CollectSample(Isolate* isolate);
0423 
0424   /**
0425    * Disposes the CPU profiler object.
0426    */
0427   void Dispose();
0428 
0429   /**
0430    * Changes default CPU profiler sampling interval to the specified number
0431    * of microseconds. Default interval is 1000us. This method must be called
0432    * when there are no profiles being recorded.
0433    */
0434   void SetSamplingInterval(int us);
0435 
0436   /**
0437    * Sets whether or not the profiler should prioritize consistency of sample
0438    * periodicity on Windows. Disabling this can greatly reduce CPU usage, but
0439    * may result in greater variance in sample timings from the platform's
0440    * scheduler. Defaults to enabled. This method must be called when there are
0441    * no profiles being recorded.
0442    */
0443   void SetUsePreciseSampling(bool);
0444 
0445   /**
0446    * Starts collecting a CPU profile. Several profiles may be collected at once.
0447    * Generates an anonymous profiler, without a String identifier.
0448    */
0449   CpuProfilingResult Start(
0450       CpuProfilingOptions options,
0451       std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
0452 
0453   /**
0454    * Starts collecting a CPU profile. Title may be an empty string. Several
0455    * profiles may be collected at once. Attempts to start collecting several
0456    * profiles with the same title are silently ignored.
0457    */
0458   CpuProfilingResult Start(
0459       Local<String> title, CpuProfilingOptions options,
0460       std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
0461 
0462   /**
0463    * Starts profiling with the same semantics as above, except with expanded
0464    * parameters.
0465    *
0466    * |record_samples| parameter controls whether individual samples should
0467    * be recorded in addition to the aggregated tree.
0468    *
0469    * |max_samples| controls the maximum number of samples that should be
0470    * recorded by the profiler. Samples obtained after this limit will be
0471    * discarded.
0472    */
0473   CpuProfilingResult Start(
0474       Local<String> title, CpuProfilingMode mode, bool record_samples = false,
0475       unsigned max_samples = CpuProfilingOptions::kNoSampleLimit);
0476 
0477   /**
0478    * The same as StartProfiling above, but the CpuProfilingMode defaults to
0479    * kLeafNodeLineNumbers mode, which was the previous default behavior of the
0480    * profiler.
0481    */
0482   CpuProfilingResult Start(Local<String> title, bool record_samples = false);
0483 
0484   /**
0485    * Starts collecting a CPU profile. Title may be an empty string. Several
0486    * profiles may be collected at once. Attempts to start collecting several
0487    * profiles with the same title are silently ignored.
0488    */
0489   CpuProfilingStatus StartProfiling(
0490       Local<String> title, CpuProfilingOptions options,
0491       std::unique_ptr<DiscardedSamplesDelegate> delegate = nullptr);
0492 
0493   /**
0494    * Starts profiling with the same semantics as above, except with expanded
0495    * parameters.
0496    *
0497    * |record_samples| parameter controls whether individual samples should
0498    * be recorded in addition to the aggregated tree.
0499    *
0500    * |max_samples| controls the maximum number of samples that should be
0501    * recorded by the profiler. Samples obtained after this limit will be
0502    * discarded.
0503    */
0504   CpuProfilingStatus StartProfiling(
0505       Local<String> title, CpuProfilingMode mode, bool record_samples = false,
0506       unsigned max_samples = CpuProfilingOptions::kNoSampleLimit);
0507 
0508   /**
0509    * The same as StartProfiling above, but the CpuProfilingMode defaults to
0510    * kLeafNodeLineNumbers mode, which was the previous default behavior of the
0511    * profiler.
0512    */
0513   CpuProfilingStatus StartProfiling(Local<String> title,
0514                                     bool record_samples = false);
0515 
0516   /**
0517    * Stops collecting CPU profile with a given id and returns it.
0518    */
0519   CpuProfile* Stop(ProfilerId id);
0520 
0521   /**
0522    * Stops collecting CPU profile with a given title and returns it.
0523    * If the title given is empty, finishes the last profile started.
0524    */
0525   CpuProfile* StopProfiling(Local<String> title);
0526 
0527   /**
0528    * Generate more detailed source positions to code objects. This results in
0529    * better results when mapping profiling samples to script source.
0530    */
0531   static void UseDetailedSourcePositionsForProfiling(Isolate* isolate);
0532 
0533  private:
0534   CpuProfiler();
0535   ~CpuProfiler();
0536   CpuProfiler(const CpuProfiler&);
0537   CpuProfiler& operator=(const CpuProfiler&);
0538 };
0539 
0540 /**
0541  * HeapSnapshotEdge represents a directed connection between heap
0542  * graph nodes: from retainers to retained nodes.
0543  */
0544 class V8_EXPORT HeapGraphEdge {
0545  public:
0546   enum Type {
0547     kContextVariable = 0,  // A variable from a function context.
0548     kElement = 1,          // An element of an array.
0549     kProperty = 2,         // A named object property.
0550     kInternal = 3,         // A link that can't be accessed from JS,
0551                            // thus, its name isn't a real property name
0552                            // (e.g. parts of a ConsString).
0553     kHidden = 4,           // A link that is needed for proper sizes
0554                            // calculation, but may be hidden from user.
0555     kShortcut = 5,         // A link that must not be followed during
0556                            // sizes calculation.
0557     kWeak = 6              // A weak reference (ignored by the GC).
0558   };
0559 
0560   /** Returns edge type (see HeapGraphEdge::Type). */
0561   Type GetType() const;
0562 
0563   /**
0564    * Returns edge name. This can be a variable name, an element index, or
0565    * a property name.
0566    */
0567   Local<Value> GetName() const;
0568 
0569   /** Returns origin node. */
0570   const HeapGraphNode* GetFromNode() const;
0571 
0572   /** Returns destination node. */
0573   const HeapGraphNode* GetToNode() const;
0574 };
0575 
0576 
0577 /**
0578  * HeapGraphNode represents a node in a heap graph.
0579  */
0580 class V8_EXPORT HeapGraphNode {
0581  public:
0582   enum Type {
0583     kHidden = 0,         // Hidden node, may be filtered when shown to user.
0584     kArray = 1,          // An array of elements.
0585     kString = 2,         // A string.
0586     kObject = 3,         // A JS object (except for arrays and strings).
0587     kCode = 4,           // Compiled code.
0588     kClosure = 5,        // Function closure.
0589     kRegExp = 6,         // RegExp.
0590     kHeapNumber = 7,     // Number stored in the heap.
0591     kNative = 8,         // Native object (not from V8 heap).
0592     kSynthetic = 9,      // Synthetic object, usually used for grouping
0593                          // snapshot items together.
0594     kConsString = 10,    // Concatenated string. A pair of pointers to strings.
0595     kSlicedString = 11,  // Sliced string. A fragment of another string.
0596     kSymbol = 12,        // A Symbol (ES6).
0597     kBigInt = 13,        // BigInt.
0598     kObjectShape = 14,   // Internal data used for tracking the shapes (or
0599                          // "hidden classes") of JS objects.
0600   };
0601 
0602   /** Returns node type (see HeapGraphNode::Type). */
0603   Type GetType() const;
0604 
0605   /**
0606    * Returns node name. Depending on node's type this can be the name
0607    * of the constructor (for objects), the name of the function (for
0608    * closures), string value, or an empty string (for compiled code).
0609    */
0610   Local<String> GetName() const;
0611 
0612   /**
0613    * Returns node id. For the same heap object, the id remains the same
0614    * across all snapshots.
0615    */
0616   SnapshotObjectId GetId() const;
0617 
0618   /** Returns node's own size, in bytes. */
0619   size_t GetShallowSize() const;
0620 
0621   /** Returns child nodes count of the node. */
0622   int GetChildrenCount() const;
0623 
0624   /** Retrieves a child by index. */
0625   const HeapGraphEdge* GetChild(int index) const;
0626 };
0627 
0628 /**
0629  * HeapSnapshots record the state of the JS heap at some moment.
0630  */
0631 class V8_EXPORT HeapSnapshot {
0632  public:
0633   enum SerializationFormat {
0634     kJSON = 0  // See format description near 'Serialize' method.
0635   };
0636 
0637   /** Returns the root node of the heap graph. */
0638   const HeapGraphNode* GetRoot() const;
0639 
0640   /** Returns a node by its id. */
0641   const HeapGraphNode* GetNodeById(SnapshotObjectId id) const;
0642 
0643   /** Returns total nodes count in the snapshot. */
0644   int GetNodesCount() const;
0645 
0646   /** Returns a node by index. */
0647   const HeapGraphNode* GetNode(int index) const;
0648 
0649   /** Returns a max seen JS object Id. */
0650   SnapshotObjectId GetMaxSnapshotJSObjectId() const;
0651 
0652   /**
0653    * Deletes the snapshot and removes it from HeapProfiler's list.
0654    * All pointers to nodes, edges and paths previously returned become
0655    * invalid.
0656    */
0657   void Delete();
0658 
0659   /**
0660    * Prepare a serialized representation of the snapshot. The result
0661    * is written into the stream provided in chunks of specified size.
0662    * The total length of the serialized snapshot is unknown in
0663    * advance, it can be roughly equal to JS heap size (that means,
0664    * it can be really big - tens of megabytes).
0665    *
0666    * For the JSON format, heap contents are represented as an object
0667    * with the following structure:
0668    *
0669    *  {
0670    *    snapshot: {
0671    *      title: "...",
0672    *      uid: nnn,
0673    *      meta: { meta-info },
0674    *      node_count: nnn,
0675    *      edge_count: nnn
0676    *    },
0677    *    nodes: [nodes array],
0678    *    edges: [edges array],
0679    *    strings: [strings array]
0680    *  }
0681    *
0682    * Nodes reference strings, other nodes, and edges by their indexes
0683    * in corresponding arrays.
0684    */
0685   void Serialize(OutputStream* stream,
0686                  SerializationFormat format = kJSON) const;
0687 };
0688 
0689 
0690 /**
0691  * An interface for reporting progress and controlling long-running
0692  * activities.
0693  */
0694 class V8_EXPORT ActivityControl {
0695  public:
0696   enum ControlOption {
0697     kContinue = 0,
0698     kAbort = 1
0699   };
0700   virtual ~ActivityControl() = default;
0701   /**
0702    * Notify about current progress. The activity can be stopped by
0703    * returning kAbort as the callback result.
0704    */
0705   virtual ControlOption ReportProgressValue(uint32_t done, uint32_t total) = 0;
0706 };
0707 
0708 /**
0709  * AllocationProfile is a sampled profile of allocations done by the program.
0710  * This is structured as a call-graph.
0711  */
0712 class V8_EXPORT AllocationProfile {
0713  public:
0714   struct Allocation {
0715     /**
0716      * Size of the sampled allocation object.
0717      */
0718     size_t size;
0719 
0720     /**
0721      * The number of objects of such size that were sampled.
0722      */
0723     unsigned int count;
0724   };
0725 
0726   /**
0727    * Represents a node in the call-graph.
0728    */
0729   struct Node {
0730     /**
0731      * Name of the function. May be empty for anonymous functions or if the
0732      * script corresponding to this function has been unloaded.
0733      */
0734     Local<String> name;
0735 
0736     /**
0737      * Name of the script containing the function. May be empty if the script
0738      * name is not available, or if the script has been unloaded.
0739      */
0740     Local<String> script_name;
0741 
0742     /**
0743      * id of the script where the function is located. May be equal to
0744      * v8::UnboundScript::kNoScriptId in cases where the script doesn't exist.
0745      */
0746     int script_id;
0747 
0748     /**
0749      * Start position of the function in the script.
0750      */
0751     int start_position;
0752 
0753     /**
0754      * 1-indexed line number where the function starts. May be
0755      * kNoLineNumberInfo if no line number information is available.
0756      */
0757     int line_number;
0758 
0759     /**
0760      * 1-indexed column number where the function starts. May be
0761      * kNoColumnNumberInfo if no line number information is available.
0762      */
0763     int column_number;
0764 
0765     /**
0766      * Unique id of the node.
0767      */
0768     uint32_t node_id;
0769 
0770     /**
0771      * List of callees called from this node for which we have sampled
0772      * allocations. The lifetime of the children is scoped to the containing
0773      * AllocationProfile.
0774      */
0775     std::vector<Node*> children;
0776 
0777     /**
0778      * List of self allocations done by this node in the call-graph.
0779      */
0780     std::vector<Allocation> allocations;
0781   };
0782 
0783   /**
0784    * Represent a single sample recorded for an allocation.
0785    */
0786   struct Sample {
0787     /**
0788      * id of the node in the profile tree.
0789      */
0790     uint32_t node_id;
0791 
0792     /**
0793      * Size of the sampled allocation object.
0794      */
0795     size_t size;
0796 
0797     /**
0798      * The number of objects of such size that were sampled.
0799      */
0800     unsigned int count;
0801 
0802     /**
0803      * Unique time-ordered id of the allocation sample. Can be used to track
0804      * what samples were added or removed between two snapshots.
0805      */
0806     uint64_t sample_id;
0807   };
0808 
0809   /**
0810    * Returns the root node of the call-graph. The root node corresponds to an
0811    * empty JS call-stack. The lifetime of the returned Node* is scoped to the
0812    * containing AllocationProfile.
0813    */
0814   virtual Node* GetRootNode() = 0;
0815   virtual const std::vector<Sample>& GetSamples() = 0;
0816 
0817   virtual ~AllocationProfile() = default;
0818 
0819   static const int kNoLineNumberInfo = Message::kNoLineNumberInfo;
0820   static const int kNoColumnNumberInfo = Message::kNoColumnInfo;
0821 };
0822 
0823 /**
0824  * An object graph consisting of embedder objects and V8 objects.
0825  * Edges of the graph are strong references between the objects.
0826  * The embedder can build this graph during heap snapshot generation
0827  * to include the embedder objects in the heap snapshot.
0828  * Usage:
0829  * 1) Define derived class of EmbedderGraph::Node for embedder objects.
0830  * 2) Set the build embedder graph callback on the heap profiler using
0831  *    HeapProfiler::AddBuildEmbedderGraphCallback.
0832  * 3) In the callback use graph->AddEdge(node1, node2) to add an edge from
0833  *    node1 to node2.
0834  * 4) To represent references from/to V8 object, construct V8 nodes using
0835  *    graph->V8Node(value).
0836  */
0837 class V8_EXPORT EmbedderGraph {
0838  public:
0839   class Node {
0840    public:
0841     /**
0842      * Detachedness specifies whether an object is attached or detached from the
0843      * main application state. While unkown in general, there may be objects
0844      * that specifically know their state. V8 passes this information along in
0845      * the snapshot. Users of the snapshot may use it to annotate the object
0846      * graph.
0847      */
0848     enum class Detachedness : uint8_t {
0849       kUnknown = 0,
0850       kAttached = 1,
0851       kDetached = 2,
0852     };
0853 
0854     Node() = default;
0855     virtual ~Node() = default;
0856     virtual const char* Name() = 0;
0857     virtual size_t SizeInBytes() = 0;
0858     /**
0859      * The corresponding V8 wrapper node if not null.
0860      * During heap snapshot generation the embedder node and the V8 wrapper
0861      * node will be merged into one node to simplify retaining paths.
0862      */
0863     virtual Node* WrapperNode() { return nullptr; }
0864     virtual bool IsRootNode() { return false; }
0865     /** Must return true for non-V8 nodes. */
0866     virtual bool IsEmbedderNode() { return true; }
0867     /**
0868      * Optional name prefix. It is used in Chrome for tagging detached nodes.
0869      */
0870     virtual const char* NamePrefix() { return nullptr; }
0871 
0872     /**
0873      * Returns the NativeObject that can be used for querying the
0874      * |HeapSnapshot|.
0875      */
0876     virtual NativeObject GetNativeObject() { return nullptr; }
0877 
0878     /**
0879      * Detachedness state of a given object. While unkown in general, there may
0880      * be objects that specifically know their state. V8 passes this information
0881      * along in the snapshot. Users of the snapshot may use it to annotate the
0882      * object graph.
0883      */
0884     virtual Detachedness GetDetachedness() { return Detachedness::kUnknown; }
0885 
0886     /**
0887      * Returns the address of the object in the embedder heap, or nullptr to not
0888      * specify the address. If this address is provided, then V8 can generate
0889      * consistent IDs for objects across subsequent heap snapshots, which allows
0890      * devtools to determine which objects were retained from one snapshot to
0891      * the next. This value is used only if GetNativeObject returns nullptr.
0892      */
0893     virtual const void* GetAddress() { return nullptr; }
0894 
0895     Node(const Node&) = delete;
0896     Node& operator=(const Node&) = delete;
0897   };
0898 
0899   /**
0900    * Returns a node corresponding to the given V8 value. Ownership is not
0901    * transferred. The result pointer is valid while the graph is alive.
0902    */
0903   virtual Node* V8Node(const v8::Local<v8::Value>& value) = 0;
0904 
0905   /**
0906    * Adds the given node to the graph and takes ownership of the node.
0907    * Returns a raw pointer to the node that is valid while the graph is alive.
0908    */
0909   virtual Node* AddNode(std::unique_ptr<Node> node) = 0;
0910 
0911   /**
0912    * Adds an edge that represents a strong reference from the given
0913    * node |from| to the given node |to|. The nodes must be added to the graph
0914    * before calling this function.
0915    *
0916    * If name is nullptr, the edge will have auto-increment indexes, otherwise
0917    * it will be named accordingly.
0918    */
0919   virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0;
0920 
0921   virtual ~EmbedderGraph() = default;
0922 };
0923 
0924 class QueryObjectPredicate {
0925  public:
0926   virtual ~QueryObjectPredicate() = default;
0927   virtual bool Filter(v8::Local<v8::Object> object) = 0;
0928 };
0929 
0930 /**
0931  * Interface for controlling heap profiling. Instance of the
0932  * profiler can be retrieved using v8::Isolate::GetHeapProfiler.
0933  */
0934 class V8_EXPORT HeapProfiler {
0935  public:
0936   void QueryObjects(v8::Local<v8::Context> context,
0937                     QueryObjectPredicate* predicate,
0938                     std::vector<v8::Global<v8::Object>>* objects);
0939 
0940   enum SamplingFlags {
0941     kSamplingNoFlags = 0,
0942     kSamplingForceGC = 1 << 0,
0943     kSamplingIncludeObjectsCollectedByMajorGC = 1 << 1,
0944     kSamplingIncludeObjectsCollectedByMinorGC = 1 << 2,
0945   };
0946 
0947   /**
0948    * Callback function invoked during heap snapshot generation to retrieve
0949    * the embedder object graph. The callback should use graph->AddEdge(..) to
0950    * add references between the objects.
0951    * The callback must not trigger garbage collection in V8.
0952    */
0953   typedef void (*BuildEmbedderGraphCallback)(v8::Isolate* isolate,
0954                                              v8::EmbedderGraph* graph,
0955                                              void* data);
0956 
0957   /**
0958    * Callback function invoked during heap snapshot generation to retrieve
0959    * the detachedness state of an object referenced by a TracedReference.
0960    *
0961    * The callback takes Local<Value> as parameter to allow the embedder to
0962    * unpack the TracedReference into a Local and reuse that Local for different
0963    * purposes.
0964    */
0965   using GetDetachednessCallback = EmbedderGraph::Node::Detachedness (*)(
0966       v8::Isolate* isolate, const v8::Local<v8::Value>& v8_value,
0967       uint16_t class_id, void* data);
0968 
0969   /** Returns the number of snapshots taken. */
0970   int GetSnapshotCount();
0971 
0972   /** Returns a snapshot by index. */
0973   const HeapSnapshot* GetHeapSnapshot(int index);
0974 
0975   /**
0976    * Returns SnapshotObjectId for a heap object referenced by |value| if
0977    * it has been seen by the heap profiler, kUnknownObjectId otherwise.
0978    */
0979   SnapshotObjectId GetObjectId(Local<Value> value);
0980 
0981   /**
0982    * Returns SnapshotObjectId for a native object referenced by |value| if it
0983    * has been seen by the heap profiler, kUnknownObjectId otherwise.
0984    */
0985   SnapshotObjectId GetObjectId(NativeObject value);
0986 
0987   /**
0988    * Returns heap object with given SnapshotObjectId if the object is alive,
0989    * otherwise empty handle is returned.
0990    */
0991   Local<Value> FindObjectById(SnapshotObjectId id);
0992 
0993   /**
0994    * Clears internal map from SnapshotObjectId to heap object. The new objects
0995    * will not be added into it unless a heap snapshot is taken or heap object
0996    * tracking is kicked off.
0997    */
0998   void ClearObjectIds();
0999 
1000   /**
1001    * A constant for invalid SnapshotObjectId. GetSnapshotObjectId will return
1002    * it in case heap profiler cannot find id  for the object passed as
1003    * parameter. HeapSnapshot::GetNodeById will always return NULL for such id.
1004    */
1005   static const SnapshotObjectId kUnknownObjectId = 0;
1006 
1007   /**
1008    * Callback interface for retrieving user friendly names of global objects.
1009    */
1010   class ObjectNameResolver {
1011    public:
1012     /**
1013      * Returns name to be used in the heap snapshot for given node. Returned
1014      * string must stay alive until snapshot collection is completed.
1015      */
1016     virtual const char* GetName(Local<Object> object) = 0;
1017 
1018    protected:
1019     virtual ~ObjectNameResolver() = default;
1020   };
1021 
1022   enum class HeapSnapshotMode {
1023     /**
1024      * Heap snapshot for regular developers.
1025      */
1026     kRegular,
1027     /**
1028      * Heap snapshot is exposing internals that may be useful for experts.
1029      */
1030     kExposeInternals,
1031   };
1032 
1033   enum class NumericsMode {
1034     /**
1035      * Numeric values are hidden as they are values of the corresponding
1036      * objects.
1037      */
1038     kHideNumericValues,
1039     /**
1040      * Numeric values are exposed in artificial fields.
1041      */
1042     kExposeNumericValues
1043   };
1044 
1045   struct HeapSnapshotOptions final {
1046     // Manually define default constructor here to be able to use it in
1047     // `TakeSnapshot()` below.
1048     // NOLINTNEXTLINE
1049     HeapSnapshotOptions() {}
1050 
1051     /**
1052      * The control used to report intermediate progress to.
1053      */
1054     ActivityControl* control = nullptr;
1055     /**
1056      * The resolver used by the snapshot generator to get names for V8 objects.
1057      */
1058     ObjectNameResolver* global_object_name_resolver = nullptr;
1059     /**
1060      * Mode for taking the snapshot, see `HeapSnapshotMode`.
1061      */
1062     HeapSnapshotMode snapshot_mode = HeapSnapshotMode::kRegular;
1063     /**
1064      * Mode for dealing with numeric values, see `NumericsMode`.
1065      */
1066     NumericsMode numerics_mode = NumericsMode::kHideNumericValues;
1067     /**
1068      * Whether stack is considered as a root set.
1069      */
1070     cppgc::EmbedderStackState stack_state =
1071         cppgc::EmbedderStackState::kMayContainHeapPointers;
1072   };
1073 
1074   /**
1075    * Takes a heap snapshot.
1076    *
1077    * \returns the snapshot.
1078    */
1079   const HeapSnapshot* TakeHeapSnapshot(
1080       const HeapSnapshotOptions& options = HeapSnapshotOptions());
1081 
1082   /**
1083    * Takes a heap snapshot. See `HeapSnapshotOptions` for details on the
1084    * parameters.
1085    *
1086    * \returns the snapshot.
1087    */
1088   const HeapSnapshot* TakeHeapSnapshot(
1089       ActivityControl* control,
1090       ObjectNameResolver* global_object_name_resolver = nullptr,
1091       bool hide_internals = true, bool capture_numeric_value = false);
1092 
1093   /**
1094    * Starts tracking of heap objects population statistics. After calling
1095    * this method, all heap objects relocations done by the garbage collector
1096    * are being registered.
1097    *
1098    * |track_allocations| parameter controls whether stack trace of each
1099    * allocation in the heap will be recorded and reported as part of
1100    * HeapSnapshot.
1101    */
1102   void StartTrackingHeapObjects(bool track_allocations = false);
1103 
1104   /**
1105    * Adds a new time interval entry to the aggregated statistics array. The
1106    * time interval entry contains information on the current heap objects
1107    * population size. The method also updates aggregated statistics and
1108    * reports updates for all previous time intervals via the OutputStream
1109    * object. Updates on each time interval are provided as a stream of the
1110    * HeapStatsUpdate structure instances.
1111    * If |timestamp_us| is supplied, timestamp of the new entry will be written
1112    * into it. The return value of the function is the last seen heap object Id.
1113    *
1114    * StartTrackingHeapObjects must be called before the first call to this
1115    * method.
1116    */
1117   SnapshotObjectId GetHeapStats(OutputStream* stream,
1118                                 int64_t* timestamp_us = nullptr);
1119 
1120   /**
1121    * Stops tracking of heap objects population statistics, cleans up all
1122    * collected data. StartHeapObjectsTracking must be called again prior to
1123    * calling GetHeapStats next time.
1124    */
1125   void StopTrackingHeapObjects();
1126 
1127   /**
1128    * Starts gathering a sampling heap profile. A sampling heap profile is
1129    * similar to tcmalloc's heap profiler and Go's mprof. It samples object
1130    * allocations and builds an online 'sampling' heap profile. At any point in
1131    * time, this profile is expected to be a representative sample of objects
1132    * currently live in the system. Each sampled allocation includes the stack
1133    * trace at the time of allocation, which makes this really useful for memory
1134    * leak detection.
1135    *
1136    * This mechanism is intended to be cheap enough that it can be used in
1137    * production with minimal performance overhead.
1138    *
1139    * Allocations are sampled using a randomized Poisson process. On average, one
1140    * allocation will be sampled every |sample_interval| bytes allocated. The
1141    * |stack_depth| parameter controls the maximum number of stack frames to be
1142    * captured on each allocation.
1143    *
1144    * NOTE: Support for native allocations doesn't exist yet, but is anticipated
1145    * in the future.
1146    *
1147    * Objects allocated before the sampling is started will not be included in
1148    * the profile.
1149    *
1150    * Returns false if a sampling heap profiler is already running.
1151    */
1152   bool StartSamplingHeapProfiler(uint64_t sample_interval = 512 * 1024,
1153                                  int stack_depth = 16,
1154                                  SamplingFlags flags = kSamplingNoFlags);
1155 
1156   /**
1157    * Stops the sampling heap profile and discards the current profile.
1158    */
1159   void StopSamplingHeapProfiler();
1160 
1161   /**
1162    * Returns the sampled profile of allocations allocated (and still live) since
1163    * StartSamplingHeapProfiler was called. The ownership of the pointer is
1164    * transferred to the caller. Returns nullptr if sampling heap profiler is not
1165    * active.
1166    */
1167   AllocationProfile* GetAllocationProfile();
1168 
1169   /**
1170    * Deletes all snapshots taken. All previously returned pointers to
1171    * snapshots and their contents become invalid after this call.
1172    */
1173   void DeleteAllHeapSnapshots();
1174 
1175   void AddBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,
1176                                      void* data);
1177   void RemoveBuildEmbedderGraphCallback(BuildEmbedderGraphCallback callback,
1178                                         void* data);
1179 
1180   void SetGetDetachednessCallback(GetDetachednessCallback callback, void* data);
1181 
1182   /**
1183    * Default value of persistent handle class ID. Must not be used to
1184    * define a class. Can be used to reset a class of a persistent
1185    * handle.
1186    */
1187   static const uint16_t kPersistentHandleNoClassId = 0;
1188 
1189  private:
1190   HeapProfiler();
1191   ~HeapProfiler();
1192   HeapProfiler(const HeapProfiler&);
1193   HeapProfiler& operator=(const HeapProfiler&);
1194 };
1195 
1196 /**
1197  * A struct for exporting HeapStats data from V8, using "push" model.
1198  * See HeapProfiler::GetHeapStats.
1199  */
1200 struct HeapStatsUpdate {
1201   HeapStatsUpdate(uint32_t index, uint32_t count, uint32_t size)
1202     : index(index), count(count), size(size) { }
1203   uint32_t index;  // Index of the time interval that was changed.
1204   uint32_t count;  // New value of count field for the interval with this index.
1205   uint32_t size;  // New value of size field for the interval with this index.
1206 };
1207 
1208 #define CODE_EVENTS_LIST(V)                          \
1209   V(Builtin)                                         \
1210   V(Callback)                                        \
1211   V(Eval)                                            \
1212   V(Function)                                        \
1213   V(InterpretedFunction)                             \
1214   V(Handler)                                         \
1215   V(BytecodeHandler)                                 \
1216   V(LazyCompile) /* Unused, use kFunction instead */ \
1217   V(RegExp)                                          \
1218   V(Script)                                          \
1219   V(Stub)                                            \
1220   V(Relocation)
1221 
1222 /**
1223  * Note that this enum may be extended in the future. Please include a default
1224  * case if this enum is used in a switch statement.
1225  */
1226 enum CodeEventType {
1227   kUnknownType = 0
1228 #define V(Name) , k##Name##Type
1229   CODE_EVENTS_LIST(V)
1230 #undef V
1231 };
1232 
1233 /**
1234  * Representation of a code creation event
1235  */
1236 class V8_EXPORT CodeEvent {
1237  public:
1238   uintptr_t GetCodeStartAddress();
1239   size_t GetCodeSize();
1240   Local<String> GetFunctionName();
1241   Local<String> GetScriptName();
1242   int GetScriptLine();
1243   int GetScriptColumn();
1244   /**
1245    * NOTE (mmarchini): We can't allocate objects in the heap when we collect
1246    * existing code, and both the code type and the comment are not stored in the
1247    * heap, so we return those as const char*.
1248    */
1249   CodeEventType GetCodeType();
1250   const char* GetComment();
1251 
1252   static const char* GetCodeEventTypeName(CodeEventType code_event_type);
1253 
1254   uintptr_t GetPreviousCodeStartAddress();
1255 };
1256 
1257 /**
1258  * Interface to listen to code creation and code relocation events.
1259  */
1260 class V8_EXPORT CodeEventHandler {
1261  public:
1262   /**
1263    * Creates a new listener for the |isolate|. The isolate must be initialized.
1264    * The listener object must be disposed after use by calling |Dispose| method.
1265    * Multiple listeners can be created for the same isolate.
1266    */
1267   explicit CodeEventHandler(Isolate* isolate);
1268   virtual ~CodeEventHandler();
1269 
1270   /**
1271    * Handle is called every time a code object is created or moved. Information
1272    * about each code event will be available through the `code_event`
1273    * parameter.
1274    *
1275    * When the CodeEventType is kRelocationType, the code for this CodeEvent has
1276    * moved from `GetPreviousCodeStartAddress()` to `GetCodeStartAddress()`.
1277    */
1278   virtual void Handle(CodeEvent* code_event) = 0;
1279 
1280   /**
1281    * Call `Enable()` to starts listening to code creation and code relocation
1282    * events. These events will be handled by `Handle()`.
1283    */
1284   void Enable();
1285 
1286   /**
1287    * Call `Disable()` to stop listening to code creation and code relocation
1288    * events.
1289    */
1290   void Disable();
1291 
1292  private:
1293   CodeEventHandler();
1294   CodeEventHandler(const CodeEventHandler&);
1295   CodeEventHandler& operator=(const CodeEventHandler&);
1296   void* internal_listener_;
1297 };
1298 
1299 }  // namespace v8
1300 
1301 
1302 #endif  // V8_V8_PROFILER_H_