profile-generator.h revision 109988c7ccb6f3fd1a58574fa3dfb88beaef6632
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,
195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      int src_line = v8::CpuProfileNode::kNoLineNumberInfo,
196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      bool update_stats = true);
1976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* root() const { return root_; }
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned next_node_id() { return next_node_id_++; }
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned GetFunctionId(const ProfileNode* node);
2006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print() {
2026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    root_->Print(0);
2036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
2046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate() const { return isolate_; }
206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  template <typename Callback>
209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  void TraverseDepthFirst(Callback* callback);
2106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry root_entry_;
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned next_node_id_;
2136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileNode* root_;
214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate_;
215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  unsigned next_function_id_;
217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  HashMap function_ids_;
2186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileTree);
2206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2236ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CpuProfile {
2246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CpuProfile(Isolate* isolate, const char* title, bool record_samples);
2266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Add pc -> ... -> main() call path to the profile.
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddPath(base::TimeTicks timestamp, const Vector<CodeEntry*>& path,
229109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch               int src_line, bool update_stats);
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CalculateTotalTicksAndSamplingRate();
2316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* title() const { return title_; }
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const ProfileTree* top_down() const { return &top_down_; }
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int samples_count() const { return samples_.length(); }
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ProfileNode* sample(int index) const { return samples_.at(index); }
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks sample_timestamp(int index) const {
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return timestamps_.at(index);
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks start_time() const { return start_time_; }
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks end_time() const { return end_time_; }
2436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void UpdateTicksScale();
2456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print();
2476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const char* title_;
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool record_samples_;
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks start_time_;
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::TimeTicks end_time_;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<ProfileNode*> samples_;
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<base::TimeTicks> timestamps_;
2556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ProfileTree top_down_;
2566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CpuProfile);
2586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
2596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2616ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CodeMap {
2626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
263014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeMap() {}
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~CodeMap();
265589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void AddCode(Address addr, CodeEntry* entry, unsigned size);
266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void MoveCode(Address from, Address to);
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CodeEntry* FindEntry(Address addr);
26844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int GetSharedId(Address addr);
2696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void Print();
2716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
2736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  struct CodeEntryInfo {
2746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CodeEntryInfo(CodeEntry* an_entry, unsigned a_size)
2756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        : entry(an_entry), size(a_size) { }
2766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    CodeEntry* entry;
2776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    unsigned size;
2786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  struct CodeTreeConfig {
2816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    typedef Address Key;
2826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    typedef CodeEntryInfo Value;
2836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    static const Key kNoKey;
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    static const Value NoValue() { return CodeEntryInfo(NULL, 0); }
2856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    static int Compare(const Key& a, const Key& b) {
2866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return a < b ? -1 : (a > b ? 1 : 0);
2876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
2886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  typedef SplayTree<CodeTreeConfig> CodeTree;
2906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  class CodeTreePrinter {
2926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block   public:
2936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    void Call(const Address& key, const CodeEntryInfo& value);
2946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  };
2956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
296589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  void DeleteAllCoveredCode(Address start, Address end);
297589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeTree tree_;
2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CodeMap);
3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3046ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass CpuProfilesCollection {
3056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit CpuProfilesCollection(Heap* heap);
3076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ~CpuProfilesCollection();
3086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool StartProfiling(const char* title, bool record_samples);
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CpuProfile* StopProfiling(const char* title);
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<CpuProfile*>* profiles() { return &finished_profiles_; }
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* GetName(Name* name) {
3137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    return function_and_resource_names_.GetName(name);
3147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
315f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  const char* GetName(int args_count) {
316f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch    return function_and_resource_names_.GetName(args_count);
317f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch  }
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* GetFunctionName(Name* name) {
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return function_and_resource_names_.GetFunctionName(name);
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const char* GetFunctionName(const char* name) {
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return function_and_resource_names_.GetFunctionName(name);
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
324756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  bool IsLastProfile(const char* title);
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void RemoveProfile(CpuProfile* profile);
3266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* NewCodeEntry(
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Logger::LogEventsAndTags tag, const char* name,
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const char* name_prefix = CodeEntry::kEmptyNamePrefix,
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      const char* resource_name = CodeEntry::kEmptyResourceName,
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      JITLineInfoTable* line_info = NULL, Address instruction_start = NULL);
3346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Called from profile generator thread.
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AddPathToCurrentProfiles(base::TimeTicks timestamp,
337109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                const Vector<CodeEntry*>& path, int src_line,
338109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                bool update_stats);
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
34080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Limits the number of profiles that can be simultaneously collected.
34180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const int kMaxSimultaneousProfiles = 100;
34280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
3436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
3447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  StringsStorage function_and_resource_names_;
3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<CodeEntry*> code_entries_;
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<CpuProfile*> finished_profiles_;
3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
348014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Isolate* isolate_;
349014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Accessed by VM thread and profile generator thread.
3516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  List<CpuProfile*> current_profiles_;
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::Semaphore current_profiles_semaphore_;
3536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(CpuProfilesCollection);
3556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass ProfileGenerator {
3596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  explicit ProfileGenerator(CpuProfilesCollection* profiles);
3616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  void RecordTickSample(const TickSample& sample);
3636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeMap* code_map() { return &code_map_; }
3656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
36644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static const char* const kProgramEntryName;
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kIdleEntryName;
36844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  static const char* const kGarbageCollectorEntryName;
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Used to represent frames for which we have no reliable way to
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // detect function.
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* const kUnresolvedFunctionName;
3726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private:
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* EntryForVMState(StateTag tag);
3756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CpuProfilesCollection* profiles_;
3776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeMap code_map_;
3786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry* program_entry_;
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* idle_entry_;
3806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  CodeEntry* gc_entry_;
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeEntry* unresolved_entry_;
3826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
3846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
3856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
3867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
3896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif  // V8_PROFILER_PROFILE_GENERATOR_H_
391