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 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); | 2253 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); |
2233 } | 2254 } |
2234 | 2255 |
2235 #ifdef DEBUG | 2256 #ifdef DEBUG |
2236 void Debug::PrintBreakLocation() { | 2257 void Debug::PrintBreakLocation() { |
2237 if (!FLAG_print_break_location) return; | 2258 if (!FLAG_print_break_location) return; |
2238 HandleScope scope(isolate_); | 2259 HandleScope scope(isolate_); |
2239 JavaScriptFrameIterator iterator(isolate_); | 2260 JavaScriptFrameIterator iterator(isolate_); |
2240 if (iterator.done()) return; | 2261 if (iterator.done()) return; |
2241 JavaScriptFrame* frame = iterator.frame(); | 2262 JavaScriptFrame* frame = iterator.frame(); |
2242 FrameSummary summary = FrameSummary::GetFirst(frame); | 2263 FrameSummary summary = GetFirstFrameSummary(frame); |
2243 int source_position = | 2264 int source_position = |
2244 summary.abstract_code()->SourcePosition(summary.code_offset()); | 2265 summary.abstract_code()->SourcePosition(summary.code_offset()); |
2245 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_); | 2266 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_); |
2246 PrintF("[debug] break in function '"); | 2267 PrintF("[debug] break in function '"); |
2247 summary.function()->PrintName(); | 2268 summary.function()->PrintName(); |
2248 PrintF("'.\n"); | 2269 PrintF("'.\n"); |
2249 if (script_obj->IsScript()) { | 2270 if (script_obj->IsScript()) { |
2250 Handle<Script> script = Handle<Script>::cast(script_obj); | 2271 Handle<Script> script = Handle<Script>::cast(script_obj); |
2251 Handle<String> source(String::cast(script->source())); | 2272 Handle<String> source(String::cast(script->source())); |
2252 Script::InitLineEnds(script); | 2273 Script::InitLineEnds(script); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2576 } | 2597 } |
2577 | 2598 |
2578 | 2599 |
2579 void LockingCommandMessageQueue::Clear() { | 2600 void LockingCommandMessageQueue::Clear() { |
2580 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2601 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2581 queue_.Clear(); | 2602 queue_.Clear(); |
2582 } | 2603 } |
2583 | 2604 |
2584 } // namespace internal | 2605 } // namespace internal |
2585 } // namespace v8 | 2606 } // namespace v8 |
OLD | NEW |