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/code_observers.h" | 5 #include "vm/code_observers.h" |
6 | 6 |
7 #include "vm/dart.h" | |
8 #include "vm/debuginfo.h" | |
9 #include "vm/flags.h" | |
10 #include "vm/isolate.h" | |
11 #include "vm/os.h" | 7 #include "vm/os.h" |
12 #include "vm/vtune.h" | |
13 #include "vm/zone.h" | |
14 | 8 |
15 namespace dart { | 9 namespace dart { |
16 | 10 |
17 DEFINE_FLAG(bool, generate_gdb_symbols, false, | |
18 "Generate symbols of generated dart functions for debugging with GDB"); | |
19 DEFINE_FLAG(bool, generate_perf_events_symbols, false, | |
20 "Generate events symbols for profiling with perf"); | |
21 | |
22 intptr_t CodeObservers::observers_length_ = 0; | 11 intptr_t CodeObservers::observers_length_ = 0; |
23 CodeObserver** CodeObservers::observers_ = NULL; | 12 CodeObserver** CodeObservers::observers_ = NULL; |
24 | 13 |
25 | 14 |
26 void CodeObservers::Register(CodeObserver* observer) { | 15 void CodeObservers::Register(CodeObserver* observer) { |
27 observers_length_++; | 16 observers_length_++; |
28 observers_ = reinterpret_cast<CodeObserver**>( | 17 observers_ = reinterpret_cast<CodeObserver**>( |
29 realloc(observers_, sizeof(observer) * observers_length_)); | 18 realloc(observers_, sizeof(observer) * observers_length_)); |
30 if (observers_ == NULL) { | 19 if (observers_ == NULL) { |
31 FATAL("failed to grow code observers array"); | 20 FATAL("failed to grow code observers array"); |
(...skipping 17 matching lines...) Expand all Loading... |
49 | 38 |
50 | 39 |
51 bool CodeObservers::AreActive() { | 40 bool CodeObservers::AreActive() { |
52 for (intptr_t i = 0; i < observers_length_; i++) { | 41 for (intptr_t i = 0; i < observers_length_; i++) { |
53 if (observers_[i]->IsActive()) return true; | 42 if (observers_[i]->IsActive()) return true; |
54 } | 43 } |
55 return false; | 44 return false; |
56 } | 45 } |
57 | 46 |
58 | 47 |
59 class PerfCodeObserver : public CodeObserver { | 48 void CodeObservers::DeleteAll() { |
60 public: | 49 for (intptr_t i = 0; i < observers_length_; i++) { |
61 PerfCodeObserver() { | 50 delete observers_[i]; |
62 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | |
63 if (file_open == NULL) { | |
64 return; | |
65 } | |
66 // TODO(7321): Move OS-specific code for perf profiling to the OS abstraction | |
67 #if defined(TARGET_OS_LINUX) | |
68 const char* format = "/tmp/perf-%ld.map"; | |
69 intptr_t pid = getpid(); | |
70 intptr_t len = OS::SNPrint(NULL, 0, format, pid); | |
71 char* filename = new char[len + 1]; | |
72 OS::SNPrint(filename, len + 1, format, pid); | |
73 out_file_ = (*file_open)(filename); | |
74 #endif | |
75 } | 51 } |
76 | 52 delete[] observers_; |
77 // Not currently being called | 53 } |
78 ~PerfCodeObserver() { | |
79 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | |
80 if (file_close == NULL) { | |
81 return; | |
82 } | |
83 ASSERT(out_file_ != NULL); | |
84 (*file_close)(out_file_); | |
85 } | |
86 | |
87 virtual bool IsActive() const { | |
88 return FLAG_generate_perf_events_symbols; | |
89 } | |
90 | |
91 virtual void Notify(const char* name, | |
92 uword base, | |
93 uword prologue_offset, | |
94 uword size, | |
95 bool optimized) { | |
96 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | |
97 ASSERT(file_write != NULL); | |
98 const char* format = "%"Px" %"Px" %s%s\n"; | |
99 const char* marker = optimized ? "*" : ""; | |
100 intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name); | |
101 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
102 OS::SNPrint(buffer, len + 1, format, base, size, marker, name); | |
103 ASSERT(out_file_ != NULL); | |
104 (*file_write)(buffer, len, out_file_); | |
105 } | |
106 | |
107 private: | |
108 void* out_file_; | |
109 }; | |
110 | |
111 | |
112 class PprofCodeObserver : public CodeObserver { | |
113 public: | |
114 virtual bool IsActive() const { | |
115 return Dart::pprof_symbol_generator() != NULL; | |
116 } | |
117 | |
118 virtual void Notify(const char* name, | |
119 uword base, | |
120 uword prologue_offset, | |
121 uword size, | |
122 bool optimized) { | |
123 DebugInfo* pprof_symbol_generator = Dart::pprof_symbol_generator(); | |
124 ASSERT(pprof_symbol_generator != NULL); | |
125 pprof_symbol_generator->AddCode(base, size); | |
126 pprof_symbol_generator->AddCodeRegion(name, base, size); | |
127 } | |
128 }; | |
129 | |
130 | |
131 class GdbCodeObserver : public CodeObserver { | |
132 public: | |
133 virtual bool IsActive() const { | |
134 return FLAG_generate_gdb_symbols; | |
135 } | |
136 | |
137 virtual void Notify(const char* name, | |
138 uword base, | |
139 uword prologue_offset, | |
140 uword size, | |
141 bool optimized) { | |
142 if (prologue_offset > 0) { | |
143 // In order to ensure that gdb sees the first instruction of a function | |
144 // as the prologue sequence we register two symbols for the cases when | |
145 // the prologue sequence is not the first instruction: | |
146 // <name>_entry is used for code preceding the prologue sequence. | |
147 // <name> for rest of the code (first instruction is prologue sequence). | |
148 const char* kFormat = "%s_%s"; | |
149 intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry"); | |
150 char* pname = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | |
151 OS::SNPrint(pname, (len + 1), kFormat, name, "entry"); | |
152 DebugInfo::RegisterSection(pname, base, size); | |
153 DebugInfo::RegisterSection(name, | |
154 (base + prologue_offset), | |
155 (size - prologue_offset)); | |
156 } else { | |
157 DebugInfo::RegisterSection(name, base, size); | |
158 } | |
159 } | |
160 }; | |
161 | 54 |
162 | 55 |
163 void CodeObservers::InitOnce() { | 56 void CodeObservers::InitOnce() { |
164 // TODO(7321): Move flag registration to the OS abstraction | 57 OS::RegisterCodeObservers(); |
165 if (FLAG_generate_perf_events_symbols) { | |
166 Register(new PerfCodeObserver); | |
167 } | |
168 Register(new PprofCodeObserver); | |
169 Register(new GdbCodeObserver); | |
170 #if defined(DART_VTUNE_SUPPORT) | |
171 Register(new VTuneCodeObserver); | |
172 #endif | |
173 } | 58 } |
174 | 59 |
175 | 60 |
176 } // namespace dart | 61 } // namespace dart |
OLD | NEW |