Chromium Code Reviews| 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 |