| 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 252 |
| 240 // Find the break point at the supplied address, or the closest one before | 253 // Find the break point at the supplied address, or the closest one before |
| 241 // the address. | 254 // the address. |
| 242 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 255 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
| 243 int offset) { | 256 int offset) { |
| 244 base::SmartPointer<Iterator> it(GetIterator(debug_info)); | 257 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
| 245 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 258 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
| 246 return it->GetBreakLocation(); | 259 return it->GetBreakLocation(); |
| 247 } | 260 } |
| 248 | 261 |
| 249 int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | |
| 250 // Code offset points to the instruction after the call. Subtract 1 to | |
| 251 // exclude that instruction from the search. For bytecode, the code offset | |
| 252 // still points to the call. | |
| 253 return is_interpreted ? code_offset : code_offset - 1; | |
| 254 } | |
| 255 | |
| 256 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 262 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
| 257 JavaScriptFrame* frame) { | 263 JavaScriptFrame* frame) { |
| 258 FrameSummary summary = FrameSummary::GetFirst(frame); | 264 int code_offset = FrameSummary::GetFirst(frame).code_offset(); |
| 259 int call_offset = | 265 int call_offset = |
| 260 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 266 CallOffsetFromCodeOffset(code_offset, frame->is_interpreted()); |
| 261 return FromCodeOffset(debug_info, call_offset); | 267 return FromCodeOffset(debug_info, call_offset); |
| 262 } | 268 } |
| 263 | 269 |
| 264 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 270 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
| 265 int statement_position, | 271 int statement_position, |
| 266 List<BreakLocation>* result_out) { | 272 List<BreakLocation>* result_out) { |
| 267 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); | 273 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
| 268 it->Next()) { | 274 it->Next()) { |
| 269 if (it->statement_position() == statement_position) { | 275 if (it->statement_position() == statement_position) { |
| 270 result_out->Add(it->GetBreakLocation()); | 276 result_out->Add(it->GetBreakLocation()); |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 | 778 |
| 773 // At least one active break point now. | 779 // At least one active break point now. |
| 774 return debug_info->GetBreakPointCount() > 0; | 780 return debug_info->GetBreakPointCount() > 0; |
| 775 } | 781 } |
| 776 | 782 |
| 777 | 783 |
| 778 bool Debug::SetBreakPointForScript(Handle<Script> script, | 784 bool Debug::SetBreakPointForScript(Handle<Script> script, |
| 779 Handle<Object> break_point_object, | 785 Handle<Object> break_point_object, |
| 780 int* source_position, | 786 int* source_position, |
| 781 BreakPositionAlignment alignment) { | 787 BreakPositionAlignment alignment) { |
| 788 if (script->type() == Script::TYPE_WASM) { |
| 789 // TODO(clemensh): set breakpoint for wasm. |
| 790 return false; |
| 791 } |
| 782 HandleScope scope(isolate_); | 792 HandleScope scope(isolate_); |
| 783 | 793 |
| 784 // Obtain shared function info for the function. | 794 // Obtain shared function info for the function. |
| 785 Handle<Object> result = | 795 Handle<Object> result = |
| 786 FindSharedFunctionInfoInScript(script, *source_position); | 796 FindSharedFunctionInfoInScript(script, *source_position); |
| 787 if (result->IsUndefined(isolate_)) return false; | 797 if (result->IsUndefined(isolate_)) return false; |
| 788 | 798 |
| 789 // Make sure the function has set up the debug info. | 799 // Make sure the function has set up the debug info. |
| 790 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); | 800 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); |
| 791 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { | 801 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1580 } | 1590 } |
| 1581 | 1591 |
| 1582 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 1592 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
| 1583 after_break_target_ = NULL; | 1593 after_break_target_ = NULL; |
| 1584 if (!LiveEdit::SetAfterBreakTarget(this)) { | 1594 if (!LiveEdit::SetAfterBreakTarget(this)) { |
| 1585 // Continue just after the slot. | 1595 // Continue just after the slot. |
| 1586 after_break_target_ = frame->pc(); | 1596 after_break_target_ = frame->pc(); |
| 1587 } | 1597 } |
| 1588 } | 1598 } |
| 1589 | 1599 |
| 1590 | |
| 1591 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1600 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
| 1592 HandleScope scope(isolate_); | 1601 HandleScope scope(isolate_); |
| 1593 | 1602 |
| 1594 // Get the executing function in which the debug break occurred. | 1603 // Get the executing function in which the debug break occurred. |
| 1595 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1604 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
| 1596 Handle<SharedFunctionInfo> shared(function->shared()); | |
| 1597 | 1605 |
| 1598 // With no debug info there are no break points, so we can't be at a return. | 1606 // With no debug info there are no break points, so we can't be at a return. |
| 1599 if (!shared->HasDebugInfo()) return false; | 1607 if (!shared->HasDebugInfo()) return false; |
| 1600 | 1608 |
| 1601 DCHECK(!frame->is_optimized()); | 1609 DCHECK(!frame->is_optimized()); |
| 1602 FrameSummary summary = FrameSummary::GetFirst(frame); | 1610 int code_offset = FrameSummary::GetFirst(frame).code_offset(); |
| 1603 | |
| 1604 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1611 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1605 BreakLocation location = | 1612 BreakLocation location = |
| 1606 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); | 1613 BreakLocation::FromCodeOffset(debug_info, code_offset); |
| 1607 return location.IsReturn() || location.IsTailCall(); | 1614 return location.IsReturn() || location.IsTailCall(); |
| 1608 } | 1615 } |
| 1609 | 1616 |
| 1610 | 1617 |
| 1611 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1618 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
| 1612 LiveEdit::FrameDropMode mode) { | 1619 LiveEdit::FrameDropMode mode) { |
| 1613 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1620 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
| 1614 thread_local_.frame_drop_mode_ = mode; | 1621 thread_local_.frame_drop_mode_ = mode; |
| 1615 } | 1622 } |
| 1616 thread_local_.break_frame_id_ = new_break_frame_id; | 1623 thread_local_.break_frame_id_ = new_break_frame_id; |
| (...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2282 StackGuard::TERMINATE_EXECUTION) { | 2289 StackGuard::TERMINATE_EXECUTION) { |
| 2283 // Link recursive debugger entry. | 2290 // Link recursive debugger entry. |
| 2284 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2291 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2285 reinterpret_cast<base::AtomicWord>(this)); | 2292 reinterpret_cast<base::AtomicWord>(this)); |
| 2286 | 2293 |
| 2287 // Store the previous break id, frame id and return value. | 2294 // Store the previous break id, frame id and return value. |
| 2288 break_id_ = debug_->break_id(); | 2295 break_id_ = debug_->break_id(); |
| 2289 break_frame_id_ = debug_->break_frame_id(); | 2296 break_frame_id_ = debug_->break_frame_id(); |
| 2290 return_value_ = debug_->return_value(); | 2297 return_value_ = debug_->return_value(); |
| 2291 | 2298 |
| 2292 // Create the new break info. If there is no JavaScript frames there is no | 2299 // Create the new break info. If there is no proper frames there is no break |
| 2293 // break frame id. | 2300 // frame id. |
| 2294 JavaScriptFrameIterator it(isolate()); | 2301 StackTraceFrameIterator it(isolate()); |
| 2295 bool has_js_frames = !it.done(); | 2302 bool has_frames = !it.done(); |
| 2296 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() | 2303 // We don't currently support breaking inside wasm framess. |
| 2297 : StackFrame::NO_ID; | 2304 DCHECK(!has_frames || !it.is_wasm()); |
| 2305 debug_->thread_local_.break_frame_id_ = |
| 2306 has_frames ? it.frame()->id() : StackFrame::NO_ID; |
| 2298 debug_->SetNextBreakId(); | 2307 debug_->SetNextBreakId(); |
| 2299 | 2308 |
| 2300 debug_->UpdateState(); | 2309 debug_->UpdateState(); |
| 2301 // Make sure that debugger is loaded and enter the debugger context. | 2310 // Make sure that debugger is loaded and enter the debugger context. |
| 2302 // The previous context is kept in save_. | 2311 // The previous context is kept in save_. |
| 2303 failed_ = !debug_->is_loaded(); | 2312 failed_ = !debug_->is_loaded(); |
| 2304 if (!failed_) isolate()->set_context(*debug->debug_context()); | 2313 if (!failed_) isolate()->set_context(*debug->debug_context()); |
| 2305 } | 2314 } |
| 2306 | 2315 |
| 2307 | 2316 |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2582 } | 2591 } |
| 2583 | 2592 |
| 2584 | 2593 |
| 2585 void LockingCommandMessageQueue::Clear() { | 2594 void LockingCommandMessageQueue::Clear() { |
| 2586 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2595 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2587 queue_.Clear(); | 2596 queue_.Clear(); |
| 2588 } | 2597 } |
| 2589 | 2598 |
| 2590 } // namespace internal | 2599 } // namespace internal |
| 2591 } // namespace v8 | 2600 } // namespace v8 |
| OLD | NEW |