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 |