OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_OS_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
7 | 7 |
8 #include "vm/os.h" | 8 #include "vm/os.h" |
9 | 9 |
10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 | 31 |
32 namespace dart { | 32 namespace dart { |
33 | 33 |
34 // Linux CodeObservers. | 34 // Linux CodeObservers. |
35 | 35 |
36 DEFINE_FLAG(bool, generate_gdb_symbols, false, | 36 DEFINE_FLAG(bool, generate_gdb_symbols, false, |
37 "Generate symbols of generated dart functions for debugging with GDB"); | 37 "Generate symbols of generated dart functions for debugging with GDB"); |
38 DEFINE_FLAG(bool, generate_perf_events_symbols, false, | 38 DEFINE_FLAG(bool, generate_perf_events_symbols, false, |
39 "Generate events symbols for profiling with perf"); | 39 "Generate events symbols for profiling with perf"); |
40 DEFINE_FLAG(bool, ll_prof, false, | |
41 "Generate compiled code log file for processing with ll_prof.py."); | |
42 DEFINE_FLAG(charp, generate_pprof_symbols, NULL, | |
43 "Writes pprof events symbols to the provided file"); | |
44 DEFINE_FLAG(bool, generate_perf_jitdump, false, | 40 DEFINE_FLAG(bool, generate_perf_jitdump, false, |
45 "Writes jitdump data for profiling with perf annotate"); | 41 "Writes jitdump data for profiling with perf annotate"); |
46 | 42 |
47 class LowLevelProfileCodeObserver : public CodeObserver { | |
48 public: | |
49 LowLevelProfileCodeObserver() { | |
50 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | |
51 if (file_open == NULL) { | |
52 return; | |
53 } | |
54 const char* filename = "v8.log.ll"; | |
55 log_file_ = (*file_open)(filename, true); | |
56 #if defined(TARGET_ARCH_IA32) | |
57 const char arch[] = "ia32"; | |
58 #elif defined(TARGET_ARCH_X64) | |
59 const char arch[] = "x64"; | |
60 #elif defined(TARGET_ARCH_ARM) | |
61 const char arch[] = "arm"; | |
62 #elif defined(TARGET_ARCH_ARM64) | |
63 const char arch[] = "arm64"; | |
64 #elif defined(TARGET_ARCH_MIPS) | |
65 const char arch[] = "mips"; | |
66 #else | |
67 #error Unknown architecture. | |
68 #endif | |
69 LowLevelLogWriteBytes(arch, sizeof(arch)); | |
70 } | |
71 | |
72 ~LowLevelProfileCodeObserver() { | |
73 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | |
74 if (file_close == NULL) { | |
75 return; | |
76 } | |
77 ASSERT(log_file_ != NULL); | |
78 (*file_close)(log_file_); | |
79 } | |
80 | |
81 virtual bool IsActive() const { | |
82 return FLAG_ll_prof; | |
83 } | |
84 | |
85 struct LowLevelCodeCreateStruct { | |
86 static const char kTag = 'C'; | |
87 | |
88 int32_t name_size; | |
89 uword code_address; | |
90 int32_t code_size; | |
91 }; | |
92 | |
93 template <typename T> | |
94 void LowLevelLogWriteStruct(const T& s) { | |
95 char tag = T::kTag; | |
96 LowLevelLogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag)); | |
97 LowLevelLogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s)); | |
98 } | |
99 | |
100 void LowLevelLogWriteBytes(const char* bytes, int size) { | |
101 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | |
102 ASSERT(file_write != NULL); | |
103 (file_write)(bytes, size, log_file_); | |
104 } | |
105 | |
106 virtual void Notify(const char* name, | |
107 uword base, | |
108 uword prologue_offset, | |
109 uword size, | |
110 bool optimized) { | |
111 const char* marker = optimized ? "*" : ""; | |
112 char* name_buffer = | |
113 Isolate::Current()->current_zone()->PrintToString("%s%s", marker, name); | |
114 intptr_t len = strlen(name_buffer); | |
115 | |
116 LowLevelCodeCreateStruct event; | |
117 event.name_size = len; | |
118 event.code_address = base; | |
119 event.code_size = size; | |
120 | |
121 { | |
122 MutexLocker ml(CodeObservers::mutex()); | |
123 LowLevelLogWriteStruct(event); | |
124 LowLevelLogWriteBytes(name_buffer, len); | |
125 LowLevelLogWriteBytes(reinterpret_cast<char*>(base), size); | |
126 } | |
127 } | |
128 | |
129 private: | |
130 void* log_file_; | |
131 | |
132 DISALLOW_COPY_AND_ASSIGN(LowLevelProfileCodeObserver); | |
133 }; | |
134 | |
135 | 43 |
136 class PerfCodeObserver : public CodeObserver { | 44 class PerfCodeObserver : public CodeObserver { |
137 public: | 45 public: |
138 PerfCodeObserver() { | 46 PerfCodeObserver() : out_file_(NULL) { |
139 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | 47 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
140 if (file_open == NULL) { | 48 if (file_open == NULL) { |
141 return; | 49 return; |
142 } | 50 } |
143 const char* format = "/tmp/perf-%" Pd ".map"; | 51 const char* format = "/tmp/perf-%" Pd ".map"; |
144 intptr_t pid = getpid(); | 52 intptr_t pid = getpid(); |
145 intptr_t len = OS::SNPrint(NULL, 0, format, pid); | 53 intptr_t len = OS::SNPrint(NULL, 0, format, pid); |
146 char* filename = new char[len + 1]; | 54 char* filename = new char[len + 1]; |
147 OS::SNPrint(filename, len + 1, format, pid); | 55 OS::SNPrint(filename, len + 1, format, pid); |
148 out_file_ = (*file_open)(filename, true); | 56 out_file_ = (*file_open)(filename, true); |
149 delete[] filename; | 57 delete[] filename; |
150 } | 58 } |
151 | 59 |
152 ~PerfCodeObserver() { | 60 ~PerfCodeObserver() { |
153 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | 61 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
154 if (file_close == NULL) { | 62 if ((file_close == NULL) || (out_file_ == NULL)) { |
155 return; | 63 return; |
156 } | 64 } |
157 ASSERT(out_file_ != NULL); | |
158 (*file_close)(out_file_); | 65 (*file_close)(out_file_); |
159 } | 66 } |
160 | 67 |
161 virtual bool IsActive() const { | 68 virtual bool IsActive() const { |
162 return FLAG_generate_perf_events_symbols; | 69 return FLAG_generate_perf_events_symbols && (out_file_ != NULL); |
163 } | 70 } |
164 | 71 |
165 virtual void Notify(const char* name, | 72 virtual void Notify(const char* name, |
166 uword base, | 73 uword base, |
167 uword prologue_offset, | 74 uword prologue_offset, |
168 uword size, | 75 uword size, |
169 bool optimized) { | 76 bool optimized) { |
170 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | 77 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
171 ASSERT(file_write != NULL); | 78 if ((file_write == NULL) || (out_file_ == NULL)) { |
| 79 return; |
| 80 } |
172 const char* format = "%" Px " %" Px " %s%s\n"; | 81 const char* format = "%" Px " %" Px " %s%s\n"; |
173 const char* marker = optimized ? "*" : ""; | 82 const char* marker = optimized ? "*" : ""; |
174 intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name); | 83 intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name); |
175 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 84 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
176 OS::SNPrint(buffer, len + 1, format, base, size, marker, name); | 85 OS::SNPrint(buffer, len + 1, format, base, size, marker, name); |
177 ASSERT(out_file_ != NULL); | |
178 { | 86 { |
179 MutexLocker ml(CodeObservers::mutex()); | 87 MutexLocker ml(CodeObservers::mutex()); |
180 (*file_write)(buffer, len, out_file_); | 88 (*file_write)(buffer, len, out_file_); |
181 } | 89 } |
182 } | 90 } |
183 | 91 |
184 private: | 92 private: |
185 void* out_file_; | 93 void* out_file_; |
186 | 94 |
187 DISALLOW_COPY_AND_ASSIGN(PerfCodeObserver); | 95 DISALLOW_COPY_AND_ASSIGN(PerfCodeObserver); |
188 }; | 96 }; |
189 | 97 |
190 class PprofCodeObserver : public CodeObserver { | |
191 public: | |
192 PprofCodeObserver() { | |
193 pprof_symbol_generator_ = DebugInfo::NewGenerator(); | |
194 } | |
195 | |
196 ~PprofCodeObserver() { | |
197 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | |
198 if (file_open == NULL) { | |
199 return; | |
200 } | |
201 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | |
202 if (file_close == NULL) { | |
203 return; | |
204 } | |
205 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | |
206 if (file_write == NULL) { | |
207 return; | |
208 } | |
209 if (FLAG_generate_pprof_symbols == NULL) { | |
210 return; | |
211 } | |
212 const char* filename = FLAG_generate_pprof_symbols; | |
213 void* out_file = (*file_open)(filename, true); | |
214 ASSERT(out_file != NULL); | |
215 DebugInfo::ByteBuffer* debug_region = new DebugInfo::ByteBuffer(); | |
216 ASSERT(debug_region != NULL); | |
217 pprof_symbol_generator_->WriteToMemory(debug_region); | |
218 int buffer_size = debug_region->size(); | |
219 void* buffer = debug_region->data(); | |
220 if (buffer_size > 0) { | |
221 MutexLocker ml(CodeObservers::mutex()); | |
222 ASSERT(buffer != NULL); | |
223 (*file_write)(buffer, buffer_size, out_file); | |
224 } | |
225 delete debug_region; | |
226 (*file_close)(out_file); | |
227 DebugInfo::UnregisterAllSections(); | |
228 } | |
229 | |
230 virtual bool IsActive() const { | |
231 return FLAG_generate_pprof_symbols != NULL; | |
232 } | |
233 | |
234 virtual void Notify(const char* name, | |
235 uword base, | |
236 uword prologue_offset, | |
237 uword size, | |
238 bool optimized) { | |
239 ASSERT(pprof_symbol_generator_ != NULL); | |
240 pprof_symbol_generator_->AddCode(base, size); | |
241 pprof_symbol_generator_->AddCodeRegion(name, base, size); | |
242 } | |
243 | |
244 private: | |
245 DebugInfo* pprof_symbol_generator_; | |
246 | |
247 DISALLOW_COPY_AND_ASSIGN(PprofCodeObserver); | |
248 }; | |
249 | 98 |
250 class GdbCodeObserver : public CodeObserver { | 99 class GdbCodeObserver : public CodeObserver { |
251 public: | 100 public: |
252 GdbCodeObserver() { } | 101 GdbCodeObserver() { } |
253 | 102 |
254 virtual bool IsActive() const { | 103 virtual bool IsActive() const { |
255 return FLAG_generate_gdb_symbols; | 104 return FLAG_generate_gdb_symbols; |
256 } | 105 } |
257 | 106 |
258 virtual void Notify(const char* name, | 107 virtual void Notify(const char* name, |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 (str[i + 2] != '\0')) { | 578 (str[i + 2] != '\0')) { |
730 base = 16; | 579 base = 16; |
731 } | 580 } |
732 errno = 0; | 581 errno = 0; |
733 *value = strtoll(str, &endptr, base); | 582 *value = strtoll(str, &endptr, base); |
734 return ((errno == 0) && (endptr != str) && (*endptr == 0)); | 583 return ((errno == 0) && (endptr != str) && (*endptr == 0)); |
735 } | 584 } |
736 | 585 |
737 | 586 |
738 void OS::RegisterCodeObservers() { | 587 void OS::RegisterCodeObservers() { |
739 if (FLAG_ll_prof) { | |
740 CodeObservers::Register(new LowLevelProfileCodeObserver); | |
741 } | |
742 if (FLAG_generate_perf_events_symbols) { | 588 if (FLAG_generate_perf_events_symbols) { |
743 CodeObservers::Register(new PerfCodeObserver); | 589 CodeObservers::Register(new PerfCodeObserver); |
744 } | 590 } |
745 if (FLAG_generate_gdb_symbols) { | 591 if (FLAG_generate_gdb_symbols) { |
746 CodeObservers::Register(new GdbCodeObserver); | 592 CodeObservers::Register(new GdbCodeObserver); |
747 } | 593 } |
748 if (FLAG_generate_pprof_symbols != NULL) { | |
749 CodeObservers::Register(new PprofCodeObserver); | |
750 } | |
751 if (FLAG_generate_perf_jitdump) { | 594 if (FLAG_generate_perf_jitdump) { |
752 CodeObservers::Register(new JitdumpCodeObserver); | 595 CodeObservers::Register(new JitdumpCodeObserver); |
753 } | 596 } |
754 #if defined(DART_VTUNE_SUPPORT) | 597 #if defined(DART_VTUNE_SUPPORT) |
755 CodeObservers::Register(new VTuneCodeObserver); | 598 CodeObservers::Register(new VTuneCodeObserver); |
756 #endif | 599 #endif |
757 } | 600 } |
758 | 601 |
759 | 602 |
760 void OS::PrintErr(const char* format, ...) { | 603 void OS::PrintErr(const char* format, ...) { |
(...skipping 23 matching lines...) Expand all Loading... |
784 } | 627 } |
785 | 628 |
786 | 629 |
787 void OS::Exit(int code) { | 630 void OS::Exit(int code) { |
788 exit(code); | 631 exit(code); |
789 } | 632 } |
790 | 633 |
791 } // namespace dart | 634 } // namespace dart |
792 | 635 |
793 #endif // defined(TARGET_OS_LINUX) | 636 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |