| 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 "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 585 return storage + ArchiveSpacePerThread(); | 585 return storage + ArchiveSpacePerThread(); |
| 586 } | 586 } |
| 587 | 587 |
| 588 | 588 |
| 589 int Debug::ArchiveSpacePerThread() { | 589 int Debug::ArchiveSpacePerThread() { |
| 590 return sizeof(ThreadLocal); | 590 return sizeof(ThreadLocal); |
| 591 } | 591 } |
| 592 | 592 |
| 593 | 593 |
| 594 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), | 594 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), |
| 595 isolate_(isolate), | 595 isolate_(isolate) { |
| 596 collected_scripts_(10) { | |
| 597 Heap* heap = isolate_->heap(); | 596 Heap* heap = isolate_->heap(); |
| 598 HandleScope scope(isolate_); | 597 HandleScope scope(isolate_); |
| 599 | 598 |
| 600 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | 599 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
| 601 // rid of all the cached script wrappers and the second gets rid of the | 600 // rid of all the cached script wrappers and the second gets rid of the |
| 602 // scripts which are no longer referenced. | 601 // scripts which are no longer referenced. |
| 603 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); | 602 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
| 604 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); | 603 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
| 605 | 604 |
| 606 // Scan heap for Script objects. | 605 // Scan heap for Script objects. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 ASSERT(entry->value != NULL); | 643 ASSERT(entry->value != NULL); |
| 645 if (entry->value != NULL) { | 644 if (entry->value != NULL) { |
| 646 instances->set(count, *reinterpret_cast<Script**>(entry->value)); | 645 instances->set(count, *reinterpret_cast<Script**>(entry->value)); |
| 647 count++; | 646 count++; |
| 648 } | 647 } |
| 649 } | 648 } |
| 650 return instances; | 649 return instances; |
| 651 } | 650 } |
| 652 | 651 |
| 653 | 652 |
| 654 void ScriptCache::ProcessCollectedScripts() { | |
| 655 Debug* debug = isolate_->debug(); | |
| 656 for (int i = 0; i < collected_scripts_.length(); i++) { | |
| 657 debug->OnScriptCollected(collected_scripts_[i]); | |
| 658 } | |
| 659 collected_scripts_.Clear(); | |
| 660 } | |
| 661 | |
| 662 | |
| 663 void ScriptCache::Clear() { | 653 void ScriptCache::Clear() { |
| 664 // Iterate the script cache to get rid of all the weak handles. | 654 // Iterate the script cache to get rid of all the weak handles. |
| 665 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { | 655 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { |
| 666 ASSERT(entry != NULL); | 656 ASSERT(entry != NULL); |
| 667 Object** location = reinterpret_cast<Object**>(entry->value); | 657 Object** location = reinterpret_cast<Object**>(entry->value); |
| 668 ASSERT((*location)->IsScript()); | 658 ASSERT((*location)->IsScript()); |
| 669 GlobalHandles::ClearWeakness(location); | 659 GlobalHandles::ClearWeakness(location); |
| 670 GlobalHandles::Destroy(location); | 660 GlobalHandles::Destroy(location); |
| 671 } | 661 } |
| 672 // Clear the content of the hash map. | 662 // Clear the content of the hash map. |
| 673 HashMap::Clear(); | 663 HashMap::Clear(); |
| 674 } | 664 } |
| 675 | 665 |
| 676 | 666 |
| 677 void ScriptCache::HandleWeakScript( | 667 void ScriptCache::HandleWeakScript( |
| 678 const v8::WeakCallbackData<v8::Value, void>& data) { | 668 const v8::WeakCallbackData<v8::Value, void>& data) { |
| 679 // Retrieve the script identifier. | 669 // Retrieve the script identifier. |
| 680 Handle<Object> object = Utils::OpenHandle(*data.GetValue()); | 670 Handle<Object> object = Utils::OpenHandle(*data.GetValue()); |
| 681 int id = Handle<Script>::cast(object)->id()->value(); | 671 int id = Handle<Script>::cast(object)->id()->value(); |
| 682 void* key = reinterpret_cast<void*>(id); | 672 void* key = reinterpret_cast<void*>(id); |
| 683 uint32_t hash = Hash(id); | 673 uint32_t hash = Hash(id); |
| 684 | 674 |
| 685 // Remove the corresponding entry from the cache. | 675 // Remove the corresponding entry from the cache. |
| 686 ScriptCache* script_cache = | 676 ScriptCache* script_cache = |
| 687 reinterpret_cast<ScriptCache*>(data.GetParameter()); | 677 reinterpret_cast<ScriptCache*>(data.GetParameter()); |
| 688 HashMap::Entry* entry = script_cache->Lookup(key, hash, false); | 678 HashMap::Entry* entry = script_cache->Lookup(key, hash, false); |
| 689 Object** location = reinterpret_cast<Object**>(entry->value); | 679 Object** location = reinterpret_cast<Object**>(entry->value); |
| 690 script_cache->Remove(key, hash); | 680 script_cache->Remove(key, hash); |
| 691 script_cache->collected_scripts_.Add(id); | |
| 692 | 681 |
| 693 // Clear the weak handle. | 682 // Clear the weak handle. |
| 694 GlobalHandles::Destroy(location); | 683 GlobalHandles::Destroy(location); |
| 695 } | 684 } |
| 696 | 685 |
| 697 | 686 |
| 698 void Debug::HandleWeakDebugInfo( | 687 void Debug::HandleWeakDebugInfo( |
| 699 const v8::WeakCallbackData<v8::Value, void>& data) { | 688 const v8::WeakCallbackData<v8::Value, void>& data) { |
| 700 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); | 689 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); |
| 701 DebugInfoListNode* node = | 690 DebugInfoListNode* node = |
| (...skipping 1791 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2493 if (!it.done()) { | 2482 if (!it.done()) { |
| 2494 script->set_eval_from_shared(it.frame()->function()->shared()); | 2483 script->set_eval_from_shared(it.frame()->function()->shared()); |
| 2495 Code* code = it.frame()->LookupCode(); | 2484 Code* code = it.frame()->LookupCode(); |
| 2496 int offset = static_cast<int>( | 2485 int offset = static_cast<int>( |
| 2497 it.frame()->pc() - code->instruction_start()); | 2486 it.frame()->pc() - code->instruction_start()); |
| 2498 script->set_eval_from_instructions_offset(Smi::FromInt(offset)); | 2487 script->set_eval_from_instructions_offset(Smi::FromInt(offset)); |
| 2499 } | 2488 } |
| 2500 } | 2489 } |
| 2501 | 2490 |
| 2502 | 2491 |
| 2503 void Debug::AfterGarbageCollection() { | |
| 2504 // Generate events for collected scripts. | |
| 2505 if (script_cache_ != NULL) { | |
| 2506 script_cache_->ProcessCollectedScripts(); | |
| 2507 } | |
| 2508 } | |
| 2509 | |
| 2510 | |
| 2511 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, | 2492 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, |
| 2512 int argc, | 2493 int argc, |
| 2513 Handle<Object> argv[]) { | 2494 Handle<Object> argv[]) { |
| 2514 AssertDebugContext(); | 2495 AssertDebugContext(); |
| 2515 // Create the execution state object. | 2496 // Create the execution state object. |
| 2516 Handle<Object> constructor = Object::GetProperty( | 2497 Handle<Object> constructor = Object::GetProperty( |
| 2517 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked(); | 2498 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked(); |
| 2518 ASSERT(constructor->IsJSFunction()); | 2499 ASSERT(constructor->IsJSFunction()); |
| 2519 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); | 2500 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); |
| 2520 // We do not handle interrupts here. In particular, termination interrupts. | 2501 // We do not handle interrupts here. In particular, termination interrupts. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2556 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, | 2537 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, |
| 2557 v8::DebugEvent type) { | 2538 v8::DebugEvent type) { |
| 2558 // Create the compile event object. | 2539 // Create the compile event object. |
| 2559 Handle<Object> script_wrapper = Script::GetWrapper(script); | 2540 Handle<Object> script_wrapper = Script::GetWrapper(script); |
| 2560 Handle<Object> argv[] = { script_wrapper, | 2541 Handle<Object> argv[] = { script_wrapper, |
| 2561 isolate_->factory()->NewNumberFromInt(type) }; | 2542 isolate_->factory()->NewNumberFromInt(type) }; |
| 2562 return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv); | 2543 return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv); |
| 2563 } | 2544 } |
| 2564 | 2545 |
| 2565 | 2546 |
| 2566 MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) { | |
| 2567 // Create the script collected event object. | |
| 2568 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | |
| 2569 Handle<Object> argv[] = { id_object }; | |
| 2570 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); | |
| 2571 } | |
| 2572 | |
| 2573 | |
| 2574 void Debug::OnException(Handle<Object> exception, bool uncaught) { | 2547 void Debug::OnException(Handle<Object> exception, bool uncaught) { |
| 2575 if (in_debug_scope() || ignore_events()) return; | 2548 if (in_debug_scope() || ignore_events()) return; |
| 2576 | 2549 |
| 2577 HandleScope scope(isolate_); | 2550 HandleScope scope(isolate_); |
| 2578 Handle<Object> promise = GetPromiseForUncaughtException(); | 2551 Handle<Object> promise = GetPromiseForUncaughtException(); |
| 2579 uncaught |= !promise->IsUndefined(); | 2552 uncaught |= !promise->IsUndefined(); |
| 2580 | 2553 |
| 2581 // Bail out if exception breaks are not active | 2554 // Bail out if exception breaks are not active |
| 2582 if (uncaught) { | 2555 if (uncaught) { |
| 2583 // Uncaught exceptions are reported by either flags. | 2556 // Uncaught exceptions are reported by either flags. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2709 // Create the compile state object. | 2682 // Create the compile state object. |
| 2710 Handle<Object> event_data; | 2683 Handle<Object> event_data; |
| 2711 // Bail out and don't call debugger if exception. | 2684 // Bail out and don't call debugger if exception. |
| 2712 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return; | 2685 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return; |
| 2713 | 2686 |
| 2714 // Process debug event. | 2687 // Process debug event. |
| 2715 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2688 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
| 2716 } | 2689 } |
| 2717 | 2690 |
| 2718 | 2691 |
| 2719 void Debug::OnScriptCollected(int id) { | |
| 2720 if (in_debug_scope() || ignore_events()) return; | |
| 2721 | |
| 2722 HandleScope scope(isolate_); | |
| 2723 DebugScope debug_scope(this); | |
| 2724 if (debug_scope.failed()) return; | |
| 2725 | |
| 2726 // Create the script collected state object. | |
| 2727 Handle<Object> event_data; | |
| 2728 // Bail out and don't call debugger if exception. | |
| 2729 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; | |
| 2730 | |
| 2731 // Process debug event. | |
| 2732 ProcessDebugEvent(v8::ScriptCollected, | |
| 2733 Handle<JSObject>::cast(event_data), | |
| 2734 true); | |
| 2735 } | |
| 2736 | |
| 2737 | |
| 2738 void Debug::ProcessDebugEvent(v8::DebugEvent event, | 2692 void Debug::ProcessDebugEvent(v8::DebugEvent event, |
| 2739 Handle<JSObject> event_data, | 2693 Handle<JSObject> event_data, |
| 2740 bool auto_continue) { | 2694 bool auto_continue) { |
| 2741 HandleScope scope(isolate_); | 2695 HandleScope scope(isolate_); |
| 2742 | 2696 |
| 2743 // Create the execution state. | 2697 // Create the execution state. |
| 2744 Handle<Object> exec_state; | 2698 Handle<Object> exec_state; |
| 2745 // Bail out and don't call debugger if exception. | 2699 // Bail out and don't call debugger if exception. |
| 2746 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 2700 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
| 2747 | 2701 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2829 sendEventMessage = !auto_continue; | 2783 sendEventMessage = !auto_continue; |
| 2830 break; | 2784 break; |
| 2831 case v8::Exception: | 2785 case v8::Exception: |
| 2832 sendEventMessage = true; | 2786 sendEventMessage = true; |
| 2833 break; | 2787 break; |
| 2834 case v8::BeforeCompile: | 2788 case v8::BeforeCompile: |
| 2835 break; | 2789 break; |
| 2836 case v8::AfterCompile: | 2790 case v8::AfterCompile: |
| 2837 sendEventMessage = true; | 2791 sendEventMessage = true; |
| 2838 break; | 2792 break; |
| 2839 case v8::ScriptCollected: | |
| 2840 sendEventMessage = true; | |
| 2841 break; | |
| 2842 case v8::NewFunction: | 2793 case v8::NewFunction: |
| 2843 break; | 2794 break; |
| 2844 default: | 2795 default: |
| 2845 UNREACHABLE(); | 2796 UNREACHABLE(); |
| 2846 } | 2797 } |
| 2847 | 2798 |
| 2848 // The debug command interrupt flag might have been set when the command was | 2799 // The debug command interrupt flag might have been set when the command was |
| 2849 // added. It should be enough to clear the flag only once while we are in the | 2800 // added. It should be enough to clear the flag only once while we are in the |
| 2850 // debugger. | 2801 // debugger. |
| 2851 ASSERT(in_debug_scope()); | 2802 ASSERT(in_debug_scope()); |
| 2852 isolate_->stack_guard()->ClearDebugCommand(); | 2803 isolate_->stack_guard()->ClearDebugCommand(); |
| 2853 | 2804 |
| 2854 // Notify the debugger that a debug event has occurred unless auto continue is | 2805 // Notify the debugger that a debug event has occurred unless auto continue is |
| 2855 // active in which case no event is send. | 2806 // active in which case no event is send. |
| 2856 if (sendEventMessage) { | 2807 if (sendEventMessage) { |
| 2857 MessageImpl message = MessageImpl::NewEvent( | 2808 MessageImpl message = MessageImpl::NewEvent( |
| 2858 event, | 2809 event, |
| 2859 auto_continue, | 2810 auto_continue, |
| 2860 Handle<JSObject>::cast(exec_state), | 2811 Handle<JSObject>::cast(exec_state), |
| 2861 Handle<JSObject>::cast(event_data)); | 2812 Handle<JSObject>::cast(event_data)); |
| 2862 InvokeMessageHandler(message); | 2813 InvokeMessageHandler(message); |
| 2863 } | 2814 } |
| 2864 | 2815 |
| 2865 // If auto continue don't make the event cause a break, but process messages | 2816 // If auto continue don't make the event cause a break, but process messages |
| 2866 // in the queue if any. For script collected events don't even process | 2817 // in the queue if any. For script collected events don't even process |
| 2867 // messages in the queue as the execution state might not be what is expected | 2818 // messages in the queue as the execution state might not be what is expected |
| 2868 // by the client. | 2819 // by the client. |
| 2869 if ((auto_continue && !has_commands()) || event == v8::ScriptCollected) { | 2820 if (auto_continue && !has_commands()) return; |
| 2870 return; | |
| 2871 } | |
| 2872 | 2821 |
| 2873 // DebugCommandProcessor goes here. | 2822 // DebugCommandProcessor goes here. |
| 2874 bool running = auto_continue; | 2823 bool running = auto_continue; |
| 2875 | 2824 |
| 2876 Handle<Object> cmd_processor_ctor = Object::GetProperty( | 2825 Handle<Object> cmd_processor_ctor = Object::GetProperty( |
| 2877 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked(); | 2826 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked(); |
| 2878 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; | 2827 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; |
| 2879 Handle<Object> cmd_processor = Execution::Call( | 2828 Handle<Object> cmd_processor = Execution::Call( |
| 2880 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked(); | 2829 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked(); |
| 2881 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast( | 2830 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast( |
| (...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3244 } else { | 3193 } else { |
| 3245 return v8::Utils::ToLocal(response_json_); | 3194 return v8::Utils::ToLocal(response_json_); |
| 3246 } | 3195 } |
| 3247 } | 3196 } |
| 3248 | 3197 |
| 3249 | 3198 |
| 3250 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { | 3199 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { |
| 3251 Isolate* isolate = event_data_->GetIsolate(); | 3200 Isolate* isolate = event_data_->GetIsolate(); |
| 3252 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); | 3201 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); |
| 3253 // Isolate::context() may be NULL when "script collected" event occures. | 3202 // Isolate::context() may be NULL when "script collected" event occures. |
| 3254 ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected); | 3203 ASSERT(!context.IsEmpty()); |
| 3255 return context; | 3204 return context; |
| 3256 } | 3205 } |
| 3257 | 3206 |
| 3258 | 3207 |
| 3259 v8::Debug::ClientData* MessageImpl::GetClientData() const { | 3208 v8::Debug::ClientData* MessageImpl::GetClientData() const { |
| 3260 return client_data_; | 3209 return client_data_; |
| 3261 } | 3210 } |
| 3262 | 3211 |
| 3263 | 3212 |
| 3264 EventDetailsImpl::EventDetailsImpl(DebugEvent event, | 3213 EventDetailsImpl::EventDetailsImpl(DebugEvent event, |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3395 logger_->DebugEvent("Put", message.text()); | 3344 logger_->DebugEvent("Put", message.text()); |
| 3396 } | 3345 } |
| 3397 | 3346 |
| 3398 | 3347 |
| 3399 void LockingCommandMessageQueue::Clear() { | 3348 void LockingCommandMessageQueue::Clear() { |
| 3400 LockGuard<Mutex> lock_guard(&mutex_); | 3349 LockGuard<Mutex> lock_guard(&mutex_); |
| 3401 queue_.Clear(); | 3350 queue_.Clear(); |
| 3402 } | 3351 } |
| 3403 | 3352 |
| 3404 } } // namespace v8::internal | 3353 } } // namespace v8::internal |
| OLD | NEW |