Chromium Code Reviews

Side by Side Diff: src/debug/debug.cc

Issue 2636913002: [liveedit] reimplement frame restarting. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
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...)
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...)
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...)
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...)
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...)
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...)
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
OLDNEW

Powered by Google App Engine