5 #ifndef V8_PROFILER_PROFILE_GENERATOR_H_ 6 #define V8_PROFILER_PROFILE_GENERATOR_H_ 13 #include <unordered_map> 17 #include "include/v8-profiler.h" 18 #include "src/allocation.h" 20 #include "src/profiler/strings-storage.h" 21 #include "src/source-position.h" 34 void SetPosition(
int pc_offset,
int line);
35 int GetSourceLineNumber(
int pc_offset)
const;
38 struct PCOffsetAndLineNumber {
39 bool operator<(
const PCOffsetAndLineNumber& other)
const {
40 return pc_offset < other.pc_offset;
48 std::vector<PCOffsetAndLineNumber> pc_offsets_to_lines_;
55 inline CodeEntry(CodeEventListener::LogEventsAndTags tag,
const char* name,
56 const char* resource_name = CodeEntry::kEmptyResourceName,
57 int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
58 int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
59 std::unique_ptr<SourcePositionTable> line_info =
nullptr,
60 Address instruction_start = kNullAddress);
62 const char* name()
const {
return name_; }
63 const char* resource_name()
const {
return resource_name_; }
64 int line_number()
const {
return line_number_; }
65 int column_number()
const {
return column_number_; }
67 int script_id()
const {
return script_id_; }
68 void set_script_id(
int script_id) { script_id_ = script_id; }
69 int position()
const {
return position_; }
70 void set_position(
int position) { position_ = position; }
71 void set_bailout_reason(
const char* bailout_reason) {
72 EnsureRareData()->bailout_reason_ = bailout_reason;
74 const char* bailout_reason()
const {
75 return rare_data_ ? rare_data_->bailout_reason_ : kEmptyBailoutReason;
78 void set_deopt_info(
const char* deopt_reason,
int deopt_id,
79 std::vector<CpuProfileDeoptFrame> inlined_frames);
82 bool has_deopt_info()
const {
83 return rare_data_ && rare_data_->deopt_id_ != kNoDeoptimizationId;
85 void clear_deopt_info() {
86 if (!rare_data_)
return;
88 rare_data_->deopt_reason_ = kNoDeoptReason;
89 rare_data_->deopt_id_ = kNoDeoptimizationId;
91 void mark_used() { bit_field_ = UsedField::update(bit_field_,
true); }
92 bool used()
const {
return UsedField::decode(bit_field_); }
96 void SetBuiltinId(Builtins::Name
id);
97 Builtins::Name builtin_id()
const {
98 return BuiltinIdField::decode(bit_field_);
102 bool IsSameFunctionAs(
const CodeEntry* entry)
const;
104 int GetSourceLine(
int pc_offset)
const;
106 void AddInlineStack(
int pc_offset,
107 std::vector<std::unique_ptr<CodeEntry>> inline_stack);
108 const std::vector<std::unique_ptr<CodeEntry>>* GetInlineStack(
109 int pc_offset)
const;
111 void set_instruction_start(
Address start) { instruction_start_ = start; }
112 Address instruction_start()
const {
return instruction_start_; }
114 CodeEventListener::LogEventsAndTags tag()
const {
115 return TagField::decode(bit_field_);
118 static const char*
const kWasmResourceNamePrefix;
119 static const char*
const kEmptyResourceName;
120 static const char*
const kEmptyBailoutReason;
121 static const char*
const kNoDeoptReason;
123 static const char*
const kProgramEntryName;
124 static const char*
const kIdleEntryName;
125 static const char*
const kGarbageCollectorEntryName;
128 static const char*
const kUnresolvedFunctionName;
130 V8_INLINE
static CodeEntry* program_entry() {
131 return kProgramEntry.Pointer();
133 V8_INLINE
static CodeEntry* idle_entry() {
return kIdleEntry.Pointer(); }
134 V8_INLINE
static CodeEntry* gc_entry() {
return kGCEntry.Pointer(); }
135 V8_INLINE
static CodeEntry* unresolved_entry() {
136 return kUnresolvedEntry.Pointer();
141 const char* deopt_reason_ = kNoDeoptReason;
142 const char* bailout_reason_ = kEmptyBailoutReason;
143 int deopt_id_ = kNoDeoptimizationId;
144 std::unordered_map<int, std::vector<std::unique_ptr<CodeEntry>>>
146 std::vector<CpuProfileDeoptFrame> deopt_inlined_frames_;
149 RareData* EnsureRareData();
151 struct ProgramEntryCreateTrait {
154 struct IdleEntryCreateTrait {
157 struct GCEntryCreateTrait {
160 struct UnresolvedEntryCreateTrait {
179 const char* resource_name_;
184 std::unique_ptr<SourcePositionTable> line_info_;
186 std::unique_ptr<RareData> rare_data_;
196 typedef std::vector<CodeEntryAndLineNumber> ProfileStackTrace;
203 int line_number = 0);
207 int line_number = v8::CpuProfileNode::kNoLineNumberInfo);
209 void IncrementSelfTicks() { ++self_ticks_; }
210 void IncreaseSelfTicks(
unsigned amount) { self_ticks_ += amount; }
211 void IncrementLineTicks(
int src_line);
213 CodeEntry* entry()
const {
return entry_; }
214 unsigned self_ticks()
const {
return self_ticks_; }
215 const std::vector<ProfileNode*>* children()
const {
return &children_list_; }
216 unsigned id()
const {
return id_; }
217 unsigned function_id()
const;
219 int line_number()
const {
220 return line_number_ != 0 ? line_number_ : entry_->line_number();
223 unsigned int GetHitLineCount()
const {
224 return static_cast<unsigned int>(line_ticks_.size());
227 unsigned int length)
const;
229 const std::vector<CpuProfileDeoptInfo>& deopt_infos()
const {
234 void Print(
int indent);
240 return lhs.code_entry->IsSameFunctionAs(rhs.code_entry) &&
241 lhs.line_number == rhs.line_number;
246 return pair.code_entry->GetHash() ^ ComputeUnseededHash(pair.line_number);
252 unsigned self_ticks_;
253 std::unordered_map<CodeEntryAndLineNumber, ProfileNode*, Hasher, Equals>
256 std::vector<ProfileNode*> children_list_;
260 std::unordered_map<int, int> line_ticks_;
262 std::vector<CpuProfileDeoptInfo> deopt_infos_;
272 typedef v8::CpuProfilingMode ProfilingMode;
275 const std::vector<CodeEntry*>& path,
276 int src_line = v8::CpuProfileNode::kNoLineNumberInfo,
277 bool update_stats =
true);
279 const ProfileStackTrace& path,
280 int src_line = v8::CpuProfileNode::kNoLineNumberInfo,
281 bool update_stats =
true,
282 ProfilingMode mode = ProfilingMode::kLeafNodeLineNumbers);
284 unsigned next_node_id() {
return next_node_id_++; }
291 Isolate* isolate()
const {
return isolate_; }
293 void EnqueueNode(
const ProfileNode* node) { pending_nodes_.push_back(node); }
294 size_t pending_nodes_count()
const {
return pending_nodes_.size(); }
295 std::vector<const ProfileNode*> TakePendingNodes() {
296 return std::move(pending_nodes_);
300 template <
typename Callback>
301 void TraverseDepthFirst(Callback* callback);
303 std::vector<const ProfileNode*> pending_nodes_;
306 unsigned next_node_id_;
310 unsigned next_function_id_;
311 std::unordered_map<CodeEntry*, unsigned> function_ids_;
319 typedef v8::CpuProfilingMode ProfilingMode;
326 int src_line,
bool update_stats);
327 void FinishProfile();
329 const char* title()
const {
return title_; }
330 const ProfileTree* top_down()
const {
return &top_down_; }
332 int samples_count()
const {
return static_cast<int>(samples_.size()); }
333 ProfileNode* sample(
int index)
const {
return samples_.at(index); }
335 return timestamps_.at(index);
340 CpuProfiler* cpu_profiler()
const {
return profiler_; }
342 void UpdateTicksScale();
347 void StreamPendingTraceEvents();
350 bool record_samples_;
354 std::vector<ProfileNode*> samples_;
355 std::vector<base::TimeTicks> timestamps_;
358 size_t streaming_next_sample_;
361 static std::atomic<uint32_t> last_id_;
377 struct CodeEntryMapInfo {
382 union CodeEntrySlotInfo {
384 unsigned next_free_slot;
387 static constexpr
unsigned kNoFreeSlot = std::numeric_limits<unsigned>::max();
391 void DeleteCodeEntry(
unsigned index);
393 CodeEntry* entry(
unsigned index) {
return code_entries_[index].entry; }
395 std::deque<CodeEntrySlotInfo> code_entries_;
396 std::map<Address, CodeEntryMapInfo> code_map_;
397 unsigned free_list_head_ = kNoFreeSlot;
399 DISALLOW_COPY_AND_ASSIGN(
CodeMap);
406 typedef v8::CpuProfilingMode ProfilingMode;
408 void set_cpu_profiler(
CpuProfiler* profiler) { profiler_ = profiler; }
409 bool StartProfiling(
const char* title,
bool record_samples,
410 ProfilingMode mode = ProfilingMode::kLeafNodeLineNumbers);
412 std::vector<std::unique_ptr<CpuProfile>>* profiles() {
413 return &finished_profiles_;
415 const char* GetName(
Name name) {
return resource_names_.GetName(name); }
416 bool IsLastProfile(
const char* title);
421 const ProfileStackTrace& path,
int src_line,
425 static const int kMaxSimultaneousProfiles = 100;
429 std::vector<std::unique_ptr<CpuProfile>> finished_profiles_;
433 std::vector<std::unique_ptr<CpuProfile>> current_profiles_;
443 void RecordTickSample(
const TickSample& sample);
445 CodeMap* code_map() {
return &code_map_; }
449 CodeEntry* EntryForVMState(StateTag tag);
460 #endif // V8_PROFILER_PROFILE_GENERATOR_H_