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 |