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

Side by Side Diff: runtime/vm/os_linux.cc

Issue 1711163002: Remove more things (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 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 (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
11 #include <limits.h> // NOLINT 11 #include <limits.h> // NOLINT
12 #include <malloc.h> // NOLINT 12 #include <malloc.h> // NOLINT
13 #include <time.h> // NOLINT 13 #include <time.h> // NOLINT
14 #include <sys/resource.h> // NOLINT 14 #include <sys/resource.h> // NOLINT
15 #include <sys/time.h> // NOLINT 15 #include <sys/time.h> // NOLINT
16 #include <sys/types.h> // NOLINT 16 #include <sys/types.h> // NOLINT
17 #include <sys/syscall.h> // NOLINT 17 #include <sys/syscall.h> // NOLINT
18 #include <sys/stat.h> // NOLINT 18 #include <sys/stat.h> // NOLINT
19 #include <fcntl.h> // NOLINT 19 #include <fcntl.h> // NOLINT
20 #include <unistd.h> // NOLINT 20 #include <unistd.h> // NOLINT
21 21
22 #include "platform/utils.h" 22 #include "platform/utils.h"
23 #include "vm/code_observers.h" 23 #include "vm/code_observers.h"
24 #include "vm/dart.h" 24 #include "vm/dart.h"
25 #include "vm/debuginfo.h" 25 #include "vm/flags.h"
26 #include "vm/isolate.h" 26 #include "vm/isolate.h"
27 #include "vm/lockers.h" 27 #include "vm/lockers.h"
28 #include "vm/os_thread.h" 28 #include "vm/os_thread.h"
29 #include "vm/vtune.h"
30 #include "vm/zone.h" 29 #include "vm/zone.h"
31 30
32 31
33 namespace dart { 32 namespace dart {
34 33
35 // Linux CodeObservers. 34 #ifndef PRODUCT
36 35
37 DEFINE_FLAG(bool, generate_gdb_symbols, false,
38 "Generate symbols of generated dart functions for debugging with GDB");
39 DEFINE_FLAG(bool, generate_perf_events_symbols, false, 36 DEFINE_FLAG(bool, generate_perf_events_symbols, false,
40 "Generate events symbols for profiling with perf"); 37 "Generate events symbols for profiling with perf");
41 DEFINE_FLAG(bool, generate_perf_jitdump, false,
42 "Writes jitdump data for profiling with perf annotate");
43 38
44 39 // Linux CodeObservers.
45 class PerfCodeObserver : public CodeObserver { 40 class PerfCodeObserver : public CodeObserver {
46 public: 41 public:
47 PerfCodeObserver() : out_file_(NULL) { 42 PerfCodeObserver() : out_file_(NULL) {
48 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); 43 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
49 if (file_open == NULL) { 44 if (file_open == NULL) {
50 return; 45 return;
51 } 46 }
52 intptr_t pid = getpid(); 47 intptr_t pid = getpid();
53 char* filename = OS::SCreate(NULL, "/tmp/perf-%" Pd ".map", pid); 48 char* filename = OS::SCreate(NULL, "/tmp/perf-%" Pd ".map", pid);
54 out_file_ = (*file_open)(filename, true); 49 out_file_ = (*file_open)(filename, true);
(...skipping 30 matching lines...) Expand all
85 } 80 }
86 } 81 }
87 82
88 private: 83 private:
89 void* out_file_; 84 void* out_file_;
90 85
91 DISALLOW_COPY_AND_ASSIGN(PerfCodeObserver); 86 DISALLOW_COPY_AND_ASSIGN(PerfCodeObserver);
92 }; 87 };
93 88
94 89
95 class GdbCodeObserver : public CodeObserver { 90 #endif // !PRODUCT
96 public:
97 GdbCodeObserver() { }
98
99 virtual bool IsActive() const {
100 return FLAG_generate_gdb_symbols;
101 }
102
103 virtual void Notify(const char* name,
104 uword base,
105 uword prologue_offset,
106 uword size,
107 bool optimized) {
108 if (prologue_offset > 0) {
109 // In order to ensure that gdb sees the first instruction of a function
110 // as the prologue sequence we register two symbols for the cases when
111 // the prologue sequence is not the first instruction:
112 // <name>_entry is used for code preceding the prologue sequence.
113 // <name> for rest of the code (first instruction is prologue sequence).
114 char* pname = OS::SCreate(Thread::Current()->zone(),
115 "%s_%s", name, "entry");
116 DebugInfo::RegisterSection(pname, base, size);
117 DebugInfo::RegisterSection(name,
118 (base + prologue_offset),
119 (size - prologue_offset));
120 } else {
121 DebugInfo::RegisterSection(name, base, size);
122 }
123 }
124
125 private:
126 DISALLOW_COPY_AND_ASSIGN(GdbCodeObserver);
127 };
128
129
130 #define CLOCKFD 3
131 #define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) // NOLINT
132
133 class JitdumpCodeObserver : public CodeObserver {
Vyacheslav Egorov (Google) 2016/05/10 09:24:16 How I am supposed to profile JIT code with CPU cou
134 public:
135 JitdumpCodeObserver() {
136 ASSERT(FLAG_generate_perf_jitdump);
137 out_file_ = NULL;
138 clock_fd_ = -1;
139 clock_id_ = kInvalidClockId;
140 code_sequence_ = 0;
141 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
142 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
143 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
144 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
145 return;
146 }
147 // The Jitdump code observer writes all jitted code into the file
148 // 'perf.jitdump' in the current working directory. We open the file once
149 // on initialization and close it when the VM is going down.
150 {
151 // Open the file.
152 const char* filename = "perf.jitdump";
153 out_file_ = (*file_open)(filename, true);
154 ASSERT(out_file_ != NULL);
155 // Write the jit dump header.
156 WriteHeader();
157 }
158 // perf uses an internal clock and because our output is merged with data
159 // collected by perf our timestamps must be consistent. Using
160 // the posix-clock-module (/dev/trace_clock) as our time source ensures
161 // we are consistent with the perf timestamps.
162 clock_id_ = kInvalidClockId;
163 clock_fd_ = open("/dev/trace_clock", O_RDONLY);
164 if (clock_fd_ >= 0) {
165 clock_id_ = FD_TO_CLOCKID(clock_fd_);
166 }
167 }
168
169 ~JitdumpCodeObserver() {
170 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
171 if (file_close == NULL) {
172 return;
173 }
174 ASSERT(out_file_ != NULL);
175 (*file_close)(out_file_);
176 if (clock_fd_ >= 0) {
177 close(clock_fd_);
178 }
179 }
180
181 virtual bool IsActive() const {
182 return FLAG_generate_perf_jitdump && (out_file_ != NULL);
183 }
184
185 virtual void Notify(const char* name,
186 uword base,
187 uword prologue_offset,
188 uword size,
189 bool optimized) {
190 WriteCodeLoad(name, base, prologue_offset, size, optimized);
191 }
192
193 private:
194 static const uint32_t kJitHeaderMagic = 0x4A695444;
195 static const uint32_t kJitHeaderMagicSw = 0x4454694A;
196 static const uint32_t kJitHeaderVersion = 0x1;
197 static const uint32_t kElfMachIA32 = 3;
198 static const uint32_t kElfMachX64 = 62;
199 static const uint32_t kElfMachARM = 40;
200 // TODO(zra): Find the right ARM64 constant.
201 static const uint32_t kElfMachARM64 = 40;
202 static const uint32_t kElfMachMIPS = 10;
203 static const int kInvalidClockId = -1;
204
205 struct jitheader {
206 uint32_t magic; /* characters "jItD" */
207 uint32_t version; /* header version */
208 uint32_t total_size; /* total size of header */
209 uint32_t elf_mach; /* elf mach target */
210 uint32_t pad1; /* reserved */
211 uint32_t pid; /* JIT process id */
212 uint64_t timestamp; /* timestamp */
213 };
214
215 /* record prefix (mandatory in each record) */
216 struct jr_prefix {
217 uint32_t id;
218 uint32_t total_size;
219 uint64_t timestamp;
220 };
221
222 enum jit_record_type {
223 JIT_CODE_LOAD = 0,
224 /* JIT_CODE_MOVE = 1, */
225 /* JIT_CODE_DEBUG_INFO = 2, */
226 /* JIT_CODE_CLOSE = 3, */
227 JIT_CODE_MAX = 4,
228 };
229
230 struct jr_code_load {
231 struct jr_prefix prefix;
232 uint32_t pid;
233 uint32_t tid;
234 uint64_t vma;
235 uint64_t code_addr;
236 uint64_t code_size;
237 uint64_t code_index;
238 };
239
240 const char* GenerateCodeName(const char* name, bool optimized) {
241 const char* marker = optimized ? "*" : "";
242 return OS::SCreate(Thread::Current()->zone(), "%s%s", marker, name);
243 }
244
245 uint32_t GetElfMach() {
246 #if defined(TARGET_ARCH_IA32)
247 return kElfMachIA32;
248 #elif defined(TARGET_ARCH_X64)
249 return kElfMachX64;
250 #elif defined(TARGET_ARCH_ARM)
251 return kElfMachARM;
252 #elif defined(TARGET_ARCH_ARM64)
253 return kElfMachARM64;
254 #elif defined(TARGET_ARCH_MIPS)
255 return kElfMachMIPS;
256 #else
257 #error Unknown architecture.
258 #endif
259 }
260
261 pid_t gettid() {
262 // libc doesn't wrap the Linux-specific gettid system call.
263 // Note that this thread id is not the same as the posix thread id.
264 return syscall(SYS_gettid);
265 }
266
267 uint64_t GetKernelTimeNanos() {
268 if (clock_id_ != kInvalidClockId) {
269 struct timespec ts;
270 int r = clock_gettime(clock_id_, &ts);
271 ASSERT(r == 0);
272 uint64_t nanos = static_cast<uint64_t>(ts.tv_sec) *
273 static_cast<uint64_t>(kNanosecondsPerSecond);
274 nanos += static_cast<uint64_t>(ts.tv_nsec);
275 return nanos;
276 } else {
277 return OS::GetCurrentTimeMicros() * kNanosecondsPerMicrosecond;
278 }
279 }
280
281 void WriteHeader() {
282 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
283 ASSERT(file_write != NULL);
284 ASSERT(out_file_ != NULL);
285 jitheader header;
286 header.magic = kJitHeaderMagic;
287 header.version = kJitHeaderVersion;
288 header.total_size = sizeof(jitheader);
289 header.pad1 = 0x0;
290 header.elf_mach = GetElfMach();
291 header.pid = getpid();
292 header.timestamp = GetKernelTimeNanos();
293 {
294 MutexLocker ml(CodeObservers::mutex());
295 (*file_write)(&header, sizeof(header), out_file_);
296 }
297 }
298
299 void WriteCodeLoad(const char* name, uword base, uword prologue_offset,
300 uword code_size, bool optimized) {
301 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
302 ASSERT(file_write != NULL);
303 ASSERT(out_file_ != NULL);
304
305 const char* code_name = GenerateCodeName(name, optimized);
306 const intptr_t code_name_size = strlen(code_name) + 1;
307 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(base);
308
309 jr_code_load code_load;
310 code_load.prefix.id = JIT_CODE_LOAD;
311 code_load.prefix.total_size =
312 sizeof(code_load) + code_name_size + code_size;
313 code_load.prefix.timestamp = GetKernelTimeNanos();
314 code_load.pid = getpid();
315 code_load.tid = gettid();
316 code_load.vma = 0x0; // Our addresses are absolute.
317 code_load.code_addr = base;
318 code_load.code_size = code_size;
319
320 {
321 MutexLocker ml(CodeObservers::mutex());
322 // Set this field under the index.
323 code_load.code_index = code_sequence_++;
324 // Write structures.
325 (*file_write)(&code_load, sizeof(code_load), out_file_);
326 (*file_write)(code_name, code_name_size, out_file_);
327 (*file_write)(code_pointer, code_size, out_file_);
328 }
329 }
330
331 void* out_file_;
332 int clock_fd_;
333 int clock_id_;
334 uint64_t code_sequence_;
335 DISALLOW_COPY_AND_ASSIGN(JitdumpCodeObserver);
336 };
337
338 91
339 const char* OS::Name() { 92 const char* OS::Name() {
340 return "linux"; 93 return "linux";
341 } 94 }
342 95
343 96
344 intptr_t OS::ProcessId() { 97 intptr_t OS::ProcessId() {
345 return static_cast<intptr_t>(getpid()); 98 return static_cast<intptr_t>(getpid());
346 } 99 }
347 100
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 (str[i + 2] != '\0')) { 363 (str[i + 2] != '\0')) {
611 base = 16; 364 base = 16;
612 } 365 }
613 errno = 0; 366 errno = 0;
614 *value = strtoll(str, &endptr, base); 367 *value = strtoll(str, &endptr, base);
615 return ((errno == 0) && (endptr != str) && (*endptr == 0)); 368 return ((errno == 0) && (endptr != str) && (*endptr == 0));
616 } 369 }
617 370
618 371
619 void OS::RegisterCodeObservers() { 372 void OS::RegisterCodeObservers() {
373 #ifndef PRODUCT
620 if (FLAG_generate_perf_events_symbols) { 374 if (FLAG_generate_perf_events_symbols) {
621 CodeObservers::Register(new PerfCodeObserver); 375 CodeObservers::Register(new PerfCodeObserver);
622 } 376 }
623 if (FLAG_generate_gdb_symbols) { 377 #endif // !PRODUCT
624 CodeObservers::Register(new GdbCodeObserver);
625 }
626 if (FLAG_generate_perf_jitdump) {
627 CodeObservers::Register(new JitdumpCodeObserver);
628 }
629 #if defined(DART_VTUNE_SUPPORT)
630 CodeObservers::Register(new VTuneCodeObserver);
631 #endif
632 } 378 }
633 379
634 380
635 void OS::PrintErr(const char* format, ...) { 381 void OS::PrintErr(const char* format, ...) {
636 va_list args; 382 va_list args;
637 va_start(args, format); 383 va_start(args, format);
638 VFPrint(stderr, format, args); 384 VFPrint(stderr, format, args);
639 va_end(args); 385 va_end(args);
640 } 386 }
641 387
(...skipping 17 matching lines...) Expand all
659 } 405 }
660 406
661 407
662 void OS::Exit(int code) { 408 void OS::Exit(int code) {
663 exit(code); 409 exit(code);
664 } 410 }
665 411
666 } // namespace dart 412 } // namespace dart
667 413
668 #endif // defined(TARGET_OS_LINUX) 414 #endif // defined(TARGET_OS_LINUX)
OLDNEW
« runtime/vm/dart.cc ('K') | « runtime/vm/os_android.cc ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698