Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |