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 | |
269 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | 263 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { |
270 // Code offset points to the instruction after the call. Subtract 1 to | 264 // Code offset points to the instruction after the call. Subtract 1 to |
271 // exclude that instruction from the search. For bytecode, the code offset | 265 // exclude that instruction from the search. For bytecode, the code offset |
272 // still points to the call. | 266 // still points to the call. |
273 return is_interpreted ? code_offset : code_offset - 1; | 267 return is_interpreted ? code_offset : code_offset - 1; |
274 } | 268 } |
275 | 269 |
276 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 270 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
277 JavaScriptFrame* frame) { | 271 JavaScriptFrame* frame) { |
278 FrameSummary summary = GetFirstFrameSummary(frame); | 272 FrameSummary summary = FrameSummary::GetFirst(frame); |
279 int call_offset = | 273 int call_offset = |
280 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 274 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); |
281 return FromCodeOffset(debug_info, call_offset); | 275 return FromCodeOffset(debug_info, call_offset); |
282 } | 276 } |
283 | 277 |
284 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 278 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
285 int statement_position, | 279 int statement_position, |
286 List<BreakLocation>* result_out) { | 280 List<BreakLocation>* result_out) { |
287 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); | 281 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
288 it->Next()) { | 282 it->Next()) { |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
624 if (current_fp < target_fp) return; | 618 if (current_fp < target_fp) return; |
625 step_break = true; | 619 step_break = true; |
626 break; | 620 break; |
627 case StepNext: | 621 case StepNext: |
628 // Step next should not break in a deeper frame. | 622 // Step next should not break in a deeper frame. |
629 if (current_fp < target_fp) return; | 623 if (current_fp < target_fp) return; |
630 // For step-next, a tail call is like a return and should break. | 624 // For step-next, a tail call is like a return and should break. |
631 step_break = location.IsTailCall(); | 625 step_break = location.IsTailCall(); |
632 // Fall through. | 626 // Fall through. |
633 case StepIn: { | 627 case StepIn: { |
634 FrameSummary summary = GetFirstFrameSummary(frame); | 628 FrameSummary summary = FrameSummary::GetFirst(frame); |
635 int offset = summary.code_offset(); | 629 int offset = summary.code_offset(); |
636 step_break = step_break || location.IsReturn() || | 630 step_break = step_break || location.IsReturn() || |
637 (current_fp != last_fp) || | 631 (current_fp != last_fp) || |
638 (thread_local_.last_statement_position_ != | 632 (thread_local_.last_statement_position_ != |
639 location.abstract_code()->SourceStatementPosition(offset)); | 633 location.abstract_code()->SourceStatementPosition(offset)); |
640 break; | 634 break; |
641 } | 635 } |
642 case StepFrame: | 636 case StepFrame: |
643 step_break = current_fp != last_fp; | 637 step_break = current_fp != last_fp; |
644 break; | 638 break; |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 // Step out: Find the calling JavaScript frame and flood it with | 998 // Step out: Find the calling JavaScript frame and flood it with |
1005 // breakpoints. | 999 // breakpoints. |
1006 frames_it.Advance(); | 1000 frames_it.Advance(); |
1007 // Fill the function to return to with one-shot break points. | 1001 // Fill the function to return to with one-shot break points. |
1008 JSFunction* function = frames_it.frame()->function(); | 1002 JSFunction* function = frames_it.frame()->function(); |
1009 FloodWithOneShot(Handle<JSFunction>(function)); | 1003 FloodWithOneShot(Handle<JSFunction>(function)); |
1010 return; | 1004 return; |
1011 } | 1005 } |
1012 | 1006 |
1013 // Get the debug info (create it if it does not exist). | 1007 // Get the debug info (create it if it does not exist). |
1014 FrameSummary summary = GetFirstFrameSummary(frame); | 1008 FrameSummary summary = FrameSummary::GetFirst(frame); |
1015 Handle<JSFunction> function(summary.function()); | 1009 Handle<JSFunction> function(summary.function()); |
1016 Handle<SharedFunctionInfo> shared(function->shared()); | 1010 Handle<SharedFunctionInfo> shared(function->shared()); |
1017 if (!EnsureDebugInfo(shared, function)) { | 1011 if (!EnsureDebugInfo(shared, function)) { |
1018 // Return if ensuring debug info failed. | 1012 // Return if ensuring debug info failed. |
1019 return; | 1013 return; |
1020 } | 1014 } |
1021 | 1015 |
1022 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1016 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1023 // Refresh frame summary if the code has been recompiled for debugging. | 1017 // Refresh frame summary if the code has been recompiled for debugging. |
1024 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { | 1018 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { |
1025 summary = GetFirstFrameSummary(frame); | 1019 summary = FrameSummary::GetFirst(frame); |
1026 } | 1020 } |
1027 | 1021 |
1028 int call_offset = | 1022 int call_offset = |
1029 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 1023 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); |
1030 BreakLocation location = | 1024 BreakLocation location = |
1031 BreakLocation::FromCodeOffset(debug_info, call_offset); | 1025 BreakLocation::FromCodeOffset(debug_info, call_offset); |
1032 | 1026 |
1033 // Any step at a return is a step-out. | 1027 // Any step at a return is a step-out. |
1034 if (location.IsReturn()) step_action = StepOut; | 1028 if (location.IsReturn()) step_action = StepOut; |
1035 // A step-next at a tail call is a step-out. | 1029 // A step-next at a tail call is a step-out. |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1597 HandleScope scope(isolate_); | 1591 HandleScope scope(isolate_); |
1598 | 1592 |
1599 // Get the executing function in which the debug break occurred. | 1593 // Get the executing function in which the debug break occurred. |
1600 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1594 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
1601 Handle<SharedFunctionInfo> shared(function->shared()); | 1595 Handle<SharedFunctionInfo> shared(function->shared()); |
1602 | 1596 |
1603 // With no debug info there are no break points, so we can't be at a return. | 1597 // With no debug info there are no break points, so we can't be at a return. |
1604 if (!shared->HasDebugInfo()) return false; | 1598 if (!shared->HasDebugInfo()) return false; |
1605 | 1599 |
1606 DCHECK(!frame->is_optimized()); | 1600 DCHECK(!frame->is_optimized()); |
1607 FrameSummary summary = GetFirstFrameSummary(frame); | 1601 FrameSummary summary = FrameSummary::GetFirst(frame); |
1608 | 1602 |
1609 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1603 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1610 BreakLocation location = | 1604 BreakLocation location = |
1611 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); | 1605 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); |
1612 return location.IsReturn() || location.IsTailCall(); | 1606 return location.IsReturn() || location.IsTailCall(); |
1613 } | 1607 } |
1614 | 1608 |
1615 | 1609 |
1616 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1610 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
1617 LiveEdit::FrameDropMode mode) { | 1611 LiveEdit::FrameDropMode mode) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1649 Script* script; | 1643 Script* script; |
1650 while ((script = iterator.Next())) { | 1644 while ((script = iterator.Next())) { |
1651 if (script->HasValidSource()) results->set(length++, script); | 1645 if (script->HasValidSource()) results->set(length++, script); |
1652 } | 1646 } |
1653 } | 1647 } |
1654 results->Shrink(length); | 1648 results->Shrink(length); |
1655 return results; | 1649 return results; |
1656 } | 1650 } |
1657 | 1651 |
1658 | 1652 |
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 | |
1674 MaybeHandle<Object> Debug::MakeExecutionState() { | 1653 MaybeHandle<Object> Debug::MakeExecutionState() { |
1675 // Create the execution state object. | 1654 // Create the execution state object. |
1676 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; | 1655 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; |
1677 return CallFunction("MakeExecutionState", arraysize(argv), argv); | 1656 return CallFunction("MakeExecutionState", arraysize(argv), argv); |
1678 } | 1657 } |
1679 | 1658 |
1680 | 1659 |
1681 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { | 1660 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { |
1682 // Create the new break event object. | 1661 // Create the new break event object. |
1683 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()), | 1662 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()), |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2253 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); | 2232 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); |
2254 } | 2233 } |
2255 | 2234 |
2256 #ifdef DEBUG | 2235 #ifdef DEBUG |
2257 void Debug::PrintBreakLocation() { | 2236 void Debug::PrintBreakLocation() { |
2258 if (!FLAG_print_break_location) return; | 2237 if (!FLAG_print_break_location) return; |
2259 HandleScope scope(isolate_); | 2238 HandleScope scope(isolate_); |
2260 JavaScriptFrameIterator iterator(isolate_); | 2239 JavaScriptFrameIterator iterator(isolate_); |
2261 if (iterator.done()) return; | 2240 if (iterator.done()) return; |
2262 JavaScriptFrame* frame = iterator.frame(); | 2241 JavaScriptFrame* frame = iterator.frame(); |
2263 FrameSummary summary = GetFirstFrameSummary(frame); | 2242 FrameSummary summary = FrameSummary::GetFirst(frame); |
2264 int source_position = | 2243 int source_position = |
2265 summary.abstract_code()->SourcePosition(summary.code_offset()); | 2244 summary.abstract_code()->SourcePosition(summary.code_offset()); |
2266 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_); | 2245 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_); |
2267 PrintF("[debug] break in function '"); | 2246 PrintF("[debug] break in function '"); |
2268 summary.function()->PrintName(); | 2247 summary.function()->PrintName(); |
2269 PrintF("'.\n"); | 2248 PrintF("'.\n"); |
2270 if (script_obj->IsScript()) { | 2249 if (script_obj->IsScript()) { |
2271 Handle<Script> script = Handle<Script>::cast(script_obj); | 2250 Handle<Script> script = Handle<Script>::cast(script_obj); |
2272 Handle<String> source(String::cast(script->source())); | 2251 Handle<String> source(String::cast(script->source())); |
2273 Script::InitLineEnds(script); | 2252 Script::InitLineEnds(script); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2597 } | 2576 } |
2598 | 2577 |
2599 | 2578 |
2600 void LockingCommandMessageQueue::Clear() { | 2579 void LockingCommandMessageQueue::Clear() { |
2601 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2580 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2602 queue_.Clear(); | 2581 queue_.Clear(); |
2603 } | 2582 } |
2604 | 2583 |
2605 } // namespace internal | 2584 } // namespace internal |
2606 } // namespace v8 | 2585 } // namespace v8 |
OLD | NEW |