Chromium Code Reviews| Index: runtime/vm/dart.cc |
| diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc |
| index fcc35014e832486b8cab4d7f14f3597c34842024..77b3e2481b46dd5d7ec779499cfb5d3b98180c0c 100644 |
| --- a/runtime/vm/dart.cc |
| +++ b/runtime/vm/dart.cc |
| @@ -5,6 +5,7 @@ |
| #include "vm/dart.h" |
| #include "vm/dart_api_state.h" |
| +#include "vm/debuginfo.h" |
| #include "vm/flags.h" |
| #include "vm/freelist.h" |
| #include "vm/handles.h" |
| @@ -18,10 +19,13 @@ |
| #include "vm/symbols.h" |
| #include "vm/thread_pool.h" |
| #include "vm/virtual_memory.h" |
| +#include "vm/vtune.h" |
| #include "vm/zone.h" |
| namespace dart { |
| +DEFINE_FLAG(bool, generate_gdb_symbols, false, |
| + "Generate symbols of generated dart functions for debugging with GDB"); |
| DECLARE_FLAG(bool, print_bootstrap); |
| DECLARE_FLAG(bool, print_class_table); |
| DECLARE_FLAG(bool, trace_isolates); |
| @@ -31,6 +35,8 @@ ThreadPool* Dart::thread_pool_ = NULL; |
| Dart_FileWriterFunction Dart::perf_events_writer_ = NULL; |
| DebugInfo* Dart::pprof_symbol_generator_ = NULL; |
| Dart_FileWriterFunction Dart::flow_graph_writer_ = NULL; |
| +intptr_t Dart::code_observers_length_ = 0; |
| +CodeObserver** Dart::code_observers_ = NULL; |
| // An object visitor which will mark all visited objects. This is used to |
| // premark all objects in the vm_isolate_ heap. |
| @@ -61,6 +67,7 @@ const char* Dart::InitOnce(Dart_IsolateCreateCallback create, |
| PortMap::InitOnce(); |
| FreeListElement::InitOnce(); |
| Api::InitOnce(); |
| + RegisterDefaultCodeObservers(); |
| // Create the VM isolate and finish the VM initialization. |
| ASSERT(thread_pool_ == NULL); |
| thread_pool_ = new ThreadPool(); |
| @@ -191,4 +198,123 @@ void Dart::ShutdownIsolate() { |
| } |
| } |
| + |
| +void Dart::RegisterCodeObserver(CodeObserver* observer) { |
| + code_observers_length_++; |
| + code_observers_ = reinterpret_cast<CodeObserver**>( |
| + realloc(code_observers_, |
| + sizeof(CodeObserver*) * code_observers_length_)); // NOLINT |
|
Ivan Posva
2012/11/27 09:11:20
sizeof(observer) should make the lint warning go a
Vyacheslav Egorov (Google)
2012/11/27 16:26:12
Done.
|
| + if (code_observers_ == NULL) { |
| + FATAL("failed to grow code observers array"); |
| + } |
| + code_observers_[code_observers_length_ - 1] = observer; |
| +} |
| + |
| + |
| +void Dart::NotifyCodeObservers(const char* name, |
| + uword base, |
| + uword prologue_offset, |
| + uword size, |
| + bool optimized) { |
| + ASSERT(!AreCodeObserversActive() || (strlen(name) != 0)); |
| + for (intptr_t i = 0; i < code_observers_length_; i++) { |
| + if (code_observers_[i]->IsActive()) { |
| + code_observers_[i]->Notify(name, base, prologue_offset, size, optimized); |
| + } |
| + } |
| +} |
| + |
| + |
| +bool Dart::AreCodeObserversActive() { |
| + for (intptr_t i = 0; i < code_observers_length_; i++) { |
| + if (code_observers_[i]->IsActive()) return true; |
| + } |
| + return false; |
| +} |
| + |
| + |
| +class PerfCodeObserver : public CodeObserver { |
| + public: |
| + virtual bool IsActive() const { |
| + return Dart::perf_events_writer() != NULL; |
| + } |
| + |
| + virtual void Notify(const char* name, |
| + uword base, |
| + uword prologue_offset, |
| + uword size, |
| + bool optimized) { |
| + Dart_FileWriterFunction perf_events_writer = Dart::perf_events_writer(); |
| + ASSERT(perf_events_writer != 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); |
| + (*perf_events_writer)(buffer, len); |
| + } |
| +}; |
| + |
| + |
| +class PprofCodeObserver : public CodeObserver { |
| + public: |
| + 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); |
| + } |
| +}; |
| + |
| + |
| +class GdbCodeObserver : public CodeObserver { |
| + public: |
| + 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 prolog sequence we register two symbols for the cases when |
| + // the prolog sequence is not the first instruction: |
| + // <name>_entry is used for code preceding the prolog sequence. |
|
Ivan Posva
2012/11/27 09:11:20
prologue
|
| + // <name> for rest of the code (first instruction is prolog sequence). |
|
Ivan Posva
2012/11/27 09:11:20
prologue
|
| + 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); |
| + } |
| + } |
| +}; |
| + |
| + |
| +void Dart::RegisterDefaultCodeObservers() { |
| + RegisterCodeObserver(new PerfCodeObserver); |
| + RegisterCodeObserver(new PprofCodeObserver); |
| + RegisterCodeObserver(new GdbCodeObserver); |
| +#if defined(DART_VTUNE_SUPPORT) |
| + RegisterCodeObserver(new VTuneCodeObserver; |
|
Ivan Posva
2012/11/27 09:11:20
Does not compile).
Vyacheslav Egorov (Google)
2012/11/27 16:26:12
Indeed. Fixed
|
| +#endif |
| +} |
| + |
| } // namespace dart |