| 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
|
|
|