| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/debug/debug.h" | 5 #include "src/debug/debug.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 | 253 |
| 254 // Find the break point at the supplied address, or the closest one before | 254 // Find the break point at the supplied address, or the closest one before |
| 255 // the address. | 255 // the address. |
| 256 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 256 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
| 257 int offset) { | 257 int offset) { |
| 258 base::SmartPointer<Iterator> it(GetIterator(debug_info)); | 258 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
| 259 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 259 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
| 260 return it->GetBreakLocation(); | 260 return it->GetBreakLocation(); |
| 261 } | 261 } |
| 262 | 262 |
| 263 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { |
| 264 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| 265 frame->Summarize(&frames); |
| 266 return frames.first(); |
| 267 } |
| 268 |
| 263 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | 269 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { |
| 264 // Code offset points to the instruction after the call. Subtract 1 to | 270 // Code offset points to the instruction after the call. Subtract 1 to |
| 265 // exclude that instruction from the search. For bytecode, the code offset | 271 // exclude that instruction from the search. For bytecode, the code offset |
| 266 // still points to the call. | 272 // still points to the call. |
| 267 return is_interpreted ? code_offset : code_offset - 1; | 273 return is_interpreted ? code_offset : code_offset - 1; |
| 268 } | 274 } |
| 269 | 275 |
| 270 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 276 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
| 271 JavaScriptFrame* frame) { | 277 JavaScriptFrame* frame) { |
| 272 FrameSummary summary = FrameSummary::GetFirst(frame); | 278 FrameSummary summary = GetFirstFrameSummary(frame); |
| 273 int call_offset = | 279 int call_offset = |
| 274 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 280 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); |
| 275 return FromCodeOffset(debug_info, call_offset); | 281 return FromCodeOffset(debug_info, call_offset); |
| 276 } | 282 } |
| 277 | 283 |
| 278 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 284 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
| 279 int statement_position, | 285 int statement_position, |
| 280 List<BreakLocation>* result_out) { | 286 List<BreakLocation>* result_out) { |
| 281 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); | 287 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
| 282 it->Next()) { | 288 it->Next()) { |
| (...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 if (current_fp < target_fp) return; | 624 if (current_fp < target_fp) return; |
| 619 step_break = true; | 625 step_break = true; |
| 620 break; | 626 break; |
| 621 case StepNext: | 627 case StepNext: |
| 622 // Step next should not break in a deeper frame. | 628 // Step next should not break in a deeper frame. |
| 623 if (current_fp < target_fp) return; | 629 if (current_fp < target_fp) return; |
| 624 // For step-next, a tail call is like a return and should break. | 630 // For step-next, a tail call is like a return and should break. |
| 625 step_break = location.IsTailCall(); | 631 step_break = location.IsTailCall(); |
| 626 // Fall through. | 632 // Fall through. |
| 627 case StepIn: { | 633 case StepIn: { |
| 628 FrameSummary summary = FrameSummary::GetFirst(frame); | 634 FrameSummary summary = GetFirstFrameSummary(frame); |
| 629 int offset = summary.code_offset(); | 635 int offset = summary.code_offset(); |
| 630 step_break = step_break || location.IsReturn() || | 636 step_break = step_break || location.IsReturn() || |
| 631 (current_fp != last_fp) || | 637 (current_fp != last_fp) || |
| 632 (thread_local_.last_statement_position_ != | 638 (thread_local_.last_statement_position_ != |
| 633 location.abstract_code()->SourceStatementPosition(offset)); | 639 location.abstract_code()->SourceStatementPosition(offset)); |
| 634 break; | 640 break; |
| 635 } | 641 } |
| 636 case StepFrame: | 642 case StepFrame: |
| 637 step_break = current_fp != last_fp; | 643 step_break = current_fp != last_fp; |
| 638 break; | 644 break; |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 // Step out: Find the calling JavaScript frame and flood it with | 1004 // Step out: Find the calling JavaScript frame and flood it with |
| 999 // breakpoints. | 1005 // breakpoints. |
| 1000 frames_it.Advance(); | 1006 frames_it.Advance(); |
| 1001 // Fill the function to return to with one-shot break points. | 1007 // Fill the function to return to with one-shot break points. |
| 1002 JSFunction* function = frames_it.frame()->function(); | 1008 JSFunction* function = frames_it.frame()->function(); |
| 1003 FloodWithOneShot(Handle<JSFunction>(function)); | 1009 FloodWithOneShot(Handle<JSFunction>(function)); |
| 1004 return; | 1010 return; |
| 1005 } | 1011 } |
| 1006 | 1012 |
| 1007 // Get the debug info (create it if it does not exist). | 1013 // Get the debug info (create it if it does not exist). |
| 1008 FrameSummary summary = FrameSummary::GetFirst(frame); | 1014 FrameSummary summary = GetFirstFrameSummary(frame); |
| 1009 Handle<JSFunction> function(summary.function()); | 1015 Handle<JSFunction> function(summary.function()); |
| 1010 Handle<SharedFunctionInfo> shared(function->shared()); | 1016 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1011 if (!EnsureDebugInfo(shared, function)) { | 1017 if (!EnsureDebugInfo(shared, function)) { |
| 1012 // Return if ensuring debug info failed. | 1018 // Return if ensuring debug info failed. |
| 1013 return; | 1019 return; |
| 1014 } | 1020 } |
| 1015 | 1021 |
| 1016 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1022 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1017 // Refresh frame summary if the code has been recompiled for debugging. | 1023 // Refresh frame summary if the code has been recompiled for debugging. |
| 1018 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { | 1024 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { |
| 1019 summary = FrameSummary::GetFirst(frame); | 1025 summary = GetFirstFrameSummary(frame); |
| 1020 } | 1026 } |
| 1021 | 1027 |
| 1022 int call_offset = | 1028 int call_offset = |
| 1023 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 1029 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); |
| 1024 BreakLocation location = | 1030 BreakLocation location = |
| 1025 BreakLocation::FromCodeOffset(debug_info, call_offset); | 1031 BreakLocation::FromCodeOffset(debug_info, call_offset); |
| 1026 | 1032 |
| 1027 // Any step at a return is a step-out. | 1033 // Any step at a return is a step-out. |
| 1028 if (location.IsReturn()) step_action = StepOut; | 1034 if (location.IsReturn()) step_action = StepOut; |
| 1029 // A step-next at a tail call is a step-out. | 1035 // A step-next at a tail call is a step-out. |
| (...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1591 HandleScope scope(isolate_); | 1597 HandleScope scope(isolate_); |
| 1592 | 1598 |
| 1593 // Get the executing function in which the debug break occurred. | 1599 // Get the executing function in which the debug break occurred. |
| 1594 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1600 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
| 1595 Handle<SharedFunctionInfo> shared(function->shared()); | 1601 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1596 | 1602 |
| 1597 // With no debug info there are no break points, so we can't be at a return. | 1603 // With no debug info there are no break points, so we can't be at a return. |
| 1598 if (!shared->HasDebugInfo()) return false; | 1604 if (!shared->HasDebugInfo()) return false; |
| 1599 | 1605 |
| 1600 DCHECK(!frame->is_optimized()); | 1606 DCHECK(!frame->is_optimized()); |
| 1601 FrameSummary summary = FrameSummary::GetFirst(frame); | 1607 FrameSummary summary = GetFirstFrameSummary(frame); |
| 1602 | 1608 |
| 1603 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1609 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1604 BreakLocation location = | 1610 BreakLocation location = |
| 1605 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); | 1611 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); |
| 1606 return location.IsReturn() || location.IsTailCall(); | 1612 return location.IsReturn() || location.IsTailCall(); |
| 1607 } | 1613 } |
| 1608 | 1614 |
| 1609 | 1615 |
| 1610 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1616 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
| 1611 LiveEdit::FrameDropMode mode) { | 1617 LiveEdit::FrameDropMode mode) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1643 Script* script; | 1649 Script* script; |
| 1644 while ((script = iterator.Next())) { | 1650 while ((script = iterator.Next())) { |
| 1645 if (script->HasValidSource()) results->set(length++, script); | 1651 if (script->HasValidSource()) results->set(length++, script); |
| 1646 } | 1652 } |
| 1647 } | 1653 } |
| 1648 results->Shrink(length); | 1654 results->Shrink(length); |
| 1649 return results; | 1655 return results; |
| 1650 } | 1656 } |
| 1651 | 1657 |
| 1652 | 1658 |
| 1659 void Debug::RecordEvalCaller(Handle<Script> script) { |
| 1660 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); |
| 1661 // For eval scripts add information on the function from which eval was |
| 1662 // called. |
| 1663 StackTraceFrameIterator it(script->GetIsolate()); |
| 1664 if (!it.done()) { |
| 1665 script->set_eval_from_shared(it.frame()->function()->shared()); |
| 1666 Code* code = it.frame()->LookupCode(); |
| 1667 int offset = static_cast<int>( |
| 1668 it.frame()->pc() - code->instruction_start()); |
| 1669 script->set_eval_from_instructions_offset(offset); |
| 1670 } |
| 1671 } |
| 1672 |
| 1673 |
| 1653 MaybeHandle<Object> Debug::MakeExecutionState() { | 1674 MaybeHandle<Object> Debug::MakeExecutionState() { |
| 1654 // Create the execution state object. | 1675 // Create the execution state object. |
| 1655 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; | 1676 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; |
| 1656 return CallFunction("MakeExecutionState", arraysize(argv), argv); | 1677 return CallFunction("MakeExecutionState", arraysize(argv), argv); |
| 1657 } | 1678 } |
| 1658 | 1679 |
| 1659 | 1680 |
| 1660 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { | 1681 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { |
| 1661 // Create the new break event object. | 1682 // Create the new break event object. |
| 1662 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()), | 1683 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()), |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2259 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); | 2280 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); |
| 2260 } | 2281 } |
| 2261 | 2282 |
| 2262 #ifdef DEBUG | 2283 #ifdef DEBUG |
| 2263 void Debug::PrintBreakLocation() { | 2284 void Debug::PrintBreakLocation() { |
| 2264 if (!FLAG_print_break_location) return; | 2285 if (!FLAG_print_break_location) return; |
| 2265 HandleScope scope(isolate_); | 2286 HandleScope scope(isolate_); |
| 2266 JavaScriptFrameIterator iterator(isolate_); | 2287 JavaScriptFrameIterator iterator(isolate_); |
| 2267 if (iterator.done()) return; | 2288 if (iterator.done()) return; |
| 2268 JavaScriptFrame* frame = iterator.frame(); | 2289 JavaScriptFrame* frame = iterator.frame(); |
| 2269 FrameSummary summary = FrameSummary::GetFirst(frame); | 2290 FrameSummary summary = GetFirstFrameSummary(frame); |
| 2270 int source_position = | 2291 int source_position = |
| 2271 summary.abstract_code()->SourcePosition(summary.code_offset()); | 2292 summary.abstract_code()->SourcePosition(summary.code_offset()); |
| 2272 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_); | 2293 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_); |
| 2273 PrintF("[debug] break in function '"); | 2294 PrintF("[debug] break in function '"); |
| 2274 summary.function()->PrintName(); | 2295 summary.function()->PrintName(); |
| 2275 PrintF("'.\n"); | 2296 PrintF("'.\n"); |
| 2276 if (script_obj->IsScript()) { | 2297 if (script_obj->IsScript()) { |
| 2277 Handle<Script> script = Handle<Script>::cast(script_obj); | 2298 Handle<Script> script = Handle<Script>::cast(script_obj); |
| 2278 Handle<String> source(String::cast(script->source())); | 2299 Handle<String> source(String::cast(script->source())); |
| 2279 Script::InitLineEnds(script); | 2300 Script::InitLineEnds(script); |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2603 } | 2624 } |
| 2604 | 2625 |
| 2605 | 2626 |
| 2606 void LockingCommandMessageQueue::Clear() { | 2627 void LockingCommandMessageQueue::Clear() { |
| 2607 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2628 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2608 queue_.Clear(); | 2629 queue_.Clear(); |
| 2609 } | 2630 } |
| 2610 | 2631 |
| 2611 } // namespace internal | 2632 } // namespace internal |
| 2612 } // namespace v8 | 2633 } // namespace v8 |
| OLD | NEW |