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 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 thread_local_.break_count_ = 0; | 507 thread_local_.break_count_ = 0; |
508 thread_local_.break_id_ = 0; | 508 thread_local_.break_id_ = 0; |
509 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 509 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
510 thread_local_.last_step_action_ = StepNone; | 510 thread_local_.last_step_action_ = StepNone; |
511 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 511 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
512 thread_local_.step_count_ = 0; | 512 thread_local_.step_count_ = 0; |
513 thread_local_.last_fp_ = 0; | 513 thread_local_.last_fp_ = 0; |
514 thread_local_.queued_step_count_ = 0; | 514 thread_local_.queued_step_count_ = 0; |
515 thread_local_.step_into_fp_ = 0; | 515 thread_local_.step_into_fp_ = 0; |
516 thread_local_.step_out_fp_ = 0; | 516 thread_local_.step_out_fp_ = 0; |
517 thread_local_.after_break_target_ = 0; | |
518 // TODO(isolates): frames_are_dropped_? | 517 // TODO(isolates): frames_are_dropped_? |
519 thread_local_.debugger_entry_ = NULL; | 518 thread_local_.debugger_entry_ = NULL; |
520 thread_local_.has_pending_interrupt_ = false; | 519 thread_local_.has_pending_interrupt_ = false; |
521 thread_local_.restarter_frame_function_pointer_ = NULL; | 520 thread_local_.restarter_frame_function_pointer_ = NULL; |
522 thread_local_.promise_on_stack_ = NULL; | 521 thread_local_.promise_on_stack_ = NULL; |
523 } | 522 } |
524 | 523 |
525 | 524 |
526 char* Debug::ArchiveDebug(char* storage) { | 525 char* Debug::ArchiveDebug(char* storage) { |
527 char* to = storage; | 526 char* to = storage; |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 | 798 |
800 // Clear the script cache. | 799 // Clear the script cache. |
801 DestroyScriptCache(); | 800 DestroyScriptCache(); |
802 | 801 |
803 // Clear debugger context global handle. | 802 // Clear debugger context global handle. |
804 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 803 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
805 debug_context_ = Handle<Context>(); | 804 debug_context_ = Handle<Context>(); |
806 } | 805 } |
807 | 806 |
808 | 807 |
809 Object* Debug::Break(Arguments args) { | 808 void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
810 Heap* heap = isolate_->heap(); | 809 Heap* heap = isolate_->heap(); |
811 HandleScope scope(isolate_); | 810 HandleScope scope(isolate_); |
812 ASSERT(args.length() == 0); | 811 ASSERT(args.length() == 0); |
813 | 812 |
814 thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; | 813 if (live_edit_enabled()) { |
815 | 814 thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; |
816 // Get the top-most JavaScript frame. | 815 } |
817 JavaScriptFrameIterator it(isolate_); | |
818 JavaScriptFrame* frame = it.frame(); | |
819 | 816 |
820 // Just continue if breaks are disabled or debugger cannot be loaded. | 817 // Just continue if breaks are disabled or debugger cannot be loaded. |
821 if (disable_break()) { | 818 if (disable_break()) return; |
822 SetAfterBreakTarget(frame); | |
823 return heap->undefined_value(); | |
824 } | |
825 | 819 |
826 // Enter the debugger. | 820 // Enter the debugger. |
827 EnterDebugger debugger(isolate_); | 821 EnterDebugger debugger(isolate_); |
828 if (debugger.FailedToEnter()) { | 822 if (debugger.FailedToEnter()) return; |
829 return heap->undefined_value(); | |
830 } | |
831 | 823 |
832 // Postpone interrupt during breakpoint processing. | 824 // Postpone interrupt during breakpoint processing. |
833 PostponeInterruptsScope postpone(isolate_); | 825 PostponeInterruptsScope postpone(isolate_); |
834 | 826 |
835 // Get the debug info (create it if it does not exist). | 827 // Get the debug info (create it if it does not exist). |
836 Handle<SharedFunctionInfo> shared = | 828 Handle<SharedFunctionInfo> shared = |
837 Handle<SharedFunctionInfo>(frame->function()->shared()); | 829 Handle<SharedFunctionInfo>(frame->function()->shared()); |
838 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 830 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
839 | 831 |
840 // Find the break point where execution has stopped. | 832 // Find the break point where execution has stopped. |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 step_action = StepOut; | 908 step_action = StepOut; |
917 step_count = count; | 909 step_count = count; |
918 } | 910 } |
919 | 911 |
920 // Clear all current stepping setup. | 912 // Clear all current stepping setup. |
921 ClearStepping(); | 913 ClearStepping(); |
922 | 914 |
923 // Set up for the remaining steps. | 915 // Set up for the remaining steps. |
924 PrepareStep(step_action, step_count, StackFrame::NO_ID); | 916 PrepareStep(step_action, step_count, StackFrame::NO_ID); |
925 } | 917 } |
926 | |
927 if (thread_local_.frame_drop_mode_ == LiveEdit::FRAMES_UNTOUCHED) { | |
928 SetAfterBreakTarget(frame); | |
929 } else if (thread_local_.frame_drop_mode_ == | |
930 LiveEdit::FRAME_DROPPED_IN_IC_CALL) { | |
931 // We must have been calling IC stub. Do not go there anymore. | |
932 Code* plain_return = isolate_->builtins()->builtin( | |
933 Builtins::kPlainReturn_LiveEdit); | |
934 thread_local_.after_break_target_ = plain_return->entry(); | |
935 } else if (thread_local_.frame_drop_mode_ == | |
936 LiveEdit::FRAME_DROPPED_IN_DEBUG_SLOT_CALL) { | |
937 // Debug break slot stub does not return normally, instead it manually | |
938 // cleans the stack and jumps. We should patch the jump address. | |
939 Code* plain_return = isolate_->builtins()->builtin( | |
940 Builtins::kFrameDropper_LiveEdit); | |
941 thread_local_.after_break_target_ = plain_return->entry(); | |
942 } else if (thread_local_.frame_drop_mode_ == | |
943 LiveEdit::FRAME_DROPPED_IN_DIRECT_CALL) { | |
944 // Nothing to do, after_break_target is not used here. | |
945 } else if (thread_local_.frame_drop_mode_ == | |
946 LiveEdit::FRAME_DROPPED_IN_RETURN_CALL) { | |
947 Code* plain_return = isolate_->builtins()->builtin( | |
948 Builtins::kFrameDropper_LiveEdit); | |
949 thread_local_.after_break_target_ = plain_return->entry(); | |
950 } else { | |
951 UNREACHABLE(); | |
952 } | |
953 | |
954 return heap->undefined_value(); | |
955 } | 918 } |
956 | 919 |
957 | 920 |
958 RUNTIME_FUNCTION(Debug_Break) { | 921 RUNTIME_FUNCTION(Debug_Break) { |
959 return isolate->debug()->Break(args); | 922 // Get the top-most JavaScript frame. |
| 923 JavaScriptFrameIterator it(isolate); |
| 924 isolate->debug()->Break(args, it.frame()); |
| 925 isolate->debug()->SetAfterBreakTarget(it.frame()); |
| 926 return isolate->heap()->undefined_value(); |
960 } | 927 } |
961 | 928 |
962 | 929 |
963 // Check the break point objects for whether one or more are actually | 930 // Check the break point objects for whether one or more are actually |
964 // triggered. This function returns a JSArray with the break point objects | 931 // triggered. This function returns a JSArray with the break point objects |
965 // which is triggered. | 932 // which is triggered. |
966 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { | 933 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { |
967 Factory* factory = isolate_->factory(); | 934 Factory* factory = isolate_->factory(); |
968 | 935 |
969 // Count the number of break points hit. If there are multiple break points | 936 // Count the number of break points hit. If there are multiple break points |
(...skipping 1358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2328 } | 2295 } |
2329 // Move to next in list. | 2296 // Move to next in list. |
2330 prev = current; | 2297 prev = current; |
2331 current = current->next(); | 2298 current = current->next(); |
2332 } | 2299 } |
2333 UNREACHABLE(); | 2300 UNREACHABLE(); |
2334 } | 2301 } |
2335 | 2302 |
2336 | 2303 |
2337 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 2304 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
| 2305 if (live_edit_enabled()) { |
| 2306 after_break_target_ = |
| 2307 LiveEdit::AfterBreakTarget(thread_local_.frame_drop_mode_, isolate_); |
| 2308 if (after_break_target_ != NULL) return; // LiveEdit did the job. |
| 2309 } |
| 2310 |
2338 HandleScope scope(isolate_); | 2311 HandleScope scope(isolate_); |
2339 | |
2340 PrepareForBreakPoints(); | 2312 PrepareForBreakPoints(); |
2341 | 2313 |
2342 // Get the executing function in which the debug break occurred. | 2314 // Get the executing function in which the debug break occurred. |
2343 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 2315 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
2344 Handle<SharedFunctionInfo> shared(function->shared()); | 2316 Handle<SharedFunctionInfo> shared(function->shared()); |
2345 if (!EnsureDebugInfo(shared, function)) { | 2317 if (!EnsureDebugInfo(shared, function)) { |
2346 // Return if we failed to retrieve the debug info. | 2318 // Return if we failed to retrieve the debug info. |
2347 return; | 2319 return; |
2348 } | 2320 } |
2349 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 2321 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
(...skipping 28 matching lines...) Expand all Loading... |
2378 it.next(); | 2350 it.next(); |
2379 } | 2351 } |
2380 | 2352 |
2381 // Handle the jump to continue execution after break point depending on the | 2353 // Handle the jump to continue execution after break point depending on the |
2382 // break location. | 2354 // break location. |
2383 if (at_js_return) { | 2355 if (at_js_return) { |
2384 // If the break point as return is still active jump to the corresponding | 2356 // If the break point as return is still active jump to the corresponding |
2385 // place in the original code. If not the break point was removed during | 2357 // place in the original code. If not the break point was removed during |
2386 // break point processing. | 2358 // break point processing. |
2387 if (break_at_js_return_active) { | 2359 if (break_at_js_return_active) { |
2388 addr += original_code->instruction_start() - code->instruction_start(); | 2360 addr += original_code->instruction_start() - code->instruction_start(); |
2389 } | 2361 } |
2390 | 2362 |
2391 // Move back to where the call instruction sequence started. | 2363 // Move back to where the call instruction sequence started. |
2392 thread_local_.after_break_target_ = | 2364 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset; |
2393 addr - Assembler::kPatchReturnSequenceAddressOffset; | |
2394 } else if (at_debug_break_slot) { | 2365 } else if (at_debug_break_slot) { |
2395 // Address of where the debug break slot starts. | 2366 // Address of where the debug break slot starts. |
2396 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset; | 2367 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset; |
2397 | 2368 |
2398 // Continue just after the slot. | 2369 // Continue just after the slot. |
2399 thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength; | 2370 after_break_target_ = addr + Assembler::kDebugBreakSlotLength; |
2400 } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) { | 2371 } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) { |
2401 // We now know that there is still a debug break call at the target address, | 2372 // We now know that there is still a debug break call at the target address, |
2402 // so the break point is still there and the original code will hold the | 2373 // so the break point is still there and the original code will hold the |
2403 // address to jump to in order to complete the call which is replaced by a | 2374 // address to jump to in order to complete the call which is replaced by a |
2404 // call to DebugBreakXXX. | 2375 // call to DebugBreakXXX. |
2405 | 2376 |
2406 // Find the corresponding address in the original code. | 2377 // Find the corresponding address in the original code. |
2407 addr += original_code->instruction_start() - code->instruction_start(); | 2378 addr += original_code->instruction_start() - code->instruction_start(); |
2408 | 2379 |
2409 // Install jump to the call address in the original code. This will be the | 2380 // Install jump to the call address in the original code. This will be the |
2410 // call which was overwritten by the call to DebugBreakXXX. | 2381 // call which was overwritten by the call to DebugBreakXXX. |
2411 thread_local_.after_break_target_ = | 2382 after_break_target_ = Assembler::target_address_at(addr, *original_code); |
2412 Assembler::target_address_at(addr, *original_code); | |
2413 } else { | 2383 } else { |
2414 // There is no longer a break point present. Don't try to look in the | 2384 // There is no longer a break point present. Don't try to look in the |
2415 // original code as the running code will have the right address. This takes | 2385 // original code as the running code will have the right address. This takes |
2416 // care of the case where the last break point is removed from the function | 2386 // care of the case where the last break point is removed from the function |
2417 // and therefore no "original code" is available. | 2387 // and therefore no "original code" is available. |
2418 thread_local_.after_break_target_ = | 2388 after_break_target_ = Assembler::target_address_at(addr, *code); |
2419 Assembler::target_address_at(addr, *code); | |
2420 } | 2389 } |
2421 } | 2390 } |
2422 | 2391 |
2423 | 2392 |
2424 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 2393 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
2425 HandleScope scope(isolate_); | 2394 HandleScope scope(isolate_); |
2426 | 2395 |
2427 // If there are no break points this cannot be break at return, as | 2396 // If there are no break points this cannot be break at return, as |
2428 // the debugger statement and stack guard bebug break cannot be at | 2397 // the debugger statement and stack guard bebug break cannot be at |
2429 // return. | 2398 // return. |
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3493 logger_->DebugEvent("Put", message.text()); | 3462 logger_->DebugEvent("Put", message.text()); |
3494 } | 3463 } |
3495 | 3464 |
3496 | 3465 |
3497 void LockingCommandMessageQueue::Clear() { | 3466 void LockingCommandMessageQueue::Clear() { |
3498 LockGuard<Mutex> lock_guard(&mutex_); | 3467 LockGuard<Mutex> lock_guard(&mutex_); |
3499 queue_.Clear(); | 3468 queue_.Clear(); |
3500 } | 3469 } |
3501 | 3470 |
3502 } } // namespace v8::internal | 3471 } } // namespace v8::internal |
OLD | NEW |