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 19 matching lines...) Expand all Loading... | |
30 namespace v8 { | 30 namespace v8 { |
31 namespace internal { | 31 namespace internal { |
32 | 32 |
33 Debug::Debug(Isolate* isolate) | 33 Debug::Debug(Isolate* isolate) |
34 : has_break_points_(false), | 34 : has_break_points_(false), |
35 script_cache_(NULL), | 35 script_cache_(NULL), |
36 debug_info_list_(NULL), | 36 debug_info_list_(NULL), |
37 disable_break_(false), | 37 disable_break_(false), |
38 break_on_exception_(false), | 38 break_on_exception_(false), |
39 break_on_uncaught_exception_(false), | 39 break_on_uncaught_exception_(false), |
40 current_promise_catch_handler_(NULL), | |
40 debug_break_return_(NULL), | 41 debug_break_return_(NULL), |
41 debug_break_slot_(NULL), | 42 debug_break_slot_(NULL), |
42 isolate_(isolate) { | 43 isolate_(isolate) { |
43 memset(registers_, 0, sizeof(JSCallerSavedBuffer)); | 44 memset(registers_, 0, sizeof(JSCallerSavedBuffer)); |
44 } | 45 } |
45 | 46 |
46 | 47 |
47 Debug::~Debug() { | 48 Debug::~Debug() { |
48 } | 49 } |
49 | 50 |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1310 | 1311 |
1311 bool Debug::IsBreakOnException(ExceptionBreakType type) { | 1312 bool Debug::IsBreakOnException(ExceptionBreakType type) { |
1312 if (type == BreakUncaughtException) { | 1313 if (type == BreakUncaughtException) { |
1313 return break_on_uncaught_exception_; | 1314 return break_on_uncaught_exception_; |
1314 } else { | 1315 } else { |
1315 return break_on_exception_; | 1316 return break_on_exception_; |
1316 } | 1317 } |
1317 } | 1318 } |
1318 | 1319 |
1319 | 1320 |
1321 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { | |
1322 Handle<Object> current_promise_getter; | |
1323 if (current_promise_getter_.ToHandle(¤t_promise_getter)) { | |
1324 isolate_->global_handles()->Destroy(current_promise_getter.location()); | |
1325 } | |
1326 current_promise_getter_ = Handle<JSFunction>::cast( | |
1327 isolate_->global_handles()->Create(*promise_getter)); | |
1328 current_promise_catch_handler_ = | |
1329 StackHandler::FromAddress(Isolate::handler(isolate_->thread_local_top())); | |
1330 } | |
1331 | |
1332 | |
1333 void Debug::PromiseHandleEpilogue() { | |
1334 current_promise_catch_handler_ = NULL; | |
rossberg
2014/04/30 12:55:17
Are we sure that PromiseHandle can never be reente
Yang
2014/04/30 13:20:14
I'm asserting now that the prologue always gets th
| |
1335 Handle<Object> promise_getter; | |
1336 if (!current_promise_getter_.ToHandle(&promise_getter)) return; | |
1337 isolate_->global_handles()->Destroy(promise_getter.location()); | |
1338 current_promise_getter_ = MaybeHandle<JSFunction>(); | |
1339 } | |
1340 | |
1341 | |
1342 Handle<Object> Debug::GetPromiseForUncaughtException() { | |
1343 Handle<JSFunction> promise_getter; | |
1344 Handle<Object> undefined = isolate_->factory()->undefined_value(); | |
1345 if (current_promise_getter_.ToHandle(&promise_getter)) { | |
1346 // Find the top-most try-catch handler. | |
1347 StackHandler* handler = StackHandler::FromAddress( | |
1348 Isolate::handler(isolate_->thread_local_top())); | |
1349 while (handler != NULL && !handler->is_catch()) { | |
1350 handler = handler->next(); | |
1351 } | |
1352 #ifdef DEBUG | |
1353 // Make sure that our promise catch handler is in the list of handlers, | |
1354 // even if it's not the top-most try-catch handler. | |
1355 StackHandler* temp = handler; | |
1356 while (temp != current_promise_catch_handler_ && !temp->is_catch()) { | |
1357 temp = temp->next(); | |
1358 CHECK(temp != NULL); | |
1359 } | |
1360 #endif // DEBUG | |
1361 | |
1362 if (handler == current_promise_catch_handler_) { | |
1363 return Execution::Call( | |
1364 isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked(); | |
1365 } | |
1366 } | |
1367 return undefined; | |
1368 } | |
1369 | |
1370 | |
1320 void Debug::PrepareStep(StepAction step_action, | 1371 void Debug::PrepareStep(StepAction step_action, |
1321 int step_count, | 1372 int step_count, |
1322 StackFrame::Id frame_id) { | 1373 StackFrame::Id frame_id) { |
1323 HandleScope scope(isolate_); | 1374 HandleScope scope(isolate_); |
1324 | 1375 |
1325 PrepareForBreakPoints(); | 1376 PrepareForBreakPoints(); |
1326 | 1377 |
1327 ASSERT(Debug::InDebugger()); | 1378 ASSERT(Debug::InDebugger()); |
1328 | 1379 |
1329 // Remember this step action and count. | 1380 // Remember this step action and count. |
(...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2633 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2684 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
2634 // Create the script collected event object. | 2685 // Create the script collected event object. |
2635 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | 2686 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); |
2636 Handle<Object> argv[] = { exec_state, id_object }; | 2687 Handle<Object> argv[] = { exec_state, id_object }; |
2637 | 2688 |
2638 return MakeJSObject( | 2689 return MakeJSObject( |
2639 CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv); | 2690 CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv); |
2640 } | 2691 } |
2641 | 2692 |
2642 | 2693 |
2643 void Debugger::OnException(Handle<Object> exception, | 2694 void Debugger::OnException(Handle<Object> exception, bool uncaught) { |
2644 bool uncaught, | |
2645 Handle<Object> promise) { | |
2646 HandleScope scope(isolate_); | 2695 HandleScope scope(isolate_); |
2647 Debug* debug = isolate_->debug(); | 2696 Debug* debug = isolate_->debug(); |
2648 | 2697 |
2649 // Bail out based on state or if there is no listener for this event | 2698 // Bail out based on state or if there is no listener for this event |
2650 if (debug->InDebugger()) return; | 2699 if (debug->InDebugger()) return; |
2651 if (!Debugger::EventActive(v8::Exception)) return; | 2700 if (!Debugger::EventActive(v8::Exception)) return; |
2652 | 2701 |
2702 Handle<Object> promise = debug->GetPromiseForUncaughtException(); | |
2703 uncaught |= !promise->IsUndefined(); | |
2704 | |
2653 // Bail out if exception breaks are not active | 2705 // Bail out if exception breaks are not active |
2654 if (uncaught) { | 2706 if (uncaught) { |
2655 // Uncaught exceptions are reported by either flags. | 2707 // Uncaught exceptions are reported by either flags. |
2656 if (!(debug->break_on_uncaught_exception() || | 2708 if (!(debug->break_on_uncaught_exception() || |
2657 debug->break_on_exception())) return; | 2709 debug->break_on_exception())) return; |
2658 } else { | 2710 } else { |
2659 // Caught exceptions are reported is activated. | 2711 // Caught exceptions are reported is activated. |
2660 if (!debug->break_on_exception()) return; | 2712 if (!debug->break_on_exception()) return; |
2661 } | 2713 } |
2662 | 2714 |
2663 // Enter the debugger. | 2715 // Enter the debugger. |
2664 EnterDebugger debugger(isolate_); | 2716 EnterDebugger debugger(isolate_); |
2665 if (debugger.FailedToEnter()) return; | 2717 if (debugger.FailedToEnter()) return; |
2666 | 2718 |
2667 // Clear all current stepping setup. | 2719 // Clear all current stepping setup. |
2668 debug->ClearStepping(); | 2720 debug->ClearStepping(); |
2669 | 2721 |
2670 // Determine event; | |
2671 DebugEvent event = promise->IsUndefined() | |
2672 ? v8::Exception : v8::PendingExceptionInPromise; | |
2673 | |
2674 // Create the event data object. | 2722 // Create the event data object. |
2675 Handle<Object> event_data; | 2723 Handle<Object> event_data; |
2676 // Bail out and don't call debugger if exception. | 2724 // Bail out and don't call debugger if exception. |
2677 if (!MakeExceptionEvent( | 2725 if (!MakeExceptionEvent( |
2678 exception, uncaught, promise).ToHandle(&event_data)) { | 2726 exception, uncaught, promise).ToHandle(&event_data)) { |
2679 return; | 2727 return; |
2680 } | 2728 } |
2681 | 2729 |
2682 // Process debug event. | 2730 // Process debug event. |
2683 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), false); | 2731 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
2684 // Return to continue execution from where the exception was thrown. | 2732 // Return to continue execution from where the exception was thrown. |
2685 } | 2733 } |
2686 | 2734 |
2687 | 2735 |
2688 void Debugger::OnDebugBreak(Handle<Object> break_points_hit, | 2736 void Debugger::OnDebugBreak(Handle<Object> break_points_hit, |
2689 bool auto_continue) { | 2737 bool auto_continue) { |
2690 HandleScope scope(isolate_); | 2738 HandleScope scope(isolate_); |
2691 | 2739 |
2692 // Debugger has already been entered by caller. | 2740 // Debugger has already been entered by caller. |
2693 ASSERT(isolate_->context() == *isolate_->debug()->debug_context()); | 2741 ASSERT(isolate_->context() == *isolate_->debug()->debug_context()); |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3155 // Send an empty command to the debugger if in a break to make JavaScript | 3203 // Send an empty command to the debugger if in a break to make JavaScript |
3156 // run again if the debugger is closed. | 3204 // run again if the debugger is closed. |
3157 if (isolate_->debug()->InDebugger()) { | 3205 if (isolate_->debug()->InDebugger()) { |
3158 ProcessCommand(Vector<const uint16_t>::empty()); | 3206 ProcessCommand(Vector<const uint16_t>::empty()); |
3159 } | 3207 } |
3160 } | 3208 } |
3161 } | 3209 } |
3162 | 3210 |
3163 | 3211 |
3164 void Debugger::ListenersChanged() { | 3212 void Debugger::ListenersChanged() { |
3165 if (IsDebuggerActive()) { | 3213 bool active = IsDebuggerActive(); |
3214 if (active) { | |
3166 // Disable the compilation cache when the debugger is active. | 3215 // Disable the compilation cache when the debugger is active. |
3167 isolate_->compilation_cache()->Disable(); | 3216 isolate_->compilation_cache()->Disable(); |
3168 debugger_unload_pending_ = false; | 3217 debugger_unload_pending_ = false; |
3169 } else { | 3218 } else { |
3170 isolate_->compilation_cache()->Enable(); | 3219 isolate_->compilation_cache()->Enable(); |
3171 // Unload the debugger if event listener and message handler cleared. | 3220 // Unload the debugger if event listener and message handler cleared. |
3172 // Schedule this for later, because we may be in non-V8 thread. | 3221 // Schedule this for later, because we may be in non-V8 thread. |
3173 debugger_unload_pending_ = true; | 3222 debugger_unload_pending_ = true; |
3174 } | 3223 } |
3175 } | 3224 } |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3720 already_signalled_ = false; | 3769 already_signalled_ = false; |
3721 } | 3770 } |
3722 { | 3771 { |
3723 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); | 3772 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_)); |
3724 isolate_->debugger()->CallMessageDispatchHandler(); | 3773 isolate_->debugger()->CallMessageDispatchHandler(); |
3725 } | 3774 } |
3726 } | 3775 } |
3727 } | 3776 } |
3728 | 3777 |
3729 } } // namespace v8::internal | 3778 } } // namespace v8::internal |
OLD | NEW |