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 "include/v8-profiler.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/compiler.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/hashmap.h"
13014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/strings-storage.h"
146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
156ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocknamespace v8 {
166ded16be15dd865a9b21ea304d5273c8be299c87Steve Blocknamespace internal {
176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Provides a mapping from the offsets within generated code to
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// the source line.
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass JITLineInfoTable : public Malloced {
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JITLineInfoTable();
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ~JITLineInfoTable();
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void SetPosition(int pc_offset, int line);
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int GetSourceLineNumber(int pc_offset) const;
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool empty() const { return pc_offset_map_.empty(); }
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // pc_offset -> source line
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  typedef std::map<int, int> PcOffsetMap;
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PcOffsetMap pc_offset_map_;
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DISALLOW_COPY_AND_ASSIGN(JITLineInfoTable);
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
386ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CodeEntry {
396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // CodeEntry doesn't own name strings, just references them.
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  inline CodeEntry(Logger::LogEventsAndTags tag, const char* name,
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   const char* name_prefix = CodeEntry::kEmptyNamePrefix,
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   const char* resource_name = CodeEntry::kEmptyResourceName,
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                   int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   JITLineInfoTable* line_info = NULL,
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                   Address instruction_start = NULL);
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~CodeEntry();
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* name_prefix() const { return name_prefix_; }
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool has_name_prefix() const { return name_prefix_[0] != '\0'; }
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* name() const { return name_; }
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* resource_name() const { return resource_name_; }
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int line_number() const { return line_number_; }
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int column_number() const { return column_number_; }
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const JITLineInfoTable* line_info() const { return line_info_; }
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int script_id() const { return script_id_; }
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_script_id(int script_id) { script_id_ = script_id; }
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int position() const { return position_; }
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void set_position(int position) { position_ = position; }
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_bailout_reason(const char* bailout_reason) {
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bailout_reason_ = bailout_reason;
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* bailout_reason() const { return bailout_reason_; }
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
66014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void set_deopt_info(const char* deopt_reason, SourcePosition position,
67014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      size_t pc_offset) {
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(deopt_position_.IsUnknown());
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    deopt_reason_ = deopt_reason;
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    deopt_position_ = position;
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    pc_offset_ = pc_offset;
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CpuProfileDeoptInfo GetDeoptInfo();
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* deopt_reason() const { return deopt_reason_; }
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SourcePosition deopt_position() const { return deopt_position_; }
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool has_deopt_info() const { return !deopt_position_.IsUnknown(); }
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void clear_deopt_info() {
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    deopt_reason_ = kNoDeoptReason;
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    deopt_position_ = SourcePosition::Unknown();
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
82014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void FillFunctionInfo(SharedFunctionInfo* shared);
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void set_inlined_function_infos(
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      const std::vector<InlinedFunctionInfo>& infos) {
86014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    inlined_function_infos_ = infos;
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const std::vector<InlinedFunctionInfo> inlined_function_infos() {
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return inlined_function_infos_;
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetBuiltinId(Builtins::Name id);
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Builtins::Name builtin_id() const {
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return BuiltinIdField::decode(bit_field_);
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  uint32_t GetHash() const;
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsSameFunctionAs(CodeEntry* entry) const;
99f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int GetSourceLine(int pc_offset) const;
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address instruction_start() const { return instruction_start_; }
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
10444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static const char* const kEmptyNamePrefix;
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kEmptyResourceName;
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kEmptyBailoutReason;
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const char* const kNoDeoptReason;
1086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class TagField : public BitField<Logger::LogEventsAndTags, 0, 8> {};
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  class BuiltinIdField : public BitField<Builtins::Name, 8, 8> {};
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Logger::LogEventsAndTags tag() const { return TagField::decode(bit_field_); }
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  uint32_t bit_field_;
1156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* name_prefix_;
1166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* name_;
1176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* resource_name_;
1186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  int line_number_;
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int column_number_;
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int script_id_;
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int position_;
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* bailout_reason_;
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const char* deopt_reason_;
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SourcePosition deopt_position_;
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t pc_offset_;
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  JITLineInfoTable* line_info_;
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address instruction_start_;
1286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  std::vector<InlinedFunctionInfo> inlined_function_infos_;
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CodeEntry);
1326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
1336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1356ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileTree;
1366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1376ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileNode {
1386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline ProfileNode(ProfileTree* tree, CodeEntry* entry);
1406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* FindChild(CodeEntry* entry);
1426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* FindOrAddChild(CodeEntry* entry);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncrementSelfTicks() { ++self_ticks_; }
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IncreaseSelfTicks(unsigned amount) { self_ticks_ += amount; }
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void IncrementLineTicks(int src_line);
1466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* entry() const { return entry_; }
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned self_ticks() const { return self_ticks_; }
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const List<ProfileNode*>* children() const { return &children_list_; }
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned id() const { return id_; }
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned function_id() const;
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  unsigned int GetHitLineCount() const { return line_ticks_.occupancy(); }
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool GetLineTicks(v8::CpuProfileNode::LineTick* entries,
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                    unsigned int length) const;
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void CollectDeoptInfo(CodeEntry* entry);
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const std::vector<CpuProfileDeoptInfo>& deopt_infos() const {
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return deopt_infos_;
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate() const;
1606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print(int indent);
1626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool CodeEntriesMatch(void* entry1, void* entry2) {
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return reinterpret_cast<CodeEntry*>(entry1)
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ->IsSameFunctionAs(reinterpret_cast<CodeEntry*>(entry2));
1666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
1676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static uint32_t CodeEntryHash(CodeEntry* entry) { return entry->GetHash(); }
1706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static bool LineTickMatch(void* a, void* b) { return a == b; }
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileTree* tree_;
1746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry* entry_;
1756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  unsigned self_ticks_;
1763bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch  // Mapping from CodeEntry* to ProfileNode*
1776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  HashMap children_;
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<ProfileNode*> children_list_;
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned id_;
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HashMap line_ticks_;
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  std::vector<CpuProfileDeoptInfo> deopt_infos_;
183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileNode);
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileTree {
1896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
190014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit ProfileTree(Isolate* isolate);
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~ProfileTree();
1926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ProfileNode* AddPathFromEnd(
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      const Vector<CodeEntry*>& path,
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int src_line = v8::CpuProfileNode::kNoLineNumberInfo);
1966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* root() const { return root_; }
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned next_node_id() { return next_node_id_++; }
198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned GetFunctionId(const ProfileNode* node);
1996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print() {
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_->Print(0);
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate() const { return isolate_; }
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  template <typename Callback>
208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void TraverseDepthFirst(Callback* callback);
2096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry root_entry_;
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned next_node_id_;
2126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* root_;
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate_;
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned next_function_id_;
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HashMap function_ids_;
2176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileTree);
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CpuProfile {
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CpuProfile(Isolate* isolate, const char* title, bool record_samples);
2256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Add pc -> ... -> main() call path to the profile.
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddPath(base::TimeTicks timestamp, const Vector<CodeEntry*>& path,
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               int src_line);
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CalculateTotalTicksAndSamplingRate();
2306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* title() const { return title_; }
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ProfileTree* top_down() const { return &top_down_; }
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int samples_count() const { return samples_.length(); }
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileNode* sample(int index) const { return samples_.at(index); }
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks sample_timestamp(int index) const {
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return timestamps_.at(index);
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks start_time() const { return start_time_; }
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks end_time() const { return end_time_; }
2426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void UpdateTicksScale();
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print();
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* title_;
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool record_samples_;
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks start_time_;
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks end_time_;
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ProfileNode*> samples_;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<base::TimeTicks> timestamps_;
2546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileTree top_down_;
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CpuProfile);
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CodeMap {
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeMap() {}
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CodeMap();
264589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AddCode(Address addr, CodeEntry* entry, unsigned size);
265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MoveCode(Address from, Address to);
266014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeEntry* FindEntry(Address addr);
26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int GetSharedId(Address addr);
2686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print();
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  struct CodeEntryInfo {
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CodeEntryInfo(CodeEntry* an_entry, unsigned a_size)
2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : entry(an_entry), size(a_size) { }
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CodeEntry* entry;
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    unsigned size;
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  struct CodeTreeConfig {
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    typedef Address Key;
2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    typedef CodeEntryInfo Value;
2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    static const Key kNoKey;
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    static const Value NoValue() { return CodeEntryInfo(NULL, 0); }
2846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    static int Compare(const Key& a, const Key& b) {
2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return a < b ? -1 : (a > b ? 1 : 0);
2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  typedef SplayTree<CodeTreeConfig> CodeTree;
2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  class CodeTreePrinter {
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   public:
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void Call(const Address& key, const CodeEntryInfo& value);
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
295589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void DeleteAllCoveredCode(Address start, Address end);
296589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeTree tree_;
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CodeMap);
3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CpuProfilesCollection {
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit CpuProfilesCollection(Heap* heap);
3066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~CpuProfilesCollection();
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool StartProfiling(const char* title, bool record_samples);
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuProfile* StopProfiling(const char* title);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<CpuProfile*>* profiles() { return &finished_profiles_; }
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* GetName(Name* name) {
3127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    return function_and_resource_names_.GetName(name);
3137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
314f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char* GetName(int args_count) {
315f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return function_and_resource_names_.GetName(args_count);
316f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* GetFunctionName(Name* name) {
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return function_and_resource_names_.GetFunctionName(name);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* GetFunctionName(const char* name) {
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return function_and_resource_names_.GetFunctionName(name);
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
323756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool IsLastProfile(const char* title);
32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void RemoveProfile(CpuProfile* profile);
3256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* NewCodeEntry(
327958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Logger::LogEventsAndTags tag, const char* name,
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const char* name_prefix = CodeEntry::kEmptyNamePrefix,
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const char* resource_name = CodeEntry::kEmptyResourceName,
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JITLineInfoTable* line_info = NULL, Address instruction_start = NULL);
3336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Called from profile generator thread.
335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddPathToCurrentProfiles(base::TimeTicks timestamp,
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                const Vector<CodeEntry*>& path, int src_line);
3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
33880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Limits the number of profiles that can be simultaneously collected.
33980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const int kMaxSimultaneousProfiles = 100;
34080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringsStorage function_and_resource_names_;
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<CodeEntry*> code_entries_;
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<CpuProfile*> finished_profiles_;
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate_;
347014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Accessed by VM thread and profile generator thread.
3496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<CpuProfile*> current_profiles_;
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::Semaphore current_profiles_semaphore_;
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection);
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileGenerator {
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit ProfileGenerator(CpuProfilesCollection* profiles);
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void RecordTickSample(const TickSample& sample);
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeMap* code_map() { return &code_map_; }
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static const char* const kProgramEntryName;
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kIdleEntryName;
36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static const char* const kGarbageCollectorEntryName;
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Used to represent frames for which we have no reliable way to
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // detect function.
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kUnresolvedFunctionName;
3706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* EntryForVMState(StateTag tag);
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CpuProfilesCollection* profiles_;
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeMap code_map_;
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry* program_entry_;
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* idle_entry_;
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry* gc_entry_;
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* unresolved_entry_;
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
386014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_PROFILER_PROFILE_GENERATOR_H_
389