Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Unified Diff: runtime/vm/profiler_service.cc

Issue 864173008: Split profiler.cc into profiler.cc and profiler_service.cc (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/profiler_service.cc
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler_service.cc
similarity index 65%
copy from runtime/vm/profiler.cc
copy to runtime/vm/profiler_service.cc
index 335d105018c0c5655d800003d5bb42656aa965c0..a6457d6cd40ad1bd1186539ef5be1c87bf14d677 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler_service.cc
@@ -1,202 +1,22 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2015, 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 "platform/address_sanitizer.h"
-#include "platform/memory_sanitizer.h"
-#include "platform/utils.h"
+#include "vm/profiler_service.h"
-#include "vm/allocation.h"
-#include "vm/atomic.h"
-#include "vm/code_patcher.h"
-#include "vm/isolate.h"
-#include "vm/json_stream.h"
-#include "vm/lockers.h"
+#include "vm/growable_array.h"
#include "vm/native_symbol.h"
#include "vm/object.h"
#include "vm/os.h"
#include "vm/profiler.h"
#include "vm/reusable_handles.h"
-#include "vm/signal_handler.h"
-#include "vm/simulator.h"
-#include "vm/stack_frame.h"
+#include "vm/scope_timer.h"
namespace dart {
-
-#if defined(TARGET_OS_ANDROID) || defined(HOST_ARCH_ARM64)
- DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler");
-#else
- DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
-#endif
-DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
-DEFINE_FLAG(bool, trace_profiler, false, "Trace profiler.");
-DEFINE_FLAG(int, profile_period, 1000,
- "Time between profiler samples in microseconds. Minimum 50.");
-DEFINE_FLAG(int, profile_depth, 8,
- "Maximum number stack frames walked. Minimum 1. Maximum 255.");
-#if defined(PROFILE_NATIVE_CODE) || defined(USING_SIMULATOR)
-DEFINE_FLAG(bool, profile_vm, true,
- "Always collect native stack traces.");
-#else
-DEFINE_FLAG(bool, profile_vm, false,
- "Always collect native stack traces.");
-#endif
-
-bool Profiler::initialized_ = false;
-SampleBuffer* Profiler::sample_buffer_ = NULL;
-
-void Profiler::InitOnce() {
- // Place some sane restrictions on user controlled flags.
- SetSamplePeriod(FLAG_profile_period);
- SetSampleDepth(FLAG_profile_depth);
- Sample::InitOnce();
- if (!FLAG_profile) {
- return;
- }
- ASSERT(!initialized_);
- sample_buffer_ = new SampleBuffer();
- NativeSymbolResolver::InitOnce();
- ThreadInterrupter::SetInterruptPeriod(FLAG_profile_period);
- ThreadInterrupter::Startup();
- initialized_ = true;
-}
-
-
-void Profiler::Shutdown() {
- if (!FLAG_profile) {
- return;
- }
- ASSERT(initialized_);
- ThreadInterrupter::Shutdown();
- NativeSymbolResolver::ShutdownOnce();
-}
-
-
-void Profiler::SetSampleDepth(intptr_t depth) {
- const int kMinimumDepth = 1;
- const int kMaximumDepth = 255;
- if (depth < kMinimumDepth) {
- FLAG_profile_depth = kMinimumDepth;
- } else if (depth > kMaximumDepth) {
- FLAG_profile_depth = kMaximumDepth;
- } else {
- FLAG_profile_depth = depth;
- }
-}
-
-
-void Profiler::SetSamplePeriod(intptr_t period) {
- const int kMinimumProfilePeriod = 50;
- if (period < kMinimumProfilePeriod) {
- FLAG_profile_period = kMinimumProfilePeriod;
- } else {
- FLAG_profile_period = period;
- }
-}
-
-
-void Profiler::InitProfilingForIsolate(Isolate* isolate, bool shared_buffer) {
- if (!FLAG_profile) {
- return;
- }
- ASSERT(isolate == Isolate::Current());
- ASSERT(isolate != NULL);
- ASSERT(sample_buffer_ != NULL);
- {
- MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
- SampleBuffer* sample_buffer = sample_buffer_;
- if (!shared_buffer) {
- sample_buffer = new SampleBuffer();
- }
- IsolateProfilerData* profiler_data =
- new IsolateProfilerData(sample_buffer, !shared_buffer);
- ASSERT(profiler_data != NULL);
- isolate->set_profiler_data(profiler_data);
- if (FLAG_trace_profiled_isolates) {
- OS::Print("Profiler Setup %p %s\n", isolate, isolate->name());
- }
- }
- BeginExecution(isolate);
-}
-
-
-void Profiler::ShutdownProfilingForIsolate(Isolate* isolate) {
- ASSERT(isolate != NULL);
- if (!FLAG_profile) {
- return;
- }
- // We do not have a current isolate.
- ASSERT(Isolate::Current() == NULL);
- {
- MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
- // Already freed.
- return;
- }
- isolate->set_profiler_data(NULL);
- delete profiler_data;
- if (FLAG_trace_profiled_isolates) {
- OS::Print("Profiler Shutdown %p %s\n", isolate, isolate->name());
- }
- }
-}
-
-
-void Profiler::BeginExecution(Isolate* isolate) {
- if (isolate == NULL) {
- return;
- }
- if (!FLAG_profile) {
- return;
- }
- ASSERT(initialized_);
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
- return;
- }
- ThreadInterrupter::Register(RecordSampleInterruptCallback, isolate);
- ThreadInterrupter::WakeUp();
-}
-
-
-void Profiler::EndExecution(Isolate* isolate) {
- if (isolate == NULL) {
- return;
- }
- if (!FLAG_profile) {
- return;
- }
- ASSERT(initialized_);
- ThreadInterrupter::Unregister();
-}
-
-
-class ScopeStopwatch : public ValueObject {
- public:
- explicit ScopeStopwatch(const char* name) : name_(name) {
- start_ = FLAG_trace_profiler ? OS::GetCurrentTimeMillis() : 0;
- }
-
- int64_t GetElapsed() const {
- int64_t end = OS::GetCurrentTimeMillis();
- ASSERT(end >= start_);
- return end - start_;
- }
-
- ~ScopeStopwatch() {
- if (FLAG_trace_profiler) {
- int64_t elapsed = GetElapsed();
- OS::Print("%s took %" Pd64 " millis.\n", name_, elapsed);
- }
- }
-
- private:
- const char* name_;
- int64_t start_;
-};
-
+DECLARE_FLAG(int, profile_depth);
+DECLARE_FLAG(bool, trace_profiler);
+DECLARE_FLAG(int, profile_period);
struct AddressEntry {
uword pc;
@@ -537,7 +357,7 @@ class CodeRegion : public ZoneAllocated {
}
}
- void PrintToJSONArray(Isolate* isolate, JSONArray* events, bool full) {
+ void PrintToJSONArray(Isolate* isolate, JSONArray* events) {
JSONObject obj(events);
obj.AddProperty("kind", KindToCString(kind()));
obj.AddPropertyF("inclusive_ticks", "%" Pd "", inclusive_ticks());
@@ -551,7 +371,7 @@ class CodeRegion : public ZoneAllocated {
code ^= Code::LookupCodeInVmIsolate(start());
}
ASSERT(!code.IsNull());
- obj.AddProperty("code", code, !full);
+ obj.AddProperty("code", code);
} else if (kind() == kCollectedCode) {
if (name() == NULL) {
// Lazily set generated name.
@@ -1225,7 +1045,7 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
ASSERT(root_index >= 0);
region->set_creation_serial(0);
root_ = new CodeRegionTrieNode(tag_code_table_offset_ + root_index);
- set_tag_order(Profiler::kUserVM);
+ set_tag_order(ProfilerService::kUserVM);
}
void VisitSample(Sample* sample) {
@@ -1248,11 +1068,11 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
return root_;
}
- Profiler::TagOrder tag_order() const {
+ ProfilerService::TagOrder tag_order() const {
return tag_order_;
}
- void set_tag_order(Profiler::TagOrder tag_order) {
+ void set_tag_order(ProfilerService::TagOrder tag_order) {
tag_order_ = tag_order;
}
@@ -1292,25 +1112,25 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
CodeRegionTrieNode* ProcessTags(Sample* sample, CodeRegionTrieNode* current) {
// None.
- if (tag_order() == Profiler::kNoTags) {
+ if (tag_order() == ProfilerService::kNoTags) {
return current;
}
// User first.
- if ((tag_order() == Profiler::kUserVM) ||
- (tag_order() == Profiler::kUser)) {
+ if ((tag_order() == ProfilerService::kUserVM) ||
+ (tag_order() == ProfilerService::kUser)) {
current = ProcessUserTags(sample, current);
// Only user.
- if (tag_order() == Profiler::kUser) {
+ if (tag_order() == ProfilerService::kUser) {
return current;
}
return ProcessVMTags(sample, current);
}
// VM first.
- ASSERT((tag_order() == Profiler::kVMUser) ||
- (tag_order() == Profiler::kVM));
+ ASSERT((tag_order() == ProfilerService::kVMUser) ||
+ (tag_order() == ProfilerService::kVM));
current = ProcessVMTags(sample, current);
// Only VM.
- if (tag_order() == Profiler::kVM) {
+ if (tag_order() == ProfilerService::kVM) {
return current;
}
return ProcessUserTags(sample, current);
@@ -1347,7 +1167,7 @@ class CodeRegionExclusiveTrieBuilder : public SampleVisitor {
return index;
}
- Profiler::TagOrder tag_order_;
+ ProfilerService::TagOrder tag_order_;
CodeRegionTrieNode* root_;
CodeRegionTable* live_code_table_;
CodeRegionTable* dead_code_table_;
@@ -1419,11 +1239,10 @@ class CodeRegionTableCallersBuilder {
};
-void Profiler::PrintJSON(Isolate* isolate, JSONStream* stream,
- bool full, TagOrder tag_order) {
- ASSERT(isolate == Isolate::Current());
+void ProfilerService::PrintJSON(JSONStream* stream, TagOrder tag_order) {
+ Isolate* isolate = Isolate::Current();
// Disable profile interrupts while processing the buffer.
- EndExecution(isolate);
+ Profiler::EndExecution(isolate);
MutexLocker profiler_data_lock(isolate->profiler_data_mutex());
IsolateProfilerData* profiler_data = isolate->profiler_data();
if (profiler_data == NULL) {
@@ -1448,7 +1267,7 @@ void Profiler::PrintJSON(Isolate* isolate, JSONStream* stream,
&dead_code_table,
&tag_code_table);
{
- ScopeStopwatch sw("FixTopFrame");
+ ScopeTimer sw("FixTopFrame", FLAG_trace_profiler);
// Preprocess samples and fix the caller when the top PC is in a
// stub or intrinsic without a frame.
FixTopFrameVisitor fixTopFrame(isolate);
@@ -1456,7 +1275,7 @@ void Profiler::PrintJSON(Isolate* isolate, JSONStream* stream,
}
{
// Build CodeRegion tables.
- ScopeStopwatch sw("CodeRegionTableBuilder");
+ ScopeTimer sw("CodeRegionTableBuilder", FLAG_trace_profiler);
sample_buffer->VisitSamples(&builder);
}
intptr_t samples = builder.visited();
@@ -1486,7 +1305,7 @@ void Profiler::PrintJSON(Isolate* isolate, JSONStream* stream,
build_trie.set_tag_order(tag_order);
{
// Build CodeRegion trie.
- ScopeStopwatch sw("CodeRegionExclusiveTrieBuilder");
+ ScopeTimer sw("CodeRegionExclusiveTrieBuilder", FLAG_trace_profiler);
sample_buffer->VisitSamples(&build_trie);
build_trie.root()->SortByCount();
}
@@ -1496,11 +1315,11 @@ void Profiler::PrintJSON(Isolate* isolate, JSONStream* stream,
&tag_code_table);
{
// Build CodeRegion callers.
- ScopeStopwatch sw("CodeRegionTableCallersBuilder");
+ ScopeTimer sw("CodeRegionTableCallersBuilder", FLAG_trace_profiler);
build_callers.Build();
}
{
- ScopeStopwatch sw("CodeTableStream");
+ ScopeTimer sw("CodeTableStream", FLAG_trace_profiler);
// Serialize to JSON.
JSONObject obj(stream);
obj.AddProperty("type", "CpuProfile");
@@ -1520,571 +1339,23 @@ void Profiler::PrintJSON(Isolate* isolate, JSONStream* stream,
for (intptr_t i = 0; i < live_code_table.Length(); i++) {
CodeRegion* region = live_code_table.At(i);
ASSERT(region != NULL);
- region->PrintToJSONArray(isolate, &codes, full);
+ region->PrintToJSONArray(isolate, &codes);
}
for (intptr_t i = 0; i < dead_code_table.Length(); i++) {
CodeRegion* region = dead_code_table.At(i);
ASSERT(region != NULL);
- region->PrintToJSONArray(isolate, &codes, full);
+ region->PrintToJSONArray(isolate, &codes);
}
for (intptr_t i = 0; i < tag_code_table.Length(); i++) {
CodeRegion* region = tag_code_table.At(i);
ASSERT(region != NULL);
- region->PrintToJSONArray(isolate, &codes, full);
+ region->PrintToJSONArray(isolate, &codes);
}
}
}
}
// Enable profile interrupts.
- BeginExecution(isolate);
-}
-
-
-IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer,
- bool own_sample_buffer) {
- ASSERT(sample_buffer != NULL);
- sample_buffer_ = sample_buffer;
- own_sample_buffer_ = own_sample_buffer;
- block_count_ = 0;
-}
-
-
-IsolateProfilerData::~IsolateProfilerData() {
- if (own_sample_buffer_) {
- delete sample_buffer_;
- sample_buffer_ = NULL;
- own_sample_buffer_ = false;
- }
-}
-
-
-void IsolateProfilerData::Block() {
- block_count_++;
-}
-
-
-void IsolateProfilerData::Unblock() {
- block_count_--;
- if (block_count_ < 0) {
- FATAL("Too many calls to Dart_IsolateUnblocked.");
- }
- if (!blocked()) {
- // We just unblocked this isolate, wake up the thread interrupter.
- ThreadInterrupter::WakeUp();
- }
-}
-
-
-intptr_t Sample::pcs_length_ = 0;
-intptr_t Sample::instance_size_ = 0;
-
-
-void Sample::InitOnce() {
- ASSERT(FLAG_profile_depth >= 1);
- pcs_length_ = FLAG_profile_depth;
- instance_size_ =
- sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT.
-}
-
-
-uword* Sample::GetPCArray() const {
- return reinterpret_cast<uword*>(
- reinterpret_cast<uintptr_t>(this) + sizeof(*this));
-}
-
-
-SampleBuffer::SampleBuffer(intptr_t capacity) {
- ASSERT(Sample::instance_size() > 0);
- samples_ = reinterpret_cast<Sample*>(
- calloc(capacity, Sample::instance_size()));
- capacity_ = capacity;
- cursor_ = 0;
-}
-
-
-Sample* SampleBuffer::At(intptr_t idx) const {
- ASSERT(idx >= 0);
- ASSERT(idx < capacity_);
- intptr_t offset = idx * Sample::instance_size();
- uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
- return reinterpret_cast<Sample*>(samples + offset);
-}
-
-
-Sample* SampleBuffer::ReserveSample() {
- ASSERT(samples_ != NULL);
- uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
- // Map back into sample buffer range.
- cursor = cursor % capacity_;
- return At(cursor);
-}
-
-
-static void SetPCMarkerIfSafe(Sample* sample) {
- ASSERT(sample != NULL);
-
- uword* fp = reinterpret_cast<uword*>(sample->fp());
- uword* sp = reinterpret_cast<uword*>(sample->sp());
-
- // If FP == SP, the pc marker hasn't been pushed.
- if (fp > sp) {
-#if defined(TARGET_OS_WINDOWS)
- // If the fp is at the beginning of a page, it may be unsafe to access
- // the pc marker, because we are reading it from a different thread on
- // Windows. The marker is below fp and the previous page may be a guard
- // page.
- const intptr_t kPageMask = VirtualMemory::PageSize() - 1;
- if ((sample->fp() & kPageMask) == 0) {
- return;
- }
-#endif
- uword* pc_marker_ptr = fp + kPcMarkerSlotFromFp;
- // MSan/ASan are unaware of frames initialized by generated code.
- MSAN_UNPOISON(pc_marker_ptr, kWordSize);
- ASAN_UNPOISON(pc_marker_ptr, kWordSize);
- sample->set_pc_marker(*pc_marker_ptr);
- }
-}
-
-
-// Given an exit frame, walk the Dart stack.
-class ProfilerDartExitStackWalker : public ValueObject {
- public:
- ProfilerDartExitStackWalker(Isolate* isolate, Sample* sample)
- : sample_(sample),
- frame_iterator_(isolate) {
- ASSERT(sample_ != NULL);
- // Mark that this sample was collected from an exit frame.
- sample_->set_exit_frame_sample(true);
- }
-
- void walk() {
- intptr_t frame_index = 0;
- StackFrame* frame = frame_iterator_.NextFrame();
- while (frame != NULL) {
- sample_->SetAt(frame_index, frame->pc());
- frame_index++;
- if (frame_index >= FLAG_profile_depth) {
- break;
- }
- frame = frame_iterator_.NextFrame();
- }
- }
-
- private:
- Sample* sample_;
- DartFrameIterator frame_iterator_;
-};
-
-
-// Executing Dart code, walk the stack.
-class ProfilerDartStackWalker : public ValueObject {
- public:
- ProfilerDartStackWalker(Isolate* isolate,
- Sample* sample,
- uword stack_lower,
- uword stack_upper,
- uword pc,
- uword fp,
- uword sp)
- : isolate_(isolate),
- sample_(sample),
- stack_upper_(stack_upper),
- stack_lower_(stack_lower) {
- ASSERT(sample_ != NULL);
- pc_ = reinterpret_cast<uword*>(pc);
- fp_ = reinterpret_cast<uword*>(fp);
- sp_ = reinterpret_cast<uword*>(sp);
- }
-
- void walk() {
- if (!ValidFramePointer()) {
- sample_->set_ignore_sample(true);
- return;
- }
- ASSERT(ValidFramePointer());
- uword return_pc = InitialReturnAddress();
- if (StubCode::InInvocationStubForIsolate(isolate_, return_pc)) {
- // Edge case- we have called out from the Invocation Stub but have not
- // created the stack frame of the callee. Attempt to locate the exit
- // frame before walking the stack.
- if (!NextExit() || !ValidFramePointer()) {
- // Nothing to sample.
- sample_->set_ignore_sample(true);
- return;
- }
- }
- for (int i = 0; i < FLAG_profile_depth; i++) {
- sample_->SetAt(i, reinterpret_cast<uword>(pc_));
- if (!Next()) {
- return;
- }
- }
- }
-
- private:
- bool Next() {
- if (!ValidFramePointer()) {
- return false;
- }
- if (StubCode::InInvocationStubForIsolate(isolate_,
- reinterpret_cast<uword>(pc_))) {
- // In invocation stub.
- return NextExit();
- }
- // In regular Dart frame.
- uword* new_pc = CallerPC();
- // Check if we've moved into the invocation stub.
- if (StubCode::InInvocationStubForIsolate(isolate_,
- reinterpret_cast<uword>(new_pc))) {
- // New PC is inside invocation stub, skip.
- return NextExit();
- }
- uword* new_fp = CallerFP();
- if (new_fp <= fp_) {
- // FP didn't move to a higher address.
- return false;
- }
- // Success, update fp and pc.
- fp_ = new_fp;
- pc_ = new_pc;
- return true;
- }
-
- bool NextExit() {
- if (!ValidFramePointer()) {
- return false;
- }
- uword* new_fp = ExitLink();
- if (new_fp == NULL) {
- // No exit link.
- return false;
- }
- if (new_fp <= fp_) {
- // FP didn't move to a higher address.
- return false;
- }
- if (!ValidFramePointer(new_fp)) {
- return false;
- }
- // Success, update fp and pc.
- fp_ = new_fp;
- pc_ = CallerPC();
- return true;
- }
-
- uword InitialReturnAddress() const {
- ASSERT(sp_ != NULL);
- return *(sp_);
- }
-
- uword* CallerPC() const {
- ASSERT(fp_ != NULL);
- return reinterpret_cast<uword*>(*(fp_ + kSavedCallerPcSlotFromFp));
- }
-
- uword* CallerFP() const {
- ASSERT(fp_ != NULL);
- return reinterpret_cast<uword*>(*(fp_ + kSavedCallerFpSlotFromFp));
- }
-
- uword* ExitLink() const {
- ASSERT(fp_ != NULL);
- return reinterpret_cast<uword*>(*(fp_ + kExitLinkSlotFromEntryFp));
- }
-
- bool ValidFramePointer() const {
- return ValidFramePointer(fp_);
- }
-
- bool ValidFramePointer(uword* fp) const {
- if (fp == NULL) {
- return false;
- }
- uword cursor = reinterpret_cast<uword>(fp);
- cursor += sizeof(fp);
- return (cursor >= stack_lower_) && (cursor < stack_upper_);
- }
-
- uword* pc_;
- uword* fp_;
- uword* sp_;
- Isolate* isolate_;
- Sample* sample_;
- const uword stack_upper_;
- uword stack_lower_;
-};
-
-
-// If the VM is compiled without frame pointers (which is the default on
-// recent GCC versions with optimizing enabled) the stack walking code may
-// fail.
-//
-class ProfilerNativeStackWalker : public ValueObject {
- public:
- ProfilerNativeStackWalker(Sample* sample,
- uword stack_lower,
- uword stack_upper,
- uword pc,
- uword fp,
- uword sp)
- : sample_(sample),
- stack_upper_(stack_upper),
- original_pc_(pc),
- original_fp_(fp),
- original_sp_(sp),
- lower_bound_(stack_lower) {
- ASSERT(sample_ != NULL);
- }
-
- void walk() {
- const uword kMaxStep = VirtualMemory::PageSize();
-
- sample_->SetAt(0, original_pc_);
-
- uword* pc = reinterpret_cast<uword*>(original_pc_);
- uword* fp = reinterpret_cast<uword*>(original_fp_);
- uword* previous_fp = fp;
-
- uword gap = original_fp_ - original_sp_;
- if (gap >= kMaxStep) {
- // Gap between frame pointer and stack pointer is
- // too large.
- return;
- }
-
- if (!ValidFramePointer(fp)) {
- return;
- }
-
- for (int i = 0; i < FLAG_profile_depth; i++) {
- sample_->SetAt(i, reinterpret_cast<uword>(pc));
-
- pc = CallerPC(fp);
- previous_fp = fp;
- fp = CallerFP(fp);
-
- if (fp == NULL) {
- return;
- }
-
- if (fp <= previous_fp) {
- // Frame pointer did not move to a higher address.
- return;
- }
-
- gap = fp - previous_fp;
- if (gap >= kMaxStep) {
- // Frame pointer step is too large.
- return;
- }
-
- if (!ValidFramePointer(fp)) {
- // Frame pointer is outside of isolate stack boundary.
- return;
- }
-
- // Move the lower bound up.
- lower_bound_ = reinterpret_cast<uword>(fp);
- }
- }
-
- private:
- uword* CallerPC(uword* fp) const {
- ASSERT(fp != NULL);
- uword* caller_pc_ptr = fp + kSavedCallerPcSlotFromFp;
- // This may actually be uninitialized, by design (see class comment above).
- MSAN_UNPOISON(caller_pc_ptr, kWordSize);
- ASAN_UNPOISON(caller_pc_ptr, kWordSize);
- return reinterpret_cast<uword*>(*caller_pc_ptr);
- }
-
- uword* CallerFP(uword* fp) const {
- ASSERT(fp != NULL);
- uword* caller_fp_ptr = fp + kSavedCallerFpSlotFromFp;
- // This may actually be uninitialized, by design (see class comment above).
- MSAN_UNPOISON(caller_fp_ptr, kWordSize);
- ASAN_UNPOISON(caller_fp_ptr, kWordSize);
- return reinterpret_cast<uword*>(*caller_fp_ptr);
- }
-
- bool ValidFramePointer(uword* fp) const {
- if (fp == NULL) {
- return false;
- }
- uword cursor = reinterpret_cast<uword>(fp);
- cursor += sizeof(fp);
- bool r = (cursor >= lower_bound_) && (cursor < stack_upper_);
- return r;
- }
-
- Sample* sample_;
- const uword stack_upper_;
- const uword original_pc_;
- const uword original_fp_;
- const uword original_sp_;
- uword lower_bound_;
-};
-
-
-void Profiler::RecordSampleInterruptCallback(
- const InterruptedThreadState& state,
- void* data) {
- Isolate* isolate = reinterpret_cast<Isolate*>(data);
- if ((isolate == NULL) || (Dart::vm_isolate() == NULL)) {
- // No isolate.
- return;
- }
-
- ASSERT(isolate != Dart::vm_isolate());
-
- uintptr_t sp = 0;
- if ((isolate->stub_code() != NULL) &&
- (isolate->top_exit_frame_info() == 0) &&
- (isolate->vm_tag() == VMTag::kDartTagId)) {
- // If we're in Dart code, use the Dart stack pointer.
- sp = state.dsp;
- } else {
- // If we're in runtime code, use the C stack pointer.
- sp = state.csp;
- }
-
- IsolateProfilerData* profiler_data = isolate->profiler_data();
- if (profiler_data == NULL) {
- // Profiler not initialized.
- return;
- }
-
- SampleBuffer* sample_buffer = profiler_data->sample_buffer();
- if (sample_buffer == NULL) {
- // Profiler not initialized.
- return;
- }
-
- if ((sp == 0) || (state.fp == 0) || (state.pc == 0)) {
- // None of these registers should be zero.
- return;
- }
-
- if (sp > state.fp) {
- // Assuming the stack grows down, we should never have a stack pointer above
- // the frame pointer.
- return;
- }
-
- if (StubCode::InJumpToExceptionHandlerStub(state.pc)) {
- // The JumpToExceptionHandler stub manually adjusts the stack pointer,
- // frame pointer, and some isolate state before jumping to a catch entry.
- // It is not safe to walk the stack when executing this stub.
- return;
- }
-
- uword stack_lower = 0;
- uword stack_upper = 0;
- if (!isolate->GetProfilerStackBounds(&stack_lower, &stack_upper) ||
- (stack_lower == 0) || (stack_upper == 0)) {
- // Could not get stack boundary.
- return;
- }
-
- if (sp > stack_lower) {
- // The stack pointer gives us a tighter lower bound.
- stack_lower = sp;
- }
-
- if (stack_lower >= stack_upper) {
- // Stack boundary is invalid.
- return;
- }
-
- if ((sp < stack_lower) || (sp >= stack_upper)) {
- // Stack pointer is outside isolate stack boundary.
- return;
- }
-
- if ((state.fp < stack_lower) || (state.fp >= stack_upper)) {
- // Frame pointer is outside isolate stack boundary.
- return;
- }
-
- // At this point we have a valid stack boundary for this isolate and
- // know that our initial stack and frame pointers are within the boundary.
-
- // Setup sample.
- Sample* sample = sample_buffer->ReserveSample();
- sample->Init(isolate, OS::GetCurrentTimeMicros(), state.tid);
- uword vm_tag = isolate->vm_tag();
-#if defined(USING_SIMULATOR)
- // When running in the simulator, the runtime entry function address
- // (stored as the vm tag) is the address of a redirect function.
- // Attempt to find the real runtime entry function address and use that.
- uword redirect_vm_tag = Simulator::FunctionForRedirect(vm_tag);
- if (redirect_vm_tag != 0) {
- vm_tag = redirect_vm_tag;
- }
-#endif
- // Increment counter for vm tag.
- VMTagCounters* counters = isolate->vm_tag_counters();
- ASSERT(counters != NULL);
- counters->Increment(vm_tag);
- sample->set_vm_tag(vm_tag);
- sample->set_user_tag(isolate->user_tag());
- sample->set_sp(sp);
- sample->set_fp(state.fp);
-#if !(defined(TARGET_OS_WINDOWS) && defined(TARGET_ARCH_X64))
- // It is never safe to read other thread's stack unless on Win64
- // other thread is inside Dart code.
- SetPCMarkerIfSafe(sample);
-#endif
-
- // Walk the call stack.
- if (FLAG_profile_vm) {
- // Always walk the native stack collecting both native and Dart frames.
- ProfilerNativeStackWalker stackWalker(sample,
- stack_lower,
- stack_upper,
- state.pc,
- state.fp,
- sp);
- stackWalker.walk();
- } else {
- // Attempt to walk only the Dart call stack, falling back to walking
- // the native stack.
- if ((isolate->stub_code() != NULL) &&
- (isolate->top_exit_frame_info() != 0) &&
- (isolate->vm_tag() != VMTag::kDartTagId)) {
- // We have a valid exit frame info, use the Dart stack walker.
- ProfilerDartExitStackWalker stackWalker(isolate, sample);
- stackWalker.walk();
- } else if ((isolate->stub_code() != NULL) &&
- (isolate->top_exit_frame_info() == 0) &&
- (isolate->vm_tag() == VMTag::kDartTagId)) {
- // We are executing Dart code. We have frame pointers.
- ProfilerDartStackWalker stackWalker(isolate,
- sample,
- stack_lower,
- stack_upper,
- state.pc,
- state.fp,
- sp);
- stackWalker.walk();
- } else {
-#if defined(TARGET_OS_WINDOWS) && defined(TARGET_ARCH_X64)
- // ProfilerNativeStackWalker is known to cause crashes on Win64.
- // BUG=20423.
- sample->set_ignore_sample(true);
-#else
- // Fall back to an extremely conservative stack walker.
- ProfilerNativeStackWalker stackWalker(sample,
- stack_lower,
- stack_upper,
- state.pc,
- state.fp,
- sp);
- stackWalker.walk();
-#endif
- }
- }
+ Profiler::BeginExecution(isolate);
}
} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698