| 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" |
| 11 #include "src/codegen.h" | 11 #include "src/codegen.h" |
| 12 #include "src/compilation-cache.h" | 12 #include "src/compilation-cache.h" |
| 13 #include "src/compiler.h" | 13 #include "src/compiler.h" |
| 14 #include "src/deoptimizer.h" | 14 #include "src/deoptimizer.h" |
| 15 #include "src/execution.h" | 15 #include "src/execution.h" |
| 16 #include "src/frames-inl.h" | 16 #include "src/frames-inl.h" |
| 17 #include "src/full-codegen/full-codegen.h" | 17 #include "src/full-codegen/full-codegen.h" |
| 18 #include "src/global-handles.h" | 18 #include "src/global-handles.h" |
| 19 #include "src/interpreter/interpreter.h" | 19 #include "src/interpreter/interpreter.h" |
| 20 #include "src/isolate-inl.h" | 20 #include "src/isolate-inl.h" |
| 21 #include "src/list.h" | 21 #include "src/list.h" |
| 22 #include "src/log.h" | 22 #include "src/log.h" |
| 23 #include "src/messages.h" | 23 #include "src/messages.h" |
| 24 #include "src/snapshot/natives.h" | 24 #include "src/snapshot/natives.h" |
| 25 #include "src/wasm/wasm-debug.h" |
| 26 #include "src/wasm/wasm-module.h" |
| 25 | 27 |
| 26 #include "include/v8-debug.h" | 28 #include "include/v8-debug.h" |
| 27 | 29 |
| 28 namespace v8 { | 30 namespace v8 { |
| 29 namespace internal { | 31 namespace internal { |
| 30 | 32 |
| 33 namespace { |
| 34 |
| 35 inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { |
| 36 // Code offset points to the instruction after the call. Subtract 1 to |
| 37 // exclude that instruction from the search. For bytecode, the code offset |
| 38 // still points to the call. |
| 39 return is_interpreted ? code_offset : code_offset - 1; |
| 40 } |
| 41 |
| 42 } // namespace |
| 43 |
| 31 Debug::Debug(Isolate* isolate) | 44 Debug::Debug(Isolate* isolate) |
| 32 : debug_context_(Handle<Context>()), | 45 : debug_context_(Handle<Context>()), |
| 33 event_listener_(Handle<Object>()), | 46 event_listener_(Handle<Object>()), |
| 34 event_listener_data_(Handle<Object>()), | 47 event_listener_data_(Handle<Object>()), |
| 35 message_handler_(NULL), | 48 message_handler_(NULL), |
| 36 command_received_(0), | 49 command_received_(0), |
| 37 command_queue_(isolate->logger(), kQueueInitialSize), | 50 command_queue_(isolate->logger(), kQueueInitialSize), |
| 38 is_active_(false), | 51 is_active_(false), |
| 39 is_suppressed_(false), | 52 is_suppressed_(false), |
| 40 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 53 live_edit_enabled_(true), // TODO(yangguo): set to false by default. |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 | 266 |
| 254 // Find the break point at the supplied address, or the closest one before | 267 // Find the break point at the supplied address, or the closest one before |
| 255 // the address. | 268 // the address. |
| 256 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 269 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
| 257 int offset) { | 270 int offset) { |
| 258 base::SmartPointer<Iterator> it(GetIterator(debug_info)); | 271 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
| 259 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 272 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
| 260 return it->GetBreakLocation(); | 273 return it->GetBreakLocation(); |
| 261 } | 274 } |
| 262 | 275 |
| 263 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | |
| 264 // Code offset points to the instruction after the call. Subtract 1 to | |
| 265 // exclude that instruction from the search. For bytecode, the code offset | |
| 266 // still points to the call. | |
| 267 return is_interpreted ? code_offset : code_offset - 1; | |
| 268 } | |
| 269 | |
| 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 int code_offset = FrameSummary::GetFirst(frame).code_offset(); |
| 273 int call_offset = | 279 int call_offset = |
| 274 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 280 CallOffsetFromCodeOffset(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()) { |
| 283 if (it->statement_position() == statement_position) { | 289 if (it->statement_position() == statement_position) { |
| 284 result_out->Add(it->GetBreakLocation()); | 290 result_out->Add(it->GetBreakLocation()); |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 786 | 792 |
| 787 // At least one active break point now. | 793 // At least one active break point now. |
| 788 return debug_info->GetBreakPointCount() > 0; | 794 return debug_info->GetBreakPointCount() > 0; |
| 789 } | 795 } |
| 790 | 796 |
| 791 | 797 |
| 792 bool Debug::SetBreakPointForScript(Handle<Script> script, | 798 bool Debug::SetBreakPointForScript(Handle<Script> script, |
| 793 Handle<Object> break_point_object, | 799 Handle<Object> break_point_object, |
| 794 int* source_position, | 800 int* source_position, |
| 795 BreakPositionAlignment alignment) { | 801 BreakPositionAlignment alignment) { |
| 802 if (script->type() == Script::TYPE_WASM) { |
| 803 // TODO(clemensh): set breakpoint for wasm. |
| 804 return false; |
| 805 } |
| 796 HandleScope scope(isolate_); | 806 HandleScope scope(isolate_); |
| 797 | 807 |
| 798 // Obtain shared function info for the function. | 808 // Obtain shared function info for the function. |
| 799 Handle<Object> result = | 809 Handle<Object> result = |
| 800 FindSharedFunctionInfoInScript(script, *source_position); | 810 FindSharedFunctionInfoInScript(script, *source_position); |
| 801 if (result->IsUndefined(isolate_)) return false; | 811 if (result->IsUndefined(isolate_)) return false; |
| 802 | 812 |
| 803 // Make sure the function has set up the debug info. | 813 // Make sure the function has set up the debug info. |
| 804 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); | 814 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); |
| 805 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { | 815 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1594 } | 1604 } |
| 1595 | 1605 |
| 1596 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 1606 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
| 1597 after_break_target_ = NULL; | 1607 after_break_target_ = NULL; |
| 1598 if (!LiveEdit::SetAfterBreakTarget(this)) { | 1608 if (!LiveEdit::SetAfterBreakTarget(this)) { |
| 1599 // Continue just after the slot. | 1609 // Continue just after the slot. |
| 1600 after_break_target_ = frame->pc(); | 1610 after_break_target_ = frame->pc(); |
| 1601 } | 1611 } |
| 1602 } | 1612 } |
| 1603 | 1613 |
| 1604 | |
| 1605 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1614 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
| 1606 HandleScope scope(isolate_); | 1615 HandleScope scope(isolate_); |
| 1607 | 1616 |
| 1608 // Get the executing function in which the debug break occurred. | 1617 // Get the executing function in which the debug break occurred. |
| 1609 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1618 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
| 1610 Handle<SharedFunctionInfo> shared(function->shared()); | |
| 1611 | 1619 |
| 1612 // With no debug info there are no break points, so we can't be at a return. | 1620 // With no debug info there are no break points, so we can't be at a return. |
| 1613 if (!shared->HasDebugInfo()) return false; | 1621 if (!shared->HasDebugInfo()) return false; |
| 1614 | 1622 |
| 1615 DCHECK(!frame->is_optimized()); | 1623 DCHECK(!frame->is_optimized()); |
| 1616 FrameSummary summary = FrameSummary::GetFirst(frame); | 1624 int code_offset = FrameSummary::GetFirst(frame).code_offset(); |
| 1617 | |
| 1618 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1625 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1619 BreakLocation location = | 1626 BreakLocation location = |
| 1620 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); | 1627 BreakLocation::FromCodeOffset(debug_info, code_offset); |
| 1621 return location.IsReturn() || location.IsTailCall(); | 1628 return location.IsReturn() || location.IsTailCall(); |
| 1622 } | 1629 } |
| 1623 | 1630 |
| 1624 | 1631 |
| 1625 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1632 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
| 1626 LiveEdit::FrameDropMode mode) { | 1633 LiveEdit::FrameDropMode mode) { |
| 1627 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1634 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
| 1628 thread_local_.frame_drop_mode_ = mode; | 1635 thread_local_.frame_drop_mode_ = mode; |
| 1629 } | 1636 } |
| 1630 thread_local_.break_frame_id_ = new_break_frame_id; | 1637 thread_local_.break_frame_id_ = new_break_frame_id; |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2296 StackGuard::TERMINATE_EXECUTION) { | 2303 StackGuard::TERMINATE_EXECUTION) { |
| 2297 // Link recursive debugger entry. | 2304 // Link recursive debugger entry. |
| 2298 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2305 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2299 reinterpret_cast<base::AtomicWord>(this)); | 2306 reinterpret_cast<base::AtomicWord>(this)); |
| 2300 | 2307 |
| 2301 // Store the previous break id, frame id and return value. | 2308 // Store the previous break id, frame id and return value. |
| 2302 break_id_ = debug_->break_id(); | 2309 break_id_ = debug_->break_id(); |
| 2303 break_frame_id_ = debug_->break_frame_id(); | 2310 break_frame_id_ = debug_->break_frame_id(); |
| 2304 return_value_ = debug_->return_value(); | 2311 return_value_ = debug_->return_value(); |
| 2305 | 2312 |
| 2306 // Create the new break info. If there is no JavaScript frames there is no | 2313 // Create the new break info. If there is no proper frames there is no break |
| 2307 // break frame id. | 2314 // frame id. |
| 2308 JavaScriptFrameIterator it(isolate()); | 2315 StackTraceFrameIterator it(isolate()); |
| 2309 bool has_js_frames = !it.done(); | 2316 bool has_frames = !it.done(); |
| 2310 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() | 2317 // We don't currently support breaking inside wasm framess. |
| 2311 : StackFrame::NO_ID; | 2318 DCHECK(!has_frames || !it.is_wasm()); |
| 2319 debug_->thread_local_.break_frame_id_ = |
| 2320 has_frames ? it.frame()->id() : StackFrame::NO_ID; |
| 2312 debug_->SetNextBreakId(); | 2321 debug_->SetNextBreakId(); |
| 2313 | 2322 |
| 2314 debug_->UpdateState(); | 2323 debug_->UpdateState(); |
| 2315 // Make sure that debugger is loaded and enter the debugger context. | 2324 // Make sure that debugger is loaded and enter the debugger context. |
| 2316 // The previous context is kept in save_. | 2325 // The previous context is kept in save_. |
| 2317 failed_ = !debug_->is_loaded(); | 2326 failed_ = !debug_->is_loaded(); |
| 2318 if (!failed_) isolate()->set_context(*debug->debug_context()); | 2327 if (!failed_) isolate()->set_context(*debug->debug_context()); |
| 2319 } | 2328 } |
| 2320 | 2329 |
| 2321 | 2330 |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2596 } | 2605 } |
| 2597 | 2606 |
| 2598 | 2607 |
| 2599 void LockingCommandMessageQueue::Clear() { | 2608 void LockingCommandMessageQueue::Clear() { |
| 2600 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2609 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2601 queue_.Clear(); | 2610 queue_.Clear(); |
| 2602 } | 2611 } |
| 2603 | 2612 |
| 2604 } // namespace internal | 2613 } // namespace internal |
| 2605 } // namespace v8 | 2614 } // namespace v8 |
| OLD | NEW |