| 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 21 matching lines...) Expand all Loading... |
| 32 | 32 |
| 33 Debug::Debug(Isolate* isolate) | 33 Debug::Debug(Isolate* isolate) |
| 34 : debug_context_(Handle<Context>()), | 34 : debug_context_(Handle<Context>()), |
| 35 event_listener_(Handle<Object>()), | 35 event_listener_(Handle<Object>()), |
| 36 event_listener_data_(Handle<Object>()), | 36 event_listener_data_(Handle<Object>()), |
| 37 message_handler_(NULL), | 37 message_handler_(NULL), |
| 38 command_received_(0), | 38 command_received_(0), |
| 39 command_queue_(isolate->logger(), kQueueInitialSize), | 39 command_queue_(isolate->logger(), kQueueInitialSize), |
| 40 event_command_queue_(isolate->logger(), kQueueInitialSize), | 40 event_command_queue_(isolate->logger(), kQueueInitialSize), |
| 41 is_active_(false), | 41 is_active_(false), |
| 42 ignore_debugger_(false), | 42 is_suppressed_(false), |
| 43 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 43 live_edit_enabled_(true), // TODO(yangguo): set to false by default. |
| 44 has_break_points_(false), | 44 has_break_points_(false), |
| 45 disable_break_(false), | 45 break_disabled_(false), |
| 46 break_on_exception_(false), | 46 break_on_exception_(false), |
| 47 break_on_uncaught_exception_(false), | 47 break_on_uncaught_exception_(false), |
| 48 script_cache_(NULL), | 48 script_cache_(NULL), |
| 49 debug_info_list_(NULL), | 49 debug_info_list_(NULL), |
| 50 isolate_(isolate) { | 50 isolate_(isolate) { |
| 51 ThreadInit(); | 51 ThreadInit(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 | 54 |
| 55 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { | 55 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 | 250 |
| 251 | 251 |
| 252 bool BreakLocationIterator::Done() const { | 252 bool BreakLocationIterator::Done() const { |
| 253 return RinfoDone(); | 253 return RinfoDone(); |
| 254 } | 254 } |
| 255 | 255 |
| 256 | 256 |
| 257 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { | 257 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { |
| 258 // If there is not already a real break point here patch code with debug | 258 // If there is not already a real break point here patch code with debug |
| 259 // break. | 259 // break. |
| 260 if (!HasBreakPoint()) { | 260 if (!HasBreakPoint()) SetDebugBreak(); |
| 261 SetDebugBreak(); | |
| 262 } | |
| 263 ASSERT(IsDebugBreak() || IsDebuggerStatement()); | 261 ASSERT(IsDebugBreak() || IsDebuggerStatement()); |
| 264 // Set the break point information. | 262 // Set the break point information. |
| 265 DebugInfo::SetBreakPoint(debug_info_, code_position(), | 263 DebugInfo::SetBreakPoint(debug_info_, code_position(), |
| 266 position(), statement_position(), | 264 position(), statement_position(), |
| 267 break_point_object); | 265 break_point_object); |
| 268 } | 266 } |
| 269 | 267 |
| 270 | 268 |
| 271 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { | 269 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { |
| 272 // Clear the break point information. | 270 // Clear the break point information. |
| 273 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); | 271 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); |
| 274 // If there are no more break points here remove the debug break. | 272 // If there are no more break points here remove the debug break. |
| 275 if (!HasBreakPoint()) { | 273 if (!HasBreakPoint()) { |
| 276 ClearDebugBreak(); | 274 ClearDebugBreak(); |
| 277 ASSERT(!IsDebugBreak()); | 275 ASSERT(!IsDebugBreak()); |
| 278 } | 276 } |
| 279 } | 277 } |
| 280 | 278 |
| 281 | 279 |
| 282 void BreakLocationIterator::SetOneShot() { | 280 void BreakLocationIterator::SetOneShot() { |
| 283 // Debugger statement always calls debugger. No need to modify it. | 281 // Debugger statement always calls debugger. No need to modify it. |
| 284 if (IsDebuggerStatement()) { | 282 if (IsDebuggerStatement()) return; |
| 285 return; | |
| 286 } | |
| 287 | 283 |
| 288 // If there is a real break point here no more to do. | 284 // If there is a real break point here no more to do. |
| 289 if (HasBreakPoint()) { | 285 if (HasBreakPoint()) { |
| 290 ASSERT(IsDebugBreak()); | 286 ASSERT(IsDebugBreak()); |
| 291 return; | 287 return; |
| 292 } | 288 } |
| 293 | 289 |
| 294 // Patch code with debug break. | 290 // Patch code with debug break. |
| 295 SetDebugBreak(); | 291 SetDebugBreak(); |
| 296 } | 292 } |
| 297 | 293 |
| 298 | 294 |
| 299 void BreakLocationIterator::ClearOneShot() { | 295 void BreakLocationIterator::ClearOneShot() { |
| 300 // Debugger statement always calls debugger. No need to modify it. | 296 // Debugger statement always calls debugger. No need to modify it. |
| 301 if (IsDebuggerStatement()) { | 297 if (IsDebuggerStatement()) return; |
| 302 return; | |
| 303 } | |
| 304 | 298 |
| 305 // If there is a real break point here no more to do. | 299 // If there is a real break point here no more to do. |
| 306 if (HasBreakPoint()) { | 300 if (HasBreakPoint()) { |
| 307 ASSERT(IsDebugBreak()); | 301 ASSERT(IsDebugBreak()); |
| 308 return; | 302 return; |
| 309 } | 303 } |
| 310 | 304 |
| 311 // Patch code removing debug break. | 305 // Patch code removing debug break. |
| 312 ClearDebugBreak(); | 306 ClearDebugBreak(); |
| 313 ASSERT(!IsDebugBreak()); | 307 ASSERT(!IsDebugBreak()); |
| 314 } | 308 } |
| 315 | 309 |
| 316 | 310 |
| 317 void BreakLocationIterator::SetDebugBreak() { | 311 void BreakLocationIterator::SetDebugBreak() { |
| 318 // Debugger statement always calls debugger. No need to modify it. | 312 // Debugger statement always calls debugger. No need to modify it. |
| 319 if (IsDebuggerStatement()) { | 313 if (IsDebuggerStatement()) return; |
| 320 return; | |
| 321 } | |
| 322 | 314 |
| 323 // If there is already a break point here just return. This might happen if | 315 // If there is already a break point here just return. This might happen if |
| 324 // the same code is flooded with break points twice. Flooding the same | 316 // the same code is flooded with break points twice. Flooding the same |
| 325 // function twice might happen when stepping in a function with an exception | 317 // function twice might happen when stepping in a function with an exception |
| 326 // handler as the handler and the function is the same. | 318 // handler as the handler and the function is the same. |
| 327 if (IsDebugBreak()) { | 319 if (IsDebugBreak()) return; |
| 328 return; | |
| 329 } | |
| 330 | 320 |
| 331 if (RelocInfo::IsJSReturn(rmode())) { | 321 if (RelocInfo::IsJSReturn(rmode())) { |
| 332 // Patch the frame exit code with a break point. | 322 // Patch the frame exit code with a break point. |
| 333 SetDebugBreakAtReturn(); | 323 SetDebugBreakAtReturn(); |
| 334 } else if (IsDebugBreakSlot()) { | 324 } else if (IsDebugBreakSlot()) { |
| 335 // Patch the code in the break slot. | 325 // Patch the code in the break slot. |
| 336 SetDebugBreakAtSlot(); | 326 SetDebugBreakAtSlot(); |
| 337 } else { | 327 } else { |
| 338 // Patch the IC call. | 328 // Patch the IC call. |
| 339 SetDebugBreakAtIC(); | 329 SetDebugBreakAtIC(); |
| 340 } | 330 } |
| 341 ASSERT(IsDebugBreak()); | 331 ASSERT(IsDebugBreak()); |
| 342 } | 332 } |
| 343 | 333 |
| 344 | 334 |
| 345 void BreakLocationIterator::ClearDebugBreak() { | 335 void BreakLocationIterator::ClearDebugBreak() { |
| 346 // Debugger statement always calls debugger. No need to modify it. | 336 // Debugger statement always calls debugger. No need to modify it. |
| 347 if (IsDebuggerStatement()) { | 337 if (IsDebuggerStatement()) return; |
| 348 return; | |
| 349 } | |
| 350 | 338 |
| 351 if (RelocInfo::IsJSReturn(rmode())) { | 339 if (RelocInfo::IsJSReturn(rmode())) { |
| 352 // Restore the frame exit code. | 340 // Restore the frame exit code. |
| 353 ClearDebugBreakAtReturn(); | 341 ClearDebugBreakAtReturn(); |
| 354 } else if (IsDebugBreakSlot()) { | 342 } else if (IsDebugBreakSlot()) { |
| 355 // Restore the code in the break slot. | 343 // Restore the code in the break slot. |
| 356 ClearDebugBreakAtSlot(); | 344 ClearDebugBreakAtSlot(); |
| 357 } else { | 345 } else { |
| 358 // Patch the IC call. | 346 // Patch the IC call. |
| 359 ClearDebugBreakAtIC(); | 347 ClearDebugBreakAtIC(); |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 | 709 |
| 722 // Mark this script as native and return successfully. | 710 // Mark this script as native and return successfully. |
| 723 Handle<Script> script(Script::cast(function->shared()->script())); | 711 Handle<Script> script(Script::cast(function->shared()->script())); |
| 724 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); | 712 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); |
| 725 return true; | 713 return true; |
| 726 } | 714 } |
| 727 | 715 |
| 728 | 716 |
| 729 bool Debug::Load() { | 717 bool Debug::Load() { |
| 730 // Return if debugger is already loaded. | 718 // Return if debugger is already loaded. |
| 731 if (IsLoaded()) return true; | 719 if (is_loaded()) return true; |
| 732 | 720 |
| 733 // Bail out if we're already in the process of compiling the native | 721 // Bail out if we're already in the process of compiling the native |
| 734 // JavaScript source code for the debugger. | 722 // JavaScript source code for the debugger. |
| 735 if (isolate_->debug()->ignore_debugger()) return false; | 723 if (is_suppressed_) return false; |
| 736 Debug::IgnoreScope during_create(isolate_->debug()); | 724 SuppressDebug while_loading(this); |
| 737 | 725 |
| 738 // Disable breakpoints and interrupts while compiling and running the | 726 // Disable breakpoints and interrupts while compiling and running the |
| 739 // debugger scripts including the context creation code. | 727 // debugger scripts including the context creation code. |
| 740 DisableBreak disable(isolate_, true); | 728 DisableBreak disable(this, true); |
| 741 PostponeInterruptsScope postpone(isolate_); | 729 PostponeInterruptsScope postpone(isolate_); |
| 742 | 730 |
| 743 // Create the debugger context. | 731 // Create the debugger context. |
| 744 HandleScope scope(isolate_); | 732 HandleScope scope(isolate_); |
| 745 ExtensionConfiguration no_extensions; | 733 ExtensionConfiguration no_extensions; |
| 746 Handle<Context> context = | 734 Handle<Context> context = |
| 747 isolate_->bootstrapper()->CreateEnvironment( | 735 isolate_->bootstrapper()->CreateEnvironment( |
| 748 Handle<Object>::null(), | 736 Handle<Object>::null(), |
| 749 v8::Handle<ObjectTemplate>(), | 737 v8::Handle<ObjectTemplate>(), |
| 750 &no_extensions); | 738 &no_extensions); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 | 775 |
| 788 | 776 |
| 789 void Debug::Unload() { | 777 void Debug::Unload() { |
| 790 ClearAllBreakPoints(); | 778 ClearAllBreakPoints(); |
| 791 ClearStepping(); | 779 ClearStepping(); |
| 792 | 780 |
| 793 // Match unmatched PromiseHandlePrologue calls. | 781 // Match unmatched PromiseHandlePrologue calls. |
| 794 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); | 782 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); |
| 795 | 783 |
| 796 // Return debugger is not loaded. | 784 // Return debugger is not loaded. |
| 797 if (!IsLoaded()) return; | 785 if (!is_loaded()) return; |
| 798 | 786 |
| 799 // Clear the script cache. | 787 // Clear the script cache. |
| 800 DestroyScriptCache(); | 788 DestroyScriptCache(); |
| 801 | 789 |
| 802 // Clear debugger context global handle. | 790 // Clear debugger context global handle. |
| 803 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 791 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
| 804 debug_context_ = Handle<Context>(); | 792 debug_context_ = Handle<Context>(); |
| 805 } | 793 } |
| 806 | 794 |
| 807 | 795 |
| 808 void Debug::Break(Arguments args, JavaScriptFrame* frame) { | 796 void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
| 809 Heap* heap = isolate_->heap(); | 797 Heap* heap = isolate_->heap(); |
| 810 HandleScope scope(isolate_); | 798 HandleScope scope(isolate_); |
| 811 ASSERT(args.length() == 0); | 799 ASSERT(args.length() == 0); |
| 812 | 800 |
| 813 if (live_edit_enabled()) { | 801 if (live_edit_enabled()) { |
| 814 thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; | 802 thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED; |
| 815 } | 803 } |
| 816 | 804 |
| 817 // Just continue if breaks are disabled or debugger cannot be loaded. | 805 // Just continue if breaks are disabled or debugger cannot be loaded. |
| 818 if (disable_break()) return; | 806 if (break_disabled_) return; |
| 819 | 807 |
| 820 // Enter the debugger. | 808 // Enter the debugger. |
| 821 EnterDebugger debugger(isolate_); | 809 EnterDebugger debugger(isolate_); |
| 822 if (debugger.FailedToEnter()) return; | 810 if (debugger.FailedToEnter()) return; |
| 823 | 811 |
| 824 // Postpone interrupt during breakpoint processing. | 812 // Postpone interrupt during breakpoint processing. |
| 825 PostponeInterruptsScope postpone(isolate_); | 813 PostponeInterruptsScope postpone(isolate_); |
| 826 | 814 |
| 827 // Get the debug info (create it if it does not exist). | 815 // Get the debug info (create it if it does not exist). |
| 828 Handle<SharedFunctionInfo> shared = | 816 Handle<SharedFunctionInfo> shared = |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 } | 1252 } |
| 1265 | 1253 |
| 1266 | 1254 |
| 1267 void Debug::PrepareStep(StepAction step_action, | 1255 void Debug::PrepareStep(StepAction step_action, |
| 1268 int step_count, | 1256 int step_count, |
| 1269 StackFrame::Id frame_id) { | 1257 StackFrame::Id frame_id) { |
| 1270 HandleScope scope(isolate_); | 1258 HandleScope scope(isolate_); |
| 1271 | 1259 |
| 1272 PrepareForBreakPoints(); | 1260 PrepareForBreakPoints(); |
| 1273 | 1261 |
| 1274 ASSERT(Debug::InDebugger()); | 1262 ASSERT(is_entered()); |
| 1275 | 1263 |
| 1276 // Remember this step action and count. | 1264 // Remember this step action and count. |
| 1277 thread_local_.last_step_action_ = step_action; | 1265 thread_local_.last_step_action_ = step_action; |
| 1278 if (step_action == StepOut) { | 1266 if (step_action == StepOut) { |
| 1279 // For step out target frame will be found on the stack so there is no need | 1267 // For step out target frame will be found on the stack so there is no need |
| 1280 // to set step counter for it. It's expected to always be 0 for StepOut. | 1268 // to set step counter for it. It's expected to always be 0 for StepOut. |
| 1281 thread_local_.step_count_ = 0; | 1269 thread_local_.step_count_ = 0; |
| 1282 } else { | 1270 } else { |
| 1283 thread_local_.step_count_ = step_count; | 1271 thread_local_.step_count_ = step_count; |
| 1284 } | 1272 } |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1640 } | 1628 } |
| 1641 | 1629 |
| 1642 locations->set(count++, position); | 1630 locations->set(count++, position); |
| 1643 } | 1631 } |
| 1644 } | 1632 } |
| 1645 } | 1633 } |
| 1646 return locations; | 1634 return locations; |
| 1647 } | 1635 } |
| 1648 | 1636 |
| 1649 | 1637 |
| 1650 void Debug::NewBreak(StackFrame::Id break_frame_id) { | |
| 1651 thread_local_.break_frame_id_ = break_frame_id; | |
| 1652 thread_local_.break_id_ = ++thread_local_.break_count_; | |
| 1653 } | |
| 1654 | |
| 1655 | |
| 1656 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) { | |
| 1657 thread_local_.break_frame_id_ = break_frame_id; | |
| 1658 thread_local_.break_id_ = break_id; | |
| 1659 } | |
| 1660 | |
| 1661 | |
| 1662 // Handle stepping into a function. | 1638 // Handle stepping into a function. |
| 1663 void Debug::HandleStepIn(Handle<JSFunction> function, | 1639 void Debug::HandleStepIn(Handle<JSFunction> function, |
| 1664 Handle<Object> holder, | 1640 Handle<Object> holder, |
| 1665 Address fp, | 1641 Address fp, |
| 1666 bool is_constructor) { | 1642 bool is_constructor) { |
| 1667 Isolate* isolate = function->GetIsolate(); | 1643 Isolate* isolate = function->GetIsolate(); |
| 1668 // If the frame pointer is not supplied by the caller find it. | 1644 // If the frame pointer is not supplied by the caller find it. |
| 1669 if (fp == 0) { | 1645 if (fp == 0) { |
| 1670 StackFrameIterator it(isolate); | 1646 StackFrameIterator it(isolate); |
| 1671 it.Advance(); | 1647 it.Advance(); |
| (...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2439 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 2415 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
| 2440 thread_local_.frame_drop_mode_ = mode; | 2416 thread_local_.frame_drop_mode_ = mode; |
| 2441 } | 2417 } |
| 2442 thread_local_.break_frame_id_ = new_break_frame_id; | 2418 thread_local_.break_frame_id_ = new_break_frame_id; |
| 2443 thread_local_.restarter_frame_function_pointer_ = | 2419 thread_local_.restarter_frame_function_pointer_ = |
| 2444 restarter_frame_function_pointer; | 2420 restarter_frame_function_pointer; |
| 2445 } | 2421 } |
| 2446 | 2422 |
| 2447 | 2423 |
| 2448 bool Debug::IsDebugGlobal(GlobalObject* global) { | 2424 bool Debug::IsDebugGlobal(GlobalObject* global) { |
| 2449 return IsLoaded() && global == debug_context()->global_object(); | 2425 return is_loaded() && global == debug_context()->global_object(); |
| 2450 } | 2426 } |
| 2451 | 2427 |
| 2452 | 2428 |
| 2453 void Debug::ClearMirrorCache() { | 2429 void Debug::ClearMirrorCache() { |
| 2454 PostponeInterruptsScope postpone(isolate_); | 2430 PostponeInterruptsScope postpone(isolate_); |
| 2455 HandleScope scope(isolate_); | 2431 HandleScope scope(isolate_); |
| 2456 ASSERT(isolate_->context() == *Debug::debug_context()); | 2432 ASSERT(isolate_->context() == *Debug::debug_context()); |
| 2457 | 2433 |
| 2458 // Clear the mirror cache. | 2434 // Clear the mirror cache. |
| 2459 Handle<String> function_name = isolate_->factory()->InternalizeOneByteString( | |
| 2460 STATIC_ASCII_VECTOR("ClearMirrorCache")); | |
| 2461 Handle<Object> fun = Object::GetProperty( | 2435 Handle<Object> fun = Object::GetProperty( |
| 2462 isolate_->global_object(), function_name).ToHandleChecked(); | 2436 isolate_, |
| 2437 isolate_->global_object(), |
| 2438 "ClearMirrorCache").ToHandleChecked(); |
| 2463 ASSERT(fun->IsJSFunction()); | 2439 ASSERT(fun->IsJSFunction()); |
| 2464 Execution::TryCall( | 2440 Execution::TryCall(Handle<JSFunction>::cast(fun), |
| 2465 Handle<JSFunction>::cast(fun), | 2441 Handle<JSObject>(Debug::debug_context()->global_object()), |
| 2466 Handle<JSObject>(Debug::debug_context()->global_object()), | 2442 0, |
| 2467 0, | 2443 NULL); |
| 2468 NULL); | |
| 2469 } | 2444 } |
| 2470 | 2445 |
| 2471 | 2446 |
| 2472 void Debug::CreateScriptCache() { | 2447 void Debug::CreateScriptCache() { |
| 2473 Heap* heap = isolate_->heap(); | 2448 Heap* heap = isolate_->heap(); |
| 2474 HandleScope scope(isolate_); | 2449 HandleScope scope(isolate_); |
| 2475 | 2450 |
| 2476 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | 2451 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
| 2477 // rid of all the cached script wrappers and the second gets rid of the | 2452 // rid of all the cached script wrappers and the second gets rid of the |
| 2478 // scripts which are no longer referenced. The second also sweeps precisely, | 2453 // scripts which are no longer referenced. The second also sweeps precisely, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2550 | 2525 |
| 2551 | 2526 |
| 2552 void Debug::AfterGarbageCollection() { | 2527 void Debug::AfterGarbageCollection() { |
| 2553 // Generate events for collected scripts. | 2528 // Generate events for collected scripts. |
| 2554 if (script_cache_ != NULL) { | 2529 if (script_cache_ != NULL) { |
| 2555 script_cache_->ProcessCollectedScripts(); | 2530 script_cache_->ProcessCollectedScripts(); |
| 2556 } | 2531 } |
| 2557 } | 2532 } |
| 2558 | 2533 |
| 2559 | 2534 |
| 2560 MaybeHandle<Object> Debug::MakeJSObject( | 2535 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, |
| 2561 Vector<const char> constructor_name, | 2536 int argc, |
| 2562 int argc, | 2537 Handle<Object> argv[]) { |
| 2563 Handle<Object> argv[]) { | 2538 ASSERT(isolate_->context() == *debug_context()); |
| 2564 ASSERT(isolate_->context() == *isolate_->debug()->debug_context()); | |
| 2565 | |
| 2566 // Create the execution state object. | 2539 // Create the execution state object. |
| 2567 Handle<String> constructor_str = | |
| 2568 isolate_->factory()->InternalizeUtf8String(constructor_name); | |
| 2569 ASSERT(!constructor_str.is_null()); | |
| 2570 Handle<Object> constructor = Object::GetProperty( | 2540 Handle<Object> constructor = Object::GetProperty( |
| 2571 isolate_->global_object(), constructor_str).ToHandleChecked(); | 2541 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked(); |
| 2572 ASSERT(constructor->IsJSFunction()); | 2542 ASSERT(constructor->IsJSFunction()); |
| 2573 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); | 2543 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); |
| 2574 return Execution::TryCall( | 2544 return Execution::TryCall(Handle<JSFunction>::cast(constructor), |
| 2575 Handle<JSFunction>::cast(constructor), | 2545 Handle<JSObject>(debug_context()->global_object()), |
| 2576 Handle<JSObject>(isolate_->debug()->debug_context()->global_object()), | 2546 argc, |
| 2577 argc, | 2547 argv); |
| 2578 argv); | |
| 2579 } | 2548 } |
| 2580 | 2549 |
| 2581 | 2550 |
| 2582 MaybeHandle<Object> Debug::MakeExecutionState() { | 2551 MaybeHandle<Object> Debug::MakeExecutionState() { |
| 2583 // Create the execution state object. | 2552 // Create the execution state object. |
| 2584 Handle<Object> break_id = isolate_->factory()->NewNumberFromInt( | 2553 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; |
| 2585 isolate_->debug()->break_id()); | 2554 return MakeJSObject("MakeExecutionState", ARRAY_SIZE(argv), argv); |
| 2586 Handle<Object> argv[] = { break_id }; | |
| 2587 return MakeJSObject(CStrVector("MakeExecutionState"), ARRAY_SIZE(argv), argv); | |
| 2588 } | 2555 } |
| 2589 | 2556 |
| 2590 | 2557 |
| 2591 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { | 2558 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { |
| 2592 Handle<Object> exec_state; | 2559 Handle<Object> exec_state; |
| 2593 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2560 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
| 2594 // Create the new break event object. | 2561 // Create the new break event object. |
| 2595 Handle<Object> argv[] = { exec_state, break_points_hit }; | 2562 Handle<Object> argv[] = { exec_state, break_points_hit }; |
| 2596 return MakeJSObject(CStrVector("MakeBreakEvent"), ARRAY_SIZE(argv), argv); | 2563 return MakeJSObject("MakeBreakEvent", ARRAY_SIZE(argv), argv); |
| 2597 } | 2564 } |
| 2598 | 2565 |
| 2599 | 2566 |
| 2600 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception, | 2567 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception, |
| 2601 bool uncaught, | 2568 bool uncaught, |
| 2602 Handle<Object> promise) { | 2569 Handle<Object> promise) { |
| 2603 Handle<Object> exec_state; | 2570 Handle<Object> exec_state; |
| 2604 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2571 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
| 2605 // Create the new exception event object. | 2572 // Create the new exception event object. |
| 2606 Handle<Object> argv[] = { exec_state, | 2573 Handle<Object> argv[] = { exec_state, |
| 2607 exception, | 2574 exception, |
| 2608 isolate_->factory()->ToBoolean(uncaught), | 2575 isolate_->factory()->ToBoolean(uncaught), |
| 2609 promise }; | 2576 promise }; |
| 2610 return MakeJSObject(CStrVector("MakeExceptionEvent"), ARRAY_SIZE(argv), argv); | 2577 return MakeJSObject("MakeExceptionEvent", ARRAY_SIZE(argv), argv); |
| 2611 } | 2578 } |
| 2612 | 2579 |
| 2613 | 2580 |
| 2614 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, | 2581 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, |
| 2615 bool before) { | 2582 bool before) { |
| 2616 Handle<Object> exec_state; | 2583 Handle<Object> exec_state; |
| 2617 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2584 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
| 2618 // Create the compile event object. | 2585 // Create the compile event object. |
| 2619 Handle<Object> script_wrapper = Script::GetWrapper(script); | 2586 Handle<Object> script_wrapper = Script::GetWrapper(script); |
| 2620 Handle<Object> argv[] = { exec_state, | 2587 Handle<Object> argv[] = { exec_state, |
| 2621 script_wrapper, | 2588 script_wrapper, |
| 2622 isolate_->factory()->ToBoolean(before) }; | 2589 isolate_->factory()->ToBoolean(before) }; |
| 2623 return MakeJSObject(CStrVector("MakeCompileEvent"), ARRAY_SIZE(argv), argv); | 2590 return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv); |
| 2624 } | 2591 } |
| 2625 | 2592 |
| 2626 | 2593 |
| 2627 MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) { | 2594 MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) { |
| 2628 Handle<Object> exec_state; | 2595 Handle<Object> exec_state; |
| 2629 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2596 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
| 2630 // Create the script collected event object. | 2597 // Create the script collected event object. |
| 2631 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | 2598 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); |
| 2632 Handle<Object> argv[] = { exec_state, id_object }; | 2599 Handle<Object> argv[] = { exec_state, id_object }; |
| 2633 | 2600 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); |
| 2634 return MakeJSObject( | |
| 2635 CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv); | |
| 2636 } | 2601 } |
| 2637 | 2602 |
| 2638 | 2603 |
| 2639 void Debug::OnException(Handle<Object> exception, bool uncaught) { | 2604 void Debug::OnException(Handle<Object> exception, bool uncaught) { |
| 2640 HandleScope scope(isolate_); | 2605 HandleScope scope(isolate_); |
| 2641 Debug* debug = isolate_->debug(); | |
| 2642 | 2606 |
| 2643 // Bail out based on state or if there is no listener for this event | 2607 // Bail out based on state or if there is no listener for this event |
| 2644 if (debug->InDebugger()) return; | 2608 if (is_entered()) return; |
| 2645 if (!EventActive()) return; | 2609 if (!EventActive()) return; |
| 2646 | 2610 |
| 2647 Handle<Object> promise = debug->GetPromiseForUncaughtException(); | 2611 Handle<Object> promise = GetPromiseForUncaughtException(); |
| 2648 uncaught |= !promise->IsUndefined(); | 2612 uncaught |= !promise->IsUndefined(); |
| 2649 | 2613 |
| 2650 // Bail out if exception breaks are not active | 2614 // Bail out if exception breaks are not active |
| 2651 if (uncaught) { | 2615 if (uncaught) { |
| 2652 // Uncaught exceptions are reported by either flags. | 2616 // Uncaught exceptions are reported by either flags. |
| 2653 if (!(debug->break_on_uncaught_exception() || | 2617 if (!(break_on_uncaught_exception() || break_on_exception())) return; |
| 2654 debug->break_on_exception())) return; | |
| 2655 } else { | 2618 } else { |
| 2656 // Caught exceptions are reported is activated. | 2619 // Caught exceptions are reported is activated. |
| 2657 if (!debug->break_on_exception()) return; | 2620 if (!break_on_exception()) return; |
| 2658 } | 2621 } |
| 2659 | 2622 |
| 2660 // Enter the debugger. | 2623 // Enter the debugger. |
| 2661 EnterDebugger debugger(isolate_); | 2624 EnterDebugger debugger(isolate_); |
| 2662 if (debugger.FailedToEnter()) return; | 2625 if (debugger.FailedToEnter()) return; |
| 2663 | 2626 |
| 2664 // Clear all current stepping setup. | 2627 // Clear all current stepping setup. |
| 2665 debug->ClearStepping(); | 2628 ClearStepping(); |
| 2666 | 2629 |
| 2667 // Create the event data object. | 2630 // Create the event data object. |
| 2668 Handle<Object> event_data; | 2631 Handle<Object> event_data; |
| 2669 // Bail out and don't call debugger if exception. | 2632 // Bail out and don't call debugger if exception. |
| 2670 if (!MakeExceptionEvent( | 2633 if (!MakeExceptionEvent( |
| 2671 exception, uncaught, promise).ToHandle(&event_data)) { | 2634 exception, uncaught, promise).ToHandle(&event_data)) { |
| 2672 return; | 2635 return; |
| 2673 } | 2636 } |
| 2674 | 2637 |
| 2675 // Process debug event. | 2638 // Process debug event. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2697 ProcessDebugEvent(v8::Break, | 2660 ProcessDebugEvent(v8::Break, |
| 2698 Handle<JSObject>::cast(event_data), | 2661 Handle<JSObject>::cast(event_data), |
| 2699 auto_continue); | 2662 auto_continue); |
| 2700 } | 2663 } |
| 2701 | 2664 |
| 2702 | 2665 |
| 2703 void Debug::OnBeforeCompile(Handle<Script> script) { | 2666 void Debug::OnBeforeCompile(Handle<Script> script) { |
| 2704 HandleScope scope(isolate_); | 2667 HandleScope scope(isolate_); |
| 2705 | 2668 |
| 2706 // Bail out based on state or if there is no listener for this event | 2669 // Bail out based on state or if there is no listener for this event |
| 2707 if (InDebugger()) return; | 2670 if (is_entered()) return; |
| 2708 if (!EventActive()) return; | 2671 if (!EventActive()) return; |
| 2709 | 2672 |
| 2710 // Enter the debugger. | 2673 // Enter the debugger. |
| 2711 EnterDebugger debugger(isolate_); | 2674 EnterDebugger debugger(isolate_); |
| 2712 if (debugger.FailedToEnter()) return; | 2675 if (debugger.FailedToEnter()) return; |
| 2713 | 2676 |
| 2714 // Create the event data object. | 2677 // Create the event data object. |
| 2715 Handle<Object> event_data; | 2678 Handle<Object> event_data; |
| 2716 // Bail out and don't call debugger if exception. | 2679 // Bail out and don't call debugger if exception. |
| 2717 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; | 2680 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2728 AfterCompileFlags after_compile_flags) { | 2691 AfterCompileFlags after_compile_flags) { |
| 2729 HandleScope scope(isolate_); | 2692 HandleScope scope(isolate_); |
| 2730 | 2693 |
| 2731 // Add the newly compiled script to the script cache. | 2694 // Add the newly compiled script to the script cache. |
| 2732 AddScriptToScriptCache(script); | 2695 AddScriptToScriptCache(script); |
| 2733 | 2696 |
| 2734 // No more to do if not debugging. | 2697 // No more to do if not debugging. |
| 2735 if (!EventActive()) return; | 2698 if (!EventActive()) return; |
| 2736 | 2699 |
| 2737 // Store whether in debugger before entering debugger. | 2700 // Store whether in debugger before entering debugger. |
| 2738 bool in_debugger = InDebugger(); | 2701 bool in_debugger = is_entered(); |
| 2739 | 2702 |
| 2740 // Enter the debugger. | 2703 // Enter the debugger. |
| 2741 EnterDebugger debugger(isolate_); | 2704 EnterDebugger debugger(isolate_); |
| 2742 if (debugger.FailedToEnter()) return; | 2705 if (debugger.FailedToEnter()) return; |
| 2743 | 2706 |
| 2744 // If debugging there might be script break points registered for this | 2707 // If debugging there might be script break points registered for this |
| 2745 // script. Make sure that these break points are set. | 2708 // script. Make sure that these break points are set. |
| 2746 | 2709 |
| 2747 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js). | 2710 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js). |
| 2748 Handle<String> update_script_break_points_string = | 2711 Handle<String> update_script_break_points_string = |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2779 | 2742 |
| 2780 // Process debug event. | 2743 // Process debug event. |
| 2781 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2744 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
| 2782 } | 2745 } |
| 2783 | 2746 |
| 2784 | 2747 |
| 2785 void Debug::OnScriptCollected(int id) { | 2748 void Debug::OnScriptCollected(int id) { |
| 2786 HandleScope scope(isolate_); | 2749 HandleScope scope(isolate_); |
| 2787 | 2750 |
| 2788 // No more to do if not debugging. | 2751 // No more to do if not debugging. |
| 2789 if (InDebugger()) return; | 2752 if (is_entered()) return; |
| 2790 if (!EventActive()) return; | 2753 if (!EventActive()) return; |
| 2791 | 2754 |
| 2792 // Enter the debugger. | 2755 // Enter the debugger. |
| 2793 EnterDebugger debugger(isolate_); | 2756 EnterDebugger debugger(isolate_); |
| 2794 if (debugger.FailedToEnter()) return; | 2757 if (debugger.FailedToEnter()) return; |
| 2795 | 2758 |
| 2796 // Create the script collected state object. | 2759 // Create the script collected state object. |
| 2797 Handle<Object> event_data; | 2760 Handle<Object> event_data; |
| 2798 // Bail out and don't call debugger if exception. | 2761 // Bail out and don't call debugger if exception. |
| 2799 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; | 2762 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; |
| 2800 | 2763 |
| 2801 // Process debug event. | 2764 // Process debug event. |
| 2802 ProcessDebugEvent(v8::ScriptCollected, | 2765 ProcessDebugEvent(v8::ScriptCollected, |
| 2803 Handle<JSObject>::cast(event_data), | 2766 Handle<JSObject>::cast(event_data), |
| 2804 true); | 2767 true); |
| 2805 } | 2768 } |
| 2806 | 2769 |
| 2807 | 2770 |
| 2808 void Debug::ProcessDebugEvent(v8::DebugEvent event, | 2771 void Debug::ProcessDebugEvent(v8::DebugEvent event, |
| 2809 Handle<JSObject> event_data, | 2772 Handle<JSObject> event_data, |
| 2810 bool auto_continue) { | 2773 bool auto_continue) { |
| 2811 HandleScope scope(isolate_); | 2774 HandleScope scope(isolate_); |
| 2812 | 2775 |
| 2813 // Clear any pending debug break if this is a real break. | 2776 // Clear any pending debug break if this is a real break. |
| 2814 if (!auto_continue) set_has_pending_interrupt(false); | 2777 if (!auto_continue) thread_local_.has_pending_interrupt_ = false; |
| 2815 | 2778 |
| 2816 // Create the execution state. | 2779 // Create the execution state. |
| 2817 Handle<Object> exec_state; | 2780 Handle<Object> exec_state; |
| 2818 // Bail out and don't call debugger if exception. | 2781 // Bail out and don't call debugger if exception. |
| 2819 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 2782 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 2820 | 2783 |
| 2821 // First notify the message handler if any. | 2784 // First notify the message handler if any. |
| 2822 if (message_handler_ != NULL) { | 2785 if (message_handler_ != NULL) { |
| 2823 NotifyMessageHandler(event, | 2786 NotifyMessageHandler(event, |
| 2824 Handle<JSObject>::cast(exec_state), | 2787 Handle<JSObject>::cast(exec_state), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2845 } | 2808 } |
| 2846 } | 2809 } |
| 2847 } | 2810 } |
| 2848 | 2811 |
| 2849 | 2812 |
| 2850 void Debug::CallEventCallback(v8::DebugEvent event, | 2813 void Debug::CallEventCallback(v8::DebugEvent event, |
| 2851 Handle<Object> exec_state, | 2814 Handle<Object> exec_state, |
| 2852 Handle<Object> event_data, | 2815 Handle<Object> event_data, |
| 2853 v8::Debug::ClientData* client_data) { | 2816 v8::Debug::ClientData* client_data) { |
| 2854 if (event_listener_->IsForeign()) { | 2817 if (event_listener_->IsForeign()) { |
| 2855 CallCEventCallback(event, exec_state, event_data, client_data); | 2818 // Invoke the C debug event listener. |
| 2819 v8::Debug::EventCallback2 callback = |
| 2820 FUNCTION_CAST<v8::Debug::EventCallback2>( |
| 2821 Handle<Foreign>::cast(event_listener_)->foreign_address()); |
| 2822 EventDetailsImpl event_details(event, |
| 2823 Handle<JSObject>::cast(exec_state), |
| 2824 Handle<JSObject>::cast(event_data), |
| 2825 event_listener_data_, |
| 2826 client_data); |
| 2827 callback(event_details); |
| 2828 ASSERT(!isolate_->has_scheduled_exception()); |
| 2856 } else { | 2829 } else { |
| 2857 CallJSEventCallback(event, exec_state, event_data); | 2830 // Invoke the JavaScript debug event listener. |
| 2831 ASSERT(event_listener_->IsJSFunction()); |
| 2832 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), |
| 2833 exec_state, |
| 2834 event_data, |
| 2835 event_listener_data_ }; |
| 2836 Execution::TryCall(Handle<JSFunction>::cast(event_listener_), |
| 2837 isolate_->global_object(), |
| 2838 ARRAY_SIZE(argv), |
| 2839 argv); |
| 2858 } | 2840 } |
| 2859 } | 2841 } |
| 2860 | 2842 |
| 2861 | 2843 |
| 2862 void Debug::CallCEventCallback(v8::DebugEvent event, | |
| 2863 Handle<Object> exec_state, | |
| 2864 Handle<Object> event_data, | |
| 2865 v8::Debug::ClientData* client_data) { | |
| 2866 Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_)); | |
| 2867 v8::Debug::EventCallback2 callback = | |
| 2868 FUNCTION_CAST<v8::Debug::EventCallback2>( | |
| 2869 callback_obj->foreign_address()); | |
| 2870 EventDetailsImpl event_details( | |
| 2871 event, | |
| 2872 Handle<JSObject>::cast(exec_state), | |
| 2873 Handle<JSObject>::cast(event_data), | |
| 2874 event_listener_data_, | |
| 2875 client_data); | |
| 2876 callback(event_details); | |
| 2877 } | |
| 2878 | |
| 2879 | |
| 2880 void Debug::CallJSEventCallback(v8::DebugEvent event, | |
| 2881 Handle<Object> exec_state, | |
| 2882 Handle<Object> event_data) { | |
| 2883 ASSERT(event_listener_->IsJSFunction()); | |
| 2884 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); | |
| 2885 | |
| 2886 // Invoke the JavaScript debug event listener. | |
| 2887 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), | |
| 2888 exec_state, | |
| 2889 event_data, | |
| 2890 event_listener_data_ }; | |
| 2891 Execution::TryCall(fun, | |
| 2892 isolate_->global_object(), | |
| 2893 ARRAY_SIZE(argv), | |
| 2894 argv); | |
| 2895 // Silently ignore exceptions from debug event listeners. | |
| 2896 } | |
| 2897 | |
| 2898 | |
| 2899 Handle<Context> Debug::GetDebugContext() { | 2844 Handle<Context> Debug::GetDebugContext() { |
| 2900 EnterDebugger debugger(isolate_); | 2845 EnterDebugger debugger(isolate_); |
| 2901 // The global handle may be destroyed soon after. Return it reboxed. | 2846 // The global handle may be destroyed soon after. Return it reboxed. |
| 2902 return handle(*debug_context(), isolate_); | 2847 return handle(*debug_context(), isolate_); |
| 2903 } | 2848 } |
| 2904 | 2849 |
| 2905 | 2850 |
| 2906 void Debug::NotifyMessageHandler(v8::DebugEvent event, | 2851 void Debug::NotifyMessageHandler(v8::DebugEvent event, |
| 2907 Handle<JSObject> exec_state, | 2852 Handle<JSObject> exec_state, |
| 2908 Handle<JSObject> event_data, | 2853 Handle<JSObject> event_data, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2929 break; | 2874 break; |
| 2930 case v8::NewFunction: | 2875 case v8::NewFunction: |
| 2931 break; | 2876 break; |
| 2932 default: | 2877 default: |
| 2933 UNREACHABLE(); | 2878 UNREACHABLE(); |
| 2934 } | 2879 } |
| 2935 | 2880 |
| 2936 // The debug command interrupt flag might have been set when the command was | 2881 // The debug command interrupt flag might have been set when the command was |
| 2937 // added. It should be enough to clear the flag only once while we are in the | 2882 // added. It should be enough to clear the flag only once while we are in the |
| 2938 // debugger. | 2883 // debugger. |
| 2939 ASSERT(InDebugger()); | 2884 ASSERT(is_entered()); |
| 2940 isolate_->stack_guard()->ClearDebugCommand(); | 2885 isolate_->stack_guard()->ClearDebugCommand(); |
| 2941 | 2886 |
| 2942 // Notify the debugger that a debug event has occurred unless auto continue is | 2887 // Notify the debugger that a debug event has occurred unless auto continue is |
| 2943 // active in which case no event is send. | 2888 // active in which case no event is send. |
| 2944 if (sendEventMessage) { | 2889 if (sendEventMessage) { |
| 2945 MessageImpl message = MessageImpl::NewEvent( | 2890 MessageImpl message = MessageImpl::NewEvent( |
| 2946 event, | 2891 event, |
| 2947 auto_continue, | 2892 auto_continue, |
| 2948 Handle<JSObject>::cast(exec_state), | 2893 Handle<JSObject>::cast(exec_state), |
| 2949 Handle<JSObject>::cast(event_data)); | 2894 Handle<JSObject>::cast(event_data)); |
| 2950 InvokeMessageHandler(message); | 2895 InvokeMessageHandler(message); |
| 2951 } | 2896 } |
| 2952 | 2897 |
| 2953 // If auto continue don't make the event cause a break, but process messages | 2898 // If auto continue don't make the event cause a break, but process messages |
| 2954 // in the queue if any. For script collected events don't even process | 2899 // in the queue if any. For script collected events don't even process |
| 2955 // messages in the queue as the execution state might not be what is expected | 2900 // messages in the queue as the execution state might not be what is expected |
| 2956 // by the client. | 2901 // by the client. |
| 2957 if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) { | 2902 if ((auto_continue && !has_commands()) || event == v8::ScriptCollected) { |
| 2958 return; | 2903 return; |
| 2959 } | 2904 } |
| 2960 | 2905 |
| 2961 // DebugCommandProcessor goes here. | 2906 // DebugCommandProcessor goes here. |
| 2962 bool running = auto_continue; | 2907 bool running = auto_continue; |
| 2963 | 2908 |
| 2964 Handle<Object> cmd_processor_ctor = Object::GetProperty( | 2909 Handle<Object> cmd_processor_ctor = Object::GetProperty( |
| 2965 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked(); | 2910 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked(); |
| 2966 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; | 2911 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; |
| 2967 Handle<Object> cmd_processor = Execution::Call( | 2912 Handle<Object> cmd_processor = Execution::Call( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3023 | 2968 |
| 3024 // Return the result. | 2969 // Return the result. |
| 3025 MessageImpl message = MessageImpl::NewResponse( | 2970 MessageImpl message = MessageImpl::NewResponse( |
| 3026 event, running, exec_state, event_data, answer, command.client_data()); | 2971 event, running, exec_state, event_data, answer, command.client_data()); |
| 3027 InvokeMessageHandler(message); | 2972 InvokeMessageHandler(message); |
| 3028 command.Dispose(); | 2973 command.Dispose(); |
| 3029 | 2974 |
| 3030 // Return from debug event processing if either the VM is put into the | 2975 // Return from debug event processing if either the VM is put into the |
| 3031 // running state (through a continue command) or auto continue is active | 2976 // running state (through a continue command) or auto continue is active |
| 3032 // and there are no more commands queued. | 2977 // and there are no more commands queued. |
| 3033 } while (!running || HasCommands()); | 2978 } while (!running || has_commands()); |
| 3034 } | 2979 } |
| 3035 | 2980 |
| 3036 | 2981 |
| 3037 void Debug::SetEventListener(Handle<Object> callback, | 2982 void Debug::SetEventListener(Handle<Object> callback, |
| 3038 Handle<Object> data) { | 2983 Handle<Object> data) { |
| 3039 GlobalHandles* global_handles = isolate_->global_handles(); | 2984 GlobalHandles* global_handles = isolate_->global_handles(); |
| 3040 | 2985 |
| 3041 // Remove existing entry. | 2986 // Remove existing entry. |
| 3042 GlobalHandles::Destroy(event_listener_.location()); | 2987 GlobalHandles::Destroy(event_listener_.location()); |
| 3043 event_listener_ = Handle<Object>(); | 2988 event_listener_ = Handle<Object>(); |
| 3044 GlobalHandles::Destroy(event_listener_data_.location()); | 2989 GlobalHandles::Destroy(event_listener_data_.location()); |
| 3045 event_listener_data_ = Handle<Object>(); | 2990 event_listener_data_ = Handle<Object>(); |
| 3046 | 2991 |
| 3047 // Set new entry. | 2992 // Set new entry. |
| 3048 if (!callback->IsUndefined() && !callback->IsNull()) { | 2993 if (!callback->IsUndefined() && !callback->IsNull()) { |
| 3049 event_listener_ = global_handles->Create(*callback); | 2994 event_listener_ = global_handles->Create(*callback); |
| 3050 if (data.is_null()) data = isolate_->factory()->undefined_value(); | 2995 if (data.is_null()) data = isolate_->factory()->undefined_value(); |
| 3051 event_listener_data_ = global_handles->Create(*data); | 2996 event_listener_data_ = global_handles->Create(*data); |
| 3052 } | 2997 } |
| 3053 | 2998 |
| 3054 UpdateState(); | 2999 UpdateState(); |
| 3055 } | 3000 } |
| 3056 | 3001 |
| 3057 | 3002 |
| 3058 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { | 3003 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { |
| 3059 message_handler_ = handler; | 3004 message_handler_ = handler; |
| 3060 UpdateState(); | 3005 UpdateState(); |
| 3061 if (handler == NULL && InDebugger()) { | 3006 if (handler == NULL && is_entered()) { |
| 3062 // Send an empty command to the debugger if in a break to make JavaScript | 3007 // Send an empty command to the debugger if in a break to make JavaScript |
| 3063 // run again if the debugger is closed. | 3008 // run again if the debugger is closed. |
| 3064 EnqueueCommandMessage(Vector<const uint16_t>::empty()); | 3009 EnqueueCommandMessage(Vector<const uint16_t>::empty()); |
| 3065 } | 3010 } |
| 3066 } | 3011 } |
| 3067 | 3012 |
| 3068 | 3013 |
| 3069 | 3014 |
| 3070 void Debug::UpdateState() { | 3015 void Debug::UpdateState() { |
| 3071 bool activate = message_handler_ != NULL || | 3016 bool activate = message_handler_ != NULL || |
| 3072 !event_listener_.is_null() || | 3017 !event_listener_.is_null() || |
| 3073 InDebugger(); | 3018 is_entered(); |
| 3074 if (!is_active_ && activate) { | 3019 if (!is_active_ && activate) { |
| 3075 // Note that the debug context could have already been loaded to | 3020 // Note that the debug context could have already been loaded to |
| 3076 // bootstrap test cases. | 3021 // bootstrap test cases. |
| 3077 isolate_->compilation_cache()->Disable(); | 3022 isolate_->compilation_cache()->Disable(); |
| 3078 activate = Load(); | 3023 activate = Load(); |
| 3079 } else if (IsLoaded() && !activate) { | 3024 } else if (is_loaded() && !activate) { |
| 3080 isolate_->compilation_cache()->Enable(); | 3025 isolate_->compilation_cache()->Enable(); |
| 3081 Unload(); | 3026 Unload(); |
| 3082 } | 3027 } |
| 3083 is_active_ = activate; | 3028 is_active_ = activate; |
| 3084 // At this point the debug context is loaded iff the debugger is active. | 3029 // At this point the debug context is loaded iff the debugger is active. |
| 3085 ASSERT(IsLoaded() == is_active_); | 3030 ASSERT(is_loaded() == is_active()); |
| 3086 } | 3031 } |
| 3087 | 3032 |
| 3088 | 3033 |
| 3089 // Calls the registered debug message handler. This callback is part of the | 3034 // Calls the registered debug message handler. This callback is part of the |
| 3090 // public API. | 3035 // public API. |
| 3091 void Debug::InvokeMessageHandler(MessageImpl message) { | 3036 void Debug::InvokeMessageHandler(MessageImpl message) { |
| 3092 if (message_handler_ != NULL) message_handler_(message); | 3037 if (message_handler_ != NULL) message_handler_(message); |
| 3093 } | 3038 } |
| 3094 | 3039 |
| 3095 | 3040 |
| 3096 // Puts a command coming from the public API on the queue. Creates | 3041 // Puts a command coming from the public API on the queue. Creates |
| 3097 // a copy of the command string managed by the debugger. Up to this | 3042 // a copy of the command string managed by the debugger. Up to this |
| 3098 // point, the command data was managed by the API client. Called | 3043 // point, the command data was managed by the API client. Called |
| 3099 // by the API client thread. | 3044 // by the API client thread. |
| 3100 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, | 3045 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, |
| 3101 v8::Debug::ClientData* client_data) { | 3046 v8::Debug::ClientData* client_data) { |
| 3102 // Need to cast away const. | 3047 // Need to cast away const. |
| 3103 CommandMessage message = CommandMessage::New( | 3048 CommandMessage message = CommandMessage::New( |
| 3104 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | 3049 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
| 3105 command.length()), | 3050 command.length()), |
| 3106 client_data); | 3051 client_data); |
| 3107 isolate_->logger()->DebugTag("Put command on command_queue."); | 3052 isolate_->logger()->DebugTag("Put command on command_queue."); |
| 3108 command_queue_.Put(message); | 3053 command_queue_.Put(message); |
| 3109 command_received_.Signal(); | 3054 command_received_.Signal(); |
| 3110 | 3055 |
| 3111 // Set the debug command break flag to have the command processed. | 3056 // Set the debug command break flag to have the command processed. |
| 3112 if (!isolate_->debug()->InDebugger()) { | 3057 if (!is_entered()) isolate_->stack_guard()->RequestDebugCommand(); |
| 3113 isolate_->stack_guard()->RequestDebugCommand(); | |
| 3114 } | |
| 3115 } | 3058 } |
| 3116 | 3059 |
| 3117 | 3060 |
| 3118 bool Debug::HasCommands() { | |
| 3119 return !command_queue_.IsEmpty(); | |
| 3120 } | |
| 3121 | |
| 3122 | |
| 3123 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { | 3061 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { |
| 3124 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); | 3062 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); |
| 3125 event_command_queue_.Put(message); | 3063 event_command_queue_.Put(message); |
| 3126 | 3064 |
| 3127 // Set the debug command break flag to have the command processed. | 3065 // Set the debug command break flag to have the command processed. |
| 3128 if (!InDebugger()) isolate_->stack_guard()->RequestDebugCommand(); | 3066 if (!is_entered()) isolate_->stack_guard()->RequestDebugCommand(); |
| 3129 } | 3067 } |
| 3130 | 3068 |
| 3131 | 3069 |
| 3132 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) { | 3070 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) { |
| 3133 // Enter the debugger. | 3071 // Enter the debugger. |
| 3134 EnterDebugger debugger(isolate_); | 3072 EnterDebugger debugger(isolate_); |
| 3135 if (debugger.FailedToEnter()) { | 3073 if (debugger.FailedToEnter()) { |
| 3136 return isolate_->factory()->undefined_value(); | 3074 return isolate_->factory()->undefined_value(); |
| 3137 } | 3075 } |
| 3138 | 3076 |
| 3139 // Create the execution state. | 3077 // Create the execution state. |
| 3140 Handle<Object> exec_state; | 3078 Handle<Object> exec_state; |
| 3141 if (!MakeExecutionState().ToHandle(&exec_state)) { | 3079 if (!MakeExecutionState().ToHandle(&exec_state)) { |
| 3142 return isolate_->factory()->undefined_value(); | 3080 return isolate_->factory()->undefined_value(); |
| 3143 } | 3081 } |
| 3144 | 3082 |
| 3145 Handle<Object> argv[] = { exec_state, data }; | 3083 Handle<Object> argv[] = { exec_state, data }; |
| 3146 return Execution::Call( | 3084 return Execution::Call( |
| 3147 isolate_, | 3085 isolate_, |
| 3148 fun, | 3086 fun, |
| 3149 Handle<Object>(debug_context()->global_proxy(), isolate_), | 3087 Handle<Object>(debug_context()->global_proxy(), isolate_), |
| 3150 ARRAY_SIZE(argv), | 3088 ARRAY_SIZE(argv), |
| 3151 argv); | 3089 argv); |
| 3152 } | 3090 } |
| 3153 | 3091 |
| 3154 | 3092 |
| 3093 void Debug::DebugBreakHelper() { |
| 3094 // Ignore debug break during bootstrapping. |
| 3095 if (isolate_->bootstrapper()->IsActive()) return; |
| 3096 // Just continue if breaks are disabled. |
| 3097 if (break_disabled_) return; |
| 3098 // Ignore debug break if debugger is not active. |
| 3099 if (!is_active()) return; |
| 3100 |
| 3101 StackLimitCheck check(isolate_); |
| 3102 if (check.HasOverflowed()) return; |
| 3103 |
| 3104 { JavaScriptFrameIterator it(isolate_); |
| 3105 ASSERT(!it.done()); |
| 3106 Object* fun = it.frame()->function(); |
| 3107 if (fun && fun->IsJSFunction()) { |
| 3108 // Don't stop in builtin functions. |
| 3109 if (JSFunction::cast(fun)->IsBuiltin()) return; |
| 3110 GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); |
| 3111 // Don't stop in debugger functions. |
| 3112 if (IsDebugGlobal(global)) return; |
| 3113 } |
| 3114 } |
| 3115 |
| 3116 // Collect the break state before clearing the flags. |
| 3117 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() && |
| 3118 !isolate_->stack_guard()->CheckDebugBreak(); |
| 3119 |
| 3120 isolate_->stack_guard()->ClearDebugBreak(); |
| 3121 |
| 3122 ProcessDebugMessages(debug_command_only); |
| 3123 } |
| 3124 |
| 3125 |
| 3126 void Debug::ProcessDebugMessages(bool debug_command_only) { |
| 3127 isolate_->stack_guard()->ClearDebugCommand(); |
| 3128 |
| 3129 StackLimitCheck check(isolate_); |
| 3130 if (check.HasOverflowed()) return; |
| 3131 |
| 3132 HandleScope scope(isolate_); |
| 3133 // Enter the debugger. Just continue if we fail to enter the debugger. |
| 3134 EnterDebugger debugger(isolate_); |
| 3135 if (debugger.FailedToEnter()) return; |
| 3136 |
| 3137 // Notify the debug event listeners. Indicate auto continue if the break was |
| 3138 // a debug command break. |
| 3139 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); |
| 3140 } |
| 3141 |
| 3142 |
| 3155 EnterDebugger::EnterDebugger(Isolate* isolate) | 3143 EnterDebugger::EnterDebugger(Isolate* isolate) |
| 3156 : isolate_(isolate), | 3144 : isolate_(isolate), |
| 3157 prev_(isolate_->debug()->debugger_entry()), | 3145 prev_(isolate_->debug()->debugger_entry()), |
| 3158 save_(isolate_) { | 3146 save_(isolate_) { |
| 3159 Debug* debug = isolate_->debug(); | 3147 Debug* debug = isolate_->debug(); |
| 3160 | 3148 |
| 3161 // Link recursive debugger entry. | 3149 // Link recursive debugger entry. |
| 3162 debug->set_debugger_entry(this); | 3150 debug->thread_local_.debugger_entry_ = this; |
| 3163 | 3151 |
| 3164 // Store the previous break id and frame id. | 3152 // Store the previous break id and frame id. |
| 3165 break_id_ = debug->break_id(); | 3153 break_id_ = debug->break_id(); |
| 3166 break_frame_id_ = debug->break_frame_id(); | 3154 break_frame_id_ = debug->break_frame_id(); |
| 3167 | 3155 |
| 3168 // Create the new break info. If there is no JavaScript frames there is no | 3156 // Create the new break info. If there is no JavaScript frames there is no |
| 3169 // break frame id. | 3157 // break frame id. |
| 3170 JavaScriptFrameIterator it(isolate_); | 3158 JavaScriptFrameIterator it(isolate_); |
| 3171 has_js_frames_ = !it.done(); | 3159 has_js_frames_ = !it.done(); |
| 3172 debug->NewBreak(has_js_frames_ ? it.frame()->id() : StackFrame::NO_ID); | 3160 debug->thread_local_.break_frame_id_ = has_js_frames_ ? it.frame()->id() |
| 3161 : StackFrame::NO_ID; |
| 3162 debug->SetNextBreakId(); |
| 3173 | 3163 |
| 3174 debug->UpdateState(); | 3164 debug->UpdateState(); |
| 3175 // Make sure that debugger is loaded and enter the debugger context. | 3165 // Make sure that debugger is loaded and enter the debugger context. |
| 3176 // The previous context is kept in save_. | 3166 // The previous context is kept in save_. |
| 3177 load_failed_ = !debug->IsLoaded(); | 3167 load_failed_ = !debug->is_loaded(); |
| 3178 if (!load_failed_) isolate_->set_context(*debug->debug_context()); | 3168 if (!load_failed_) isolate_->set_context(*debug->debug_context()); |
| 3179 } | 3169 } |
| 3180 | 3170 |
| 3181 | 3171 |
| 3182 EnterDebugger::~EnterDebugger() { | 3172 EnterDebugger::~EnterDebugger() { |
| 3183 Debug* debug = isolate_->debug(); | 3173 Debug* debug = isolate_->debug(); |
| 3184 | 3174 |
| 3185 // Restore to the previous break state. | 3175 // Restore to the previous break state. |
| 3186 debug->SetBreak(break_frame_id_, break_id_); | 3176 debug->thread_local_.break_frame_id_ = break_frame_id_; |
| 3177 debug->thread_local_.break_id_ = break_id_; |
| 3187 | 3178 |
| 3188 // Check for leaving the debugger. | 3179 // Check for leaving the debugger. |
| 3189 if (!load_failed_ && prev_ == NULL) { | 3180 if (!load_failed_ && prev_ == NULL) { |
| 3190 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3181 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 3191 // pending exception as clearing the mirror cache calls back into | 3182 // pending exception as clearing the mirror cache calls back into |
| 3192 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3183 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 3193 // case the exception should end up in the calling code. | 3184 // case the exception should end up in the calling code. |
| 3194 if (!isolate_->has_pending_exception()) { | 3185 if (!isolate_->has_pending_exception()) { |
| 3195 debug->ClearMirrorCache(); | 3186 debug->ClearMirrorCache(); |
| 3196 } | 3187 } |
| 3197 | 3188 |
| 3198 // If there are commands in the queue when leaving the debugger request | 3189 // If there are commands in the queue when leaving the debugger request |
| 3199 // that these commands are processed. | 3190 // that these commands are processed. |
| 3200 if (debug->HasCommands()) { | 3191 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); |
| 3201 isolate_->stack_guard()->RequestDebugCommand(); | |
| 3202 } | |
| 3203 } | 3192 } |
| 3204 | 3193 |
| 3205 // Leaving this debugger entry. | 3194 // Leaving this debugger entry. |
| 3206 debug->set_debugger_entry(prev_); | 3195 debug->thread_local_.debugger_entry_ = prev_; |
| 3207 | 3196 |
| 3208 debug->UpdateState(); | 3197 debug->UpdateState(); |
| 3209 } | 3198 } |
| 3210 | 3199 |
| 3211 | 3200 |
| 3212 MessageImpl MessageImpl::NewEvent(DebugEvent event, | 3201 MessageImpl MessageImpl::NewEvent(DebugEvent event, |
| 3213 bool running, | 3202 bool running, |
| 3214 Handle<JSObject> exec_state, | 3203 Handle<JSObject> exec_state, |
| 3215 Handle<JSObject> event_data) { | 3204 Handle<JSObject> event_data) { |
| 3216 MessageImpl message(true, event, running, | 3205 MessageImpl message(true, event, running, |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3462 logger_->DebugEvent("Put", message.text()); | 3451 logger_->DebugEvent("Put", message.text()); |
| 3463 } | 3452 } |
| 3464 | 3453 |
| 3465 | 3454 |
| 3466 void LockingCommandMessageQueue::Clear() { | 3455 void LockingCommandMessageQueue::Clear() { |
| 3467 LockGuard<Mutex> lock_guard(&mutex_); | 3456 LockGuard<Mutex> lock_guard(&mutex_); |
| 3468 queue_.Clear(); | 3457 queue_.Clear(); |
| 3469 } | 3458 } |
| 3470 | 3459 |
| 3471 } } // namespace v8::internal | 3460 } } // namespace v8::internal |
| OLD | NEW |