| 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 |