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

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: Remove forgotten printfs. Created 7 years, 1 month 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
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 explicit PerfBasicLogger();
danno 2013/11/13 17:18:10 Don't need explicit here, only for single argument
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,
danno 2013/11/13 17:18:10 nit: 4 char indent
286 kFilenameFormatString,
287 OS::GetCurrentProcessId());
288 CHECK_NE(size, -1);
289 perf_output_handle_ = OS::FOpen(perf_dump_name.start(), OS::LogFileOpenMode);
bnoordhuis 2013/11/13 23:40:52 This should check for NULL, shouldn't it? Calling
290 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
291 }
292
293
294 PerfBasicLogger::~PerfBasicLogger() {
295 fclose(perf_output_handle_);
296 perf_output_handle_ = NULL;
297 }
298
299
300 void PerfBasicLogger::LogRecordedBuffer(Code* code,
301 SharedFunctionInfo*,
302 const char* name,
303 int length) {
304 ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
305
306 OS::FPrint(perf_output_handle_, "%llx %x %.*s\n",
307 (uint64_t)code->instruction_start(),
danno 2013/11/13 17:18:10 nit: 4 char indent (2 is for nested scopes only)
bnoordhuis 2013/11/13 23:40:52 static_cast? (Here and in a few other places.)
308 code->instruction_size(),
309 length, name);
310 }
311
312
313 // Linux perf tool logging support
314 class PerfJitLogger : public CodeEventLogger {
315 public:
316 explicit PerfJitLogger();
danno 2013/11/13 17:18:10 Don't need explicit here, only for single argument
317 virtual ~PerfJitLogger();
318
319 virtual void CodeMoveEvent(Address from, Address to) { }
320 virtual void CodeDeleteEvent(Address from) { }
321
322 private:
323 virtual void LogRecordedBuffer(Code* code,
324 SharedFunctionInfo* shared,
325 const char* name,
326 int length);
327
328 // Extension added to V8 log file name to get the low-level log name.
329 static const char kFilenameFormatString[];
330 static const int kFilenameBufferPadding;
331
332 // File buffer size of the low-level log. We don't use the default to
333 // minimize the associated overhead.
334 static const int kLogBufferSize = 2 * MB;
335
336 void LogWriteBytes(const char* bytes, int size);
337 void LogWriteHeader();
338
339 static const uint32_t kJitHeaderMagic = 0x4F74496A;
340 static const uint32_t kJitHeaderVersion = 0x2;
341 static const uint32_t kElfMachIA32 = 3;
342 static const uint32_t kElfMachX64 = 62;
343 static const uint32_t kElfMachARM = 40;
344 static const uint32_t kElfMachMIPS = 10;
345
346 struct jitheader {
347 uint32_t magic;
348 uint32_t version;
349 uint32_t total_size;
350 uint32_t elf_mach;
351 uint32_t pad1;
352 uint32_t pid;
353 uint64_t timestamp;
354 };
355
356 enum jit_record_type {
357 JIT_CODE_LOAD = 0
358 // JIT_CODE_UNLOAD = 1,
359 // JIT_CODE_CLOSE = 2,
360 // JIT_CODE_DEBUG_INFO = 3,
361 // JIT_CODE_PAGE_MAP = 4,
362 // JIT_CODE_MAX = 5
363 };
364
365 struct jr_code_load {
366 uint32_t id;
367 uint32_t total_size;
368 uint64_t timestamp;
369 uint64_t vma;
370 uint64_t code_addr;
371 uint32_t code_size;
372 uint32_t align;
373 };
374
375 uint32_t GetElfMach() {
376 #if V8_TARGET_ARCH_IA32
377 return kElfMachIA32;
378 #elif V8_TARGET_ARCH_X64
379 return kElfMachX64;
380 #elif V8_TARGET_ARCH_ARM
381 return kElfMachARM;
382 #elif V8_TARGET_ARCH_MIPS
383 return kElfMachMIPS;
384 #else
385 UNIMPLEMENTED();
386 return 0;
387 #endif
388 }
389
390 FILE* perf_output_handle_;
391 };
392
393 const char PerfJitLogger::kFilenameFormatString[] = "/tmp/jit-%d.dump";
394
395 // Extra padding for the PID in the filename
396 const int PerfJitLogger::kFilenameBufferPadding = 16;
397
398 PerfJitLogger::PerfJitLogger()
399 : perf_output_handle_(NULL) {
400 // Open the perf JIT dump file.
401 int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
402 ScopedVector<char> perf_dump_name(bufferSize);
403 int size = OS::SNPrintF(
404 perf_dump_name,
danno 2013/11/13 17:18:10 Indent 4 characters on line continuations
405 kFilenameFormatString,
406 OS::GetCurrentProcessId());
407 CHECK_NE(size, -1);
408 perf_output_handle_ = OS::FOpen(perf_dump_name.start(), OS::LogFileOpenMode);
409 setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
410
411 LogWriteHeader();
412 }
413
414
415 PerfJitLogger::~PerfJitLogger() {
416 fclose(perf_output_handle_);
417 perf_output_handle_ = NULL;
418 }
419
420
421 void PerfJitLogger::LogRecordedBuffer(Code* code,
422 SharedFunctionInfo*,
danno 2013/11/13 17:18:10 nit: indentation one char too many on this line an
423 const char* name,
424 int length) {
425 ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
426 ASSERT(perf_output_handle_ != NULL);
427
428 const char* code_name = name;
429 uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->instruction_start());
430 uint32_t code_size = code->instruction_size();
431
432 static const char string_terminator[] = "\0";
433
434 jr_code_load code_load;
435 code_load.id = JIT_CODE_LOAD;
436 code_load.total_size = sizeof(code_load) + length + 1 + code_size;
437 code_load.timestamp = (uint64_t)(OS::TimeCurrentMillis() * 1000.0);
438 code_load.vma = 0x0; // Our addresses are absolute.
439 code_load.code_addr = reinterpret_cast<uint64_t>(code->instruction_start());
440 code_load.code_size = code_size;
441 code_load.align = 0;
442
443 LogWriteBytes(reinterpret_cast<const char*>(&code_load), sizeof(code_load));
444 LogWriteBytes(code_name, length);
445 LogWriteBytes(string_terminator, 1);
446 LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size);
447 }
448
449
450 void PerfJitLogger::LogWriteBytes(const char* bytes, int size) {
451 size_t rv = fwrite(bytes, 1, size, perf_output_handle_);
452 ASSERT(static_cast<size_t>(size) == rv);
bnoordhuis 2013/11/13 23:40:52 I don't think that's a safe assumption to make. f
453 USE(rv);
454 }
455
456
457 void PerfJitLogger::LogWriteHeader() {
458 ASSERT(perf_output_handle_ != NULL);
459 jitheader header;
460 header.magic = kJitHeaderMagic;
461 header.version = kJitHeaderVersion;
462 header.total_size = sizeof(jitheader);
463 header.pad1 = 0xdeadbeef;
464 header.elf_mach = GetElfMach();
465 header.pid = OS::GetCurrentProcessId();
466 header.timestamp = (uint64_t)(OS::TimeCurrentMillis() * 1000.0);
467 LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header));
468 }
469
470
249 // Low-level logging support. 471 // Low-level logging support.
250 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call; 472 #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
251 473
252 class LowLevelLogger : public CodeEventLogger { 474 class LowLevelLogger : public CodeEventLogger {
253 public: 475 public:
254 explicit LowLevelLogger(const char* file_name); 476 explicit LowLevelLogger(const char* file_name);
255 virtual ~LowLevelLogger(); 477 virtual ~LowLevelLogger();
256 478
257 virtual void CodeMoveEvent(Address from, Address to); 479 virtual void CodeMoveEvent(Address from, Address to);
258 virtual void CodeDeleteEvent(Address from); 480 virtual void CodeDeleteEvent(Address from);
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 // Logger class implementation. 926 // Logger class implementation.
705 // 927 //
706 928
707 Logger::Logger(Isolate* isolate) 929 Logger::Logger(Isolate* isolate)
708 : isolate_(isolate), 930 : isolate_(isolate),
709 ticker_(NULL), 931 ticker_(NULL),
710 profiler_(NULL), 932 profiler_(NULL),
711 log_events_(NULL), 933 log_events_(NULL),
712 is_logging_(false), 934 is_logging_(false),
713 log_(new Log(this)), 935 log_(new Log(this)),
936 perf_basic_logger_(NULL),
937 perf_jit_logger_(NULL),
714 ll_logger_(NULL), 938 ll_logger_(NULL),
715 jit_logger_(NULL), 939 jit_logger_(NULL),
716 listeners_(5), 940 listeners_(5),
717 is_initialized_(false) { 941 is_initialized_(false) {
718 } 942 }
719 943
720 944
721 Logger::~Logger() { 945 Logger::~Logger() {
722 delete log_; 946 delete log_;
723 } 947 }
(...skipping 1113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1837 2061
1838 // --ll-prof implies --log-code and --log-snapshot-positions. 2062 // --ll-prof implies --log-code and --log-snapshot-positions.
1839 if (FLAG_ll_prof) { 2063 if (FLAG_ll_prof) {
1840 FLAG_log_snapshot_positions = true; 2064 FLAG_log_snapshot_positions = true;
1841 } 2065 }
1842 2066
1843 SmartArrayPointer<const char> log_file_name = 2067 SmartArrayPointer<const char> log_file_name =
1844 PrepareLogFileName(isolate, FLAG_logfile); 2068 PrepareLogFileName(isolate, FLAG_logfile);
1845 log_->Initialize(*log_file_name); 2069 log_->Initialize(*log_file_name);
1846 2070
2071
2072 if (FLAG_perf_basic_prof) {
2073 perf_basic_logger_ = new PerfBasicLogger();
2074 addCodeEventListener(perf_basic_logger_);
2075 }
2076
2077 if (FLAG_perf_jit_prof) {
2078 perf_jit_logger_ = new PerfJitLogger();
2079 addCodeEventListener(perf_jit_logger_);
2080 }
2081
1847 if (FLAG_ll_prof) { 2082 if (FLAG_ll_prof) {
1848 ll_logger_ = new LowLevelLogger(*log_file_name); 2083 ll_logger_ = new LowLevelLogger(*log_file_name);
1849 addCodeEventListener(ll_logger_); 2084 addCodeEventListener(ll_logger_);
1850 } 2085 }
1851 2086
1852 ticker_ = new Ticker(isolate, kSamplingIntervalMs); 2087 ticker_ = new Ticker(isolate, kSamplingIntervalMs);
1853 2088
1854 if (Log::InitLogAtStart()) { 2089 if (Log::InitLogAtStart()) {
1855 is_logging_ = true; 2090 is_logging_ = true;
1856 } 2091 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1899 // Stop the profiler before closing the file. 2134 // Stop the profiler before closing the file.
1900 if (profiler_ != NULL) { 2135 if (profiler_ != NULL) {
1901 profiler_->Disengage(); 2136 profiler_->Disengage();
1902 delete profiler_; 2137 delete profiler_;
1903 profiler_ = NULL; 2138 profiler_ = NULL;
1904 } 2139 }
1905 2140
1906 delete ticker_; 2141 delete ticker_;
1907 ticker_ = NULL; 2142 ticker_ = NULL;
1908 2143
2144 if (perf_basic_logger_) {
2145 removeCodeEventListener(perf_basic_logger_);
2146 delete perf_basic_logger_;
2147 perf_basic_logger_ = NULL;
2148 }
2149
2150 if (perf_jit_logger_) {
2151 removeCodeEventListener(perf_jit_logger_);
2152 delete perf_jit_logger_;
2153 perf_jit_logger_ = NULL;
2154 }
2155
1909 if (ll_logger_) { 2156 if (ll_logger_) {
1910 removeCodeEventListener(ll_logger_); 2157 removeCodeEventListener(ll_logger_);
1911 delete ll_logger_; 2158 delete ll_logger_;
1912 ll_logger_ = NULL; 2159 ll_logger_ = NULL;
1913 } 2160 }
1914 2161
1915 if (jit_logger_) { 2162 if (jit_logger_) {
1916 removeCodeEventListener(jit_logger_); 2163 removeCodeEventListener(jit_logger_);
1917 delete jit_logger_; 2164 delete jit_logger_;
1918 jit_logger_ = NULL; 2165 jit_logger_ = NULL;
1919 } 2166 }
1920 2167
1921 return log_->Close(); 2168 return log_->Close();
1922 } 2169 }
1923 2170
1924 } } // namespace v8::internal 2171 } } // namespace v8::internal
OLDNEW
« src/flag-definitions.h ('K') | « src/log.h ('k') | src/log-utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698