v8-profiler.h 38 KB

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