| 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 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 | 394 |
| 395 // Threading support. | 395 // Threading support. |
| 396 void Debug::ThreadInit() { | 396 void Debug::ThreadInit() { |
| 397 thread_local_.break_count_ = 0; | 397 thread_local_.break_count_ = 0; |
| 398 thread_local_.break_id_ = 0; | 398 thread_local_.break_id_ = 0; |
| 399 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 399 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 400 thread_local_.last_step_action_ = StepNone; | 400 thread_local_.last_step_action_ = StepNone; |
| 401 thread_local_.last_statement_position_ = kNoSourcePosition; | 401 thread_local_.last_statement_position_ = kNoSourcePosition; |
| 402 thread_local_.last_fp_ = 0; | 402 thread_local_.last_fp_ = 0; |
| 403 thread_local_.target_fp_ = 0; | 403 thread_local_.target_fp_ = 0; |
| 404 thread_local_.return_value_ = Handle<Object>(); | 404 thread_local_.return_value_ = Smi::kZero; |
| 405 thread_local_.async_task_count_ = 0; | 405 thread_local_.async_task_count_ = 0; |
| 406 clear_suspended_generator(); | 406 clear_suspended_generator(); |
| 407 // TODO(isolates): frames_are_dropped_? | 407 thread_local_.restart_fp_ = nullptr; |
| 408 base::NoBarrier_Store(&thread_local_.current_debug_scope_, | 408 base::NoBarrier_Store(&thread_local_.current_debug_scope_, |
| 409 static_cast<base::AtomicWord>(0)); | 409 static_cast<base::AtomicWord>(0)); |
| 410 UpdateHookOnFunctionCall(); | 410 UpdateHookOnFunctionCall(); |
| 411 } | 411 } |
| 412 | 412 |
| 413 | 413 |
| 414 char* Debug::ArchiveDebug(char* storage) { | 414 char* Debug::ArchiveDebug(char* storage) { |
| 415 // Simply reset state. Don't archive anything. | 415 // Simply reset state. Don't archive anything. |
| 416 ThreadInit(); | 416 ThreadInit(); |
| 417 return storage + ArchiveSpacePerThread(); | 417 return storage + ArchiveSpacePerThread(); |
| 418 } | 418 } |
| 419 | 419 |
| 420 | 420 |
| 421 char* Debug::RestoreDebug(char* storage) { | 421 char* Debug::RestoreDebug(char* storage) { |
| 422 // Simply reset state. Don't restore anything. | 422 // Simply reset state. Don't restore anything. |
| 423 ThreadInit(); | 423 ThreadInit(); |
| 424 return storage + ArchiveSpacePerThread(); | 424 return storage + ArchiveSpacePerThread(); |
| 425 } | 425 } |
| 426 | 426 |
| 427 int Debug::ArchiveSpacePerThread() { return 0; } | 427 int Debug::ArchiveSpacePerThread() { return 0; } |
| 428 | 428 |
| 429 void Debug::Iterate(ObjectVisitor* v) { | 429 void Debug::Iterate(ObjectVisitor* v) { |
| 430 v->VisitPointer(&thread_local_.return_value_); |
| 430 v->VisitPointer(&thread_local_.suspended_generator_); | 431 v->VisitPointer(&thread_local_.suspended_generator_); |
| 431 } | 432 } |
| 432 | 433 |
| 433 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 434 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
| 434 // Globalize the request debug info object and make it weak. | 435 // Globalize the request debug info object and make it weak. |
| 435 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); | 436 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); |
| 436 debug_info_ = | 437 debug_info_ = |
| 437 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); | 438 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); |
| 438 } | 439 } |
| 439 | 440 |
| (...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1578 return; | 1579 return; |
| 1579 } | 1580 } |
| 1580 // Move to next in list. | 1581 // Move to next in list. |
| 1581 prev = current; | 1582 prev = current; |
| 1582 current = current->next(); | 1583 current = current->next(); |
| 1583 } | 1584 } |
| 1584 | 1585 |
| 1585 UNREACHABLE(); | 1586 UNREACHABLE(); |
| 1586 } | 1587 } |
| 1587 | 1588 |
| 1588 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | |
| 1589 after_break_target_ = NULL; | |
| 1590 if (!LiveEdit::SetAfterBreakTarget(this)) { | |
| 1591 // Continue just after the slot. | |
| 1592 after_break_target_ = frame->pc(); | |
| 1593 } | |
| 1594 } | |
| 1595 | |
| 1596 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1589 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
| 1597 HandleScope scope(isolate_); | 1590 HandleScope scope(isolate_); |
| 1598 | 1591 |
| 1599 // Get the executing function in which the debug break occurred. | 1592 // Get the executing function in which the debug break occurred. |
| 1600 Handle<SharedFunctionInfo> shared(frame->function()->shared()); | 1593 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
| 1601 | 1594 |
| 1602 // With no debug info there are no break points, so we can't be at a return. | 1595 // With no debug info there are no break points, so we can't be at a return. |
| 1603 if (!shared->HasDebugInfo()) return false; | 1596 if (!shared->HasDebugInfo()) return false; |
| 1604 | 1597 |
| 1605 DCHECK(!frame->is_optimized()); | 1598 DCHECK(!frame->is_optimized()); |
| 1606 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1599 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
| 1607 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); | 1600 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
| 1608 return location.IsReturn() || location.IsTailCall(); | 1601 return location.IsReturn() || location.IsTailCall(); |
| 1609 } | 1602 } |
| 1610 | 1603 |
| 1611 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1604 void Debug::ScheduleFrameRestart(StackFrame* frame) { |
| 1612 LiveEditFrameDropMode mode) { | 1605 // Set a target FP for the FrameDropperTrampoline builtin to drop to once |
| 1613 if (mode != LIVE_EDIT_CURRENTLY_SET_MODE) { | 1606 // we return from the debugger. |
| 1614 thread_local_.frame_drop_mode_ = mode; | 1607 DCHECK(frame->is_java_script()); |
| 1608 // Only reschedule to a frame further below a frame we already scheduled for. |
| 1609 if (frame->fp() <= thread_local_.restart_fp_) return; |
| 1610 // If the frame is optimized, trigger a deopt and jump into the |
| 1611 // FrameDropperTrampoline in the deoptimizer. |
| 1612 thread_local_.restart_fp_ = frame->fp(); |
| 1613 |
| 1614 // Reset break frame ID to the frame below the restarted frame. |
| 1615 StackTraceFrameIterator it(isolate_); |
| 1616 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
| 1617 for (StackTraceFrameIterator it(isolate_); !it.done(); it.Advance()) { |
| 1618 if (it.frame()->fp() > thread_local_.restart_fp_) { |
| 1619 thread_local_.break_frame_id_ = it.frame()->id(); |
| 1620 return; |
| 1621 } |
| 1615 } | 1622 } |
| 1616 thread_local_.break_frame_id_ = new_break_frame_id; | |
| 1617 } | 1623 } |
| 1618 | 1624 |
| 1619 | 1625 |
| 1620 bool Debug::IsDebugGlobal(JSGlobalObject* global) { | 1626 bool Debug::IsDebugGlobal(JSGlobalObject* global) { |
| 1621 return is_loaded() && global == debug_context()->global_object(); | 1627 return is_loaded() && global == debug_context()->global_object(); |
| 1622 } | 1628 } |
| 1623 | 1629 |
| 1624 | 1630 |
| 1625 void Debug::ClearMirrorCache() { | 1631 void Debug::ClearMirrorCache() { |
| 1626 PostponeInterruptsScope postpone(isolate_); | 1632 PostponeInterruptsScope postpone(isolate_); |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2195 return Execution::Call( | 2201 return Execution::Call( |
| 2196 isolate_, | 2202 isolate_, |
| 2197 fun, | 2203 fun, |
| 2198 Handle<Object>(debug_context()->global_proxy(), isolate_), | 2204 Handle<Object>(debug_context()->global_proxy(), isolate_), |
| 2199 arraysize(argv), | 2205 arraysize(argv), |
| 2200 argv); | 2206 argv); |
| 2201 } | 2207 } |
| 2202 | 2208 |
| 2203 | 2209 |
| 2204 void Debug::HandleDebugBreak() { | 2210 void Debug::HandleDebugBreak() { |
| 2211 // Initialize LiveEdit. |
| 2212 LiveEdit::InitializeThreadLocal(this); |
| 2205 // Ignore debug break during bootstrapping. | 2213 // Ignore debug break during bootstrapping. |
| 2206 if (isolate_->bootstrapper()->IsActive()) return; | 2214 if (isolate_->bootstrapper()->IsActive()) return; |
| 2207 // Just continue if breaks are disabled. | 2215 // Just continue if breaks are disabled. |
| 2208 if (break_disabled()) return; | 2216 if (break_disabled()) return; |
| 2209 // Ignore debug break if debugger is not active. | 2217 // Ignore debug break if debugger is not active. |
| 2210 if (!is_active()) return; | 2218 if (!is_active()) return; |
| 2211 | 2219 |
| 2212 StackLimitCheck check(isolate_); | 2220 StackLimitCheck check(isolate_); |
| 2213 if (check.HasOverflowed()) return; | 2221 if (check.HasOverflowed()) return; |
| 2214 | 2222 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2296 save_(debug_->isolate_), | 2304 save_(debug_->isolate_), |
| 2297 no_termination_exceptons_(debug_->isolate_, | 2305 no_termination_exceptons_(debug_->isolate_, |
| 2298 StackGuard::TERMINATE_EXECUTION) { | 2306 StackGuard::TERMINATE_EXECUTION) { |
| 2299 // Link recursive debugger entry. | 2307 // Link recursive debugger entry. |
| 2300 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2308 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2301 reinterpret_cast<base::AtomicWord>(this)); | 2309 reinterpret_cast<base::AtomicWord>(this)); |
| 2302 | 2310 |
| 2303 // Store the previous break id, frame id and return value. | 2311 // Store the previous break id, frame id and return value. |
| 2304 break_id_ = debug_->break_id(); | 2312 break_id_ = debug_->break_id(); |
| 2305 break_frame_id_ = debug_->break_frame_id(); | 2313 break_frame_id_ = debug_->break_frame_id(); |
| 2306 return_value_ = debug_->return_value(); | 2314 return_value_ = handle(debug_->return_value(), isolate()); |
| 2307 | 2315 |
| 2308 // Create the new break info. If there is no proper frames there is no break | 2316 // Create the new break info. If there is no proper frames there is no break |
| 2309 // frame id. | 2317 // frame id. |
| 2310 StackTraceFrameIterator it(isolate()); | 2318 StackTraceFrameIterator it(isolate()); |
| 2311 bool has_frames = !it.done(); | 2319 bool has_frames = !it.done(); |
| 2312 debug_->thread_local_.break_frame_id_ = | 2320 debug_->thread_local_.break_frame_id_ = |
| 2313 has_frames ? it.frame()->id() : StackFrame::NO_ID; | 2321 has_frames ? it.frame()->id() : StackFrame::NO_ID; |
| 2314 debug_->SetNextBreakId(); | 2322 debug_->SetNextBreakId(); |
| 2315 | 2323 |
| 2316 debug_->UpdateState(); | 2324 debug_->UpdateState(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2330 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); | 2338 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); |
| 2331 } | 2339 } |
| 2332 | 2340 |
| 2333 // Leaving this debugger entry. | 2341 // Leaving this debugger entry. |
| 2334 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, | 2342 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, |
| 2335 reinterpret_cast<base::AtomicWord>(prev_)); | 2343 reinterpret_cast<base::AtomicWord>(prev_)); |
| 2336 | 2344 |
| 2337 // Restore to the previous break state. | 2345 // Restore to the previous break state. |
| 2338 debug_->thread_local_.break_frame_id_ = break_frame_id_; | 2346 debug_->thread_local_.break_frame_id_ = break_frame_id_; |
| 2339 debug_->thread_local_.break_id_ = break_id_; | 2347 debug_->thread_local_.break_id_ = break_id_; |
| 2340 debug_->thread_local_.return_value_ = return_value_; | 2348 debug_->thread_local_.return_value_ = *return_value_; |
| 2341 | 2349 |
| 2342 debug_->UpdateState(); | 2350 debug_->UpdateState(); |
| 2343 } | 2351 } |
| 2344 | 2352 |
| 2345 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) { | 2353 bool Debug::PerformSideEffectCheck(Handle<JSFunction> function) { |
| 2346 DCHECK(isolate_->needs_side_effect_check()); | 2354 DCHECK(isolate_->needs_side_effect_check()); |
| 2347 DisallowJavascriptExecution no_js(isolate_); | 2355 DisallowJavascriptExecution no_js(isolate_); |
| 2348 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false; | 2356 if (!Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) return false; |
| 2349 Deoptimizer::DeoptimizeFunction(*function); | 2357 Deoptimizer::DeoptimizeFunction(*function); |
| 2350 if (!function->shared()->HasNoSideEffect()) { | 2358 if (!function->shared()->HasNoSideEffect()) { |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2419 return v8::Utils::ToLocal(callback_data_); | 2427 return v8::Utils::ToLocal(callback_data_); |
| 2420 } | 2428 } |
| 2421 | 2429 |
| 2422 | 2430 |
| 2423 v8::Isolate* EventDetailsImpl::GetIsolate() const { | 2431 v8::Isolate* EventDetailsImpl::GetIsolate() const { |
| 2424 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); | 2432 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); |
| 2425 } | 2433 } |
| 2426 | 2434 |
| 2427 } // namespace internal | 2435 } // namespace internal |
| 2428 } // namespace v8 | 2436 } // namespace v8 |
| OLD | NEW |