| 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 |