Chromium Code Reviews| Index: runtime/vm/os_linux.cc |
| =================================================================== |
| --- runtime/vm/os_linux.cc (revision 19040) |
| +++ runtime/vm/os_linux.cc (working copy) |
| @@ -32,9 +32,96 @@ |
| "Generate symbols of generated dart functions for debugging with GDB"); |
| DEFINE_FLAG(bool, generate_perf_events_symbols, false, |
| "Generate events symbols for profiling with perf"); |
| +DEFINE_FLAG(bool, ll_prof, false, |
| + "Generate compiled code log file for processing with ll_prof.py."); |
| DEFINE_FLAG(charp, generate_pprof_symbols, NULL, |
| "Writes pprof events symbols to the provided file"); |
| +class LowLevelProfileCodeObserver : public CodeObserver { |
| + public: |
| + LowLevelProfileCodeObserver() { |
| + Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
| + if (file_open == NULL) { |
| + return; |
| + } |
| + const char* filename = "v8.log.ll"; |
|
Vyacheslav Egorov (Google)
2013/02/26 14:19:25
I like the name.
You can consider making ll_prof
|
| + log_file_ = (*file_open)(filename); |
| +#if defined(TARGET_ARCH_IA32) |
| + const char arch[] = "ia32"; |
| +#elif defined(TARGET_ARCH_X64) |
| + const char arch[] = "x64"; |
| +#elif defined(TARGET_ARCH_ARM) |
| + const char arch[] = "arm"; |
| +#elif defined(TARGET_ARCH_MIPS) |
| + const char arch[] = "mips"; |
| +#else |
| + const char arch[] = "unknown"; |
| +#endif |
| + LowLevelLogWriteBytes(arch, sizeof(arch)); |
| + } |
| + |
| + ~LowLevelProfileCodeObserver() { |
| + Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
| + if (file_close == NULL) { |
| + return; |
| + } |
| + ASSERT(log_file_ != NULL); |
| + (*file_close)(log_file_); |
| + } |
| + |
| + virtual bool IsActive() const { |
| + return FLAG_ll_prof; |
| + } |
| + |
| + struct LowLevelCodeCreateStruct { |
| + static const char kTag = 'C'; |
| + |
| + intptr_t name_size; |
| + uword code_address; |
| + uword code_size; |
| + }; |
| + |
| + template <typename T> |
| + void LowLevelLogWriteStruct(const T& s) { |
|
Vyacheslav Egorov (Google)
2013/02/26 14:19:25
There is only a single structure so for now we don
|
| + char tag = T::kTag; |
| + LowLevelLogWriteBytes(reinterpret_cast<const char*>(&tag), sizeof(tag)); |
| + LowLevelLogWriteBytes(reinterpret_cast<const char*>(&s), sizeof(s)); |
| + } |
| + |
| + void LowLevelLogWriteBytes(const char* bytes, int size) { |
| + Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
| + ASSERT(file_write != NULL); |
| + (file_write)(bytes, size, log_file_); |
| + } |
| + |
| + virtual void Notify(const char* name, |
| + uword base, |
| + uword prologue_offset, |
| + uword size, |
| + bool optimized) { |
| + const char* format = "%s%s"; |
|
Vyacheslav Egorov (Google)
2013/02/26 14:24:17
Use Zone::PrintToString here.
|
| + const char* marker = optimized ? "*" : ""; |
| + intptr_t len = OS::SNPrint(NULL, 0, format, marker, name); |
| + char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| + OS::SNPrint(buffer, len + 1, format, marker, name); |
| + |
| + LowLevelCodeCreateStruct event; |
| + event.name_size = len; |
| + event.code_address = base; |
| + event.code_size = size; |
| + |
| + LowLevelLogWriteStruct(event); |
| + LowLevelLogWriteBytes(buffer, len); |
| + LowLevelLogWriteBytes(reinterpret_cast<char*>(base), size); |
| + } |
| + |
| + private: |
| + void* log_file_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(LowLevelProfileCodeObserver); |
| +}; |
| + |
| + |
| class PerfCodeObserver : public CodeObserver { |
| public: |
| PerfCodeObserver() { |
| @@ -378,6 +465,9 @@ |
| void OS::RegisterCodeObservers() { |
| + if (FLAG_ll_prof) { |
| + CodeObservers::Register(new LowLevelProfileCodeObserver); |
| + } |
| if (FLAG_generate_perf_events_symbols) { |
| CodeObservers::Register(new PerfCodeObserver); |
| } |