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 int GetCodeOffset(StandardFrame* frame) { | |
36 if (frame->is_java_script()) { | |
37 return FrameSummary::GetFirst(JavaScriptFrame::cast(frame)).code_offset(); | |
Yang
2016/06/16 14:10:41
Is it not feasible to extend FrameSummary for wasm
Clemens Hammacher
2016/06/16 17:02:31
FrameSummary is very JS-specific, and it's only pu
| |
38 } | |
39 DCHECK(frame->is_wasm()); | |
40 return static_cast<int>(frame->pc() - | |
41 frame->unchecked_code()->instruction_start()); | |
42 } | |
43 | |
44 inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | |
45 // Code offset points to the instruction after the call. Subtract 1 to | |
46 // exclude that instruction from the search. For bytecode, the code offset | |
47 // still points to the call. | |
48 return is_interpreted ? code_offset : code_offset - 1; | |
49 } | |
50 | |
51 } // namespace | |
52 | |
31 Debug::Debug(Isolate* isolate) | 53 Debug::Debug(Isolate* isolate) |
32 : debug_context_(Handle<Context>()), | 54 : debug_context_(Handle<Context>()), |
33 event_listener_(Handle<Object>()), | 55 event_listener_(Handle<Object>()), |
34 event_listener_data_(Handle<Object>()), | 56 event_listener_data_(Handle<Object>()), |
35 message_handler_(NULL), | 57 message_handler_(NULL), |
36 command_received_(0), | 58 command_received_(0), |
37 command_queue_(isolate->logger(), kQueueInitialSize), | 59 command_queue_(isolate->logger(), kQueueInitialSize), |
38 is_active_(false), | 60 is_active_(false), |
39 is_suppressed_(false), | 61 is_suppressed_(false), |
40 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 62 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 | 275 |
254 // Find the break point at the supplied address, or the closest one before | 276 // Find the break point at the supplied address, or the closest one before |
255 // the address. | 277 // the address. |
256 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 278 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, |
257 int offset) { | 279 int offset) { |
258 base::SmartPointer<Iterator> it(GetIterator(debug_info)); | 280 base::SmartPointer<Iterator> it(GetIterator(debug_info)); |
259 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 281 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); |
260 return it->GetBreakLocation(); | 282 return it->GetBreakLocation(); |
261 } | 283 } |
262 | 284 |
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, | 285 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
271 JavaScriptFrame* frame) { | 286 StandardFrame* frame) { |
272 FrameSummary summary = FrameSummary::GetFirst(frame); | 287 int code_offset = GetCodeOffset(frame); |
273 int call_offset = | 288 int call_offset = |
274 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | 289 CallOffsetFromCodeOffset(code_offset, frame->is_interpreted()); |
275 return FromCodeOffset(debug_info, call_offset); | 290 return FromCodeOffset(debug_info, call_offset); |
276 } | 291 } |
277 | 292 |
278 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 293 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, |
279 int statement_position, | 294 int statement_position, |
280 List<BreakLocation>* result_out) { | 295 List<BreakLocation>* result_out) { |
281 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); | 296 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done(); |
282 it->Next()) { | 297 it->Next()) { |
283 if (it->statement_position() == statement_position) { | 298 if (it->statement_position() == statement_position) { |
284 result_out->Add(it->GetBreakLocation()); | 299 result_out->Add(it->GetBreakLocation()); |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
786 | 801 |
787 // At least one active break point now. | 802 // At least one active break point now. |
788 return debug_info->GetBreakPointCount() > 0; | 803 return debug_info->GetBreakPointCount() > 0; |
789 } | 804 } |
790 | 805 |
791 | 806 |
792 bool Debug::SetBreakPointForScript(Handle<Script> script, | 807 bool Debug::SetBreakPointForScript(Handle<Script> script, |
793 Handle<Object> break_point_object, | 808 Handle<Object> break_point_object, |
794 int* source_position, | 809 int* source_position, |
795 BreakPositionAlignment alignment) { | 810 BreakPositionAlignment alignment) { |
811 if (script->type() == Script::TYPE_WASM) { | |
812 // TODO(clemensh): set breakpoint for wasm. | |
813 } | |
796 HandleScope scope(isolate_); | 814 HandleScope scope(isolate_); |
797 | 815 |
798 // Obtain shared function info for the function. | 816 // Obtain shared function info for the function. |
799 Handle<Object> result = | 817 Handle<Object> result = |
800 FindSharedFunctionInfoInScript(script, *source_position); | 818 FindSharedFunctionInfoInScript(script, *source_position); |
801 if (result->IsUndefined(isolate_)) return false; | 819 if (result->IsUndefined(isolate_)) return false; |
802 | 820 |
803 // Make sure the function has set up the debug info. | 821 // Make sure the function has set up the debug info. |
804 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); | 822 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); |
805 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { | 823 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { |
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1594 } | 1612 } |
1595 | 1613 |
1596 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 1614 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
1597 after_break_target_ = NULL; | 1615 after_break_target_ = NULL; |
1598 if (!LiveEdit::SetAfterBreakTarget(this)) { | 1616 if (!LiveEdit::SetAfterBreakTarget(this)) { |
1599 // Continue just after the slot. | 1617 // Continue just after the slot. |
1600 after_break_target_ = frame->pc(); | 1618 after_break_target_ = frame->pc(); |
1601 } | 1619 } |
1602 } | 1620 } |
1603 | 1621 |
1604 | 1622 bool Debug::IsBreakAtReturn(StandardFrame* frame) { |
1605 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | |
1606 HandleScope scope(isolate_); | 1623 HandleScope scope(isolate_); |
1607 | 1624 |
1625 if (frame->is_wasm()) { | |
1626 // TODO(clemensh): find out what we want to do for wasm | |
1627 return false; | |
1628 } | |
1629 | |
1630 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); | |
1608 // Get the executing function in which the debug break occurred. | 1631 // Get the executing function in which the debug break occurred. |
1609 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 1632 Handle<SharedFunctionInfo> shared(js_frame->function()->shared()); |
1610 Handle<SharedFunctionInfo> shared(function->shared()); | |
1611 | 1633 |
1612 // With no debug info there are no break points, so we can't be at a return. | 1634 // With no debug info there are no break points, so we can't be at a return. |
1613 if (!shared->HasDebugInfo()) return false; | 1635 if (!shared->HasDebugInfo()) return false; |
1614 | 1636 |
1615 DCHECK(!frame->is_optimized()); | 1637 DCHECK(!frame->is_optimized()); |
1616 FrameSummary summary = FrameSummary::GetFirst(frame); | 1638 int code_offset = GetCodeOffset(frame); |
Yang
2016/06/16 14:10:41
At this point the frame is already known to be a j
Clemens Hammacher
2016/06/16 17:02:31
Right, but calling the function we already have se
| |
1617 | |
1618 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1639 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1619 BreakLocation location = | 1640 BreakLocation location = |
1620 BreakLocation::FromCodeOffset(debug_info, summary.code_offset()); | 1641 BreakLocation::FromCodeOffset(debug_info, code_offset); |
1621 return location.IsReturn() || location.IsTailCall(); | 1642 return location.IsReturn() || location.IsTailCall(); |
1622 } | 1643 } |
1623 | 1644 |
1624 | 1645 |
1625 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1646 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
1626 LiveEdit::FrameDropMode mode) { | 1647 LiveEdit::FrameDropMode mode) { |
1627 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1648 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
1628 thread_local_.frame_drop_mode_ = mode; | 1649 thread_local_.frame_drop_mode_ = mode; |
1629 } | 1650 } |
1630 thread_local_.break_frame_id_ = new_break_frame_id; | 1651 thread_local_.break_frame_id_ = new_break_frame_id; |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2298 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2319 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
2299 reinterpret_cast<base::AtomicWord>(this)); | 2320 reinterpret_cast<base::AtomicWord>(this)); |
2300 | 2321 |
2301 // Store the previous break id, frame id and return value. | 2322 // Store the previous break id, frame id and return value. |
2302 break_id_ = debug_->break_id(); | 2323 break_id_ = debug_->break_id(); |
2303 break_frame_id_ = debug_->break_frame_id(); | 2324 break_frame_id_ = debug_->break_frame_id(); |
2304 return_value_ = debug_->return_value(); | 2325 return_value_ = debug_->return_value(); |
2305 | 2326 |
2306 // Create the new break info. If there is no JavaScript frames there is no | 2327 // Create the new break info. If there is no JavaScript frames there is no |
2307 // break frame id. | 2328 // break frame id. |
2308 JavaScriptFrameIterator it(isolate()); | 2329 StackTraceFrameIterator it(isolate()); |
2309 bool has_js_frames = !it.done(); | 2330 bool has_frames = !it.done(); |
2310 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() | 2331 debug_->thread_local_.break_frame_id_ = |
2311 : StackFrame::NO_ID; | 2332 has_frames ? it.frame()->id() : StackFrame::NO_ID; |
2312 debug_->SetNextBreakId(); | 2333 debug_->SetNextBreakId(); |
2313 | 2334 |
2314 debug_->UpdateState(); | 2335 debug_->UpdateState(); |
2315 // Make sure that debugger is loaded and enter the debugger context. | 2336 // Make sure that debugger is loaded and enter the debugger context. |
2316 // The previous context is kept in save_. | 2337 // The previous context is kept in save_. |
2317 failed_ = !debug_->is_loaded(); | 2338 failed_ = !debug_->is_loaded(); |
2318 if (!failed_) isolate()->set_context(*debug->debug_context()); | 2339 if (!failed_) isolate()->set_context(*debug->debug_context()); |
2319 } | 2340 } |
2320 | 2341 |
2321 | 2342 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2596 } | 2617 } |
2597 | 2618 |
2598 | 2619 |
2599 void LockingCommandMessageQueue::Clear() { | 2620 void LockingCommandMessageQueue::Clear() { |
2600 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2621 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2601 queue_.Clear(); | 2622 queue_.Clear(); |
2602 } | 2623 } |
2603 | 2624 |
2604 } // namespace internal | 2625 } // namespace internal |
2605 } // namespace v8 | 2626 } // namespace v8 |
OLD | NEW |