Index: runtime/vm/code_observers.cc |
diff --git a/runtime/vm/code_observers.cc b/runtime/vm/code_observers.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b476a0dd07570138a7ea1949e11a7f01afaf9d76 |
--- /dev/null |
+++ b/runtime/vm/code_observers.cc |
@@ -0,0 +1,142 @@ |
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+ |
+#include "vm/code_observers.h" |
+ |
+#include "vm/dart.h" |
+#include "vm/debuginfo.h" |
+#include "vm/flags.h" |
+#include "vm/isolate.h" |
+#include "vm/os.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"); |
+ |
+intptr_t CodeObservers::observers_length_ = 0; |
+CodeObserver** CodeObservers::observers_ = NULL; |
+ |
+ |
+void CodeObservers::Register(CodeObserver* observer) { |
+ observers_length_++; |
+ observers_ = reinterpret_cast<CodeObserver**>( |
+ realloc(observers_, sizeof(observer) * observers_length_)); |
+ if (observers_ == NULL) { |
+ FATAL("failed to grow code observers array"); |
+ } |
+ observers_[observers_length_ - 1] = observer; |
+} |
+ |
+ |
+void CodeObservers::NotifyAll(const char* name, |
+ uword base, |
+ uword prologue_offset, |
+ uword size, |
+ bool optimized) { |
+ ASSERT(!AreActive() || (strlen(name) != 0)); |
+ for (intptr_t i = 0; i < observers_length_; i++) { |
+ if (observers_[i]->IsActive()) { |
+ observers_[i]->Notify(name, base, prologue_offset, size, optimized); |
+ } |
+ } |
+} |
+ |
+ |
+bool CodeObservers::AreActive() { |
+ for (intptr_t i = 0; i < observers_length_; i++) { |
+ if (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 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); |
+ } |
+ } |
+}; |
+ |
+ |
+void CodeObservers::InitOnce() { |
+ Register(new PerfCodeObserver); |
+ Register(new PprofCodeObserver); |
+ Register(new GdbCodeObserver); |
+#if defined(DART_VTUNE_SUPPORT) |
+ Register(new VTuneCodeObserver); |
+#endif |
+} |
+ |
+ |
+} // namespace dart |