Chromium Code Reviews| Index: runtime/vm/os_linux.cc |
| diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc |
| index c7bfcbcce6f185f1725687776eef9616b7109715..a2d2807e91f41f85223464b5d0b3e3fcf79bcce4 100644 |
| --- a/runtime/vm/os_linux.cc |
| +++ b/runtime/vm/os_linux.cc |
| @@ -14,10 +14,132 @@ |
| #include <unistd.h> |
| #include "platform/utils.h" |
| +#include "vm/code_observers.h" |
| +#include "vm/dart.h" |
| +#include "vm/debuginfo.h" |
| #include "vm/isolate.h" |
| +#include "vm/zone.h" |
| + |
| namespace dart { |
| +// Linux-specific CodeObservers |
|
siva
2012/12/14 19:13:40
Ditto.
Max Heinritz (Google)
2012/12/14 19:59:47
Done.
|
| + |
| +DEFINE_FLAG(bool, generate_gdb_symbols, false, |
| + "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"); |
| + |
| +class PerfCodeObserver : public CodeObserver { |
| + public: |
| + PerfCodeObserver() { |
| + Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
| + if (file_open == NULL) { |
| + return; |
| + } |
| + const char* format = "/tmp/perf-%ld.map"; |
| + intptr_t pid = getpid(); |
| + intptr_t len = OS::SNPrint(NULL, 0, format, pid); |
| + char* filename = new char[len + 1]; |
| + OS::SNPrint(filename, len + 1, format, pid); |
| + out_file_ = (*file_open)(filename); |
| + } |
| + |
| + ~PerfCodeObserver() { |
| + Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
| + if (file_close == NULL) { |
| + return; |
| + } |
| + ASSERT(out_file_ != NULL); |
| + (*file_close)(out_file_); |
| + } |
| + |
| + virtual bool IsActive() const { |
| + return FLAG_generate_perf_events_symbols; |
| + } |
| + |
| + virtual void Notify(const char* name, |
| + uword base, |
| + uword prologue_offset, |
| + uword size, |
| + bool optimized) { |
| + Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
| + ASSERT(file_write != NULL); |
| + const char* format = "%"Px" %"Px" %s%s\n"; |
| + const char* marker = optimized ? "*" : ""; |
| + intptr_t len = OS::SNPrint(NULL, 0, format, base, size, marker, name); |
| + char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| + OS::SNPrint(buffer, len + 1, format, base, size, marker, name); |
| + ASSERT(out_file_ != NULL); |
| + (*file_write)(buffer, len, out_file_); |
| + } |
| + |
| + private: |
| + void* out_file_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(PerfCodeObserver); |
| +}; |
| + |
| +class PprofCodeObserver : public CodeObserver { |
| + public: |
| + PprofCodeObserver() { } |
| + |
| + virtual bool IsActive() const { |
| + return Dart::pprof_symbol_generator() != NULL; |
| + } |
| + |
| + virtual void Notify(const char* name, |
| + uword base, |
| + uword prologue_offset, |
| + uword size, |
| + bool optimized) { |
| + DebugInfo* pprof_symbol_generator = Dart::pprof_symbol_generator(); |
| + ASSERT(pprof_symbol_generator != NULL); |
| + pprof_symbol_generator->AddCode(base, size); |
| + pprof_symbol_generator->AddCodeRegion(name, base, size); |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(PprofCodeObserver); |
| +}; |
| + |
| +class GdbCodeObserver : public CodeObserver { |
| + public: |
| + GdbCodeObserver() { } |
| + |
| + virtual bool IsActive() const { |
| + return FLAG_generate_gdb_symbols; |
| + } |
| + |
| + virtual void Notify(const char* name, |
| + uword base, |
| + uword prologue_offset, |
| + uword size, |
| + bool optimized) { |
| + if (prologue_offset > 0) { |
| + // In order to ensure that gdb sees the first instruction of a function |
| + // as the prologue sequence we register two symbols for the cases when |
| + // the prologue sequence is not the first instruction: |
| + // <name>_entry is used for code preceding the prologue sequence. |
| + // <name> for rest of the code (first instruction is prologue sequence). |
| + const char* kFormat = "%s_%s"; |
| + intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry"); |
| + char* pname = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| + OS::SNPrint(pname, (len + 1), kFormat, name, "entry"); |
| + DebugInfo::RegisterSection(pname, base, size); |
| + DebugInfo::RegisterSection(name, |
| + (base + prologue_offset), |
| + (size - prologue_offset)); |
| + } else { |
| + DebugInfo::RegisterSection(name, base, size); |
| + } |
| + } |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(GdbCodeObserver); |
| +}; |
| + |
| + |
| static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { |
| time_t seconds = static_cast<time_t>(seconds_since_epoch); |
| if (seconds != seconds_since_epoch) return false; |
| @@ -199,6 +321,20 @@ bool OS::StringToInt64(const char* str, int64_t* value) { |
| } |
| +void OS::RegisterCodeObservers() { |
| + if (FLAG_generate_perf_events_symbols) { |
| + CodeObservers::Register(new PerfCodeObserver); |
| + } |
| + if (FLAG_generate_gdb_symbols) { |
| + CodeObservers::Register(new GdbCodeObserver); |
| + } |
| + CodeObservers::Register(new PprofCodeObserver); |
| +#if defined(DART_VTUNE_SUPPORT) |
| + Register(new VTuneCodeObserver); |
| +#endif |
| +} |
|
siva
2012/12/14 19:13:40
You need to add the same setup to os_android.cc al
Max Heinritz (Google)
2012/12/14 19:59:47
Done.
|
| + |
| + |
| void OS::PrintErr(const char* format, ...) { |
| va_list args; |
| va_start(args, format); |
| @@ -227,6 +363,7 @@ void OS::Abort() { |
| void OS::Exit(int code) { |
| + CodeObservers::DeleteAll(); |
| exit(code); |
| } |