| Index: src/log.cc
|
| diff --git a/src/log.cc b/src/log.cc
|
| index ae5d37a8027366d1f19453b81c1b5627518b9044..e8ecb1412b3ad5d08894bb798c1e16defa1e22b6 100644
|
| --- a/src/log.cc
|
| +++ b/src/log.cc
|
| @@ -15,6 +15,7 @@
|
| #include "src/log.h"
|
| #include "src/log-utils.h"
|
| #include "src/macro-assembler.h"
|
| +#include "src/perf-jit.h"
|
| #include "src/runtime-profiler.h"
|
| #include "src/serialize.h"
|
| #include "src/string-stream.h"
|
| @@ -289,172 +290,6 @@ void PerfBasicLogger::LogRecordedBuffer(Code* code,
|
| }
|
|
|
|
|
| -// Linux perf tool logging support
|
| -class PerfJitLogger : public CodeEventLogger {
|
| - public:
|
| - PerfJitLogger();
|
| - virtual ~PerfJitLogger();
|
| -
|
| - virtual void CodeMoveEvent(Address from, Address to) { }
|
| - virtual void CodeDisableOptEvent(Code* code, SharedFunctionInfo* shared) { }
|
| - virtual void CodeDeleteEvent(Address from) { }
|
| -
|
| - private:
|
| - virtual void LogRecordedBuffer(Code* code,
|
| - SharedFunctionInfo* shared,
|
| - const char* name,
|
| - int length);
|
| -
|
| - // Extension added to V8 log file name to get the low-level log name.
|
| - static const char kFilenameFormatString[];
|
| - static const int kFilenameBufferPadding;
|
| -
|
| - // File buffer size of the low-level log. We don't use the default to
|
| - // minimize the associated overhead.
|
| - static const int kLogBufferSize = 2 * MB;
|
| -
|
| - void LogWriteBytes(const char* bytes, int size);
|
| - void LogWriteHeader();
|
| -
|
| - static const uint32_t kJitHeaderMagic = 0x4F74496A;
|
| - static const uint32_t kJitHeaderVersion = 0x2;
|
| - static const uint32_t kElfMachIA32 = 3;
|
| - static const uint32_t kElfMachX64 = 62;
|
| - static const uint32_t kElfMachARM = 40;
|
| - static const uint32_t kElfMachMIPS = 10;
|
| - static const uint32_t kElfMachX87 = 3;
|
| -
|
| - struct jitheader {
|
| - uint32_t magic;
|
| - uint32_t version;
|
| - uint32_t total_size;
|
| - uint32_t elf_mach;
|
| - uint32_t pad1;
|
| - uint32_t pid;
|
| - uint64_t timestamp;
|
| - };
|
| -
|
| - enum jit_record_type {
|
| - JIT_CODE_LOAD = 0
|
| - // JIT_CODE_UNLOAD = 1,
|
| - // JIT_CODE_CLOSE = 2,
|
| - // JIT_CODE_DEBUG_INFO = 3,
|
| - // JIT_CODE_PAGE_MAP = 4,
|
| - // JIT_CODE_MAX = 5
|
| - };
|
| -
|
| - struct jr_code_load {
|
| - uint32_t id;
|
| - uint32_t total_size;
|
| - uint64_t timestamp;
|
| - uint64_t vma;
|
| - uint64_t code_addr;
|
| - uint32_t code_size;
|
| - uint32_t align;
|
| - };
|
| -
|
| - uint32_t GetElfMach() {
|
| -#if V8_TARGET_ARCH_IA32
|
| - return kElfMachIA32;
|
| -#elif V8_TARGET_ARCH_X64
|
| - return kElfMachX64;
|
| -#elif V8_TARGET_ARCH_ARM
|
| - return kElfMachARM;
|
| -#elif V8_TARGET_ARCH_MIPS
|
| - return kElfMachMIPS;
|
| -#elif V8_TARGET_ARCH_X87
|
| - return kElfMachX87;
|
| -#else
|
| - UNIMPLEMENTED();
|
| - return 0;
|
| -#endif
|
| - }
|
| -
|
| - FILE* perf_output_handle_;
|
| -};
|
| -
|
| -const char PerfJitLogger::kFilenameFormatString[] = "/tmp/jit-%d.dump";
|
| -
|
| -// Extra padding for the PID in the filename
|
| -const int PerfJitLogger::kFilenameBufferPadding = 16;
|
| -
|
| -PerfJitLogger::PerfJitLogger()
|
| - : perf_output_handle_(NULL) {
|
| - // Open the perf JIT dump file.
|
| - int bufferSize = sizeof(kFilenameFormatString) + kFilenameBufferPadding;
|
| - ScopedVector<char> perf_dump_name(bufferSize);
|
| - int size = SNPrintF(
|
| - perf_dump_name,
|
| - kFilenameFormatString,
|
| - base::OS::GetCurrentProcessId());
|
| - CHECK_NE(size, -1);
|
| - perf_output_handle_ =
|
| - base::OS::FOpen(perf_dump_name.start(), base::OS::LogFileOpenMode);
|
| - CHECK_NE(perf_output_handle_, NULL);
|
| - setvbuf(perf_output_handle_, NULL, _IOFBF, kLogBufferSize);
|
| -
|
| - LogWriteHeader();
|
| -}
|
| -
|
| -
|
| -PerfJitLogger::~PerfJitLogger() {
|
| - fclose(perf_output_handle_);
|
| - perf_output_handle_ = NULL;
|
| -}
|
| -
|
| -
|
| -void PerfJitLogger::LogRecordedBuffer(Code* code,
|
| - SharedFunctionInfo*,
|
| - const char* name,
|
| - int length) {
|
| - ASSERT(code->instruction_start() == code->address() + Code::kHeaderSize);
|
| - ASSERT(perf_output_handle_ != NULL);
|
| -
|
| - const char* code_name = name;
|
| - uint8_t* code_pointer = reinterpret_cast<uint8_t*>(code->instruction_start());
|
| - uint32_t code_size = code->instruction_size();
|
| -
|
| - static const char string_terminator[] = "\0";
|
| -
|
| - jr_code_load code_load;
|
| - code_load.id = JIT_CODE_LOAD;
|
| - code_load.total_size = sizeof(code_load) + length + 1 + code_size;
|
| - code_load.timestamp =
|
| - static_cast<uint64_t>(base::OS::TimeCurrentMillis() * 1000.0);
|
| - code_load.vma = 0x0; // Our addresses are absolute.
|
| - code_load.code_addr = reinterpret_cast<uint64_t>(code->instruction_start());
|
| - code_load.code_size = code_size;
|
| - code_load.align = 0;
|
| -
|
| - LogWriteBytes(reinterpret_cast<const char*>(&code_load), sizeof(code_load));
|
| - LogWriteBytes(code_name, length);
|
| - LogWriteBytes(string_terminator, 1);
|
| - LogWriteBytes(reinterpret_cast<const char*>(code_pointer), code_size);
|
| -}
|
| -
|
| -
|
| -void PerfJitLogger::LogWriteBytes(const char* bytes, int size) {
|
| - size_t rv = fwrite(bytes, 1, size, perf_output_handle_);
|
| - ASSERT(static_cast<size_t>(size) == rv);
|
| - USE(rv);
|
| -}
|
| -
|
| -
|
| -void PerfJitLogger::LogWriteHeader() {
|
| - ASSERT(perf_output_handle_ != NULL);
|
| - jitheader header;
|
| - header.magic = kJitHeaderMagic;
|
| - header.version = kJitHeaderVersion;
|
| - header.total_size = sizeof(jitheader);
|
| - header.pad1 = 0xdeadbeef;
|
| - header.elf_mach = GetElfMach();
|
| - header.pid = base::OS::GetCurrentProcessId();
|
| - header.timestamp =
|
| - static_cast<uint64_t>(base::OS::TimeCurrentMillis() * 1000.0);
|
| - LogWriteBytes(reinterpret_cast<const char*>(&header), sizeof(header));
|
| -}
|
| -
|
| -
|
| // Low-level logging support.
|
| #define LL_LOG(Call) if (ll_logger_) ll_logger_->Call;
|
|
|
|
|