Find correct source position in inlined functions on debug break.
BUG=110010 TEST=test-debug/DebugBreakInline Review URL: https://chromiumcodereview.appspot.com/9295014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10551 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
375be4ae25
commit
f7c09d99b7
@ -1603,6 +1603,7 @@ DeoptimizedFrameInfo::DeoptimizedFrameInfo(
|
||||
SetFunction(output_frame->GetFunction());
|
||||
expression_count_ = output_frame->GetExpressionCount();
|
||||
expression_stack_ = new Object*[expression_count_];
|
||||
pc_ = output_frame->GetPc();
|
||||
for (int i = 0; i < expression_count_; i++) {
|
||||
SetExpression(i, output_frame->GetExpression(i));
|
||||
}
|
||||
|
@ -749,6 +749,10 @@ class DeoptimizedFrameInfo : public Malloced {
|
||||
return expression_stack_[index];
|
||||
}
|
||||
|
||||
Address GetPc() {
|
||||
return reinterpret_cast<Address>(pc_);
|
||||
}
|
||||
|
||||
private:
|
||||
// Set the frame function.
|
||||
void SetFunction(JSFunction* function) {
|
||||
@ -772,6 +776,7 @@ class DeoptimizedFrameInfo : public Malloced {
|
||||
int expression_count_;
|
||||
Object** parameters_;
|
||||
Object** expression_stack_;
|
||||
intptr_t pc_;
|
||||
|
||||
friend class Deoptimizer;
|
||||
};
|
||||
|
@ -10747,6 +10747,11 @@ class FrameInspector {
|
||||
? deoptimized_frame_->GetExpression(index)
|
||||
: frame_->GetExpression(index);
|
||||
}
|
||||
Address GetPc() {
|
||||
return is_optimized_
|
||||
? deoptimized_frame_->GetPc()
|
||||
: frame_->pc();
|
||||
}
|
||||
|
||||
// To inspect all the provided arguments the frame might need to be
|
||||
// replaced with the arguments frame.
|
||||
@ -10852,17 +10857,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
|
||||
// Get the frame id.
|
||||
Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
|
||||
|
||||
// Find source position.
|
||||
int position =
|
||||
it.frame()->LookupCode()->SourcePosition(it.frame()->pc());
|
||||
// Find source position in unoptimized code.
|
||||
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
int position = shared->code()->SourcePosition(frame_inspector.GetPc());
|
||||
|
||||
// Check for constructor frame. Inlined frames cannot be construct calls.
|
||||
bool inlined_frame = is_optimized && inlined_jsframe_index != 0;
|
||||
bool constructor = !inlined_frame && it.frame()->IsConstructor();
|
||||
|
||||
// Get scope info and read from it for local variable information.
|
||||
Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
Handle<ScopeInfo> scope_info(shared->scope_info());
|
||||
ASSERT(*scope_info != ScopeInfo::Empty());
|
||||
|
||||
|
@ -7286,4 +7286,65 @@ TEST(DebugBreakLoop) {
|
||||
}
|
||||
|
||||
|
||||
v8::Local<v8::Script> inline_script;
|
||||
|
||||
static void DebugBreakInlineListener(v8::DebugEvent event,
|
||||
v8::Handle<v8::Object> exec_state,
|
||||
v8::Handle<v8::Object> event_data,
|
||||
v8::Handle<v8::Value> data) {
|
||||
if (event != v8::Break) return;
|
||||
|
||||
int expected_frame_count = 4;
|
||||
int expected_line_number[] = {1, 4, 7, 12};
|
||||
|
||||
i::Handle<i::Object> compiled_script = v8::Utils::OpenHandle(*inline_script);
|
||||
i::Handle<i::Script> source_script = i::Handle<i::Script>(i::Script::cast(
|
||||
i::JSFunction::cast(*compiled_script)->shared()->script()));
|
||||
|
||||
int break_id = v8::internal::Isolate::Current()->debug()->break_id();
|
||||
char script[128];
|
||||
i::Vector<char> script_vector(script, sizeof(script));
|
||||
OS::SNPrintF(script_vector, "%%GetFrameCount(%d)", break_id);
|
||||
v8::Local<v8::Value> result = CompileRun(script);
|
||||
|
||||
int frame_count = result->Int32Value();
|
||||
CHECK_EQ(expected_frame_count, frame_count);
|
||||
|
||||
for (int i = 0; i < frame_count; i++) {
|
||||
// The 5. element in the returned array of GetFrameDetails contains the
|
||||
// source position of that frame.
|
||||
OS::SNPrintF(script_vector, "%%GetFrameDetails(%d, %d)[5]", break_id, i);
|
||||
v8::Local<v8::Value> result = CompileRun(script);
|
||||
CHECK_EQ(expected_line_number[i],
|
||||
i::GetScriptLineNumber(source_script, result->Int32Value()));
|
||||
}
|
||||
v8::Debug::SetDebugEventListener(NULL);
|
||||
v8::V8::TerminateExecution();
|
||||
}
|
||||
|
||||
|
||||
TEST(DebugBreakInline) {
|
||||
i::FLAG_allow_natives_syntax = true;
|
||||
v8::HandleScope scope;
|
||||
DebugLocalContext env;
|
||||
const char* source =
|
||||
"function debug(b) { \n"
|
||||
" if (b) debugger; \n"
|
||||
"} \n"
|
||||
"function f(b) { \n"
|
||||
" debug(b) \n"
|
||||
"}; \n"
|
||||
"function g(b) { \n"
|
||||
" f(b); \n"
|
||||
"}; \n"
|
||||
"g(false); \n"
|
||||
"g(false); \n"
|
||||
"%OptimizeFunctionOnNextCall(g); \n"
|
||||
"g(true);";
|
||||
v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
|
||||
inline_script = v8::Script::Compile(v8::String::New(source));
|
||||
inline_script->Run();
|
||||
}
|
||||
|
||||
|
||||
#endif // ENABLE_DEBUGGER_SUPPORT
|
||||
|
Loading…
Reference in New Issue
Block a user