v8-profiler.h 33 KB

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