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

Side by Side Diff: src/log.cc

Issue 70013002: Support for the Linux 'perf report' and 'perf annotate' tools. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 7 years 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 | « src/log.h ('k') | src/log-utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 239 }
240 240
241 241
242 void CodeEventLogger::RegExpCodeCreateEvent(Code* code, String* source) { 242 void CodeEventLogger::RegExpCodeCreateEvent(Code* code, String* source) {
243 name_buffer_->Init(Logger::REG_EXP_TAG); 243 name_buffer_->Init(Logger::REG_EXP_TAG);
244 name_buffer_->AppendString(source); 244 name_buffer_->AppendString(source);
245 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size()); 245 LogRecordedBuffer(code, NULL, name_buffer_->get(), name_buffer_->size());
246 } 246 }
247 247
248 248
249 // Linux perf tool logging support
250 class PerfBasicLogger : public CodeEventLogger {
251 public:
252 PerfBasicLogger();
253 virtual ~PerfBasicLogger();
254
255 virtual void CodeMoveEvent(Address from, Address to) { }
256 virtual void CodeDeleteEvent(Address from) { }
257
258 private:
259 virtual void LogRecordedBuffer(Code* code,
260 SharedFunctionInfo* shared,
261 const char* name,
262 int length);
263
264 // Extension added to V8 log file name to get the low-level log name.
265 static const char kFilenameFormatString[];
266 static const int kFilenameBufferPadding;
267
268 // File buffer size of the low-level log. We don't use the default to
269 // minimize the associated overhead.
270 static const int kLogBufferSize = 2 * MB;
271
272 FILE* perf_output_handle_;
273 };
274
275 const char PerfBasicLogger::kFilenameFormatString[] = "/tmp/perf-%d.map";
276 // Extra space for the PID in the filename
277 const int PerfBasicLogger::kFilenameBufferPadding = 16;
278
279 PerfBasicLogger::PerfBasicLogger()
280 : perf_output_handle_(NULL) {
281 // Open the perf JIT dump file.
282 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
283 ScopedVector<char> perf_dump_name(bufferSize);
284 int size = OS::SNPrintF(
285 perf_dump_name,
286 kFilenameFormatString,
287 OS::GetCurrentProcessId());
288 CHECK_NE(size, -1);
289 perf_output_handle_ = OS::FOpen(perf_dump_name.start(), OS::LogFileOpenMode);
290 CHECK_NE(perf_output_handle_, NULL);
291 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
292 }
293
294
295 PerfBasicLogger::~PerfBasicLogger() {
296 fclose(perf_output_handle_);
297 perf_output_handle_ = NULL;
298 }
299
300
301 void PerfBasicLogger::LogRecordedBuffer(Code* code,
302 SharedFunctionInfo*,
303 const char* name,
304 int length) {
305 ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
306
307 OS::FPrint(perf_output_handle_, "%llx %x %.*s\n",
308 reinterpret_cast<uint64_t>(code->instruction_start()),
309 code->instruction_size(),
310 length, name);
311 }
312
313
314 // Linux perf tool logging support
315 class PerfJitLogger : public CodeEventLogger {
316 public:
317 PerfJitLogger();
318 virtual ~PerfJitLogger();
319
320 virtual void CodeMoveEvent(Address from, Address to) { }
321 virtual void CodeDeleteEvent(Address from) { }
322
323 private:
324 virtual void LogRecordedBuffer(Code* code,
325 SharedFunctionInfo* shared,
326 const char* name,
327 int length);
328
329 // Extension added to V8 log file name to get the low-level log name.
330 static const char kFilenameFormatString[];
331 static const int kFilenameBufferPadding;
332
333 // File buffer size of the low-level log. We don't use the default to
334 // minimize the associated overhead.
335 static const int kLogBufferSize = 2 * MB;
336
337 void LogWriteBytes(const char* bytes, int size);
338 void LogWriteHeader();
339
340 static const uint32_t kJitHeaderMagic = 0x4F74496A;
341 static const uint32_t kJitHeaderVersion = 0x2;
342 static const uint32_t kElfMachIA32 = 3;
343 static const uint32_t kElfMachX64 = 62;
344 static const uint32_t kElfMachARM = 40;
345 static const uint32_t kElfMachMIPS = 10;
346
347 struct jitheader {
348 uint32_t magic;
349 uint32_t version;
350 uint32_t total_size;
351 uint32_t elf_mach;
352 uint32_t pad1;
353 uint32_t pid;
354 uint64_t timestamp;
355 };
356
357 enum jit_record_type {
358 JIT_CODE_LOAD = 0
359 // JIT_CODE_UNLOAD = 1,
360 // JIT_CODE_CLOSE = 2,
361 // JIT_CODE_DEBUG_INFO = 3,
362 // JIT_CODE_PAGE_MAP = 4,
363 // JIT_CODE_MAX = 5
364 };
365
366 struct jr_code_load {
367 uint32_t id;
368 uint32_t total_size;
369 uint64_t timestamp;
370 uint64_t vma;
371 uint64_t code_addr;
372 uint32_t code_size;
373 uint32_t align;
374 };
375
376 uint32_t GetElfMach() {
377 #if V8_TARGET_ARCH_IA32
378 return kElfMachIA32;
379 #elif V8_TARGET_ARCH_X64
380 return kElfMachX64;
381 #elif V8_TARGET_ARCH_ARM
382 return kElfMachARM;
383 #elif V8_TARGET_ARCH_MIPS
384 return kElfMachMIPS;
385 #else
386 UNIMPLEMENTED();
387 return 0;
388 #endif
389 }
390
391 FILE* perf_output_handle_;
392 };
393
394 const char PerfJitLogger::kFilenameFormatString[] = "/tmp/jit-%d.dump";
395
396 // Extra padding for the PID in the filename
397 const int PerfJitLogger::kFilenameBufferPadding = 16;
398
399 PerfJitLogger::PerfJitLogger()
400 : perf_output_handle_(NULL) {
401 // Open the perf JIT dump file.
402 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
403 ScopedVector<char> perf_dump_name(bufferSize);
404 int size = OS::SNPrintF(
405 perf_dump_name,
406 kFilenameFormatString,
407 OS::GetCurrentProcessId());
408 CHECK_NE(size, -1);
409 perf_output_handle_ = OS::FOpen(perf_dump_name.start(), OS::LogFileOpenMode);
410 CHECK_NE(perf_output_handle_, NULL);
411 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
412
413 LogWriteHeader();
414 }
415
416
417 PerfJitLogger::~PerfJitLogger() {
418 fclose(perf_output_handle_);
419 perf_output_handle_ = NULL;
420 }
421
422
423 void PerfJitLogger::LogRecordedBuffer(Code* code,
424 SharedFunctionInfo*,
425 const char* name,
426 int length) {
427 ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
428 ASSERT(perf_output_handle_ != NULL);
429
430 const char* code_name = name;
431 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->instruction_start());
432 uint32_t code_size = code->instruction_size();
433
434 static const char string_terminator[] = "\0";
435
436 jr_code_load code_load;
437 code_load.id = JIT_CODE_LOAD;
438 code_load.total_size = sizeof(code_load) + length + 1 + code_size;
439 code_load.timestamp =
440 static_cast<uint64_t>(OS::TimeCurrentMillis() * 1000.0);
441 code_load.vma = 0x0; // Our addresses are absolute.
442 code_load.code_addr = reinterpret_cast<uint64_t>(code->instruction_start());
443 code_load.code_size = code_size;
444 code_load.align = 0;
445
446 LogWriteBytes(reinterpret_cast<const char*>(&code_load), sizeof(code_load));
447 LogWriteBytes(code_name, length);
448 LogWriteBytes(string_terminator, 1);
449 LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size);
450 }
451
452
453 void PerfJitLogger::LogWriteBytes(const char* bytes, int size) {
454 size_t rv = fwrite(bytes, 1, size, perf_output_handle_);
455 ASSERT(static_cast<size_t>(size) == rv);
456 USE(rv);
457 }
458
459
460 void PerfJitLogger::LogWriteHeader() {
461 ASSERT(perf_output_handle_ != NULL);
462 jitheader header;
463 header.magic = kJitHeaderMagic;
464 header.version = kJitHeaderVersion;
465 header.total_size = sizeof(jitheader);
466 header.pad1 = 0xdeadbeef;
467 header.elf_mach = GetElfMach();
468 header.pid = OS::GetCurrentProcessId();
469 header.timestamp = static_cast<uint64_t>(OS::TimeCurrentMillis() * 1000.0);
470 LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header));
471 }
472
473
249 // Low-level logging support. 474 // Low-level logging support.
250 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call; 475 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
251 476
252 class LowLevelLogger : public CodeEventLogger { 477 class LowLevelLogger : public CodeEventLogger {
253 public: 478 public:
254 explicit LowLevelLogger(const char* file_name); 479 explicit LowLevelLogger(const char* file_name);
255 virtual ~LowLevelLogger(); 480 virtual ~LowLevelLogger();
256 481
257 virtual void CodeMoveEvent(Address from, Address to); 482 virtual void CodeMoveEvent(Address from, Address to);
258 virtual void CodeDeleteEvent(Address from); 483 virtual void CodeDeleteEvent(Address from);
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 // Logger class implementation. 929 // Logger class implementation.
705 // 930 //
706 931
707 Logger::Logger(Isolate* isolate) 932 Logger::Logger(Isolate* isolate)
708 : isolate_(isolate), 933 : isolate_(isolate),
709 ticker_(NULL), 934 ticker_(NULL),
710 profiler_(NULL), 935 profiler_(NULL),
711 log_events_(NULL), 936 log_events_(NULL),
712 is_logging_(false), 937 is_logging_(false),
713 log_(new Log(this)), 938 log_(new Log(this)),
939 perf_basic_logger_(NULL),
940 perf_jit_logger_(NULL),
714 ll_logger_(NULL), 941 ll_logger_(NULL),
715 jit_logger_(NULL), 942 jit_logger_(NULL),
716 listeners_(5), 943 listeners_(5),
717 is_initialized_(false) { 944 is_initialized_(false) {
718 } 945 }
719 946
720 947
721 Logger::~Logger() { 948 Logger::~Logger() {
722 delete log_; 949 delete log_;
723 } 950 }
(...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 2064
1838 // --ll-prof implies --log-code and --log-snapshot-positions. 2065 // --ll-prof implies --log-code and --log-snapshot-positions.
1839 if (FLAG_ll_prof) { 2066 if (FLAG_ll_prof) {
1840 FLAG_log_snapshot_positions = true; 2067 FLAG_log_snapshot_positions = true;
1841 } 2068 }
1842 2069
1843 SmartArrayPointer<const char> log_file_name = 2070 SmartArrayPointer<const char> log_file_name =
1844 PrepareLogFileName(isolate, FLAG_logfile); 2071 PrepareLogFileName(isolate, FLAG_logfile);
1845 log_->Initialize(*log_file_name); 2072 log_->Initialize(*log_file_name);
1846 2073
2074
2075 if (FLAG_perf_basic_prof) {
2076 perf_basic_logger_ = new PerfBasicLogger();
2077 addCodeEventListener(perf_basic_logger_);
2078 }
2079
2080 if (FLAG_perf_jit_prof) {
2081 perf_jit_logger_ = new PerfJitLogger();
2082 addCodeEventListener(perf_jit_logger_);
2083 }
2084
1847 if (FLAG_ll_prof) { 2085 if (FLAG_ll_prof) {
1848 ll_logger_ = new LowLevelLogger(*log_file_name); 2086 ll_logger_ = new LowLevelLogger(*log_file_name);
1849 addCodeEventListener(ll_logger_); 2087 addCodeEventListener(ll_logger_);
1850 } 2088 }
1851 2089
1852 ticker_ = new Ticker(isolate, kSamplingIntervalMs); 2090 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1853 2091
1854 if (Log::InitLogAtStart()) { 2092 if (Log::InitLogAtStart()) {
1855 is_logging_ = true; 2093 is_logging_ = true;
1856 } 2094 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 // Stop the profiler before closing the file. 2137 // Stop the profiler before closing the file.
1900 if (profiler_ != NULL) { 2138 if (profiler_ != NULL) {
1901 profiler_->Disengage(); 2139 profiler_->Disengage();
1902 delete profiler_; 2140 delete profiler_;
1903 profiler_ = NULL; 2141 profiler_ = NULL;
1904 } 2142 }
1905 2143
1906 delete ticker_; 2144 delete ticker_;
1907 ticker_ = NULL; 2145 ticker_ = NULL;
1908 2146
2147 if (perf_basic_logger_) {
2148 removeCodeEventListener(perf_basic_logger_);
2149 delete perf_basic_logger_;
2150 perf_basic_logger_ = NULL;
2151 }
2152
2153 if (perf_jit_logger_) {
2154 removeCodeEventListener(perf_jit_logger_);
2155 delete perf_jit_logger_;
2156 perf_jit_logger_ = NULL;
2157 }
2158
1909 if (ll_logger_) { 2159 if (ll_logger_) {
1910 removeCodeEventListener(ll_logger_); 2160 removeCodeEventListener(ll_logger_);
1911 delete ll_logger_; 2161 delete ll_logger_;
1912 ll_logger_ = NULL; 2162 ll_logger_ = NULL;
1913 } 2163 }
1914 2164
1915 if (jit_logger_) { 2165 if (jit_logger_) {
1916 removeCodeEventListener(jit_logger_); 2166 removeCodeEventListener(jit_logger_);
1917 delete jit_logger_; 2167 delete jit_logger_;
1918 jit_logger_ = NULL; 2168 jit_logger_ = NULL;
1919 } 2169 }
1920 2170
1921 return log_->Close(); 2171 return log_->Close();
1922 } 2172 }
1923 2173
1924 } } // namespace v8::internal 2174 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/log.h ('k') | src/log-utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698