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 |