13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
46ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifndef V8_PROFILER_PROFILE_GENERATOR_H_
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define V8_PROFILER_PROFILE_GENERATOR_H_
76ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include <map>
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h"
1013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/hashmap.h"
11f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/log.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/strings-storage.h"
13f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/source-position.h"
146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocknamespace v8 {
166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocknamespace internal {
176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochstruct TickSample;
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Provides a mapping from the offsets within generated code to
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the source line.
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass JITLineInfoTable : public Malloced {
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JITLineInfoTable();
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ~JITLineInfoTable();
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void SetPosition(int pc_offset, int line);
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int GetSourceLineNumber(int pc_offset) const;
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool empty() const { return pc_offset_map_.empty(); }
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // pc_offset -> source line
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  typedef std::map<int, int> PcOffsetMap;
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PcOffsetMap pc_offset_map_;
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DISALLOW_COPY_AND_ASSIGN(JITLineInfoTable);
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
406ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CodeEntry {
416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // CodeEntry doesn't own name strings, just references them.
4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline CodeEntry(CodeEventListener::LogEventsAndTags tag, const char* name,
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   const char* name_prefix = CodeEntry::kEmptyNamePrefix,
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   const char* resource_name = CodeEntry::kEmptyResourceName,
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   JITLineInfoTable* line_info = NULL,
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   Address instruction_start = NULL);
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~CodeEntry();
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* name_prefix() const { return name_prefix_; }
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* name() const { return name_; }
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* resource_name() const { return resource_name_; }
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int line_number() const { return line_number_; }
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int column_number() const { return column_number_; }
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const JITLineInfoTable* line_info() const { return line_info_; }
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int script_id() const { return script_id_; }
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_script_id(int script_id) { script_id_ = script_id; }
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int position() const { return position_; }
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void set_position(int position) { position_ = position; }
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_bailout_reason(const char* bailout_reason) {
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bailout_reason_ = bailout_reason;
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* bailout_reason() const { return bailout_reason_; }
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
68c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void set_deopt_info(const char* deopt_reason, int deopt_id) {
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK(!has_deopt_info());
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    deopt_reason_ = deopt_reason;
71bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    deopt_id_ = deopt_id;
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CpuProfileDeoptInfo GetDeoptInfo();
74f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  bool has_deopt_info() const { return deopt_id_ != kNoDeoptimizationId; }
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void clear_deopt_info() {
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    deopt_reason_ = kNoDeoptReason;
77f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    deopt_id_ = kNoDeoptimizationId;
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void FillFunctionInfo(SharedFunctionInfo* shared);
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetBuiltinId(Builtins::Name id);
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Builtins::Name builtin_id() const {
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return BuiltinIdField::decode(bit_field_);
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t GetHash() const;
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsSameFunctionAs(CodeEntry* entry) const;
89f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int GetSourceLine(int pc_offset) const;
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
92c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void AddInlineStack(int pc_offset, std::vector<CodeEntry*> inline_stack);
933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  const std::vector<CodeEntry*>* GetInlineStack(int pc_offset) const;
943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
95c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void AddDeoptInlinedFrames(int deopt_id, std::vector<CpuProfileDeoptFrame>);
96bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool HasDeoptInlinedFramesFor(int deopt_id) const;
97bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address instruction_start() const { return instruction_start_; }
9913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CodeEventListener::LogEventsAndTags tag() const {
10013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return TagField::decode(bit_field_);
10113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
10344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static const char* const kEmptyNamePrefix;
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kEmptyResourceName;
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kEmptyBailoutReason;
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const char* const kNoDeoptReason;
1076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const char* const kProgramEntryName;
10913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const char* const kIdleEntryName;
11013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const char* const kGarbageCollectorEntryName;
11113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Used to represent frames for which we have no reliable way to
11213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // detect function.
11313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static const char* const kUnresolvedFunctionName;
11413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  V8_INLINE static CodeEntry* program_entry() {
11613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return kProgramEntry.Pointer();
11713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
11813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  V8_INLINE static CodeEntry* idle_entry() { return kIdleEntry.Pointer(); }
11913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  V8_INLINE static CodeEntry* gc_entry() { return kGCEntry.Pointer(); }
12013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  V8_INLINE static CodeEntry* unresolved_entry() {
12113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return kUnresolvedEntry.Pointer();
12213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct ProgramEntryCreateTrait {
12613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    static CodeEntry* Create();
12713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct IdleEntryCreateTrait {
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    static CodeEntry* Create();
13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct GCEntryCreateTrait {
13213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    static CodeEntry* Create();
13313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
13413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  struct UnresolvedEntryCreateTrait {
13513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    static CodeEntry* Create();
13613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  };
13713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
13813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::LazyDynamicInstance<CodeEntry, ProgramEntryCreateTrait>::type
13913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      kProgramEntry;
14013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::LazyDynamicInstance<CodeEntry, IdleEntryCreateTrait>::type
14113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      kIdleEntry;
14213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::LazyDynamicInstance<CodeEntry, GCEntryCreateTrait>::type
14313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      kGCEntry;
14413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static base::LazyDynamicInstance<CodeEntry, UnresolvedEntryCreateTrait>::type
14513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      kUnresolvedEntry;
14613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class TagField : public BitField<Logger::LogEventsAndTags, 0, 8> {};
14813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  class BuiltinIdField : public BitField<Builtins::Name, 8, 24> {};
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  uint32_t bit_field_;
1516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* name_prefix_;
1526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* name_;
1536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* resource_name_;
1546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int line_number_;
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int column_number_;
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int script_id_;
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int position_;
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* bailout_reason_;
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* deopt_reason_;
160bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  int deopt_id_;
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JITLineInfoTable* line_info_;
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address instruction_start_;
1633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Should be an unordered_map, but it doesn't currently work on Win & MacOS.
1643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  std::map<int, std::vector<CodeEntry*>> inline_locations_;
165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  std::map<int, std::vector<CpuProfileDeoptFrame>> deopt_inlined_frames_;
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CodeEntry);
1686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
1696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1716ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileTree;
1726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileNode {
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
175c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline ProfileNode(ProfileTree* tree, CodeEntry* entry, ProfileNode* parent);
1766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* FindChild(CodeEntry* entry);
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* FindOrAddChild(CodeEntry* entry);
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncrementSelfTicks() { ++self_ticks_; }
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; }
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void IncrementLineTicks(int src_line);
1826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* entry() const { return entry_; }
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned self_ticks() const { return self_ticks_; }
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const List<ProfileNode*>* children() const { return &children_list_; }
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned id() const { return id_; }
187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned function_id() const;
188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ProfileNode* parent() const { return parent_; }
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  unsigned int GetHitLineCount() const { return line_ticks_.occupancy(); }
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GetLineTicks(v8::CpuProfileNode::LineTick* entries,
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                    unsigned int length) const;
192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CollectDeoptInfo(CodeEntry* entry);
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const std::vector<CpuProfileDeoptInfo>& deopt_infos() const {
194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return deopt_infos_;
195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate() const;
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print(int indent);
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool CodeEntriesMatch(void* entry1, void* entry2) {
201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reinterpret_cast<CodeEntry*>(entry1)
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ->IsSameFunctionAs(reinterpret_cast<CodeEntry*>(entry2));
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static uint32_t CodeEntryHash(CodeEntry* entry) { return entry->GetHash(); }
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool LineTickMatch(void* a, void* b) { return a == b; }
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileTree* tree_;
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry* entry_;
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  unsigned self_ticks_;
2133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Mapping from CodeEntry* to ProfileNode*
214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::CustomMatcherHashMap children_;
2156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<ProfileNode*> children_list_;
216c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ProfileNode* parent_;
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned id_;
218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::CustomMatcherHashMap line_ticks_;
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  std::vector<CpuProfileDeoptInfo> deopt_infos_;
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileNode);
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileTree {
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit ProfileTree(Isolate* isolate);
2296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~ProfileTree();
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ProfileNode* AddPathFromEnd(
2323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      const std::vector<CodeEntry*>& path,
233109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      int src_line = v8::CpuProfileNode::kNoLineNumberInfo,
234109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      bool update_stats = true);
2356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* root() const { return root_; }
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned next_node_id() { return next_node_id_++; }
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned GetFunctionId(const ProfileNode* node);
2386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print() {
2406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_->Print(0);
2416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate() const { return isolate_; }
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void EnqueueNode(const ProfileNode* node) { pending_nodes_.push_back(node); }
246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t pending_nodes_count() const { return pending_nodes_.size(); }
247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  std::vector<const ProfileNode*> TakePendingNodes() {
248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return std::move(pending_nodes_);
249c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
250c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
2516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  template <typename Callback>
253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void TraverseDepthFirst(Callback* callback);
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  std::vector<const ProfileNode*> pending_nodes_;
256c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry root_entry_;
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned next_node_id_;
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* root_;
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate_;
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned next_function_id_;
263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::CustomMatcherHashMap function_ids_;
2646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileTree);
2666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CpuProfile {
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
27113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CpuProfile(CpuProfiler* profiler, const char* title, bool record_samples);
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Add pc -> ... -> main() call path to the profile.
2743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AddPath(base::TimeTicks timestamp, const std::vector<CodeEntry*>& path,
275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch               int src_line, bool update_stats);
276c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void FinishProfile();
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* title() const { return title_; }
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ProfileTree* top_down() const { return &top_down_; }
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int samples_count() const { return samples_.length(); }
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileNode* sample(int index) const { return samples_.at(index); }
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks sample_timestamp(int index) const {
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return timestamps_.at(index);
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks start_time() const { return start_time_; }
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks end_time() const { return end_time_; }
28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CpuProfiler* cpu_profiler() const { return profiler_; }
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void UpdateTicksScale();
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print();
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void StreamPendingTraceEvents();
297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* title_;
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool record_samples_;
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks start_time_;
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks end_time_;
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ProfileNode*> samples_;
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<base::TimeTicks> timestamps_;
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileTree top_down_;
30513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CpuProfiler* const profiler_;
306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int streaming_next_sample_;
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CpuProfile);
3096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3116ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CodeMap {
3126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeMap() {}
31413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
315589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AddCode(Address addr, CodeEntry* entry, unsigned size);
316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MoveCode(Address from, Address to);
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeEntry* FindEntry(Address addr);
3186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print();
3196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  struct CodeEntryInfo {
3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CodeEntryInfo(CodeEntry* an_entry, unsigned a_size)
3236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : entry(an_entry), size(a_size) { }
3246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CodeEntry* entry;
3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    unsigned size;
3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
3276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void DeleteAllCoveredCode(Address start, Address end);
329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
33013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  std::map<Address, CodeEntryInfo> code_map_;
3316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CodeMap);
3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CpuProfilesCollection {
3366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
33713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  explicit CpuProfilesCollection(Isolate* isolate);
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~CpuProfilesCollection();
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
34013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void set_cpu_profiler(CpuProfiler* profiler) { profiler_ = profiler; }
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool StartProfiling(const char* title, bool record_samples);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuProfile* StopProfiling(const char* title);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<CpuProfile*>* profiles() { return &finished_profiles_; }
34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  const char* GetName(Name* name) { return resource_names_.GetName(name); }
345756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool IsLastProfile(const char* title);
34644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void RemoveProfile(CpuProfile* profile);
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Called from profile generator thread.
349958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddPathToCurrentProfiles(base::TimeTicks timestamp,
3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                const std::vector<CodeEntry*>& path,
3513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                int src_line, bool update_stats);
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
35380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Limits the number of profiles that can be simultaneously collected.
35480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const int kMaxSimultaneousProfiles = 100;
35580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
35713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  StringsStorage resource_names_;
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<CpuProfile*> finished_profiles_;
35913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CpuProfiler* profiler_;
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Accessed by VM thread and profile generator thread.
3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<CpuProfile*> current_profiles_;
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::Semaphore current_profiles_semaphore_;
3646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection);
3666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3696ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileGenerator {
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  explicit ProfileGenerator(CpuProfilesCollection* profiles);
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void RecordTickSample(const TickSample& sample);
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeMap* code_map() { return &code_map_; }
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
378c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CodeEntry* FindEntry(void* address);
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* EntryForVMState(StateTag tag);
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CpuProfilesCollection* profiles_;
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeMap code_map_;
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_PROFILER_PROFILE_GENERATOR_H_
392