| 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 <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 | 399 |
| 400 // Threading support. | 400 // Threading support. |
| 401 void Debug::ThreadInit() { | 401 void Debug::ThreadInit() { |
| 402 thread_local_.break_count_ = 0; | 402 thread_local_.break_count_ = 0; |
| 403 thread_local_.break_id_ = 0; | 403 thread_local_.break_id_ = 0; |
| 404 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 404 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 405 thread_local_.last_step_action_ = StepNone; | 405 thread_local_.last_step_action_ = StepNone; |
| 406 thread_local_.last_statement_position_ = kNoSourcePosition; | 406 thread_local_.last_statement_position_ = kNoSourcePosition; |
| 407 thread_local_.last_fp_ = 0; | 407 thread_local_.last_fp_ = 0; |
| 408 thread_local_.target_fp_ = 0; | 408 thread_local_.target_fp_ = 0; |
| 409 thread_local_.return_value_ = Handle<Object>(); | 409 thread_local_.return_value_ = Smi::kZero; |
| 410 thread_local_.async_task_count_ = 0; | 410 thread_local_.async_task_count_ = 0; |
| 411 clear_suspended_generator(); | 411 clear_suspended_generator(); |
| 412 // TODO(isolates): frames_are_dropped_? | 412 thread_local_.new_fp_ = nullptr; |
| 413 base::NoBarrier_Store(&thread_local_.current_debug_scope_, | 413 base::NoBarrier_Store(&thread_local_.current_debug_scope_, |
| 414 static_cast<base::AtomicWord>(0)); | 414 static_cast<base::AtomicWord>(0)); |
| 415 UpdateHookOnFunctionCall(); | 415 UpdateHookOnFunctionCall(); |
| 416 } | 416 } |
| 417 | 417 |
| 418 | 418 |
| 419 char* Debug::ArchiveDebug(char* storage) { | 419 char* Debug::ArchiveDebug(char* storage) { |
| 420 // Simply reset state. Don't archive anything. | 420 // Simply reset state. Don't archive anything. |
| 421 ThreadInit(); | 421 ThreadInit(); |
| 422 return storage + ArchiveSpacePerThread(); | 422 return storage + ArchiveSpacePerThread(); |
| 423 } | 423 } |
| 424 | 424 |
| 425 | 425 |
| 426 char* Debug::RestoreDebug(char* storage) { | 426 char* Debug::RestoreDebug(char* storage) { |
| 427 // Simply reset state. Don't restore anything. | 427 // Simply reset state. Don't restore anything. |
| 428 ThreadInit(); | 428 ThreadInit(); |
| 429 return storage + ArchiveSpacePerThread(); | 429 return storage + ArchiveSpacePerThread(); |
| 430 } | 430 } |
| 431 | 431 |
| 432 int Debug::ArchiveSpacePerThread() { return 0; } | 432 int Debug::ArchiveSpacePerThread() { return 0; } |
| 433 | 433 |
| 434 void Debug::Iterate(ObjectVisitor* v) { | 434 void Debug::Iterate(ObjectVisitor* v) { |
| 435 v->VisitPointer(&thread_local_.return_value_); |
| 435 v->VisitPointer(&thread_local_.suspended_generator_); | 436 v->VisitPointer(&thread_local_.suspended_generator_); |
| 436 } | 437 } |
| 437 | 438 |
| 438 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 439 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
| 439 // Globalize the request debug info object and make it weak. | 440 // Globalize the request debug info object and make it weak. |
| 440 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); | 441 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); |
| 441 debug_info_ = | 442 debug_info_ = |
| 442 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); | 443 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); |
| 443 } | 444 } |
| 444 | 445 |
| (...skipping 1131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 return; | 1577 return; |
| 1577 } | 1578 } |
| 1578 // Move to next in list. | 1579 // Move to next in list. |
| 1579 prev = current; | 1580 prev = current; |
| 1580 current = current->next(); | 1581 current = current->next(); |
| 1581 } | 1582 } |
| 1582 | 1583 |
| 1583 UNREACHABLE(); | 1584 UNREACHABLE(); |
| 1584 } | 1585 } |
| 1585 | 1586 |
| 1586 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | |
| 1587 after_break_target_ = NULL; | |
| 1588 if (!LiveEdit::SetAfterBreakTarget(this)) { | |
| 1589 // Continue just after the slot. | |
| 1590 after_break_target_ = frame->pc(); | |
| 1591 } | |
| 1592 } | |
| 1593 | |
| 1594 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1587 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
| 1595 HandleScope scope(isolate_); | 1588 HandleScope scope(isolate_); |
| 1596 | 1589 |
| 1597 // With no debug info there are no break points, so we can't be at a return. | 1590 // With no debug info there are no break points, so we can't be at a return. |
| 1598 if (!frame->function()->shared()->HasDebugInfo()) return false; | 1591 if (!frame->function()->shared()->HasDebugInfo()) return false; |
| 1599 | 1592 |
| 1600 DCHECK(!frame->is_optimized()); | 1593 DCHECK(!frame->is_optimized()); |
| 1601 BreakLocation location = BreakLocation::FromFrame(frame); | 1594 BreakLocation location = BreakLocation::FromFrame(frame); |
| 1602 return location.IsReturn() || location.IsTailCall(); | 1595 return location.IsReturn() || location.IsTailCall(); |
| 1603 } | 1596 } |
| 1604 | 1597 |
| 1605 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1598 void Debug::UpdateBreakFrameId() { |
| 1606 LiveEditFrameDropMode mode) { | 1599 if (thread_local_.new_fp_ == nullptr) return; |
| 1607 if (mode != LIVE_EDIT_CURRENTLY_SET_MODE) { | 1600 StackTraceFrameIterator it(isolate_); |
| 1608 thread_local_.frame_drop_mode_ = mode; | 1601 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 1602 for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) { |
| 1603 if (it.frame()->fp() > thread_local_.new_fp_) { |
| 1604 thread_local_.break_frame_id_ = it.frame()->id(); |
| 1605 return; |
| 1606 } |
| 1609 } | 1607 } |
| 1610 thread_local_.break_frame_id_ = new_break_frame_id; | |
| 1611 } | 1608 } |
| 1612 | 1609 |
| 1613 | 1610 |
| 1614 bool Debug::IsDebugGlobal(JSGlobalObject* global) { | 1611 bool Debug::IsDebugGlobal(JSGlobalObject* global) { |
| 1615 return is_loaded() && global == debug_context()->global_object(); | 1612 return is_loaded() && global == debug_context()->global_object(); |
| 1616 } | 1613 } |
| 1617 | 1614 |
| 1618 | 1615 |
| 1619 void Debug::ClearMirrorCache() { | 1616 void Debug::ClearMirrorCache() { |
| 1620 PostponeInterruptsScope postpone(isolate_); | 1617 PostponeInterruptsScope postpone(isolate_); |
| (...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2226 return Execution::Call( | 2223 return Execution::Call( |
| 2227 isolate_, | 2224 isolate_, |
| 2228 fun, | 2225 fun, |
| 2229 Handle<Object>(debug_context()->global_proxy(), isolate_), | 2226 Handle<Object>(debug_context()->global_proxy(), isolate_), |
| 2230 arraysize(argv), | 2227 arraysize(argv), |
| 2231 argv); | 2228 argv); |
| 2232 } | 2229 } |
| 2233 | 2230 |
| 2234 | 2231 |
| 2235 void Debug::HandleDebugBreak() { | 2232 void Debug::HandleDebugBreak() { |
| 2233 // Initialize LiveEdit. |
| 2234 LiveEdit::InitializeThreadLocal(this); |
| 2236 // Ignore debug break during bootstrapping. | 2235 // Ignore debug break during bootstrapping. |
| 2237 if (isolate_->bootstrapper()->IsActive()) return; | 2236 if (isolate_->bootstrapper()->IsActive()) return; |
| 2238 // Just continue if breaks are disabled. | 2237 // Just continue if breaks are disabled. |
| 2239 if (break_disabled()) return; | 2238 if (break_disabled()) return; |
| 2240 // Ignore debug break if debugger is not active. | 2239 // Ignore debug break if debugger is not active. |
| 2241 if (!is_active()) return; | 2240 if (!is_active()) return; |
| 2242 | 2241 |
| 2243 StackLimitCheck check(isolate_); | 2242 StackLimitCheck check(isolate_); |
| 2244 if (check.HasOverflowed()) return; | 2243 if (check.HasOverflowed()) return; |
| 2245 | 2244 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2331 save_(debug_->isolate_), | 2330 save_(debug_->isolate_), |
| 2332 no_termination_exceptons_(debug_->isolate_, | 2331 no_termination_exceptons_(debug_->isolate_, |
| 2333 StackGuard::TERMINATE_EXECUTION) { | 2332 StackGuard::TERMINATE_EXECUTION) { |
| 2334 // Link recursive debugger entry. | 2333 // Link recursive debugger entry. |
| 2335 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2334 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2336 reinterpret_cast<base::AtomicWord>(this)); | 2335 reinterpret_cast<base::AtomicWord>(this)); |
| 2337 | 2336 |
| 2338 // Store the previous break id, frame id and return value. | 2337 // Store the previous break id, frame id and return value. |
| 2339 break_id_ = debug_->break_id(); | 2338 break_id_ = debug_->break_id(); |
| 2340 break_frame_id_ = debug_->break_frame_id(); | 2339 break_frame_id_ = debug_->break_frame_id(); |
| 2341 return_value_ = debug_->return_value(); | 2340 return_value_ = handle(debug_->return_value(), isolate()); |
| 2342 | 2341 |
| 2343 // Create the new break info. If there is no proper frames there is no break | 2342 // Create the new break info. If there is no proper frames there is no break |
| 2344 // frame id. | 2343 // frame id. |
| 2345 StackTraceFrameIterator it(isolate()); | 2344 StackTraceFrameIterator it(isolate()); |
| 2346 bool has_frames = !it.done(); | 2345 bool has_frames = !it.done(); |
| 2347 // We don't currently support breaking inside wasm framess. | 2346 // We don't currently support breaking inside wasm framess. |
| 2348 DCHECK(!has_frames || !it.is_wasm()); | 2347 DCHECK(!has_frames || !it.is_wasm()); |
| 2349 debug_->thread_local_.break_frame_id_ = | 2348 debug_->thread_local_.break_frame_id_ = |
| 2350 has_frames ? it.frame()->id() : StackFrame::NO_ID; | 2349 has_frames ? it.frame()->id() : StackFrame::NO_ID; |
| 2351 debug_->SetNextBreakId(); | 2350 debug_->SetNextBreakId(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2371 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand(); | 2370 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand(); |
| 2372 } | 2371 } |
| 2373 | 2372 |
| 2374 // Leaving this debugger entry. | 2373 // Leaving this debugger entry. |
| 2375 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2374 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2376 reinterpret_cast<base::AtomicWord>(prev_)); | 2375 reinterpret_cast<base::AtomicWord>(prev_)); |
| 2377 | 2376 |
| 2378 // Restore to the previous break state. | 2377 // Restore to the previous break state. |
| 2379 debug_->thread_local_.break_frame_id_ = break_frame_id_; | 2378 debug_->thread_local_.break_frame_id_ = break_frame_id_; |
| 2380 debug_->thread_local_.break_id_ = break_id_; | 2379 debug_->thread_local_.break_id_ = break_id_; |
| 2381 debug_->thread_local_.return_value_ = return_value_; | 2380 debug_->thread_local_.return_value_ = *return_value_; |
| 2382 | 2381 |
| 2383 debug_->UpdateState(); | 2382 debug_->UpdateState(); |
| 2384 } | 2383 } |
| 2385 | 2384 |
| 2386 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) { | 2385 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) { |
| 2387 DCHECK(isolate_->needs_side_effect_check()); | 2386 DCHECK(isolate_->needs_side_effect_check()); |
| 2388 DisallowJavascriptExecution no_js(isolate_); | 2387 DisallowJavascriptExecution no_js(isolate_); |
| 2389 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false; | 2388 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false; |
| 2390 Deoptimizer::DeoptimizeFunction(*function); | 2389 Deoptimizer::DeoptimizeFunction(*function); |
| 2391 if (!function->shared()->HasNoSideEffect()) { | 2390 if (!function->shared()->HasNoSideEffect()) { |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2648 logger_->DebugEvent("Put", message.text()); | 2647 logger_->DebugEvent("Put", message.text()); |
| 2649 } | 2648 } |
| 2650 | 2649 |
| 2651 void LockingCommandMessageQueue::Clear() { | 2650 void LockingCommandMessageQueue::Clear() { |
| 2652 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2651 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 2653 queue_.Clear(); | 2652 queue_.Clear(); |
| 2654 } | 2653 } |
| 2655 | 2654 |
| 2656 } // namespace internal | 2655 } // namespace internal |
| 2657 } // namespace v8 | 2656 } // namespace v8 |
| OLD | NEW |