Get rid or heap allocation in stack sampler to avoid deadlocks.

Review URL: http://codereview.chromium.org/40219

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1440 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3f402fb9
...@@ -138,39 +138,31 @@ bool Profiler::paused_ = false; ...@@ -138,39 +138,31 @@ bool Profiler::paused_ = false;
// //
void StackTracer::Trace(TickSample* sample) { void StackTracer::Trace(TickSample* sample) {
if (sample->state == GC) { if (sample->state == GC) {
sample->InitStack(0); sample->frames_count = 0;
return; return;
} }
// If c_entry_fp is available, this means that we are inside a C++ // If c_entry_fp is available, this means that we are inside a C++
// function and sample->fp value isn't reliable due to FPO // function and sample->fp value isn't reliable due to FPO.
if (Top::c_entry_fp(Top::GetCurrentThread()) != NULL) { if (Top::c_entry_fp(Top::GetCurrentThread()) != NULL) {
SafeStackTraceFrameIterator it( SafeStackTraceFrameIterator it(
reinterpret_cast<Address>(sample->sp), reinterpret_cast<Address>(sample->sp),
reinterpret_cast<Address>(low_stack_bound_)); reinterpret_cast<Address>(low_stack_bound_));
// Pass 1: Calculate depth int i = 0;
int depth = 0; while (!it.done() && i < TickSample::kMaxFramesCount) {
while (!it.done() && depth <= kMaxStackFrames) { sample->stack[i++] = it.frame()->pc();
++depth;
it.Advance(); it.Advance();
} }
// Pass 2: Save stack sample->frames_count = i;
sample->InitStack(depth);
if (depth > 0) {
it.Reset();
for (int i = 0; i < depth && !it.done(); ++i, it.Advance()) {
sample->stack[i] = it.frame()->pc();
}
}
} else if (sample->sp < sample->fp && sample->fp < low_stack_bound_) { } else if (sample->sp < sample->fp && sample->fp < low_stack_bound_) {
// The check assumes that stack grows from lower addresses // The check assumes that stack grows from lower addresses.
sample->InitStack(1);
sample->stack[0] = Memory::Address_at( sample->stack[0] = Memory::Address_at(
(Address)(sample->fp + StandardFrameConstants::kCallerPCOffset)); (Address)(sample->fp + StandardFrameConstants::kCallerPCOffset));
sample->frames_count = 1;
} else { } else {
// FP seems to be in some intermediate state, // FP seems to be in some intermediate state,
// better discard this sample // better discard this sample
sample->InitStack(0); sample->frames_count = 0;
} }
} }
...@@ -945,10 +937,8 @@ void Logger::TickEvent(TickSample* sample, bool overflow) { ...@@ -945,10 +937,8 @@ void Logger::TickEvent(TickSample* sample, bool overflow) {
if (overflow) { if (overflow) {
msg.Append(",overflow"); msg.Append(",overflow");
} }
if (*(sample->stack)) { for (int i = 0; i < sample->frames_count; ++i) {
for (size_t i = 0; sample->stack[i]; ++i) { msg.Append(",%p", sample->stack[i]);
msg.Append(",0x%x", reinterpret_cast<unsigned int>(sample->stack[i]));
}
} }
msg.Append('\n'); msg.Append('\n');
msg.WriteToLogFile(); msg.WriteToLogFile();
......
...@@ -277,8 +277,6 @@ class StackTracer BASE_EMBEDDED { ...@@ -277,8 +277,6 @@ class StackTracer BASE_EMBEDDED {
: low_stack_bound_(low_stack_bound) { } : low_stack_bound_(low_stack_bound) { }
void Trace(TickSample* sample); void Trace(TickSample* sample);
private: private:
// Maximum number of stack frames to capture
static const int kMaxStackFrames = 5;
unsigned int low_stack_bound_; unsigned int low_stack_bound_;
}; };
......
...@@ -466,26 +466,9 @@ class TickSample { ...@@ -466,26 +466,9 @@ class TickSample {
unsigned int sp; // Stack pointer. unsigned int sp; // Stack pointer.
unsigned int fp; // Frame pointer. unsigned int fp; // Frame pointer.
StateTag state; // The state of the VM. StateTag state; // The state of the VM.
SmartPointer<Address> stack; // Call stack, null-terminated. static const int kMaxFramesCount = 5;
EmbeddedVector<Address, kMaxFramesCount> stack; // Call stack.
inline TickSample& operator=(const TickSample& rhs) { int frames_count; // Number of captured frames.
if (this == &rhs) return *this;
pc = rhs.pc;
sp = rhs.sp;
fp = rhs.fp;
state = rhs.state;
DeleteArray(stack.Detach());
stack = rhs.stack;
return *this;
}
inline void InitStack(int depth) {
if (depth) {
stack = SmartPointer<Address>(NewArray<Address>(depth + 1));
// null-terminate
stack[depth] = 0;
}
}
}; };
class Sampler { class Sampler {
......
...@@ -94,9 +94,9 @@ TEST(PureCStackTrace) { ...@@ -94,9 +94,9 @@ TEST(PureCStackTrace) {
#ifdef DEBUG #ifdef DEBUG
// C stack trace works only in debug mode, in release mode EBP is // C stack trace works only in debug mode, in release mode EBP is
// usually treated as a general-purpose register // usually treated as a general-purpose register
CHECK_GT(sample.frames_count, 0);
CheckRetAddrIsInCFunction(reinterpret_cast<unsigned int>(sample.stack[0]), CheckRetAddrIsInCFunction(reinterpret_cast<unsigned int>(sample.stack[0]),
reinterpret_cast<unsigned int>(&CFunc)); reinterpret_cast<unsigned int>(&CFunc));
CHECK_EQ(0, sample.stack[1]);
#endif #endif
} }
...@@ -217,7 +217,7 @@ TEST(PureJSStackTrace) { ...@@ -217,7 +217,7 @@ TEST(PureJSStackTrace) {
" JSFuncDoTrace();" " JSFuncDoTrace();"
"};\n" "};\n"
"JSTrace();"); "JSTrace();");
CHECK_NE(0, *(sample.stack)); CHECK_GT(sample.frames_count, 1);
CheckRetAddrIsInFunction( CheckRetAddrIsInFunction(
reinterpret_cast<unsigned int>(sample.stack[0]), reinterpret_cast<unsigned int>(sample.stack[0]),
reinterpret_cast<unsigned int>(call_trace_code->instruction_start()), reinterpret_cast<unsigned int>(call_trace_code->instruction_start()),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment