OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
34 #include "codegen.h" | 34 #include "codegen.h" |
35 #include "compilation-cache.h" | 35 #include "compilation-cache.h" |
36 #include "compiler.h" | 36 #include "compiler.h" |
37 #include "debug.h" | 37 #include "debug.h" |
38 #include "deoptimizer.h" | 38 #include "deoptimizer.h" |
39 #include "execution.h" | 39 #include "execution.h" |
40 #include "global-handles.h" | 40 #include "global-handles.h" |
41 #include "ic.h" | 41 #include "ic.h" |
42 #include "ic-inl.h" | 42 #include "ic-inl.h" |
| 43 #include "isolate-inl.h" |
43 #include "list.h" | 44 #include "list.h" |
44 #include "messages.h" | 45 #include "messages.h" |
45 #include "natives.h" | 46 #include "natives.h" |
46 #include "stub-cache.h" | 47 #include "stub-cache.h" |
47 #include "log.h" | 48 #include "log.h" |
48 | 49 |
49 #include "../include/v8-debug.h" | 50 #include "../include/v8-debug.h" |
50 | 51 |
51 namespace v8 { | 52 namespace v8 { |
52 namespace internal { | 53 namespace internal { |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 ASSERT(!IsDebugBreak()); | 395 ASSERT(!IsDebugBreak()); |
395 } | 396 } |
396 | 397 |
397 | 398 |
398 void BreakLocationIterator::PrepareStepIn() { | 399 void BreakLocationIterator::PrepareStepIn() { |
399 HandleScope scope; | 400 HandleScope scope; |
400 | 401 |
401 // Step in can only be prepared if currently positioned on an IC call, | 402 // Step in can only be prepared if currently positioned on an IC call, |
402 // construct call or CallFunction stub call. | 403 // construct call or CallFunction stub call. |
403 Address target = rinfo()->target_address(); | 404 Address target = rinfo()->target_address(); |
404 Handle<Code> code(Code::GetCodeFromTargetAddress(target)); | 405 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); |
405 if (code->is_call_stub() || code->is_keyed_call_stub()) { | 406 if (target_code->is_call_stub() || target_code->is_keyed_call_stub()) { |
406 // Step in through IC call is handled by the runtime system. Therefore make | 407 // Step in through IC call is handled by the runtime system. Therefore make |
407 // sure that the any current IC is cleared and the runtime system is | 408 // sure that the any current IC is cleared and the runtime system is |
408 // called. If the executing code has a debug break at the location change | 409 // called. If the executing code has a debug break at the location change |
409 // the call in the original code as it is the code there that will be | 410 // the call in the original code as it is the code there that will be |
410 // executed in place of the debug break call. | 411 // executed in place of the debug break call. |
411 Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count(), | 412 Handle<Code> stub = ComputeCallDebugPrepareStepIn( |
412 code->kind()); | 413 target_code->arguments_count(), target_code->kind()); |
413 if (IsDebugBreak()) { | 414 if (IsDebugBreak()) { |
414 original_rinfo()->set_target_address(stub->entry()); | 415 original_rinfo()->set_target_address(stub->entry()); |
415 } else { | 416 } else { |
416 rinfo()->set_target_address(stub->entry()); | 417 rinfo()->set_target_address(stub->entry()); |
417 } | 418 } |
418 } else { | 419 } else { |
419 #ifdef DEBUG | 420 #ifdef DEBUG |
420 // All the following stuff is needed only for assertion checks so the code | 421 // All the following stuff is needed only for assertion checks so the code |
421 // is wrapped in ifdef. | 422 // is wrapped in ifdef. |
422 Handle<Code> maybe_call_function_stub = code; | 423 Handle<Code> maybe_call_function_stub = target_code; |
423 if (IsDebugBreak()) { | 424 if (IsDebugBreak()) { |
424 Address original_target = original_rinfo()->target_address(); | 425 Address original_target = original_rinfo()->target_address(); |
425 maybe_call_function_stub = | 426 maybe_call_function_stub = |
426 Handle<Code>(Code::GetCodeFromTargetAddress(original_target)); | 427 Handle<Code>(Code::GetCodeFromTargetAddress(original_target)); |
427 } | 428 } |
428 bool is_call_function_stub = | 429 bool is_call_function_stub = |
429 (maybe_call_function_stub->kind() == Code::STUB && | 430 (maybe_call_function_stub->kind() == Code::STUB && |
430 maybe_call_function_stub->major_key() == CodeStub::CallFunction); | 431 maybe_call_function_stub->major_key() == CodeStub::CallFunction); |
431 | 432 |
432 // Step in through construct call requires no changes to the running code. | 433 // Step in through construct call requires no changes to the running code. |
433 // Step in through getters/setters should already be prepared as well | 434 // Step in through getters/setters should already be prepared as well |
434 // because caller of this function (Debug::PrepareStep) is expected to | 435 // because caller of this function (Debug::PrepareStep) is expected to |
435 // flood the top frame's function with one shot breakpoints. | 436 // flood the top frame's function with one shot breakpoints. |
436 // Step in through CallFunction stub should also be prepared by caller of | 437 // Step in through CallFunction stub should also be prepared by caller of |
437 // this function (Debug::PrepareStep) which should flood target function | 438 // this function (Debug::PrepareStep) which should flood target function |
438 // with breakpoints. | 439 // with breakpoints. |
439 ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() | 440 ASSERT(RelocInfo::IsConstructCall(rmode()) || |
440 || is_call_function_stub); | 441 target_code->is_inline_cache_stub() || |
| 442 is_call_function_stub); |
441 #endif | 443 #endif |
442 } | 444 } |
443 } | 445 } |
444 | 446 |
445 | 447 |
446 // Check whether the break point is at a position which will exit the function. | 448 // Check whether the break point is at a position which will exit the function. |
447 bool BreakLocationIterator::IsExit() const { | 449 bool BreakLocationIterator::IsExit() const { |
448 return (RelocInfo::IsJSReturn(rmode())); | 450 return (RelocInfo::IsJSReturn(rmode())); |
449 } | 451 } |
450 | 452 |
(...skipping 16 matching lines...) Expand all Loading... |
467 | 469 |
468 | 470 |
469 void BreakLocationIterator::SetDebugBreakAtIC() { | 471 void BreakLocationIterator::SetDebugBreakAtIC() { |
470 // Patch the original code with the current address as the current address | 472 // Patch the original code with the current address as the current address |
471 // might have changed by the inline caching since the code was copied. | 473 // might have changed by the inline caching since the code was copied. |
472 original_rinfo()->set_target_address(rinfo()->target_address()); | 474 original_rinfo()->set_target_address(rinfo()->target_address()); |
473 | 475 |
474 RelocInfo::Mode mode = rmode(); | 476 RelocInfo::Mode mode = rmode(); |
475 if (RelocInfo::IsCodeTarget(mode)) { | 477 if (RelocInfo::IsCodeTarget(mode)) { |
476 Address target = rinfo()->target_address(); | 478 Address target = rinfo()->target_address(); |
477 Handle<Code> code(Code::GetCodeFromTargetAddress(target)); | 479 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); |
478 | 480 |
479 // Patch the code to invoke the builtin debug break function matching the | 481 // Patch the code to invoke the builtin debug break function matching the |
480 // calling convention used by the call site. | 482 // calling convention used by the call site. |
481 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(code, mode)); | 483 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode)); |
482 rinfo()->set_target_address(dbgbrk_code->entry()); | 484 rinfo()->set_target_address(dbgbrk_code->entry()); |
483 } | 485 } |
484 } | 486 } |
485 | 487 |
486 | 488 |
487 void BreakLocationIterator::ClearDebugBreakAtIC() { | 489 void BreakLocationIterator::ClearDebugBreakAtIC() { |
488 // Patch the code to the original invoke. | 490 // Patch the code to the original invoke. |
489 rinfo()->set_target_address(original_rinfo()->target_address()); | 491 rinfo()->set_target_address(original_rinfo()->target_address()); |
490 } | 492 } |
491 | 493 |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 | 767 |
766 // Silently ignore stack overflows during compilation. | 768 // Silently ignore stack overflows during compilation. |
767 if (function_info.is_null()) { | 769 if (function_info.is_null()) { |
768 ASSERT(isolate->has_pending_exception()); | 770 ASSERT(isolate->has_pending_exception()); |
769 isolate->clear_pending_exception(); | 771 isolate->clear_pending_exception(); |
770 return false; | 772 return false; |
771 } | 773 } |
772 | 774 |
773 // Execute the shared function in the debugger context. | 775 // Execute the shared function in the debugger context. |
774 Handle<Context> context = isolate->global_context(); | 776 Handle<Context> context = isolate->global_context(); |
775 bool caught_exception = false; | 777 bool caught_exception; |
776 Handle<JSFunction> function = | 778 Handle<JSFunction> function = |
777 factory->NewFunctionFromSharedFunctionInfo(function_info, context); | 779 factory->NewFunctionFromSharedFunctionInfo(function_info, context); |
778 | 780 |
779 Execution::TryCall(function, Handle<Object>(context->global()), | 781 Execution::TryCall(function, Handle<Object>(context->global()), |
780 0, NULL, &caught_exception); | 782 0, NULL, &caught_exception); |
781 | 783 |
782 // Check for caught exceptions. | 784 // Check for caught exceptions. |
783 if (caught_exception) { | 785 if (caught_exception) { |
784 Handle<Object> message = MessageHandler::MakeMessageObject( | 786 Handle<Object> message = MessageHandler::MakeMessageObject( |
785 "error_loading_debugger", NULL, Vector<Handle<Object> >::empty(), | 787 "error_loading_debugger", NULL, Vector<Handle<Object> >::empty(), |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 factory->LookupAsciiSymbol("IsBreakPointTriggered"); | 1098 factory->LookupAsciiSymbol("IsBreakPointTriggered"); |
1097 Handle<JSFunction> check_break_point = | 1099 Handle<JSFunction> check_break_point = |
1098 Handle<JSFunction>(JSFunction::cast( | 1100 Handle<JSFunction>(JSFunction::cast( |
1099 debug_context()->global()->GetPropertyNoExceptionThrown( | 1101 debug_context()->global()->GetPropertyNoExceptionThrown( |
1100 *is_break_point_triggered_symbol))); | 1102 *is_break_point_triggered_symbol))); |
1101 | 1103 |
1102 // Get the break id as an object. | 1104 // Get the break id as an object. |
1103 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id()); | 1105 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id()); |
1104 | 1106 |
1105 // Call HandleBreakPointx. | 1107 // Call HandleBreakPointx. |
1106 bool caught_exception = false; | 1108 bool caught_exception; |
1107 const int argc = 2; | 1109 const int argc = 2; |
1108 Object** argv[argc] = { | 1110 Object** argv[argc] = { |
1109 break_id.location(), | 1111 break_id.location(), |
1110 reinterpret_cast<Object**>(break_point_object.location()) | 1112 reinterpret_cast<Object**>(break_point_object.location()) |
1111 }; | 1113 }; |
1112 Handle<Object> result = Execution::TryCall(check_break_point, | 1114 Handle<Object> result = Execution::TryCall(check_break_point, |
1113 isolate_->js_builtins_object(), argc, argv, &caught_exception); | 1115 isolate_->js_builtins_object(), argc, argv, &caught_exception); |
1114 | 1116 |
1115 // If exception or non boolean result handle as not triggered | 1117 // If exception or non boolean result handle as not triggered |
1116 if (caught_exception || !result->IsBoolean()) { | 1118 if (caught_exception || !result->IsBoolean()) { |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1725 thread_local_.last_fp_ = 0; | 1727 thread_local_.last_fp_ = 0; |
1726 } | 1728 } |
1727 | 1729 |
1728 | 1730 |
1729 void Debug::PrepareForBreakPoints() { | 1731 void Debug::PrepareForBreakPoints() { |
1730 // If preparing for the first break point make sure to deoptimize all | 1732 // If preparing for the first break point make sure to deoptimize all |
1731 // functions as debugging does not work with optimized code. | 1733 // functions as debugging does not work with optimized code. |
1732 if (!has_break_points_) { | 1734 if (!has_break_points_) { |
1733 Deoptimizer::DeoptimizeAll(); | 1735 Deoptimizer::DeoptimizeAll(); |
1734 | 1736 |
| 1737 // We are going to iterate heap to find all functions without |
| 1738 // debug break slots. |
| 1739 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
| 1740 |
1735 AssertNoAllocation no_allocation; | 1741 AssertNoAllocation no_allocation; |
1736 Builtins* builtins = isolate_->builtins(); | 1742 Builtins* builtins = isolate_->builtins(); |
1737 Code* lazy_compile = builtins->builtin(Builtins::kLazyCompile); | 1743 Code* lazy_compile = builtins->builtin(Builtins::kLazyCompile); |
1738 | 1744 |
1739 // Find all non-optimized code functions with activation frames on | 1745 // Find all non-optimized code functions with activation frames on |
1740 // the stack. | 1746 // the stack. |
1741 List<JSFunction*> active_functions(100); | 1747 List<JSFunction*> active_functions(100); |
1742 for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) { | 1748 for (JavaScriptFrameIterator it(isolate_); !it.done(); it.Advance()) { |
1743 JavaScriptFrame* frame = it.frame(); | 1749 JavaScriptFrame* frame = it.frame(); |
1744 if (frame->function()->IsJSFunction()) { | 1750 if (frame->function()->IsJSFunction()) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1990 0, NULL, &caught_exception); | 1996 0, NULL, &caught_exception); |
1991 } | 1997 } |
1992 | 1998 |
1993 | 1999 |
1994 void Debug::CreateScriptCache() { | 2000 void Debug::CreateScriptCache() { |
1995 Heap* heap = isolate_->heap(); | 2001 Heap* heap = isolate_->heap(); |
1996 HandleScope scope(isolate_); | 2002 HandleScope scope(isolate_); |
1997 | 2003 |
1998 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | 2004 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
1999 // rid of all the cached script wrappers and the second gets rid of the | 2005 // rid of all the cached script wrappers and the second gets rid of the |
2000 // scripts which are no longer referenced. | 2006 // scripts which are no longer referenced. The second also sweeps precisely, |
2001 heap->CollectAllGarbage(false); | 2007 // which saves us doing yet another GC to make the heap iterable. |
2002 heap->CollectAllGarbage(false); | 2008 heap->CollectAllGarbage(Heap::kNoGCFlags); |
| 2009 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask); |
2003 | 2010 |
2004 ASSERT(script_cache_ == NULL); | 2011 ASSERT(script_cache_ == NULL); |
2005 script_cache_ = new ScriptCache(); | 2012 script_cache_ = new ScriptCache(); |
2006 | 2013 |
2007 // Scan heap for Script objects. | 2014 // Scan heap for Script objects. |
2008 int count = 0; | 2015 int count = 0; |
2009 HeapIterator iterator; | 2016 HeapIterator iterator; |
| 2017 AssertNoAllocation no_allocation; |
| 2018 |
2010 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 2019 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
2011 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | 2020 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { |
2012 script_cache_->Add(Handle<Script>(Script::cast(obj))); | 2021 script_cache_->Add(Handle<Script>(Script::cast(obj))); |
2013 count++; | 2022 count++; |
2014 } | 2023 } |
2015 } | 2024 } |
2016 } | 2025 } |
2017 | 2026 |
2018 | 2027 |
2019 void Debug::DestroyScriptCache() { | 2028 void Debug::DestroyScriptCache() { |
(...skipping 20 matching lines...) Expand all Loading... |
2040 } | 2049 } |
2041 | 2050 |
2042 // If the script cache is not active just return an empty array. | 2051 // If the script cache is not active just return an empty array. |
2043 ASSERT(script_cache_ != NULL); | 2052 ASSERT(script_cache_ != NULL); |
2044 if (script_cache_ == NULL) { | 2053 if (script_cache_ == NULL) { |
2045 isolate_->factory()->NewFixedArray(0); | 2054 isolate_->factory()->NewFixedArray(0); |
2046 } | 2055 } |
2047 | 2056 |
2048 // Perform GC to get unreferenced scripts evicted from the cache before | 2057 // Perform GC to get unreferenced scripts evicted from the cache before |
2049 // returning the content. | 2058 // returning the content. |
2050 isolate_->heap()->CollectAllGarbage(false); | 2059 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags); |
2051 | 2060 |
2052 // Get the scripts from the cache. | 2061 // Get the scripts from the cache. |
2053 return script_cache_->GetScripts(); | 2062 return script_cache_->GetScripts(); |
2054 } | 2063 } |
2055 | 2064 |
2056 | 2065 |
2057 void Debug::AfterGarbageCollection() { | 2066 void Debug::AfterGarbageCollection() { |
2058 // Generate events for collected scripts. | 2067 // Generate events for collected scripts. |
2059 if (script_cache_ != NULL) { | 2068 if (script_cache_ != NULL) { |
2060 script_cache_->ProcessCollectedScripts(); | 2069 script_cache_->ProcessCollectedScripts(); |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2338 if (!update_script_break_points->IsJSFunction()) { | 2347 if (!update_script_break_points->IsJSFunction()) { |
2339 return; | 2348 return; |
2340 } | 2349 } |
2341 ASSERT(update_script_break_points->IsJSFunction()); | 2350 ASSERT(update_script_break_points->IsJSFunction()); |
2342 | 2351 |
2343 // Wrap the script object in a proper JS object before passing it | 2352 // Wrap the script object in a proper JS object before passing it |
2344 // to JavaScript. | 2353 // to JavaScript. |
2345 Handle<JSValue> wrapper = GetScriptWrapper(script); | 2354 Handle<JSValue> wrapper = GetScriptWrapper(script); |
2346 | 2355 |
2347 // Call UpdateScriptBreakPoints expect no exceptions. | 2356 // Call UpdateScriptBreakPoints expect no exceptions. |
2348 bool caught_exception = false; | 2357 bool caught_exception; |
2349 const int argc = 1; | 2358 const int argc = 1; |
2350 Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) }; | 2359 Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) }; |
2351 Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), | 2360 Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), |
2352 Isolate::Current()->js_builtins_object(), argc, argv, | 2361 Isolate::Current()->js_builtins_object(), argc, argv, |
2353 &caught_exception); | 2362 &caught_exception); |
2354 if (caught_exception) { | 2363 if (caught_exception) { |
2355 return; | 2364 return; |
2356 } | 2365 } |
2357 // Bail out based on state or if there is no listener for this event | 2366 // Bail out based on state or if there is no listener for this event |
2358 if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return; | 2367 if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2479 Handle<Object> event_data) { | 2488 Handle<Object> event_data) { |
2480 ASSERT(event_listener_->IsJSFunction()); | 2489 ASSERT(event_listener_->IsJSFunction()); |
2481 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); | 2490 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); |
2482 | 2491 |
2483 // Invoke the JavaScript debug event listener. | 2492 // Invoke the JavaScript debug event listener. |
2484 const int argc = 4; | 2493 const int argc = 4; |
2485 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), | 2494 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), |
2486 exec_state.location(), | 2495 exec_state.location(), |
2487 Handle<Object>::cast(event_data).location(), | 2496 Handle<Object>::cast(event_data).location(), |
2488 event_listener_data_.location() }; | 2497 event_listener_data_.location() }; |
2489 bool caught_exception = false; | 2498 bool caught_exception; |
2490 Execution::TryCall(fun, isolate_->global(), argc, argv, &caught_exception); | 2499 Execution::TryCall(fun, isolate_->global(), argc, argv, &caught_exception); |
2491 // Silently ignore exceptions from debug event listeners. | 2500 // Silently ignore exceptions from debug event listeners. |
2492 } | 2501 } |
2493 | 2502 |
2494 | 2503 |
2495 Handle<Context> Debugger::GetDebugContext() { | 2504 Handle<Context> Debugger::GetDebugContext() { |
2496 never_unload_debugger_ = true; | 2505 never_unload_debugger_ = true; |
2497 EnterDebugger debugger; | 2506 EnterDebugger debugger; |
2498 return isolate_->debug()->debug_context(); | 2507 return isolate_->debug()->debug_context(); |
2499 } | 2508 } |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2922 { | 2931 { |
2923 ScopedLock with(dispatch_handler_access_); | 2932 ScopedLock with(dispatch_handler_access_); |
2924 handler = Debugger::debug_message_dispatch_handler_; | 2933 handler = Debugger::debug_message_dispatch_handler_; |
2925 } | 2934 } |
2926 if (handler != NULL) { | 2935 if (handler != NULL) { |
2927 handler(); | 2936 handler(); |
2928 } | 2937 } |
2929 } | 2938 } |
2930 | 2939 |
2931 | 2940 |
| 2941 EnterDebugger::EnterDebugger() |
| 2942 : isolate_(Isolate::Current()), |
| 2943 prev_(isolate_->debug()->debugger_entry()), |
| 2944 it_(isolate_), |
| 2945 has_js_frames_(!it_.done()), |
| 2946 save_(isolate_) { |
| 2947 Debug* debug = isolate_->debug(); |
| 2948 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT)); |
| 2949 ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK)); |
| 2950 |
| 2951 // Link recursive debugger entry. |
| 2952 debug->set_debugger_entry(this); |
| 2953 |
| 2954 // Store the previous break id and frame id. |
| 2955 break_id_ = debug->break_id(); |
| 2956 break_frame_id_ = debug->break_frame_id(); |
| 2957 |
| 2958 // Create the new break info. If there is no JavaScript frames there is no |
| 2959 // break frame id. |
| 2960 if (has_js_frames_) { |
| 2961 debug->NewBreak(it_.frame()->id()); |
| 2962 } else { |
| 2963 debug->NewBreak(StackFrame::NO_ID); |
| 2964 } |
| 2965 |
| 2966 // Make sure that debugger is loaded and enter the debugger context. |
| 2967 load_failed_ = !debug->Load(); |
| 2968 if (!load_failed_) { |
| 2969 // NOTE the member variable save which saves the previous context before |
| 2970 // this change. |
| 2971 isolate_->set_context(*debug->debug_context()); |
| 2972 } |
| 2973 } |
| 2974 |
| 2975 |
| 2976 EnterDebugger::~EnterDebugger() { |
| 2977 ASSERT(Isolate::Current() == isolate_); |
| 2978 Debug* debug = isolate_->debug(); |
| 2979 |
| 2980 // Restore to the previous break state. |
| 2981 debug->SetBreak(break_frame_id_, break_id_); |
| 2982 |
| 2983 // Check for leaving the debugger. |
| 2984 if (prev_ == NULL) { |
| 2985 // Clear mirror cache when leaving the debugger. Skip this if there is a |
| 2986 // pending exception as clearing the mirror cache calls back into |
| 2987 // JavaScript. This can happen if the v8::Debug::Call is used in which |
| 2988 // case the exception should end up in the calling code. |
| 2989 if (!isolate_->has_pending_exception()) { |
| 2990 // Try to avoid any pending debug break breaking in the clear mirror |
| 2991 // cache JavaScript code. |
| 2992 if (isolate_->stack_guard()->IsDebugBreak()) { |
| 2993 debug->set_interrupts_pending(DEBUGBREAK); |
| 2994 isolate_->stack_guard()->Continue(DEBUGBREAK); |
| 2995 } |
| 2996 debug->ClearMirrorCache(); |
| 2997 } |
| 2998 |
| 2999 // Request preemption and debug break when leaving the last debugger entry |
| 3000 // if any of these where recorded while debugging. |
| 3001 if (debug->is_interrupt_pending(PREEMPT)) { |
| 3002 // This re-scheduling of preemption is to avoid starvation in some |
| 3003 // debugging scenarios. |
| 3004 debug->clear_interrupt_pending(PREEMPT); |
| 3005 isolate_->stack_guard()->Preempt(); |
| 3006 } |
| 3007 if (debug->is_interrupt_pending(DEBUGBREAK)) { |
| 3008 debug->clear_interrupt_pending(DEBUGBREAK); |
| 3009 isolate_->stack_guard()->DebugBreak(); |
| 3010 } |
| 3011 |
| 3012 // If there are commands in the queue when leaving the debugger request |
| 3013 // that these commands are processed. |
| 3014 if (isolate_->debugger()->HasCommands()) { |
| 3015 isolate_->stack_guard()->DebugCommand(); |
| 3016 } |
| 3017 |
| 3018 // If leaving the debugger with the debugger no longer active unload it. |
| 3019 if (!isolate_->debugger()->IsDebuggerActive()) { |
| 3020 isolate_->debugger()->UnloadDebugger(); |
| 3021 } |
| 3022 } |
| 3023 |
| 3024 // Leaving this debugger entry. |
| 3025 debug->set_debugger_entry(prev_); |
| 3026 } |
| 3027 |
| 3028 |
2932 MessageImpl MessageImpl::NewEvent(DebugEvent event, | 3029 MessageImpl MessageImpl::NewEvent(DebugEvent event, |
2933 bool running, | 3030 bool running, |
2934 Handle<JSObject> exec_state, | 3031 Handle<JSObject> exec_state, |
2935 Handle<JSObject> event_data) { | 3032 Handle<JSObject> event_data) { |
2936 MessageImpl message(true, event, running, | 3033 MessageImpl message(true, event, running, |
2937 exec_state, event_data, Handle<String>(), NULL); | 3034 exec_state, event_data, Handle<String>(), NULL); |
2938 return message; | 3035 return message; |
2939 } | 3036 } |
2940 | 3037 |
2941 | 3038 |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3224 { | 3321 { |
3225 Locker locker; | 3322 Locker locker; |
3226 Isolate::Current()->debugger()->CallMessageDispatchHandler(); | 3323 Isolate::Current()->debugger()->CallMessageDispatchHandler(); |
3227 } | 3324 } |
3228 } | 3325 } |
3229 } | 3326 } |
3230 | 3327 |
3231 #endif // ENABLE_DEBUGGER_SUPPORT | 3328 #endif // ENABLE_DEBUGGER_SUPPORT |
3232 | 3329 |
3233 } } // namespace v8::internal | 3330 } } // namespace v8::internal |
OLD | NEW |