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 |