Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/profiler/profiler-listener.h

Issue 2053523003: Refactor CpuProfiler. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_PROFILER_CPU_PROFILER_H_ 5 #ifndef V8_PROFILER_PROFILER_LISTENER_H_
6 #define V8_PROFILER_CPU_PROFILER_H_ 6 #define V8_PROFILER_PROFILER_LISTENER_H_
7 7
8 #include "src/allocation.h" 8 #include "src/profiler/profile-generator.h"
9 #include "src/base/atomic-utils.h" 9
10 #include "src/base/atomicops.h" 10 // TODO(lpy): This is a workaround to resolve entry name
11 #include "src/base/platform/time.h" 11 // in order to build code entry. The logic of resolving
12 #include "src/compiler.h" 12 // entry name in ProfilerListener will be cleaned up
13 #include "src/libsampler/v8-sampler.h" 13 // in following up patches.
14 #include "src/locked-queue.h" 14 #define RESOLVE_CODE_EVENT(isolate) \
15 #include "src/profiler/circular-queue.h" 15 do { \
16 #include "src/profiler/tick-sample.h" 16 v8::internal::Logger* logger = (isolate)->logger(); \
17 logger->profiler_listener()->ResolveCodeEvent(); \
alph 2016/06/14 03:48:45 It's not clear what it does. Perhaps the name is m
lpy 2016/06/14 09:53:47 Done.
18 } while (false)
17 19
18 namespace v8 { 20 namespace v8 {
19 namespace internal { 21 namespace internal {
20 22
21 // Forward declarations. 23 class CodeEventsContainer;
22 class CodeEntry;
23 class CodeMap;
24 class CpuProfile;
25 class CpuProfilesCollection;
26 class ProfileGenerator;
27 24
28 #define CODE_EVENTS_TYPE_LIST(V) \ 25 class CodeEventObserver {
29 V(CODE_CREATION, CodeCreateEventRecord) \
30 V(CODE_MOVE, CodeMoveEventRecord) \
31 V(CODE_DISABLE_OPT, CodeDisableOptEventRecord) \
32 V(CODE_DEOPT, CodeDeoptEventRecord) \
33 V(REPORT_BUILTIN, ReportBuiltinEventRecord)
34
35
36 class CodeEventRecord {
37 public: 26 public:
38 #define DECLARE_TYPE(type, ignore) type, 27 virtual void CodeEventHandler(const CodeEventsContainer& evt_rec) = 0;
39 enum Type { 28 virtual ~CodeEventObserver() {}
40 NONE = 0,
41 CODE_EVENTS_TYPE_LIST(DECLARE_TYPE)
42 NUMBER_OF_TYPES
43 };
44 #undef DECLARE_TYPE
45
46 Type type;
47 mutable unsigned order;
48 }; 29 };
49 30
31 class ProfilerListener : public CodeEventListener {
32 public:
33 explicit ProfilerListener(Isolate* isolate)
34 : function_and_resource_names_(isolate->heap()),
35 is_resolving_code_entry_(false) {}
36 ~ProfilerListener() override;
50 37
51 class CodeCreateEventRecord : public CodeEventRecord {
52 public:
53 Address start;
54 CodeEntry* entry;
55 unsigned size;
56
57 INLINE(void UpdateCodeMap(CodeMap* code_map));
58 };
59
60
61 class CodeMoveEventRecord : public CodeEventRecord {
62 public:
63 Address from;
64 Address to;
65
66 INLINE(void UpdateCodeMap(CodeMap* code_map));
67 };
68
69
70 class CodeDisableOptEventRecord : public CodeEventRecord {
71 public:
72 Address start;
73 const char* bailout_reason;
74
75 INLINE(void UpdateCodeMap(CodeMap* code_map));
76 };
77
78
79 class CodeDeoptEventRecord : public CodeEventRecord {
80 public:
81 Address start;
82 const char* deopt_reason;
83 SourcePosition position;
84 int deopt_id;
85
86 INLINE(void UpdateCodeMap(CodeMap* code_map));
87 };
88
89
90 class ReportBuiltinEventRecord : public CodeEventRecord {
91 public:
92 Address start;
93 Builtins::Name builtin_id;
94
95 INLINE(void UpdateCodeMap(CodeMap* code_map));
96 };
97
98
99 class TickSampleEventRecord {
100 public:
101 // The parameterless constructor is used when we dequeue data from
102 // the ticks buffer.
103 TickSampleEventRecord() { }
104 explicit TickSampleEventRecord(unsigned order) : order(order) { }
105
106 unsigned order;
107 TickSample sample;
108 };
109
110
111 class CodeEventsContainer {
112 public:
113 explicit CodeEventsContainer(
114 CodeEventRecord::Type type = CodeEventRecord::NONE) {
115 generic.type = type;
116 }
117 union {
118 CodeEventRecord generic;
119 #define DECLARE_CLASS(ignore, type) type type##_;
120 CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
121 #undef DECLARE_TYPE
122 };
123 };
124
125
126 // This class implements both the profile events processor thread and
127 // methods called by event producers: VM and stack sampler threads.
128 class ProfilerEventsProcessor : public base::Thread {
129 public:
130 ProfilerEventsProcessor(ProfileGenerator* generator,
131 sampler::Sampler* sampler,
132 base::TimeDelta period);
133 virtual ~ProfilerEventsProcessor();
134
135 // Thread control.
136 virtual void Run();
137 void StopSynchronously();
138 INLINE(bool running()) { return !!base::NoBarrier_Load(&running_); }
139 void Enqueue(const CodeEventsContainer& event);
140
141 // Puts current stack into tick sample events buffer.
142 void AddCurrentStack(Isolate* isolate, bool update_stats = false);
143 void AddDeoptStack(Isolate* isolate, Address from, int fp_to_sp_delta);
144
145 // Tick sample events are filled directly in the buffer of the circular
146 // queue (because the structure is of fixed width, but usually not all
147 // stack frame entries are filled.) This method returns a pointer to the
148 // next record of the buffer.
149 inline TickSample* StartTickSample();
150 inline void FinishTickSample();
151
152 // SamplingCircularQueue has stricter alignment requirements than a normal new
153 // can fulfil, so we need to provide our own new/delete here.
154 void* operator new(size_t size);
155 void operator delete(void* ptr);
156
157 private:
158 // Called from events processing thread (Run() method.)
159 bool ProcessCodeEvent();
160
161 enum SampleProcessingResult {
162 OneSampleProcessed,
163 FoundSampleForNextCodeEvent,
164 NoSamplesInQueue
165 };
166 SampleProcessingResult ProcessOneSample();
167
168 ProfileGenerator* generator_;
169 sampler::Sampler* sampler_;
170 base::Atomic32 running_;
171 const base::TimeDelta period_; // Samples & code events processing period.
172 LockedQueue<CodeEventsContainer> events_buffer_;
173 static const size_t kTickSampleBufferSize = 1 * MB;
174 static const size_t kTickSampleQueueLength =
175 kTickSampleBufferSize / sizeof(TickSampleEventRecord);
176 SamplingCircularQueue<TickSampleEventRecord,
177 kTickSampleQueueLength> ticks_buffer_;
178 LockedQueue<TickSampleEventRecord> ticks_from_vm_buffer_;
179 base::AtomicNumber<unsigned> last_code_event_id_;
180 unsigned last_processed_code_event_id_;
181 };
182
183 #define PROFILE(IsolateGetter, Call) \
184 do { \
185 Isolate* the_isolate = (IsolateGetter); \
186 v8::internal::Logger* logger = the_isolate->logger(); \
187 if (logger->is_logging_code_events() || the_isolate->is_profiling()) { \
188 logger->Call; \
189 } \
190 } while (false)
191
192 class CpuProfiler : public CodeEventListener {
193 public:
194 explicit CpuProfiler(Isolate* isolate);
195
196 CpuProfiler(Isolate* isolate,
197 CpuProfilesCollection* test_collection,
198 ProfileGenerator* test_generator,
199 ProfilerEventsProcessor* test_processor);
200
201 ~CpuProfiler() override;
202
203 void set_sampling_interval(base::TimeDelta value);
204 void CollectSample();
205 void StartProfiling(const char* title, bool record_samples = false);
206 void StartProfiling(String* title, bool record_samples);
207 CpuProfile* StopProfiling(const char* title);
208 CpuProfile* StopProfiling(String* title);
209 int GetProfilesCount();
210 CpuProfile* GetProfile(int index);
211 void DeleteAllProfiles();
212 void DeleteProfile(CpuProfile* profile);
213
214 // Invoked from stack sampler (thread or signal handler.)
215 inline TickSample* StartTickSample();
216 inline void FinishTickSample();
217
218 // Must be called via PROFILE macro, otherwise will crash when
219 // profiling is not enabled.
220 void CallbackEvent(Name* name, Address entry_point) override; 38 void CallbackEvent(Name* name, Address entry_point) override;
221 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code, 39 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
222 const char* comment) override; 40 const char* comment) override;
223 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code, 41 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
224 Name* name) override; 42 Name* name) override;
225 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code, 43 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
226 SharedFunctionInfo* shared, Name* script_name) override; 44 SharedFunctionInfo* shared, Name* script_name) override;
227 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code, 45 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
228 SharedFunctionInfo* shared, Name* script_name, int line, 46 SharedFunctionInfo* shared, Name* script_name, int line,
229 int column) override; 47 int column) override;
230 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code, 48 void CodeCreateEvent(Logger::LogEventsAndTags tag, AbstractCode* code,
231 int args_count) override; 49 int args_count) override;
232 void CodeMovingGCEvent() override {} 50 void CodeMovingGCEvent() override {}
233 void CodeMoveEvent(AbstractCode* from, Address to) override; 51 void CodeMoveEvent(AbstractCode* from, Address to) override;
234 void CodeDisableOptEvent(AbstractCode* code, 52 void CodeDisableOptEvent(AbstractCode* code,
235 SharedFunctionInfo* shared) override; 53 SharedFunctionInfo* shared) override;
236 void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta); 54 void CodeDeoptEvent(Code* code, Address pc, int fp_to_sp_delta);
237 void GetterCallbackEvent(Name* name, Address entry_point) override; 55 void GetterCallbackEvent(Name* name, Address entry_point) override;
238 void RegExpCodeCreateEvent(AbstractCode* code, String* source) override; 56 void RegExpCodeCreateEvent(AbstractCode* code, String* source) override;
239 void SetterCallbackEvent(Name* name, Address entry_point) override; 57 void SetterCallbackEvent(Name* name, Address entry_point) override;
240 void SharedFunctionInfoMoveEvent(Address from, Address to) override {} 58 void SharedFunctionInfoMoveEvent(Address from, Address to) override {}
241 59
242 bool is_profiling() const { return is_profiling_; } 60 void ResolveCodeEvent();
61 CodeEntry* NewCodeEntry(
62 Logger::LogEventsAndTags tag, const char* name,
63 const char* name_prefix = CodeEntry::kEmptyNamePrefix,
64 const char* resource_name = CodeEntry::kEmptyResourceName,
65 int line_number = v8::CpuProfileNode::kNoLineNumberInfo,
66 int column_number = v8::CpuProfileNode::kNoColumnNumberInfo,
67 JITLineInfoTable* line_info = NULL, Address instruction_start = NULL);
243 68
244 ProfileGenerator* generator() const { return generator_; } 69 void RegisterObserver(CodeEventObserver* observer);
245 ProfilerEventsProcessor* processor() const { return processor_; } 70 void RemoveObserver(CodeEventObserver* observer);
246 Isolate* isolate() const { return isolate_; } 71
72 const char* GetName(Name* name) {
73 if (!is_resolving_code_entry_) return "";
74 return function_and_resource_names_.GetName(name);
75 }
76 const char* GetName(int args_count) {
77 if (!is_resolving_code_entry_) return "";
78 return function_and_resource_names_.GetName(args_count);
79 }
80 const char* GetFunctionName(Name* name) {
81 if (!is_resolving_code_entry_) return "";
82 return function_and_resource_names_.GetFunctionName(name);
83 }
84 const char* GetFunctionName(const char* name) {
85 if (!is_resolving_code_entry_) return "";
86 return function_and_resource_names_.GetFunctionName(name);
87 }
247 88
248 private: 89 private:
249 void StartProcessorIfNotStarted();
250 void StopProcessorIfLastProfile(const char* title);
251 void StopProcessor();
252 void ResetProfiles();
253 void LogBuiltins();
254 void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code); 90 void RecordInliningInfo(CodeEntry* entry, AbstractCode* abstract_code);
255 void RecordDeoptInlinedFrames(CodeEntry* entry, AbstractCode* abstract_code); 91 void RecordDeoptInlinedFrames(CodeEntry* entry, AbstractCode* abstract_code);
256 Name* InferScriptName(Name* name, SharedFunctionInfo* info); 92 Name* InferScriptName(Name* name, SharedFunctionInfo* info);
257 93
258 Isolate* isolate_; 94 StringsStorage function_and_resource_names_;
259 base::TimeDelta sampling_interval_; 95 bool is_resolving_code_entry_;
260 CpuProfilesCollection* profiles_; 96 List<CodeEntry*> code_entries_;
261 ProfileGenerator* generator_; 97 List<CodeEventObserver*> observers_;
262 ProfilerEventsProcessor* processor_;
263 bool saved_is_logging_;
264 bool is_profiling_;
265 98
266 DISALLOW_COPY_AND_ASSIGN(CpuProfiler); 99 DISALLOW_COPY_AND_ASSIGN(ProfilerListener);
267 }; 100 };
268 101
269 } // namespace internal 102 } // namespace internal
270 } // namespace v8 103 } // namespace v8
271 104
272 105 #endif // V8_PROFILER_PROFILER_LISTENER_H_
273 #endif // V8_PROFILER_CPU_PROFILER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698