| 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 "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #include "api.h" | 7 #include "api.h" |
| 8 #include "arguments.h" | 8 #include "arguments.h" |
| 9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
| 10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 519 thread_local_.last_step_action_ = StepNone; | 519 thread_local_.last_step_action_ = StepNone; |
| 520 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 520 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
| 521 thread_local_.step_count_ = 0; | 521 thread_local_.step_count_ = 0; |
| 522 thread_local_.last_fp_ = 0; | 522 thread_local_.last_fp_ = 0; |
| 523 thread_local_.queued_step_count_ = 0; | 523 thread_local_.queued_step_count_ = 0; |
| 524 thread_local_.step_into_fp_ = 0; | 524 thread_local_.step_into_fp_ = 0; |
| 525 thread_local_.step_out_fp_ = 0; | 525 thread_local_.step_out_fp_ = 0; |
| 526 thread_local_.after_break_target_ = 0; | 526 thread_local_.after_break_target_ = 0; |
| 527 // TODO(isolates): frames_are_dropped_? | 527 // TODO(isolates): frames_are_dropped_? |
| 528 thread_local_.debugger_entry_ = NULL; | 528 thread_local_.debugger_entry_ = NULL; |
| 529 thread_local_.pending_interrupts_ = 0; | 529 thread_local_.has_pending_interrupt_ = false; |
| 530 thread_local_.restarter_frame_function_pointer_ = NULL; | 530 thread_local_.restarter_frame_function_pointer_ = NULL; |
| 531 } | 531 } |
| 532 | 532 |
| 533 | 533 |
| 534 char* Debug::ArchiveDebug(char* storage) { | 534 char* Debug::ArchiveDebug(char* storage) { |
| 535 char* to = storage; | 535 char* to = storage; |
| 536 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 536 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
| 537 to += sizeof(ThreadLocal); | 537 to += sizeof(ThreadLocal); |
| 538 OS::MemCopy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_)); | 538 OS::MemCopy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_)); |
| 539 ThreadInit(); | 539 ThreadInit(); |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 853 | 853 |
| 854 // Clear the script cache. | 854 // Clear the script cache. |
| 855 DestroyScriptCache(); | 855 DestroyScriptCache(); |
| 856 | 856 |
| 857 // Clear debugger context global handle. | 857 // Clear debugger context global handle. |
| 858 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); | 858 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); |
| 859 debug_context_ = Handle<Context>(); | 859 debug_context_ = Handle<Context>(); |
| 860 } | 860 } |
| 861 | 861 |
| 862 | 862 |
| 863 // Set the flag indicating that preemption happened during debugging. | |
| 864 void Debug::PreemptionWhileInDebugger() { | |
| 865 ASSERT(InDebugger()); | |
| 866 Debug::set_interrupts_pending(PREEMPT); | |
| 867 } | |
| 868 | |
| 869 | |
| 870 Object* Debug::Break(Arguments args) { | 863 Object* Debug::Break(Arguments args) { |
| 871 Heap* heap = isolate_->heap(); | 864 Heap* heap = isolate_->heap(); |
| 872 HandleScope scope(isolate_); | 865 HandleScope scope(isolate_); |
| 873 ASSERT(args.length() == 0); | 866 ASSERT(args.length() == 0); |
| 874 | 867 |
| 875 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED; | 868 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED; |
| 876 | 869 |
| 877 // Get the top-most JavaScript frame. | 870 // Get the top-most JavaScript frame. |
| 878 JavaScriptFrameIterator it(isolate_); | 871 JavaScriptFrameIterator it(isolate_); |
| 879 JavaScriptFrame* frame = it.frame(); | 872 JavaScriptFrame* frame = it.frame(); |
| (...skipping 2068 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2948 } | 2941 } |
| 2949 | 2942 |
| 2950 | 2943 |
| 2951 void Debugger::ProcessDebugEvent(v8::DebugEvent event, | 2944 void Debugger::ProcessDebugEvent(v8::DebugEvent event, |
| 2952 Handle<JSObject> event_data, | 2945 Handle<JSObject> event_data, |
| 2953 bool auto_continue) { | 2946 bool auto_continue) { |
| 2954 HandleScope scope(isolate_); | 2947 HandleScope scope(isolate_); |
| 2955 | 2948 |
| 2956 // Clear any pending debug break if this is a real break. | 2949 // Clear any pending debug break if this is a real break. |
| 2957 if (!auto_continue) { | 2950 if (!auto_continue) { |
| 2958 isolate_->debug()->clear_interrupt_pending(DEBUGBREAK); | 2951 isolate_->debug()->set_has_pending_interrupt(false); |
| 2959 } | 2952 } |
| 2960 | 2953 |
| 2961 // Create the execution state. | 2954 // Create the execution state. |
| 2962 Handle<Object> exec_state; | 2955 Handle<Object> exec_state; |
| 2963 // Bail out and don't call debugger if exception. | 2956 // Bail out and don't call debugger if exception. |
| 2964 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 2957 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 2965 | 2958 |
| 2966 // First notify the message handler if any. | 2959 // First notify the message handler if any. |
| 2967 if (message_handler_ != NULL) { | 2960 if (message_handler_ != NULL) { |
| 2968 NotifyMessageHandler(event, | 2961 NotifyMessageHandler(event, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3094 case v8::NewFunction: | 3087 case v8::NewFunction: |
| 3095 break; | 3088 break; |
| 3096 default: | 3089 default: |
| 3097 UNREACHABLE(); | 3090 UNREACHABLE(); |
| 3098 } | 3091 } |
| 3099 | 3092 |
| 3100 // The debug command interrupt flag might have been set when the command was | 3093 // The debug command interrupt flag might have been set when the command was |
| 3101 // added. It should be enough to clear the flag only once while we are in the | 3094 // added. It should be enough to clear the flag only once while we are in the |
| 3102 // debugger. | 3095 // debugger. |
| 3103 ASSERT(isolate_->debug()->InDebugger()); | 3096 ASSERT(isolate_->debug()->InDebugger()); |
| 3104 isolate_->stack_guard()->Continue(DEBUGCOMMAND); | 3097 isolate_->stack_guard()->ClearDebugCommand(); |
| 3105 | 3098 |
| 3106 // Notify the debugger that a debug event has occurred unless auto continue is | 3099 // Notify the debugger that a debug event has occurred unless auto continue is |
| 3107 // active in which case no event is send. | 3100 // active in which case no event is send. |
| 3108 if (sendEventMessage) { | 3101 if (sendEventMessage) { |
| 3109 MessageImpl message = MessageImpl::NewEvent( | 3102 MessageImpl message = MessageImpl::NewEvent( |
| 3110 event, | 3103 event, |
| 3111 auto_continue, | 3104 auto_continue, |
| 3112 Handle<JSObject>::cast(exec_state), | 3105 Handle<JSObject>::cast(exec_state), |
| 3113 Handle<JSObject>::cast(event_data)); | 3106 Handle<JSObject>::cast(event_data)); |
| 3114 InvokeMessageHandler(message); | 3107 InvokeMessageHandler(message); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3342 CommandMessage message = CommandMessage::New( | 3335 CommandMessage message = CommandMessage::New( |
| 3343 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | 3336 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
| 3344 command.length()), | 3337 command.length()), |
| 3345 client_data); | 3338 client_data); |
| 3346 isolate_->logger()->DebugTag("Put command on command_queue."); | 3339 isolate_->logger()->DebugTag("Put command on command_queue."); |
| 3347 command_queue_.Put(message); | 3340 command_queue_.Put(message); |
| 3348 command_received_.Signal(); | 3341 command_received_.Signal(); |
| 3349 | 3342 |
| 3350 // Set the debug command break flag to have the command processed. | 3343 // Set the debug command break flag to have the command processed. |
| 3351 if (!isolate_->debug()->InDebugger()) { | 3344 if (!isolate_->debug()->InDebugger()) { |
| 3352 isolate_->stack_guard()->DebugCommand(); | 3345 isolate_->stack_guard()->RequestDebugCommand(); |
| 3353 } | 3346 } |
| 3354 | 3347 |
| 3355 MessageDispatchHelperThread* dispatch_thread; | 3348 MessageDispatchHelperThread* dispatch_thread; |
| 3356 { | 3349 { |
| 3357 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); | 3350 LockGuard<Mutex> lock_guard(&dispatch_handler_access_); |
| 3358 dispatch_thread = message_dispatch_helper_thread_; | 3351 dispatch_thread = message_dispatch_helper_thread_; |
| 3359 } | 3352 } |
| 3360 | 3353 |
| 3361 if (dispatch_thread == NULL) { | 3354 if (dispatch_thread == NULL) { |
| 3362 CallMessageDispatchHandler(); | 3355 CallMessageDispatchHandler(); |
| 3363 } else { | 3356 } else { |
| 3364 dispatch_thread->Schedule(); | 3357 dispatch_thread->Schedule(); |
| 3365 } | 3358 } |
| 3366 } | 3359 } |
| 3367 | 3360 |
| 3368 | 3361 |
| 3369 bool Debugger::HasCommands() { | 3362 bool Debugger::HasCommands() { |
| 3370 return !command_queue_.IsEmpty(); | 3363 return !command_queue_.IsEmpty(); |
| 3371 } | 3364 } |
| 3372 | 3365 |
| 3373 | 3366 |
| 3374 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { | 3367 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { |
| 3375 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); | 3368 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); |
| 3376 event_command_queue_.Put(message); | 3369 event_command_queue_.Put(message); |
| 3377 | 3370 |
| 3378 // Set the debug command break flag to have the command processed. | 3371 // Set the debug command break flag to have the command processed. |
| 3379 if (!isolate_->debug()->InDebugger()) { | 3372 if (!isolate_->debug()->InDebugger()) { |
| 3380 isolate_->stack_guard()->DebugCommand(); | 3373 isolate_->stack_guard()->RequestDebugCommand(); |
| 3381 } | 3374 } |
| 3382 } | 3375 } |
| 3383 | 3376 |
| 3384 | 3377 |
| 3385 bool Debugger::IsDebuggerActive() { | 3378 bool Debugger::IsDebuggerActive() { |
| 3386 LockGuard<RecursiveMutex> with(debugger_access_); | 3379 LockGuard<RecursiveMutex> with(debugger_access_); |
| 3387 | 3380 |
| 3388 return message_handler_ != NULL || | 3381 return message_handler_ != NULL || |
| 3389 !event_listener_.is_null() || | 3382 !event_listener_.is_null() || |
| 3390 force_debugger_active_; | 3383 force_debugger_active_; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3473 } | 3466 } |
| 3474 | 3467 |
| 3475 | 3468 |
| 3476 EnterDebugger::EnterDebugger(Isolate* isolate) | 3469 EnterDebugger::EnterDebugger(Isolate* isolate) |
| 3477 : isolate_(isolate), | 3470 : isolate_(isolate), |
| 3478 prev_(isolate_->debug()->debugger_entry()), | 3471 prev_(isolate_->debug()->debugger_entry()), |
| 3479 it_(isolate_), | 3472 it_(isolate_), |
| 3480 has_js_frames_(!it_.done()), | 3473 has_js_frames_(!it_.done()), |
| 3481 save_(isolate_) { | 3474 save_(isolate_) { |
| 3482 Debug* debug = isolate_->debug(); | 3475 Debug* debug = isolate_->debug(); |
| 3483 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT)); | |
| 3484 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK)); | |
| 3485 | |
| 3486 // Link recursive debugger entry. | 3476 // Link recursive debugger entry. |
| 3487 debug->set_debugger_entry(this); | 3477 debug->set_debugger_entry(this); |
| 3488 | 3478 |
| 3489 // Store the previous break id and frame id. | 3479 // Store the previous break id and frame id. |
| 3490 break_id_ = debug->break_id(); | 3480 break_id_ = debug->break_id(); |
| 3491 break_frame_id_ = debug->break_frame_id(); | 3481 break_frame_id_ = debug->break_frame_id(); |
| 3492 | 3482 |
| 3493 // Create the new break info. If there is no JavaScript frames there is no | 3483 // Create the new break info. If there is no JavaScript frames there is no |
| 3494 // break frame id. | 3484 // break frame id. |
| 3495 if (has_js_frames_) { | 3485 if (has_js_frames_) { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3516 | 3506 |
| 3517 // Check for leaving the debugger. | 3507 // Check for leaving the debugger. |
| 3518 if (!load_failed_ && prev_ == NULL) { | 3508 if (!load_failed_ && prev_ == NULL) { |
| 3519 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3509 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 3520 // pending exception as clearing the mirror cache calls back into | 3510 // pending exception as clearing the mirror cache calls back into |
| 3521 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3511 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 3522 // case the exception should end up in the calling code. | 3512 // case the exception should end up in the calling code. |
| 3523 if (!isolate_->has_pending_exception()) { | 3513 if (!isolate_->has_pending_exception()) { |
| 3524 // Try to avoid any pending debug break breaking in the clear mirror | 3514 // Try to avoid any pending debug break breaking in the clear mirror |
| 3525 // cache JavaScript code. | 3515 // cache JavaScript code. |
| 3526 if (isolate_->stack_guard()->IsDebugBreak()) { | 3516 if (isolate_->stack_guard()->CheckDebugBreak()) { |
| 3527 debug->set_interrupts_pending(DEBUGBREAK); | 3517 debug->set_has_pending_interrupt(true); |
| 3528 isolate_->stack_guard()->Continue(DEBUGBREAK); | 3518 isolate_->stack_guard()->ClearDebugBreak(); |
| 3529 } | 3519 } |
| 3530 debug->ClearMirrorCache(); | 3520 debug->ClearMirrorCache(); |
| 3531 } | 3521 } |
| 3532 | 3522 |
| 3533 // Request preemption and debug break when leaving the last debugger entry | 3523 // Request debug break when leaving the last debugger entry |
| 3534 // if any of these where recorded while debugging. | 3524 // if one was recorded while debugging. |
| 3535 if (debug->is_interrupt_pending(PREEMPT)) { | 3525 if (debug->has_pending_interrupt()) { |
| 3536 // This re-scheduling of preemption is to avoid starvation in some | 3526 debug->set_has_pending_interrupt(false); |
| 3537 // debugging scenarios. | 3527 isolate_->stack_guard()->RequestDebugBreak(); |
| 3538 debug->clear_interrupt_pending(PREEMPT); | |
| 3539 isolate_->stack_guard()->Preempt(); | |
| 3540 } | |
| 3541 if (debug->is_interrupt_pending(DEBUGBREAK)) { | |
| 3542 debug->clear_interrupt_pending(DEBUGBREAK); | |
| 3543 isolate_->stack_guard()->DebugBreak(); | |
| 3544 } | 3528 } |
| 3545 | 3529 |
| 3546 // If there are commands in the queue when leaving the debugger request | 3530 // If there are commands in the queue when leaving the debugger request |
| 3547 // that these commands are processed. | 3531 // that these commands are processed. |
| 3548 if (isolate_->debugger()->HasCommands()) { | 3532 if (isolate_->debugger()->HasCommands()) { |
| 3549 isolate_->stack_guard()->DebugCommand(); | 3533 isolate_->stack_guard()->RequestDebugCommand(); |
| 3550 } | 3534 } |
| 3551 | 3535 |
| 3552 // If leaving the debugger with the debugger no longer active unload it. | 3536 // If leaving the debugger with the debugger no longer active unload it. |
| 3553 if (!isolate_->debugger()->IsDebuggerActive()) { | 3537 if (!isolate_->debugger()->IsDebuggerActive()) { |
| 3554 isolate_->debugger()->UnloadDebugger(); | 3538 isolate_->debugger()->UnloadDebugger(); |
| 3555 } | 3539 } |
| 3556 } | 3540 } |
| 3557 | 3541 |
| 3558 // Leaving this debugger entry. | 3542 // Leaving this debugger entry. |
| 3559 debug->set_debugger_entry(prev_); | 3543 debug->set_debugger_entry(prev_); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3847 already_signalled_ = false; | 3831 already_signalled_ = false; |
| 3848 } | 3832 } |
| 3849 { | 3833 { |
| 3850 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); | 3834 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); |
| 3851 isolate_->debugger()->CallMessageDispatchHandler(); | 3835 isolate_->debugger()->CallMessageDispatchHandler(); |
| 3852 } | 3836 } |
| 3853 } | 3837 } |
| 3854 } | 3838 } |
| 3855 | 3839 |
| 3856 } } // namespace v8::internal | 3840 } } // namespace v8::internal |
| OLD | NEW |