Revision: 15348
Author: [email protected]
Date: Thu Jun 27 02:28:11 2013
Log: Do not iterate stack handlers in SafeStackFrameIterator
CPU profiler doesn't use stack handlers so there is no need to iterate
through them while traversing stack. This change SafeStackFrameIterator
always iterate only frames and removes checks corresponding to the handlers
iteration.
The problem described in the bug occurred because of a false assumption in
SafeStackFrameIterator that if Isolate::c_entry_fp is not NULL then the top
frame on the stack is always a C++ frame. It is false because we may have
entered JS code again, in which case JS_ENTRY code stub generated by
JSEntryStub::GenerateBody() will save current c_entry_fp value but not
reset it to NULL and after that it will create ENTRY stack frame and
JS_ENTRY handler on the stack and put the latter into
Isolate::handler(top). This means that if we start iterating from
c_entry_fp frame and try to compare the frame's sp with
Isolate::handler()->address() it will turn out that frame->sp() >
handler->address() and the condition in
SafeStackFrameIterator::CanIterateHandles is not held.
BUG=252097
[email protected], [email protected]
Review URL: https://codereview.chromium.org/17589022
http://code.google.com/p/v8/source/detail?r=15348
Modified:
/branches/bleeding_edge/src/frames.cc
/branches/bleeding_edge/src/frames.h
/branches/bleeding_edge/test/cctest/test-cpu-profiler.cc
=======================================
--- /branches/bleeding_edge/src/frames.cc Wed Jun 26 07:04:25 2013
+++ /branches/bleeding_edge/src/frames.cc Thu Jun 27 02:28:11 2013
@@ -112,8 +112,7 @@
frame_(NULL), handler_(NULL),
thread_(use_top ? isolate_->thread_local_top() : NULL),
fp_(use_top ? NULL : fp), sp_(sp),
- advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
- &StackFrameIterator::AdvanceWithoutHandler),
+ advance_(&StackFrameIterator::AdvanceWithoutHandler),
can_access_heap_objects_(false) {
if (use_top || fp != NULL) {
Reset();
@@ -299,7 +298,6 @@
Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
// Before advancing to the next stack frame, perform pointer validity
tests
iteration_done_ = !IsValidFrame(last_frame) ||
- !CanIterateHandles(last_frame, iterator_.handler()) ||
!IsValidCaller(last_frame);
if (iteration_done_) return;
@@ -309,15 +307,6 @@
StackFrame* prev_frame = iterator_.frame();
iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() <
last_fp;
}
-
-
-bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
- StackHandler* handler) {
- // If StackIterator iterates over StackHandles, verify that
- // StackHandlerIterator can be instantiated (see StackHandlerIterator
- // constructor.)
- return !is_valid_top_ || (frame->sp() <= handler->address());
-}
bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
=======================================
--- /branches/bleeding_edge/src/frames.h Tue Jun 25 03:09:19 2013
+++ /branches/bleeding_edge/src/frames.h Thu Jun 27 02:28:11 2013
@@ -919,7 +919,6 @@
bool IsValidStackAddress(Address addr) const {
return stack_validator_.IsValid(addr);
}
- bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
bool IsValidFrame(StackFrame* frame) const;
bool IsValidCaller(StackFrame* frame);
static bool IsValidTop(Isolate* isolate,
=======================================
--- /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Thu Jun 13
12:16:35 2013
+++ /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Thu Jun 27
02:28:11 2013
@@ -914,3 +914,54 @@
cpu_profiler->DeleteAllCpuProfiles();
}
+
+
+static const char* bound_function_test_source = "function foo(iterations)
{\n"
+" var r = 0;\n"
+" for (var i = 0; i < iterations; i++) { r += i; }\n"
+" return r;\n"
+"}\n"
+"function start(duration) {\n"
+" var callback = foo.bind(this);\n"
+" var start = Date.now();\n"
+" while (Date.now() - start < duration) {\n"
+" callback(10 * 1000);\n"
+" }\n"
+"}";
+
+
+TEST(BoundFunctionCall) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::New(bound_function_test_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("start")));
+
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+ v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+
+ cpu_profiler->StartCpuProfiling(profile_name);
+ int32_t duration_ms = 100;
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(duration_ms) };
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+ const v8::CpuProfile* profile =
cpu_profiler->StopCpuProfiling(profile_name);
+
+ CHECK_NE(NULL, profile);
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(
+ const_cast<v8::CpuProfile*>(profile))->Print();
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ ScopedVector<v8::Handle<v8::String> > names(3);
+ names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName);
+ names[1] = v8::String::New(ProfileGenerator::kProgramEntryName);
+ names[2] = v8::String::New("start");
+ // Don't allow |foo| node to be at the top level.
+ CheckChildrenNames(root, names);
+
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ GetChild(startNode, "foo");
+
+ cpu_profiler->DeleteAllCpuProfiles();
+}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.