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

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

Issue 23437046: Add support for dumping code in jitdump file format (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
18 #include <sys/stat.h> // NOLINT
19 #include <fcntl.h> // NOLINT
17 #include <unistd.h> // NOLINT 20 #include <unistd.h> // NOLINT
18 21
19 #include "platform/utils.h" 22 #include "platform/utils.h"
20 #include "vm/code_observers.h" 23 #include "vm/code_observers.h"
21 #include "vm/dart.h" 24 #include "vm/dart.h"
22 #include "vm/debuginfo.h" 25 #include "vm/debuginfo.h"
23 #include "vm/isolate.h" 26 #include "vm/isolate.h"
24 #include "vm/vtune.h" 27 #include "vm/vtune.h"
25 #include "vm/zone.h" 28 #include "vm/zone.h"
26 29
27 30
28 namespace dart { 31 namespace dart {
29 32
30 // Linux CodeObservers. 33 // Linux CodeObservers.
31 34
32 DEFINE_FLAG(bool, generate_gdb_symbols, false, 35 DEFINE_FLAG(bool, generate_gdb_symbols, false,
33 "Generate symbols of generated dart functions for debugging with GDB"); 36 "Generate symbols of generated dart functions for debugging with GDB");
34 DEFINE_FLAG(bool, generate_perf_events_symbols, false, 37 DEFINE_FLAG(bool, generate_perf_events_symbols, false,
35 "Generate events symbols for profiling with perf"); 38 "Generate events symbols for profiling with perf");
36 DEFINE_FLAG(bool, ll_prof, false, 39 DEFINE_FLAG(bool, ll_prof, false,
37 "Generate compiled code log file for processing with ll_prof.py."); 40 "Generate compiled code log file for processing with ll_prof.py.");
38 DEFINE_FLAG(charp, generate_pprof_symbols, NULL, 41 DEFINE_FLAG(charp, generate_pprof_symbols, NULL,
39 "Writes pprof events symbols to the provided file"); 42 "Writes pprof events symbols to the provided file");
43 DEFINE_FLAG(bool, generate_perf_jitdump, true,
44 "Writes jitdump data for profiling with perf annotate");
40 45
41 class LowLevelProfileCodeObserver : public CodeObserver { 46 class LowLevelProfileCodeObserver : public CodeObserver {
42 public: 47 public:
43 LowLevelProfileCodeObserver() { 48 LowLevelProfileCodeObserver() {
44 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); 49 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
45 if (file_open == NULL) { 50 if (file_open == NULL) {
46 return; 51 return;
47 } 52 }
48 const char* filename = "v8.log.ll"; 53 const char* filename = "v8.log.ll";
49 log_file_ = (*file_open)(filename, true); 54 log_file_ = (*file_open)(filename, true);
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 } else { 267 } else {
263 DebugInfo::RegisterSection(name, base, size); 268 DebugInfo::RegisterSection(name, base, size);
264 } 269 }
265 } 270 }
266 271
267 private: 272 private:
268 DISALLOW_COPY_AND_ASSIGN(GdbCodeObserver); 273 DISALLOW_COPY_AND_ASSIGN(GdbCodeObserver);
269 }; 274 };
270 275
271 276
277 #define CLOCKFD 3
278 #define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) // NOLINT
279 #define CLOCKID_TO_FD(id) ((~(int) (id) >> 3) & ~CLOCKFD) // NOLINT
280
281 class JitdumpCodeObserver : public CodeObserver {
282 public:
283 JitdumpCodeObserver() {
Ivan Posva 2014/02/06 00:33:26 ASSERT that the relevant flag is set.
Cutch 2014/02/13 19:16:58 Done.
284 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
285 if (file_open == NULL) {
286 return;
287 }
288 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
289 if (file_write == NULL) {
290 return;
291 }
Ivan Posva 2014/02/06 00:33:26 Don't you want to check the file_close callback he
Cutch 2014/02/13 19:16:58 Done.
292 const char* format = "/tmp/jit-%ld.dump";
Ivan Posva 2014/02/06 00:33:26 // Comments please. What are we going to access he
Cutch 2014/02/13 19:16:58 Done.
293 intptr_t pid = getpid();
294 intptr_t len = OS::SNPrint(NULL, 0, format, pid);
295 char* filename = new char[len + 1];
296 OS::SNPrint(filename, len + 1, format, pid);
297 out_file_ = (*file_open)(filename, true);
298 ASSERT(out_file_ != NULL);
299 clock_id_ = kInvalidClockId;
300 clock_fd_ = open("/dev/trace_clock", O_RDONLY);
301 if (clock_fd_ >= 0) {
302 clock_id_ = FD_TO_CLOCKID(clock_fd_);
303 printf("Using /dev/trace_clock as timesource (%x).\n", clock_id_);
Ivan Posva 2014/02/06 00:33:26 Do you really want to print this every time?
Cutch 2014/02/13 19:16:58 Removed.
304 }
305 WriteHeader();
306 }
307
308 ~JitdumpCodeObserver() {
309 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
310 if (file_close == NULL) {
311 return;
312 }
313 ASSERT(out_file_ != NULL);
314 (*file_close)(out_file_);
315 if (clock_fd_ >= 0) {
316 close(clock_fd_);
317 }
318 }
319
320 virtual bool IsActive() const {
321 return FLAG_generate_perf_jitdump && (out_file_ != NULL);
322 }
323
324 virtual void Notify(const char* name,
325 uword base,
326 uword prologue_offset,
327 uword size,
328 bool optimized) {
329 WriteCodeLoad(name, base, prologue_offset, size, optimized);
330 }
331
332 private:
333 void* out_file_;
334
335 static const uint32_t kJitHeaderMagic = 0x4F74496A;
336 static const uint32_t kJitHeaderVersion = 0x2;
337 static const uint32_t kElfMachIA32 = 3;
338 static const uint32_t kElfMachX64 = 62;
339 static const uint32_t kElfMachARM = 40;
340 static const uint32_t kElfMachMIPS = 10;
341 static const int kInvalidClockId = -1;
342
343 struct jitheader {
344 uint32_t magic;
345 uint32_t version;
346 uint32_t total_size;
347 uint32_t elf_mach;
348 uint32_t pad1;
349 uint32_t pid;
350 uint64_t timestamp;
351 };
352
353 enum jit_record_type {
354 JIT_CODE_LOAD = 0,
355 /* JIT_CODE_UNLOAD = 1, */
356 /* JIT_CODE_CLOSE = 2, */
357 /* JIT_CODE_DEBUG_INFO = 3, */
358 JIT_CODE_MAX = 4,
359 };
360
361 struct jr_code_load {
362 uint32_t id;
363 uint32_t total_size;
364 uint64_t timestamp;
365 uint32_t pid;
366 uint32_t tid;
367 uint64_t vma;
368 uint64_t code_addr;
369 uint32_t code_size;
370 uint32_t align;
371 };
372
373 const char* GenerateCodeName(const char* name, bool optimized) {
374 const char* format = "%s%s";
375 const char* marker = optimized ? "*" : "";
376 intptr_t len = OS::SNPrint(NULL, 0, format, marker, name);
377 char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
378 OS::SNPrint(buffer, len + 1, format, marker, name);
379 return buffer;
380 }
381
382 uint32_t GetElfMach() {
383 #if defined(TARGET_ARCH_IA32)
384 return kElfMachIA32;
385 #elif defined(TARGET_ARCH_X64)
386 return kElfMachX64;
387 #elif defined(TARGET_ARCH_ARM)
388 return kElfMachARM;
389 #elif defined(TARGET_ARCH_MIPS)
390 return kElfMachMIPS;
391 #else
Ivan Posva 2014/02/06 00:33:26 Generally we want to get compilation errors if we
Cutch 2014/02/13 19:16:58 Done.
392 UNIMPLEMENTED();
393 #endif
394 }
395
396 pid_t gettid() {
397 return syscall(SYS_gettid);
Ivan Posva 2014/02/06 00:33:26 Why do we have to go through syscall here? Is ther
Cutch 2014/02/13 19:16:58 libc doesn't wrap Linux-specific gettid, i've adde
398 }
399
400 uint64_t GetKernelTimeNanos() {
401 if (clock_id_ != kInvalidClockId) {
402 struct timespec ts;
403 int r = clock_gettime(clock_id_, &ts);
404 ASSERT(r == 0);
405 uint64_t nanos = static_cast<uint64_t>(ts.tv_sec) *
406 static_cast<uint64_t>(kNanosecondsPerSecond);
407 nanos += static_cast<uint64_t>(ts.tv_nsec);
408 return nanos;
409 } else {
410 return OS::GetCurrentTimeMicros() * kNanosecondsPerMicrosecond;
411 }
412 }
413
414 void WriteHeader() {
415 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
416 ASSERT(file_write != NULL);
417 ASSERT(out_file_ != NULL);
418 jitheader header;
419 header.magic = kJitHeaderMagic;
420 header.version = kJitHeaderVersion;
421 header.total_size = sizeof(jitheader);
422 header.pad1 = 0xdeadbeef;
423 header.elf_mach = GetElfMach();
424 header.pid = getpid();
425 header.timestamp = GetKernelTimeNanos();
426 (*file_write)(&header, sizeof(header), out_file_);
427 }
428
429 void WriteCodeLoad(const char* name, uword base, uword prologue_offset,
430 uword code_size, bool optimized) {
431 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
432 ASSERT(file_write != NULL);
433 ASSERT(out_file_ != NULL);
434
435 const char* code_name = GenerateCodeName(name, optimized);
436 const intptr_t code_name_size = strlen(code_name) + 1;
437 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(base);
438
439 jr_code_load code_load;
440 code_load.id = JIT_CODE_LOAD;
441 code_load.total_size = sizeof(code_load) + code_name_size + code_size;
442 code_load.timestamp = GetKernelTimeNanos();
443 code_load.pid = getpid();
444 code_load.tid = gettid();
445 code_load.vma = 0x0; // Our addresses are absolute.
446 code_load.code_addr = base;
447 code_load.code_size = code_size;
448 code_load.align = OS::PreferredCodeAlignment();
449
450 (*file_write)(&code_load, sizeof(code_load), out_file_);
Ivan Posva 2014/02/06 00:33:26 Multiple isolates will collide here. Please verif
Cutch 2014/02/13 19:16:58 Done.
451 (*file_write)(code_name, code_name_size, out_file_);
452 (*file_write)(code_pointer, code_size, out_file_);
453 }
454
455 int clock_fd_;
456 int clock_id_;
457 DISALLOW_COPY_AND_ASSIGN(JitdumpCodeObserver);
458 };
459
460
272 const char* OS::Name() { 461 const char* OS::Name() {
273 return "linux"; 462 return "linux";
274 } 463 }
275 464
276 465
277 intptr_t OS::ProcessId() { 466 intptr_t OS::ProcessId() {
278 return static_cast<intptr_t>(getpid()); 467 return static_cast<intptr_t>(getpid());
279 } 468 }
280 469
281 470
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 } 694 }
506 if (FLAG_generate_perf_events_symbols) { 695 if (FLAG_generate_perf_events_symbols) {
507 CodeObservers::Register(new PerfCodeObserver); 696 CodeObservers::Register(new PerfCodeObserver);
508 } 697 }
509 if (FLAG_generate_gdb_symbols) { 698 if (FLAG_generate_gdb_symbols) {
510 CodeObservers::Register(new GdbCodeObserver); 699 CodeObservers::Register(new GdbCodeObserver);
511 } 700 }
512 if (FLAG_generate_pprof_symbols != NULL) { 701 if (FLAG_generate_pprof_symbols != NULL) {
513 CodeObservers::Register(new PprofCodeObserver); 702 CodeObservers::Register(new PprofCodeObserver);
514 } 703 }
704 if (FLAG_generate_perf_jitdump) {
705 CodeObservers::Register(new JitdumpCodeObserver);
706 }
515 #if defined(DART_VTUNE_SUPPORT) 707 #if defined(DART_VTUNE_SUPPORT)
516 CodeObservers::Register(new VTuneCodeObserver); 708 CodeObservers::Register(new VTuneCodeObserver);
517 #endif 709 #endif
518 } 710 }
519 711
520 712
521 void OS::PrintErr(const char* format, ...) { 713 void OS::PrintErr(const char* format, ...) {
522 va_list args; 714 va_list args;
523 va_start(args, format); 715 va_start(args, format);
524 VFPrint(stderr, format, args); 716 VFPrint(stderr, format, args);
(...skipping 20 matching lines...) Expand all
545 } 737 }
546 738
547 739
548 void OS::Exit(int code) { 740 void OS::Exit(int code) {
549 exit(code); 741 exit(code);
550 } 742 }
551 743
552 } // namespace dart 744 } // namespace dart
553 745
554 #endif // defined(TARGET_OS_LINUX) 746 #endif // defined(TARGET_OS_LINUX)
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698