OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
496 reloc_iterator_->next(); | 496 reloc_iterator_->next(); |
497 reloc_iterator_original_->next(); | 497 reloc_iterator_original_->next(); |
498 #ifdef DEBUG | 498 #ifdef DEBUG |
499 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); | 499 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); |
500 if (!reloc_iterator_->done()) { | 500 if (!reloc_iterator_->done()) { |
501 ASSERT(rmode() == original_rmode()); | 501 ASSERT(rmode() == original_rmode()); |
502 } | 502 } |
503 #endif | 503 #endif |
504 } | 504 } |
505 | 505 |
506 | 506 DebugData::DebugData() |
507 bool Debug::has_break_points_ = false; | 507 :has_break_points_(false), |
508 ScriptCache* Debug::script_cache_ = NULL; | 508 script_cache_(NULL), |
509 DebugInfoListNode* Debug::debug_info_list_ = NULL; | 509 debug_info_list_(NULL), |
510 | 510 disable_break_(false), |
| 511 break_on_exception_(false), |
| 512 break_on_uncaught_exception_(true), |
| 513 debug_context_(Handle<Context>()), |
| 514 debug_break_return_(NULL) { |
| 515 } |
511 | 516 |
512 // Threading support. | 517 // Threading support. |
513 void Debug::ThreadInit() { | 518 void Debug::ThreadInit() { |
514 thread_local_.break_count_ = 0; | 519 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
515 thread_local_.break_id_ = 0; | 520 thread_local.break_count_ = 0; |
516 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 521 thread_local.break_id_ = 0; |
517 thread_local_.last_step_action_ = StepNone; | 522 thread_local.break_frame_id_ = StackFrame::NO_ID; |
518 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 523 thread_local.last_step_action_ = StepNone; |
519 thread_local_.step_count_ = 0; | 524 thread_local.last_statement_position_ = RelocInfo::kNoPosition; |
520 thread_local_.last_fp_ = 0; | 525 thread_local.step_count_ = 0; |
521 thread_local_.step_into_fp_ = 0; | 526 thread_local.last_fp_ = 0; |
522 thread_local_.step_out_fp_ = 0; | 527 thread_local.step_into_fp_ = 0; |
523 thread_local_.after_break_target_ = 0; | 528 thread_local.step_out_fp_ = 0; |
524 thread_local_.debugger_entry_ = NULL; | 529 thread_local.after_break_target_ = 0; |
525 thread_local_.pending_interrupts_ = 0; | 530 thread_local.debugger_entry_ = NULL; |
| 531 thread_local.pending_interrupts_ = 0; |
526 } | 532 } |
527 | 533 |
528 | |
529 JSCallerSavedBuffer Debug::registers_; | |
530 Debug::ThreadLocal Debug::thread_local_; | |
531 | |
532 | |
533 char* Debug::ArchiveDebug(char* storage) { | 534 char* Debug::ArchiveDebug(char* storage) { |
534 char* to = storage; | 535 char* to = storage; |
535 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 536 DebugData& data = v8_context()->debug_data_; |
| 537 memcpy(to, reinterpret_cast<char*>(&data.thread_local_), |
| 538 sizeof(ThreadLocal)); |
536 to += sizeof(ThreadLocal); | 539 to += sizeof(ThreadLocal); |
537 memcpy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_)); | 540 memcpy(to, reinterpret_cast<char*>(&data.registers_), |
| 541 sizeof(JSCallerSavedBuffer)); |
538 ThreadInit(); | 542 ThreadInit(); |
539 ASSERT(to <= storage + ArchiveSpacePerThread()); | 543 ASSERT(to <= storage + ArchiveSpacePerThread()); |
540 return storage + ArchiveSpacePerThread(); | 544 return storage + ArchiveSpacePerThread(); |
541 } | 545 } |
542 | 546 |
543 | 547 |
544 char* Debug::RestoreDebug(char* storage) { | 548 char* Debug::RestoreDebug(char* storage) { |
545 char* from = storage; | 549 char* from = storage; |
546 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); | 550 DebugData& data = v8_context()->debug_data_; |
| 551 memcpy(reinterpret_cast<char*>(&data.thread_local_), from, |
| 552 sizeof(ThreadLocal)); |
547 from += sizeof(ThreadLocal); | 553 from += sizeof(ThreadLocal); |
548 memcpy(reinterpret_cast<char*>(®isters_), from, sizeof(registers_)); | 554 memcpy(reinterpret_cast<char*>(&data.registers_), from, |
| 555 sizeof(JSCallerSavedBuffer)); |
549 ASSERT(from <= storage + ArchiveSpacePerThread()); | 556 ASSERT(from <= storage + ArchiveSpacePerThread()); |
550 return storage + ArchiveSpacePerThread(); | 557 return storage + ArchiveSpacePerThread(); |
551 } | 558 } |
552 | 559 |
553 | 560 |
554 int Debug::ArchiveSpacePerThread() { | 561 int Debug::ArchiveSpacePerThread() { |
555 return sizeof(ThreadLocal) + sizeof(registers_); | 562 return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer); |
556 } | 563 } |
557 | 564 |
558 | |
559 // Default break enabled. | |
560 bool Debug::disable_break_ = false; | |
561 | |
562 // Default call debugger on uncaught exception. | |
563 bool Debug::break_on_exception_ = false; | |
564 bool Debug::break_on_uncaught_exception_ = true; | |
565 | |
566 Handle<Context> Debug::debug_context_ = Handle<Context>(); | |
567 Code* Debug::debug_break_return_ = NULL; | |
568 | |
569 | |
570 void ScriptCache::Add(Handle<Script> script) { | 565 void ScriptCache::Add(Handle<Script> script) { |
571 // Create an entry in the hash map for the script. | 566 // Create an entry in the hash map for the script. |
572 int id = Smi::cast(script->id())->value(); | 567 int id = Smi::cast(script->id())->value(); |
573 HashMap::Entry* entry = | 568 HashMap::Entry* entry = |
574 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); | 569 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); |
575 if (entry->value != NULL) { | 570 if (entry->value != NULL) { |
576 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); | 571 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); |
577 return; | 572 return; |
578 } | 573 } |
579 | 574 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 | 632 |
638 // Clear the weak handle. | 633 // Clear the weak handle. |
639 obj.Dispose(); | 634 obj.Dispose(); |
640 obj.Clear(); | 635 obj.Clear(); |
641 } | 636 } |
642 | 637 |
643 | 638 |
644 void Debug::Setup(bool create_heap_objects) { | 639 void Debug::Setup(bool create_heap_objects) { |
645 ThreadInit(); | 640 ThreadInit(); |
646 if (create_heap_objects) { | 641 if (create_heap_objects) { |
| 642 DebugData& data = v8_context()->debug_data_; |
647 // Get code to handle debug break on return. | 643 // Get code to handle debug break on return. |
648 debug_break_return_ = | 644 data.debug_break_return_ = |
649 Builtins::builtin(Builtins::Return_DebugBreak); | 645 Builtins::builtin(Builtins::Return_DebugBreak); |
650 ASSERT(debug_break_return_->IsCode()); | 646 ASSERT(data.debug_break_return_->IsCode()); |
651 } | 647 } |
652 } | 648 } |
653 | 649 |
654 | 650 |
655 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { | 651 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { |
656 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); | 652 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); |
657 RemoveDebugInfo(node->debug_info()); | 653 RemoveDebugInfo(node->debug_info()); |
658 #ifdef DEBUG | 654 #ifdef DEBUG |
659 node = Debug::debug_info_list_; | 655 node = v8_context()->debug_data_.debug_info_list_; |
660 while (node != NULL) { | 656 while (node != NULL) { |
661 ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data)); | 657 ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data)); |
662 node = node->next(); | 658 node = node->next(); |
663 } | 659 } |
664 #endif | 660 #endif |
665 } | 661 } |
666 | 662 |
667 | 663 |
668 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 664 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
669 // Globalize the request debug info object and make it weak. | 665 // Globalize the request debug info object and make it weak. |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 Debugger::set_compiling_natives(false); | 765 Debugger::set_compiling_natives(false); |
770 | 766 |
771 // Make sure we mark the debugger as not loading before we might | 767 // Make sure we mark the debugger as not loading before we might |
772 // return. | 768 // return. |
773 Debugger::set_loading_debugger(false); | 769 Debugger::set_loading_debugger(false); |
774 | 770 |
775 // Check for caught exceptions. | 771 // Check for caught exceptions. |
776 if (caught_exception) return false; | 772 if (caught_exception) return false; |
777 | 773 |
778 // Debugger loaded. | 774 // Debugger loaded. |
779 debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context)); | 775 v8_context()->debug_data_.debug_context_ = |
| 776 Handle<Context>::cast(GlobalHandles::Create(*context)); |
780 | 777 |
781 return true; | 778 return true; |
782 } | 779 } |
783 | 780 |
784 | 781 |
785 void Debug::Unload() { | 782 void Debug::Unload() { |
786 // Return debugger is not loaded. | 783 // Return debugger is not loaded. |
787 if (!IsLoaded()) { | 784 if (!IsLoaded()) { |
788 return; | 785 return; |
789 } | 786 } |
790 | 787 |
791 // Clear the script cache. | 788 // Clear the script cache. |
792 DestroyScriptCache(); | 789 DestroyScriptCache(); |
793 | 790 |
| 791 DebugData& data = v8_context()->debug_data_; |
794 // Clear debugger context global handle. | 792 // Clear debugger context global handle. |
795 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location())); | 793 GlobalHandles::Destroy( |
796 debug_context_ = Handle<Context>(); | 794 reinterpret_cast<Object**>(data.debug_context_.location())); |
| 795 data.debug_context_ = Handle<Context>(); |
797 } | 796 } |
798 | 797 |
799 | 798 |
800 // Set the flag indicating that preemption happened during debugging. | 799 // Set the flag indicating that preemption happened during debugging. |
801 void Debug::PreemptionWhileInDebugger() { | 800 void Debug::PreemptionWhileInDebugger() { |
802 ASSERT(InDebugger()); | 801 ASSERT(InDebugger()); |
803 Debug::set_interrupts_pending(PREEMPT); | 802 Debug::set_interrupts_pending(PREEMPT); |
804 } | 803 } |
805 | 804 |
806 | 805 |
807 void Debug::Iterate(ObjectVisitor* v) { | 806 void Debug::Iterate(ObjectVisitor* v) { |
808 v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_))); | 807 v->VisitPointer(bit_cast<Object**, Code**>( |
| 808 &(v8_context()->debug_data_.debug_break_return_))); |
809 } | 809 } |
810 | 810 |
811 | 811 |
812 Object* Debug::Break(Arguments args) { | 812 Object* Debug::Break(Arguments args) { |
813 HandleScope scope; | 813 HandleScope scope; |
814 ASSERT(args.length() == 0); | 814 ASSERT(args.length() == 0); |
815 | 815 |
816 // Get the top-most JavaScript frame. | 816 // Get the top-most JavaScript frame. |
817 JavaScriptFrameIterator it; | 817 JavaScriptFrameIterator it; |
818 JavaScriptFrame* frame = it.frame(); | 818 JavaScriptFrame* frame = it.frame(); |
(...skipping 15 matching lines...) Expand all Loading... |
834 | 834 |
835 // Get the debug info (create it if it does not exist). | 835 // Get the debug info (create it if it does not exist). |
836 Handle<SharedFunctionInfo> shared = | 836 Handle<SharedFunctionInfo> shared = |
837 Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared()); | 837 Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared()); |
838 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 838 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
839 | 839 |
840 // Find the break point where execution has stopped. | 840 // Find the break point where execution has stopped. |
841 BreakLocationIterator break_location_iterator(debug_info, | 841 BreakLocationIterator break_location_iterator(debug_info, |
842 ALL_BREAK_LOCATIONS); | 842 ALL_BREAK_LOCATIONS); |
843 break_location_iterator.FindBreakLocationFromAddress(frame->pc()); | 843 break_location_iterator.FindBreakLocationFromAddress(frame->pc()); |
| 844 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
844 | 845 |
845 // Check whether step next reached a new statement. | 846 // Check whether step next reached a new statement. |
846 if (!StepNextContinue(&break_location_iterator, frame)) { | 847 if (!StepNextContinue(&break_location_iterator, frame)) { |
847 // Decrease steps left if performing multiple steps. | 848 // Decrease steps left if performing multiple steps. |
848 if (thread_local_.step_count_ > 0) { | 849 if (thread_local.step_count_ > 0) { |
849 thread_local_.step_count_--; | 850 thread_local.step_count_--; |
850 } | 851 } |
851 } | 852 } |
852 | 853 |
853 // If there is one or more real break points check whether any of these are | 854 // If there is one or more real break points check whether any of these are |
854 // triggered. | 855 // triggered. |
855 Handle<Object> break_points_hit(Heap::undefined_value()); | 856 Handle<Object> break_points_hit(Heap::undefined_value()); |
856 if (break_location_iterator.HasBreakPoint()) { | 857 if (break_location_iterator.HasBreakPoint()) { |
857 Handle<Object> break_point_objects = | 858 Handle<Object> break_point_objects = |
858 Handle<Object>(break_location_iterator.BreakPointObjects()); | 859 Handle<Object>(break_location_iterator.BreakPointObjects()); |
859 break_points_hit = CheckBreakPoints(break_point_objects); | 860 break_points_hit = CheckBreakPoints(break_point_objects); |
860 } | 861 } |
861 | 862 |
862 // If step out is active skip everything until the frame where we need to step | 863 // If step out is active skip everything until the frame where we need to step |
863 // out to is reached, unless real breakpoint is hit. | 864 // out to is reached, unless real breakpoint is hit. |
864 if (Debug::StepOutActive() && frame->fp() != Debug::step_out_fp() && | 865 if (Debug::StepOutActive() && frame->fp() != Debug::step_out_fp() && |
865 break_points_hit->IsUndefined() ) { | 866 break_points_hit->IsUndefined() ) { |
866 // Step count should always be 0 for StepOut. | 867 // Step count should always be 0 for StepOut. |
867 ASSERT(thread_local_.step_count_ == 0); | 868 ASSERT(thread_local.step_count_ == 0); |
868 } else if (!break_points_hit->IsUndefined() || | 869 } else if (!break_points_hit->IsUndefined() || |
869 (thread_local_.last_step_action_ != StepNone && | 870 (thread_local.last_step_action_ != StepNone && |
870 thread_local_.step_count_ == 0)) { | 871 thread_local.step_count_ == 0)) { |
871 // Notify debugger if a real break point is triggered or if performing | 872 // Notify debugger if a real break point is triggered or if performing |
872 // single stepping with no more steps to perform. Otherwise do another step. | 873 // single stepping with no more steps to perform. Otherwise do another step. |
873 | 874 |
874 // Clear all current stepping setup. | 875 // Clear all current stepping setup. |
875 ClearStepping(); | 876 ClearStepping(); |
876 | 877 |
877 // Notify the debug event listeners. | 878 // Notify the debug event listeners. |
878 Debugger::OnDebugBreak(break_points_hit, false); | 879 Debugger::OnDebugBreak(break_points_hit, false); |
879 } else if (thread_local_.last_step_action_ != StepNone) { | 880 } else if (thread_local.last_step_action_ != StepNone) { |
880 // Hold on to last step action as it is cleared by the call to | 881 // Hold on to last step action as it is cleared by the call to |
881 // ClearStepping. | 882 // ClearStepping. |
882 StepAction step_action = thread_local_.last_step_action_; | 883 StepAction step_action = thread_local.last_step_action_; |
883 int step_count = thread_local_.step_count_; | 884 int step_count = thread_local.step_count_; |
884 | 885 |
885 // Clear all current stepping setup. | 886 // Clear all current stepping setup. |
886 ClearStepping(); | 887 ClearStepping(); |
887 | 888 |
888 // Set up for the remaining steps. | 889 // Set up for the remaining steps. |
889 PrepareStep(step_action, step_count); | 890 PrepareStep(step_action, step_count); |
890 } | 891 } |
891 | 892 |
892 // Install jump to the call address which was overwritten. | 893 // Install jump to the call address which was overwritten. |
893 SetAfterBreakTarget(frame); | 894 SetAfterBreakTarget(frame); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
999 it.SetBreakPoint(break_point_object); | 1000 it.SetBreakPoint(break_point_object); |
1000 | 1001 |
1001 // At least one active break point now. | 1002 // At least one active break point now. |
1002 ASSERT(debug_info->GetBreakPointCount() > 0); | 1003 ASSERT(debug_info->GetBreakPointCount() > 0); |
1003 } | 1004 } |
1004 | 1005 |
1005 | 1006 |
1006 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { | 1007 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { |
1007 HandleScope scope; | 1008 HandleScope scope; |
1008 | 1009 |
1009 DebugInfoListNode* node = debug_info_list_; | 1010 DebugData& data = v8_context()->debug_data_; |
| 1011 DebugInfoListNode* node = data.debug_info_list_; |
1010 while (node != NULL) { | 1012 while (node != NULL) { |
1011 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), | 1013 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), |
1012 break_point_object); | 1014 break_point_object); |
1013 if (!result->IsUndefined()) { | 1015 if (!result->IsUndefined()) { |
1014 // Get information in the break point. | 1016 // Get information in the break point. |
1015 BreakPointInfo* break_point_info = BreakPointInfo::cast(result); | 1017 BreakPointInfo* break_point_info = BreakPointInfo::cast(result); |
1016 Handle<DebugInfo> debug_info = node->debug_info(); | 1018 Handle<DebugInfo> debug_info = node->debug_info(); |
1017 Handle<SharedFunctionInfo> shared(debug_info->shared()); | 1019 Handle<SharedFunctionInfo> shared(debug_info->shared()); |
1018 int source_position = break_point_info->statement_position()->value(); | 1020 int source_position = break_point_info->statement_position()->value(); |
1019 | 1021 |
(...skipping 12 matching lines...) Expand all Loading... |
1032 } | 1034 } |
1033 | 1035 |
1034 return; | 1036 return; |
1035 } | 1037 } |
1036 node = node->next(); | 1038 node = node->next(); |
1037 } | 1039 } |
1038 } | 1040 } |
1039 | 1041 |
1040 | 1042 |
1041 void Debug::ClearAllBreakPoints() { | 1043 void Debug::ClearAllBreakPoints() { |
1042 DebugInfoListNode* node = debug_info_list_; | 1044 DebugData& data = v8_context()->debug_data_; |
| 1045 DebugInfoListNode* node = data.debug_info_list_; |
1043 while (node != NULL) { | 1046 while (node != NULL) { |
1044 // Remove all debug break code. | 1047 // Remove all debug break code. |
1045 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1048 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
1046 it.ClearAllDebugBreak(); | 1049 it.ClearAllDebugBreak(); |
1047 node = node->next(); | 1050 node = node->next(); |
1048 } | 1051 } |
1049 | 1052 |
1050 // Remove all debug info. | 1053 // Remove all debug info. |
1051 while (debug_info_list_ != NULL) { | 1054 while (data.debug_info_list_ != NULL) { |
1052 RemoveDebugInfo(debug_info_list_->debug_info()); | 1055 RemoveDebugInfo(data.debug_info_list_->debug_info()); |
1053 } | 1056 } |
1054 } | 1057 } |
1055 | 1058 |
1056 | 1059 |
1057 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) { | 1060 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) { |
1058 // Make sure the function has setup the debug info. | 1061 // Make sure the function has setup the debug info. |
1059 if (!EnsureDebugInfo(shared)) { | 1062 if (!EnsureDebugInfo(shared)) { |
1060 // Return if we failed to retrieve the debug info. | 1063 // Return if we failed to retrieve the debug info. |
1061 return; | 1064 return; |
1062 } | 1065 } |
(...skipping 22 matching lines...) Expand all Loading... |
1085 JSFunction::cast(frame->function())->shared()); | 1088 JSFunction::cast(frame->function())->shared()); |
1086 // Flood the function with the catch block with break points | 1089 // Flood the function with the catch block with break points |
1087 FloodWithOneShot(shared); | 1090 FloodWithOneShot(shared); |
1088 return; | 1091 return; |
1089 } | 1092 } |
1090 } | 1093 } |
1091 } | 1094 } |
1092 | 1095 |
1093 | 1096 |
1094 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { | 1097 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { |
| 1098 DebugData& data = v8_context()->debug_data_; |
1095 if (type == BreakUncaughtException) { | 1099 if (type == BreakUncaughtException) { |
1096 break_on_uncaught_exception_ = enable; | 1100 data.break_on_uncaught_exception_ = enable; |
1097 } else { | 1101 } else { |
1098 break_on_exception_ = enable; | 1102 data.break_on_exception_ = enable; |
1099 } | 1103 } |
1100 } | 1104 } |
1101 | 1105 |
1102 | 1106 |
1103 void Debug::PrepareStep(StepAction step_action, int step_count) { | 1107 void Debug::PrepareStep(StepAction step_action, int step_count) { |
1104 HandleScope scope; | 1108 HandleScope scope; |
1105 ASSERT(Debug::InDebugger()); | 1109 ASSERT(Debug::InDebugger()); |
| 1110 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
1106 | 1111 |
1107 // Remember this step action and count. | 1112 // Remember this step action and count. |
1108 thread_local_.last_step_action_ = step_action; | 1113 thread_local.last_step_action_ = step_action; |
1109 if (step_action == StepOut) { | 1114 if (step_action == StepOut) { |
1110 // For step out target frame will be found on the stack so there is no need | 1115 // For step out target frame will be found on the stack so there is no need |
1111 // to set step counter for it. It's expected to always be 0 for StepOut. | 1116 // to set step counter for it. It's expected to always be 0 for StepOut. |
1112 thread_local_.step_count_ = 0; | 1117 thread_local.step_count_ = 0; |
1113 } else { | 1118 } else { |
1114 thread_local_.step_count_ = step_count; | 1119 thread_local.step_count_ = step_count; |
1115 } | 1120 } |
1116 | 1121 |
1117 // Get the frame where the execution has stopped and skip the debug frame if | 1122 // Get the frame where the execution has stopped and skip the debug frame if |
1118 // any. The debug frame will only be present if execution was stopped due to | 1123 // any. The debug frame will only be present if execution was stopped due to |
1119 // hitting a break point. In other situations (e.g. unhandled exception) the | 1124 // hitting a break point. In other situations (e.g. unhandled exception) the |
1120 // debug frame is not present. | 1125 // debug frame is not present. |
1121 StackFrame::Id id = break_frame_id(); | 1126 StackFrame::Id id = break_frame_id(); |
1122 if (id == StackFrame::NO_ID) { | 1127 if (id == StackFrame::NO_ID) { |
1123 // If there is no JavaScript stack don't do anything. | 1128 // If there is no JavaScript stack don't do anything. |
1124 return; | 1129 return; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 } | 1221 } |
1217 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || | 1222 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || |
1218 !call_function_stub.is_null()) | 1223 !call_function_stub.is_null()) |
1219 || step_action == StepNext || step_action == StepMin) { | 1224 || step_action == StepNext || step_action == StepMin) { |
1220 // Step next or step min. | 1225 // Step next or step min. |
1221 | 1226 |
1222 // Fill the current function with one-shot break points. | 1227 // Fill the current function with one-shot break points. |
1223 FloodWithOneShot(shared); | 1228 FloodWithOneShot(shared); |
1224 | 1229 |
1225 // Remember source position and frame to handle step next. | 1230 // Remember source position and frame to handle step next. |
1226 thread_local_.last_statement_position_ = | 1231 thread_local.last_statement_position_ = |
1227 debug_info->code()->SourceStatementPosition(frame->pc()); | 1232 debug_info->code()->SourceStatementPosition(frame->pc()); |
1228 thread_local_.last_fp_ = frame->fp(); | 1233 thread_local.last_fp_ = frame->fp(); |
1229 } else { | 1234 } else { |
1230 // If it's CallFunction stub ensure target function is compiled and flood | 1235 // If it's CallFunction stub ensure target function is compiled and flood |
1231 // it with one shot breakpoints. | 1236 // it with one shot breakpoints. |
1232 if (!call_function_stub.is_null()) { | 1237 if (!call_function_stub.is_null()) { |
1233 // Find out number of arguments from the stub minor key. | 1238 // Find out number of arguments from the stub minor key. |
1234 // Reverse lookup required as the minor key cannot be retrieved | 1239 // Reverse lookup required as the minor key cannot be retrieved |
1235 // from the code object. | 1240 // from the code object. |
1236 Handle<Object> obj( | 1241 Handle<Object> obj( |
1237 Heap::code_stubs()->SlowReverseLookup(*call_function_stub)); | 1242 Heap::code_stubs()->SlowReverseLookup(*call_function_stub)); |
1238 ASSERT(*obj != Heap::undefined_value()); | 1243 ASSERT(*obj != Heap::undefined_value()); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 // a call target as the function called might be a native function for | 1275 // a call target as the function called might be a native function for |
1271 // which step in will not stop. It also prepares for stepping in | 1276 // which step in will not stop. It also prepares for stepping in |
1272 // getters/setters. | 1277 // getters/setters. |
1273 FloodWithOneShot(shared); | 1278 FloodWithOneShot(shared); |
1274 | 1279 |
1275 if (is_load_or_store) { | 1280 if (is_load_or_store) { |
1276 // Remember source position and frame to handle step in getter/setter. If | 1281 // Remember source position and frame to handle step in getter/setter. If |
1277 // there is a custom getter/setter it will be handled in | 1282 // there is a custom getter/setter it will be handled in |
1278 // Object::Get/SetPropertyWithCallback, otherwise the step action will be | 1283 // Object::Get/SetPropertyWithCallback, otherwise the step action will be |
1279 // propagated on the next Debug::Break. | 1284 // propagated on the next Debug::Break. |
1280 thread_local_.last_statement_position_ = | 1285 thread_local.last_statement_position_ = |
1281 debug_info->code()->SourceStatementPosition(frame->pc()); | 1286 debug_info->code()->SourceStatementPosition(frame->pc()); |
1282 thread_local_.last_fp_ = frame->fp(); | 1287 thread_local.last_fp_ = frame->fp(); |
1283 } | 1288 } |
1284 | 1289 |
1285 // Step in or Step in min | 1290 // Step in or Step in min |
1286 it.PrepareStepIn(); | 1291 it.PrepareStepIn(); |
1287 ActivateStepIn(frame); | 1292 ActivateStepIn(frame); |
1288 } | 1293 } |
1289 } | 1294 } |
1290 | 1295 |
1291 | 1296 |
1292 // Check whether the current debug break should be reported to the debugger. It | 1297 // Check whether the current debug break should be reported to the debugger. It |
1293 // is used to have step next and step in only report break back to the debugger | 1298 // is used to have step next and step in only report break back to the debugger |
1294 // if on a different frame or in a different statement. In some situations | 1299 // if on a different frame or in a different statement. In some situations |
1295 // there will be several break points in the same statement when the code is | 1300 // there will be several break points in the same statement when the code is |
1296 // flooded with one-shot break points. This function helps to perform several | 1301 // flooded with one-shot break points. This function helps to perform several |
1297 // steps before reporting break back to the debugger. | 1302 // steps before reporting break back to the debugger. |
1298 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, | 1303 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, |
1299 JavaScriptFrame* frame) { | 1304 JavaScriptFrame* frame) { |
| 1305 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
1300 // If the step last action was step next or step in make sure that a new | 1306 // If the step last action was step next or step in make sure that a new |
1301 // statement is hit. | 1307 // statement is hit. |
1302 if (thread_local_.last_step_action_ == StepNext || | 1308 if (thread_local.last_step_action_ == StepNext || |
1303 thread_local_.last_step_action_ == StepIn) { | 1309 thread_local.last_step_action_ == StepIn) { |
1304 // Never continue if returning from function. | 1310 // Never continue if returning from function. |
1305 if (break_location_iterator->IsExit()) return false; | 1311 if (break_location_iterator->IsExit()) return false; |
1306 | 1312 |
1307 // Continue if we are still on the same frame and in the same statement. | 1313 // Continue if we are still on the same frame and in the same statement. |
1308 int current_statement_position = | 1314 int current_statement_position = |
1309 break_location_iterator->code()->SourceStatementPosition(frame->pc()); | 1315 break_location_iterator->code()->SourceStatementPosition(frame->pc()); |
1310 return thread_local_.last_fp_ == frame->fp() && | 1316 return thread_local.last_fp_ == frame->fp() && |
1311 thread_local_.last_statement_position_ == current_statement_position; | 1317 thread_local.last_statement_position_ == current_statement_position; |
1312 } | 1318 } |
1313 | 1319 |
1314 // No step next action - don't continue. | 1320 // No step next action - don't continue. |
1315 return false; | 1321 return false; |
1316 } | 1322 } |
1317 | 1323 |
1318 | 1324 |
1319 // Check whether the code object at the specified address is a debug break code | 1325 // Check whether the code object at the specified address is a debug break code |
1320 // object. | 1326 // object. |
1321 bool Debug::IsDebugBreak(Address addr) { | 1327 bool Debug::IsDebugBreak(Address addr) { |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 if (break_point_info->GetBreakPointCount() > 0) { | 1408 if (break_point_info->GetBreakPointCount() > 0) { |
1403 locations->set(count++, break_point_info->statement_position()); | 1409 locations->set(count++, break_point_info->statement_position()); |
1404 } | 1410 } |
1405 } | 1411 } |
1406 } | 1412 } |
1407 return locations; | 1413 return locations; |
1408 } | 1414 } |
1409 | 1415 |
1410 | 1416 |
1411 void Debug::NewBreak(StackFrame::Id break_frame_id) { | 1417 void Debug::NewBreak(StackFrame::Id break_frame_id) { |
1412 thread_local_.break_frame_id_ = break_frame_id; | 1418 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
1413 thread_local_.break_id_ = ++thread_local_.break_count_; | 1419 thread_local.break_frame_id_ = break_frame_id; |
| 1420 thread_local.break_id_ = ++thread_local.break_count_; |
1414 } | 1421 } |
1415 | 1422 |
1416 | 1423 |
1417 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) { | 1424 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) { |
1418 thread_local_.break_frame_id_ = break_frame_id; | 1425 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
1419 thread_local_.break_id_ = break_id; | 1426 thread_local.break_frame_id_ = break_frame_id; |
| 1427 thread_local.break_id_ = break_id; |
1420 } | 1428 } |
1421 | 1429 |
1422 | 1430 |
1423 // Handle stepping into a function. | 1431 // Handle stepping into a function. |
1424 void Debug::HandleStepIn(Handle<JSFunction> function, | 1432 void Debug::HandleStepIn(Handle<JSFunction> function, |
1425 Handle<Object> holder, | 1433 Handle<Object> holder, |
1426 Address fp, | 1434 Address fp, |
1427 bool is_constructor) { | 1435 bool is_constructor) { |
1428 // If the frame pointer is not supplied by the caller find it. | 1436 // If the frame pointer is not supplied by the caller find it. |
1429 if (fp == 0) { | 1437 if (fp == 0) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1465 | 1473 |
1466 | 1474 |
1467 void Debug::ClearStepping() { | 1475 void Debug::ClearStepping() { |
1468 // Clear the various stepping setup. | 1476 // Clear the various stepping setup. |
1469 ClearOneShot(); | 1477 ClearOneShot(); |
1470 ClearStepIn(); | 1478 ClearStepIn(); |
1471 ClearStepOut(); | 1479 ClearStepOut(); |
1472 ClearStepNext(); | 1480 ClearStepNext(); |
1473 | 1481 |
1474 // Clear multiple step counter. | 1482 // Clear multiple step counter. |
1475 thread_local_.step_count_ = 0; | 1483 v8_context()->debug_data_.thread_local_.step_count_ = 0; |
1476 } | 1484 } |
1477 | 1485 |
1478 // Clears all the one-shot break points that are currently set. Normally this | 1486 // Clears all the one-shot break points that are currently set. Normally this |
1479 // function is called each time a break point is hit as one shot break points | 1487 // function is called each time a break point is hit as one shot break points |
1480 // are used to support stepping. | 1488 // are used to support stepping. |
1481 void Debug::ClearOneShot() { | 1489 void Debug::ClearOneShot() { |
1482 // The current implementation just runs through all the breakpoints. When the | 1490 // The current implementation just runs through all the breakpoints. When the |
1483 // last break point for a function is removed that function is automatically | 1491 // last break point for a function is removed that function is automatically |
1484 // removed from the list. | 1492 // removed from the list. |
1485 | 1493 |
1486 DebugInfoListNode* node = debug_info_list_; | 1494 DebugInfoListNode* node = v8_context()->debug_data_.debug_info_list_; |
1487 while (node != NULL) { | 1495 while (node != NULL) { |
1488 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1496 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
1489 while (!it.Done()) { | 1497 while (!it.Done()) { |
1490 it.ClearOneShot(); | 1498 it.ClearOneShot(); |
1491 it.Next(); | 1499 it.Next(); |
1492 } | 1500 } |
1493 node = node->next(); | 1501 node = node->next(); |
1494 } | 1502 } |
1495 } | 1503 } |
1496 | 1504 |
1497 | 1505 |
1498 void Debug::ActivateStepIn(StackFrame* frame) { | 1506 void Debug::ActivateStepIn(StackFrame* frame) { |
1499 ASSERT(!StepOutActive()); | 1507 ASSERT(!StepOutActive()); |
1500 thread_local_.step_into_fp_ = frame->fp(); | 1508 v8_context()->debug_data_.thread_local_.step_into_fp_ = frame->fp(); |
1501 } | 1509 } |
1502 | 1510 |
1503 | 1511 |
1504 void Debug::ClearStepIn() { | 1512 void Debug::ClearStepIn() { |
1505 thread_local_.step_into_fp_ = 0; | 1513 v8_context()->debug_data_.thread_local_.step_into_fp_ = 0; |
1506 } | 1514 } |
1507 | 1515 |
1508 | 1516 |
1509 void Debug::ActivateStepOut(StackFrame* frame) { | 1517 void Debug::ActivateStepOut(StackFrame* frame) { |
1510 ASSERT(!StepInActive()); | 1518 ASSERT(!StepInActive()); |
1511 thread_local_.step_out_fp_ = frame->fp(); | 1519 v8_context()->debug_data_.thread_local_.step_out_fp_ = frame->fp(); |
1512 } | 1520 } |
1513 | 1521 |
1514 | 1522 |
1515 void Debug::ClearStepOut() { | 1523 void Debug::ClearStepOut() { |
1516 thread_local_.step_out_fp_ = 0; | 1524 v8_context()->debug_data_.thread_local_.step_out_fp_ = 0; |
1517 } | 1525 } |
1518 | 1526 |
1519 | 1527 |
1520 void Debug::ClearStepNext() { | 1528 void Debug::ClearStepNext() { |
1521 thread_local_.last_step_action_ = StepNone; | 1529 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
1522 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 1530 thread_local.last_step_action_ = StepNone; |
1523 thread_local_.last_fp_ = 0; | 1531 thread_local.last_statement_position_ = RelocInfo::kNoPosition; |
| 1532 thread_local.last_fp_ = 0; |
1524 } | 1533 } |
1525 | 1534 |
1526 | 1535 |
1527 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) { | 1536 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) { |
1528 if (shared->is_compiled()) return true; | 1537 if (shared->is_compiled()) return true; |
1529 return CompileLazyShared(shared, CLEAR_EXCEPTION, 0); | 1538 return CompileLazyShared(shared, CLEAR_EXCEPTION, 0); |
1530 } | 1539 } |
1531 | 1540 |
1532 | 1541 |
1533 // Ensures the debug information is present for shared. | 1542 // Ensures the debug information is present for shared. |
1534 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) { | 1543 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) { |
1535 // Return if we already have the debug info for shared. | 1544 // Return if we already have the debug info for shared. |
1536 if (HasDebugInfo(shared)) return true; | 1545 if (HasDebugInfo(shared)) return true; |
1537 | 1546 |
1538 // Ensure shared in compiled. Return false if this failed. | 1547 // Ensure shared in compiled. Return false if this failed. |
1539 if (!EnsureCompiled(shared)) return false; | 1548 if (!EnsureCompiled(shared)) return false; |
1540 | 1549 |
1541 // Create the debug info object. | 1550 // Create the debug info object. |
1542 Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared); | 1551 Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared); |
1543 | 1552 |
1544 // Add debug info to the list. | 1553 // Add debug info to the list. |
1545 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 1554 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
1546 node->set_next(debug_info_list_); | 1555 DebugData& data = v8_context()->debug_data_; |
1547 debug_info_list_ = node; | 1556 node->set_next(data.debug_info_list_); |
| 1557 data.debug_info_list_ = node; |
1548 | 1558 |
1549 // Now there is at least one break point. | 1559 // Now there is at least one break point. |
1550 has_break_points_ = true; | 1560 data.has_break_points_ = true; |
1551 | 1561 |
1552 return true; | 1562 return true; |
1553 } | 1563 } |
1554 | 1564 |
1555 | 1565 |
1556 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { | 1566 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { |
1557 ASSERT(debug_info_list_ != NULL); | 1567 DebugData& data = v8_context()->debug_data_; |
| 1568 ASSERT(data.debug_info_list_ != NULL); |
1558 // Run through the debug info objects to find this one and remove it. | 1569 // Run through the debug info objects to find this one and remove it. |
1559 DebugInfoListNode* prev = NULL; | 1570 DebugInfoListNode* prev = NULL; |
1560 DebugInfoListNode* current = debug_info_list_; | 1571 DebugInfoListNode* current = data.debug_info_list_; |
1561 while (current != NULL) { | 1572 while (current != NULL) { |
1562 if (*current->debug_info() == *debug_info) { | 1573 if (*current->debug_info() == *debug_info) { |
1563 // Unlink from list. If prev is NULL we are looking at the first element. | 1574 // Unlink from list. If prev is NULL we are looking at the first element. |
1564 if (prev == NULL) { | 1575 if (prev == NULL) { |
1565 debug_info_list_ = current->next(); | 1576 data.debug_info_list_ = current->next(); |
1566 } else { | 1577 } else { |
1567 prev->set_next(current->next()); | 1578 prev->set_next(current->next()); |
1568 } | 1579 } |
1569 current->debug_info()->shared()->set_debug_info(Heap::undefined_value()); | 1580 current->debug_info()->shared()->set_debug_info(Heap::undefined_value()); |
1570 delete current; | 1581 delete current; |
1571 | 1582 |
1572 // If there are no more debug info objects there are not more break | 1583 // If there are no more debug info objects there are not more break |
1573 // points. | 1584 // points. |
1574 has_break_points_ = debug_info_list_ != NULL; | 1585 data.has_break_points_ = data.debug_info_list_ != NULL; |
1575 | 1586 |
1576 return; | 1587 return; |
1577 } | 1588 } |
1578 // Move to next in list. | 1589 // Move to next in list. |
1579 prev = current; | 1590 prev = current; |
1580 current = current->next(); | 1591 current = current->next(); |
1581 } | 1592 } |
1582 UNREACHABLE(); | 1593 UNREACHABLE(); |
1583 } | 1594 } |
1584 | 1595 |
(...skipping 28 matching lines...) Expand all Loading... |
1613 RelocIterator it(debug_info->code()); | 1624 RelocIterator it(debug_info->code()); |
1614 while (!it.done()) { | 1625 while (!it.done()) { |
1615 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { | 1626 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { |
1616 at_js_return = (it.rinfo()->pc() == | 1627 at_js_return = (it.rinfo()->pc() == |
1617 addr - Assembler::kPatchReturnSequenceAddressOffset); | 1628 addr - Assembler::kPatchReturnSequenceAddressOffset); |
1618 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence(); | 1629 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence(); |
1619 } | 1630 } |
1620 it.next(); | 1631 it.next(); |
1621 } | 1632 } |
1622 | 1633 |
| 1634 ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_; |
1623 // Handle the jump to continue execution after break point depending on the | 1635 // Handle the jump to continue execution after break point depending on the |
1624 // break location. | 1636 // break location. |
1625 if (at_js_return) { | 1637 if (at_js_return) { |
1626 // If the break point as return is still active jump to the corresponding | 1638 // If the break point as return is still active jump to the corresponding |
1627 // place in the original code. If not the break point was removed during | 1639 // place in the original code. If not the break point was removed during |
1628 // break point processing. | 1640 // break point processing. |
1629 if (break_at_js_return_active) { | 1641 if (break_at_js_return_active) { |
1630 addr += original_code->instruction_start() - code->instruction_start(); | 1642 addr += original_code->instruction_start() - code->instruction_start(); |
1631 } | 1643 } |
1632 | 1644 |
1633 // Move back to where the call instruction sequence started. | 1645 // Move back to where the call instruction sequence started. |
1634 thread_local_.after_break_target_ = | 1646 thread_local.after_break_target_ = |
1635 addr - Assembler::kPatchReturnSequenceAddressOffset; | 1647 addr - Assembler::kPatchReturnSequenceAddressOffset; |
1636 } else { | 1648 } else { |
1637 // Check if there still is a debug break call at the target address. If the | 1649 // Check if there still is a debug break call at the target address. If the |
1638 // break point has been removed it will have disappeared. If it have | 1650 // break point has been removed it will have disappeared. If it have |
1639 // disappeared don't try to look in the original code as the running code | 1651 // disappeared don't try to look in the original code as the running code |
1640 // will have the right address. This takes care of the case where the last | 1652 // will have the right address. This takes care of the case where the last |
1641 // break point is removed from the function and therefore no "original code" | 1653 // break point is removed from the function and therefore no "original code" |
1642 // is available. If the debug break call is still there find the address in | 1654 // is available. If the debug break call is still there find the address in |
1643 // the original code. | 1655 // the original code. |
1644 if (IsDebugBreak(Assembler::target_address_at(addr))) { | 1656 if (IsDebugBreak(Assembler::target_address_at(addr))) { |
1645 // If the break point is still there find the call address which was | 1657 // If the break point is still there find the call address which was |
1646 // overwritten in the original code by the call to DebugBreakXXX. | 1658 // overwritten in the original code by the call to DebugBreakXXX. |
1647 | 1659 |
1648 // Find the corresponding address in the original code. | 1660 // Find the corresponding address in the original code. |
1649 addr += original_code->instruction_start() - code->instruction_start(); | 1661 addr += original_code->instruction_start() - code->instruction_start(); |
1650 } | 1662 } |
1651 | 1663 |
1652 // Install jump to the call address in the original code. This will be the | 1664 // Install jump to the call address in the original code. This will be the |
1653 // call which was overwritten by the call to DebugBreakXXX. | 1665 // call which was overwritten by the call to DebugBreakXXX. |
1654 thread_local_.after_break_target_ = Assembler::target_address_at(addr); | 1666 thread_local.after_break_target_ = Assembler::target_address_at(addr); |
1655 } | 1667 } |
1656 } | 1668 } |
1657 | 1669 |
1658 | 1670 |
1659 bool Debug::IsDebugGlobal(GlobalObject* global) { | 1671 bool Debug::IsDebugGlobal(GlobalObject* global) { |
1660 return IsLoaded() && global == Debug::debug_context()->global(); | 1672 return IsLoaded() && global == Debug::debug_context()->global(); |
1661 } | 1673 } |
1662 | 1674 |
1663 | 1675 |
1664 void Debug::ClearMirrorCache() { | 1676 void Debug::ClearMirrorCache() { |
(...skipping 15 matching lines...) Expand all Loading... |
1680 | 1692 |
1681 void Debug::CreateScriptCache() { | 1693 void Debug::CreateScriptCache() { |
1682 HandleScope scope; | 1694 HandleScope scope; |
1683 | 1695 |
1684 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | 1696 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
1685 // rid of all the cached script wrappers and the second gets rid of the | 1697 // rid of all the cached script wrappers and the second gets rid of the |
1686 // scripts which is no longer referenced. | 1698 // scripts which is no longer referenced. |
1687 Heap::CollectAllGarbage(false); | 1699 Heap::CollectAllGarbage(false); |
1688 Heap::CollectAllGarbage(false); | 1700 Heap::CollectAllGarbage(false); |
1689 | 1701 |
1690 ASSERT(script_cache_ == NULL); | 1702 DebugData& data = v8_context()->debug_data_; |
1691 script_cache_ = new ScriptCache(); | 1703 ASSERT(data.script_cache_ == NULL); |
| 1704 data.script_cache_ = new ScriptCache(); |
1692 | 1705 |
1693 // Scan heap for Script objects. | 1706 // Scan heap for Script objects. |
1694 int count = 0; | 1707 int count = 0; |
1695 HeapIterator iterator; | 1708 HeapIterator iterator; |
1696 while (iterator.has_next()) { | 1709 while (iterator.has_next()) { |
1697 HeapObject* obj = iterator.next(); | 1710 HeapObject* obj = iterator.next(); |
1698 ASSERT(obj != NULL); | 1711 ASSERT(obj != NULL); |
1699 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | 1712 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { |
1700 script_cache_->Add(Handle<Script>(Script::cast(obj))); | 1713 data.script_cache_->Add(Handle<Script>(Script::cast(obj))); |
1701 count++; | 1714 count++; |
1702 } | 1715 } |
1703 } | 1716 } |
1704 } | 1717 } |
1705 | 1718 |
1706 | 1719 |
1707 void Debug::DestroyScriptCache() { | 1720 void Debug::DestroyScriptCache() { |
| 1721 DebugData& data = v8_context()->debug_data_; |
1708 // Get rid of the script cache if it was created. | 1722 // Get rid of the script cache if it was created. |
1709 if (script_cache_ != NULL) { | 1723 if (data.script_cache_ != NULL) { |
1710 delete script_cache_; | 1724 delete data.script_cache_; |
1711 script_cache_ = NULL; | 1725 data.script_cache_ = NULL; |
1712 } | 1726 } |
1713 } | 1727 } |
1714 | 1728 |
1715 | 1729 |
1716 void Debug::AddScriptToScriptCache(Handle<Script> script) { | 1730 void Debug::AddScriptToScriptCache(Handle<Script> script) { |
1717 if (script_cache_ != NULL) { | 1731 DebugData& data = v8_context()->debug_data_; |
1718 script_cache_->Add(script); | 1732 if (data.script_cache_ != NULL) { |
| 1733 data.script_cache_->Add(script); |
1719 } | 1734 } |
1720 } | 1735 } |
1721 | 1736 |
1722 | 1737 |
1723 Handle<FixedArray> Debug::GetLoadedScripts() { | 1738 Handle<FixedArray> Debug::GetLoadedScripts() { |
| 1739 DebugData& data = v8_context()->debug_data_; |
1724 // Create and fill the script cache when the loaded scripts is requested for | 1740 // Create and fill the script cache when the loaded scripts is requested for |
1725 // the first time. | 1741 // the first time. |
1726 if (script_cache_ == NULL) { | 1742 if (data.script_cache_ == NULL) { |
1727 CreateScriptCache(); | 1743 CreateScriptCache(); |
1728 } | 1744 } |
1729 | 1745 |
1730 // If the script cache is not active just return an empty array. | 1746 // If the script cache is not active just return an empty array. |
1731 ASSERT(script_cache_ != NULL); | 1747 ASSERT(data.script_cache_ != NULL); |
1732 if (script_cache_ == NULL) { | 1748 if (data.script_cache_ == NULL) { |
1733 Factory::NewFixedArray(0); | 1749 Factory::NewFixedArray(0); |
1734 } | 1750 } |
1735 | 1751 |
1736 // Perform GC to get unreferenced scripts evicted from the cache before | 1752 // Perform GC to get unreferenced scripts evicted from the cache before |
1737 // returning the content. | 1753 // returning the content. |
1738 Heap::CollectAllGarbage(false); | 1754 Heap::CollectAllGarbage(false); |
1739 | 1755 |
1740 // Get the scripts from the cache. | 1756 // Get the scripts from the cache. |
1741 return script_cache_->GetScripts(); | 1757 return data.script_cache_->GetScripts(); |
1742 } | 1758 } |
1743 | 1759 |
1744 | 1760 |
1745 void Debug::AfterGarbageCollection() { | 1761 void Debug::AfterGarbageCollection() { |
| 1762 DebugData& data = v8_context()->debug_data_; |
1746 // Generate events for collected scripts. | 1763 // Generate events for collected scripts. |
1747 if (script_cache_ != NULL) { | 1764 if (data.script_cache_ != NULL) { |
1748 script_cache_->ProcessCollectedScripts(); | 1765 data.script_cache_->ProcessCollectedScripts(); |
1749 } | 1766 } |
1750 } | 1767 } |
1751 | 1768 |
1752 | 1769 DebuggerData::DebuggerData() |
1753 Mutex* Debugger::debugger_access_ = OS::CreateMutex(); | 1770 :debugger_access_(OS::CreateMutex()), |
1754 Handle<Object> Debugger::event_listener_ = Handle<Object>(); | 1771 event_listener_(Handle<Object>()), |
1755 Handle<Object> Debugger::event_listener_data_ = Handle<Object>(); | 1772 event_listener_data_(Handle<Object>()), |
1756 bool Debugger::compiling_natives_ = false; | 1773 compiling_natives_(false), |
1757 bool Debugger::is_loading_debugger_ = false; | 1774 is_loading_debugger_(false), |
1758 bool Debugger::never_unload_debugger_ = false; | 1775 never_unload_debugger_(false), |
1759 v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL; | 1776 message_handler_(NULL), |
1760 bool Debugger::debugger_unload_pending_ = false; | 1777 debugger_unload_pending_(false), |
1761 v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL; | 1778 host_dispatch_handler_(NULL), |
1762 v8::Debug::DebugMessageDispatchHandler | 1779 host_dispatch_micros_(100 * 1000), |
1763 Debugger::debug_message_dispatch_handler_ = NULL; | 1780 agent_(NULL), |
1764 int Debugger::host_dispatch_micros_ = 100 * 1000; | 1781 command_queue_(kQueueInitialSize), |
1765 DebuggerAgent* Debugger::agent_ = NULL; | 1782 command_received_(OS::CreateSemaphore(0)) { |
1766 LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize); | 1783 } |
1767 Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0); | |
1768 | |
1769 | 1784 |
1770 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, | 1785 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, |
1771 int argc, Object*** argv, | 1786 int argc, Object*** argv, |
1772 bool* caught_exception) { | 1787 bool* caught_exception) { |
1773 ASSERT(Top::context() == *Debug::debug_context()); | 1788 ASSERT(Top::context() == *Debug::debug_context()); |
1774 | 1789 |
1775 // Create the execution state object. | 1790 // Create the execution state object. |
1776 Handle<String> constructor_str = Factory::LookupSymbol(constructor_name); | 1791 Handle<String> constructor_str = Factory::LookupSymbol(constructor_name); |
1777 Handle<Object> constructor(Top::global()->GetProperty(*constructor_str)); | 1792 Handle<Object> constructor(Top::global()->GetProperty(*constructor_str)); |
1778 ASSERT(constructor->IsJSFunction()); | 1793 ASSERT(constructor->IsJSFunction()); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2100 if (!auto_continue) { | 2115 if (!auto_continue) { |
2101 Debug::clear_interrupt_pending(DEBUGBREAK); | 2116 Debug::clear_interrupt_pending(DEBUGBREAK); |
2102 } | 2117 } |
2103 | 2118 |
2104 // Create the execution state. | 2119 // Create the execution state. |
2105 bool caught_exception = false; | 2120 bool caught_exception = false; |
2106 Handle<Object> exec_state = MakeExecutionState(&caught_exception); | 2121 Handle<Object> exec_state = MakeExecutionState(&caught_exception); |
2107 if (caught_exception) { | 2122 if (caught_exception) { |
2108 return; | 2123 return; |
2109 } | 2124 } |
| 2125 |
| 2126 DebuggerData& data = v8_context()->debugger_data_; |
2110 // First notify the message handler if any. | 2127 // First notify the message handler if any. |
2111 if (message_handler_ != NULL) { | 2128 if (data.message_handler_ != NULL) { |
2112 NotifyMessageHandler(event, | 2129 NotifyMessageHandler(event, |
2113 Handle<JSObject>::cast(exec_state), | 2130 Handle<JSObject>::cast(exec_state), |
2114 event_data, | 2131 event_data, |
2115 auto_continue); | 2132 auto_continue); |
2116 } | 2133 } |
2117 // Notify registered debug event listener. This can be either a C or a | 2134 // Notify registered debug event listener. This can be either a C or a |
2118 // JavaScript function. | 2135 // JavaScript function. |
2119 if (!event_listener_.is_null()) { | 2136 if (!data.event_listener_.is_null()) { |
2120 if (event_listener_->IsProxy()) { | 2137 if (data.event_listener_->IsProxy()) { |
2121 // C debug event listener. | 2138 // C debug event listener. |
2122 Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_)); | 2139 Handle<Proxy> callback_obj(Handle<Proxy>::cast(data.event_listener_)); |
2123 v8::Debug::EventCallback callback = | 2140 v8::Debug::EventCallback callback = |
2124 FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy()); | 2141 FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy()); |
2125 callback(event, | 2142 callback(event, |
2126 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), | 2143 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)), |
2127 v8::Utils::ToLocal(event_data), | 2144 v8::Utils::ToLocal(event_data), |
2128 v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_))); | 2145 v8::Utils::ToLocal(Handle<Object>::cast( |
| 2146 data.event_listener_data_))); |
2129 } else { | 2147 } else { |
2130 // JavaScript debug event listener. | 2148 // JavaScript debug event listener. |
2131 ASSERT(event_listener_->IsJSFunction()); | 2149 ASSERT(data.event_listener_->IsJSFunction()); |
2132 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_)); | 2150 Handle<JSFunction> fun(Handle<JSFunction>::cast(data.event_listener_)); |
2133 | 2151 |
2134 // Invoke the JavaScript debug event listener. | 2152 // Invoke the JavaScript debug event listener. |
2135 const int argc = 4; | 2153 const int argc = 4; |
2136 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), | 2154 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(), |
2137 exec_state.location(), | 2155 exec_state.location(), |
2138 Handle<Object>::cast(event_data).location(), | 2156 Handle<Object>::cast(event_data).location(), |
2139 event_listener_data_.location() }; | 2157 data.event_listener_data_.location() }; |
2140 Handle<Object> result = Execution::TryCall(fun, Top::global(), | 2158 Handle<Object> result = Execution::TryCall(fun, Top::global(), |
2141 argc, argv, &caught_exception); | 2159 argc, argv, &caught_exception); |
2142 // Silently ignore exceptions from debug event listeners. | 2160 // Silently ignore exceptions from debug event listeners. |
2143 } | 2161 } |
2144 } | 2162 } |
2145 } | 2163 } |
2146 | 2164 |
2147 | 2165 |
2148 void Debugger::UnloadDebugger() { | 2166 void Debugger::UnloadDebugger() { |
2149 // Make sure that there are no breakpoints left. | 2167 // Make sure that there are no breakpoints left. |
2150 Debug::ClearAllBreakPoints(); | 2168 Debug::ClearAllBreakPoints(); |
2151 | 2169 |
| 2170 DebuggerData& data = v8_context()->debugger_data_; |
2152 // Unload the debugger if feasible. | 2171 // Unload the debugger if feasible. |
2153 if (!never_unload_debugger_) { | 2172 if (!data.never_unload_debugger_) { |
2154 Debug::Unload(); | 2173 Debug::Unload(); |
2155 } | 2174 } |
2156 | 2175 |
2157 // Clear the flag indicating that the debugger should be unloaded. | 2176 // Clear the flag indicating that the debugger should be unloaded. |
2158 debugger_unload_pending_ = false; | 2177 data.debugger_unload_pending_ = false; |
2159 } | 2178 } |
2160 | 2179 |
2161 | 2180 |
2162 void Debugger::NotifyMessageHandler(v8::DebugEvent event, | 2181 void Debugger::NotifyMessageHandler(v8::DebugEvent event, |
2163 Handle<JSObject> exec_state, | 2182 Handle<JSObject> exec_state, |
2164 Handle<JSObject> event_data, | 2183 Handle<JSObject> event_data, |
2165 bool auto_continue) { | 2184 bool auto_continue) { |
2166 HandleScope scope; | 2185 HandleScope scope; |
2167 | 2186 |
2168 if (!Debug::Load()) return; | 2187 if (!Debug::Load()) return; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 static const int kArgc = 1; | 2251 static const int kArgc = 1; |
2233 v8::Handle<Value> argv[kArgc] = { running }; | 2252 v8::Handle<Value> argv[kArgc] = { running }; |
2234 cmd_processor = v8::Object::Cast(*fun->Call(api_exec_state, kArgc, argv)); | 2253 cmd_processor = v8::Object::Cast(*fun->Call(api_exec_state, kArgc, argv)); |
2235 if (try_catch.HasCaught()) { | 2254 if (try_catch.HasCaught()) { |
2236 PrintLn(try_catch.Exception()); | 2255 PrintLn(try_catch.Exception()); |
2237 return; | 2256 return; |
2238 } | 2257 } |
2239 } | 2258 } |
2240 | 2259 |
2241 bool running = auto_continue; | 2260 bool running = auto_continue; |
| 2261 DebuggerData& data = v8_context()->debugger_data_; |
2242 | 2262 |
2243 // Process requests from the debugger. | 2263 // Process requests from the debugger. |
2244 while (true) { | 2264 while (true) { |
2245 // Wait for new command in the queue. | 2265 // Wait for new command in the queue. |
2246 if (Debugger::host_dispatch_handler_) { | 2266 if (data.host_dispatch_handler_) { |
2247 // In case there is a host dispatch - do periodic dispatches. | 2267 // In case there is a host dispatch - do periodic dispatches. |
2248 if (!command_received_->Wait(host_dispatch_micros_)) { | 2268 if (!data.command_received_->Wait(data.host_dispatch_micros_)) { |
2249 // Timout expired, do the dispatch. | 2269 // Timout expired, do the dispatch. |
2250 Debugger::host_dispatch_handler_(); | 2270 data.host_dispatch_handler_(); |
2251 continue; | 2271 continue; |
2252 } | 2272 } |
2253 } else { | 2273 } else { |
2254 // In case there is no host dispatch - just wait. | 2274 // In case there is no host dispatch - just wait. |
2255 command_received_->Wait(); | 2275 data.command_received_->Wait(); |
2256 } | 2276 } |
2257 | 2277 |
2258 // Get the command from the queue. | 2278 // Get the command from the queue. |
2259 CommandMessage command = command_queue_.Get(); | 2279 CommandMessage command = data.command_queue_.Get(); |
2260 Logger::DebugTag("Got request from command queue, in interactive loop."); | 2280 Logger::DebugTag("Got request from command queue, in interactive loop."); |
2261 if (!Debugger::IsDebuggerActive()) { | 2281 if (!Debugger::IsDebuggerActive()) { |
2262 // Delete command text and user data. | 2282 // Delete command text and user data. |
2263 command.Dispose(); | 2283 command.Dispose(); |
2264 return; | 2284 return; |
2265 } | 2285 } |
2266 | 2286 |
2267 // Invoke JavaScript to process the debug request. | 2287 // Invoke JavaScript to process the debug request. |
2268 v8::Local<v8::String> fun_name; | 2288 v8::Local<v8::String> fun_name; |
2269 v8::Local<v8::Function> fun; | 2289 v8::Local<v8::Function> fun; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2326 return; | 2346 return; |
2327 } | 2347 } |
2328 } | 2348 } |
2329 } | 2349 } |
2330 | 2350 |
2331 | 2351 |
2332 void Debugger::SetEventListener(Handle<Object> callback, | 2352 void Debugger::SetEventListener(Handle<Object> callback, |
2333 Handle<Object> data) { | 2353 Handle<Object> data) { |
2334 HandleScope scope; | 2354 HandleScope scope; |
2335 | 2355 |
| 2356 DebuggerData& debugger_data = v8_context()->debugger_data_; |
| 2357 |
2336 // Clear the global handles for the event listener and the event listener data | 2358 // Clear the global handles for the event listener and the event listener data |
2337 // object. | 2359 // object. |
2338 if (!event_listener_.is_null()) { | 2360 if (!debugger_data.event_listener_.is_null()) { |
2339 GlobalHandles::Destroy( | 2361 GlobalHandles::Destroy( |
2340 reinterpret_cast<Object**>(event_listener_.location())); | 2362 reinterpret_cast<Object**>(debugger_data.event_listener_.location())); |
2341 event_listener_ = Handle<Object>(); | 2363 debugger_data.event_listener_ = Handle<Object>(); |
2342 } | 2364 } |
2343 if (!event_listener_data_.is_null()) { | 2365 if (!debugger_data.event_listener_data_.is_null()) { |
2344 GlobalHandles::Destroy( | 2366 GlobalHandles::Destroy(reinterpret_cast<Object**>( |
2345 reinterpret_cast<Object**>(event_listener_data_.location())); | 2367 debugger_data.event_listener_data_.location())); |
2346 event_listener_data_ = Handle<Object>(); | 2368 debugger_data.event_listener_data_ = Handle<Object>(); |
2347 } | 2369 } |
2348 | 2370 |
2349 // If there is a new debug event listener register it together with its data | 2371 // If there is a new debug event listener register it together with its data |
2350 // object. | 2372 // object. |
2351 if (!callback->IsUndefined() && !callback->IsNull()) { | 2373 if (!callback->IsUndefined() && !callback->IsNull()) { |
2352 event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback)); | 2374 debugger_data.event_listener_ = |
| 2375 Handle<Object>::cast(GlobalHandles::Create(*callback)); |
2353 if (data.is_null()) { | 2376 if (data.is_null()) { |
2354 data = Factory::undefined_value(); | 2377 data = Factory::undefined_value(); |
2355 } | 2378 } |
2356 event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data)); | 2379 debugger_data.event_listener_data_ = |
| 2380 Handle<Object>::cast(GlobalHandles::Create(*data)); |
2357 } | 2381 } |
2358 | 2382 |
2359 ListenersChanged(); | 2383 ListenersChanged(); |
2360 } | 2384 } |
2361 | 2385 |
2362 | 2386 |
2363 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) { | 2387 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) { |
2364 ScopedLock with(debugger_access_); | 2388 DebuggerData& data = v8_context()->debugger_data_; |
| 2389 ScopedLock with(data.debugger_access_); |
2365 | 2390 |
2366 message_handler_ = handler; | 2391 data.message_handler_ = handler; |
2367 ListenersChanged(); | 2392 ListenersChanged(); |
2368 if (handler == NULL) { | 2393 if (handler == NULL) { |
2369 // Send an empty command to the debugger if in a break to make JavaScript | 2394 // Send an empty command to the debugger if in a break to make JavaScript |
2370 // run again if the debugger is closed. | 2395 // run again if the debugger is closed. |
2371 if (Debug::InDebugger()) { | 2396 if (Debug::InDebugger()) { |
2372 ProcessCommand(Vector<const uint16_t>::empty()); | 2397 ProcessCommand(Vector<const uint16_t>::empty()); |
2373 } | 2398 } |
2374 } | 2399 } |
2375 } | 2400 } |
2376 | 2401 |
2377 | 2402 |
2378 void Debugger::ListenersChanged() { | 2403 void Debugger::ListenersChanged() { |
2379 if (IsDebuggerActive()) { | 2404 if (IsDebuggerActive()) { |
2380 // Disable the compilation cache when the debugger is active. | 2405 // Disable the compilation cache when the debugger is active. |
2381 CompilationCache::Disable(); | 2406 CompilationCache::Disable(); |
2382 } else { | 2407 } else { |
2383 CompilationCache::Enable(); | 2408 CompilationCache::Enable(); |
2384 | 2409 |
2385 // Unload the debugger if event listener and message handler cleared. | 2410 // Unload the debugger if event listener and message handler cleared. |
2386 if (Debug::InDebugger()) { | 2411 if (Debug::InDebugger()) { |
2387 // If we are in debugger set the flag to unload the debugger when last | 2412 // If we are in debugger set the flag to unload the debugger when last |
2388 // EnterDebugger on the current stack is destroyed. | 2413 // EnterDebugger on the current stack is destroyed. |
2389 debugger_unload_pending_ = true; | 2414 v8_context()->debugger_data_.debugger_unload_pending_ = true; |
2390 } else { | 2415 } else { |
2391 UnloadDebugger(); | 2416 UnloadDebugger(); |
2392 } | 2417 } |
2393 } | 2418 } |
2394 } | 2419 } |
2395 | 2420 |
2396 | 2421 |
2397 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, | 2422 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler, |
2398 int period) { | 2423 int period) { |
2399 host_dispatch_handler_ = handler; | 2424 DebuggerData& data = v8_context()->debugger_data_; |
2400 host_dispatch_micros_ = period * 1000; | 2425 data.host_dispatch_handler_ = handler; |
| 2426 data.host_dispatch_micros_ = period * 1000; |
2401 } | 2427 } |
2402 | 2428 |
2403 | 2429 |
2404 void Debugger::SetDebugMessageDispatchHandler( | 2430 void Debugger::SetDebugMessageDispatchHandler( |
2405 v8::Debug::DebugMessageDispatchHandler handler) { | 2431 v8::Debug::DebugMessageDispatchHandler handler) { |
2406 debug_message_dispatch_handler_ = handler; | 2432 v8_context()->debugger_data_.debug_message_dispatch_handler_ = handler; |
2407 } | 2433 } |
2408 | 2434 |
2409 | 2435 |
2410 // Calls the registered debug message handler. This callback is part of the | 2436 // Calls the registered debug message handler. This callback is part of the |
2411 // public API. | 2437 // public API. |
2412 void Debugger::InvokeMessageHandler(MessageImpl message) { | 2438 void Debugger::InvokeMessageHandler(MessageImpl message) { |
2413 ScopedLock with(debugger_access_); | 2439 DebuggerData& data = v8_context()->debugger_data_; |
| 2440 ScopedLock with(data.debugger_access_); |
2414 | 2441 |
2415 if (message_handler_ != NULL) { | 2442 if (data.message_handler_ != NULL) { |
2416 message_handler_(message); | 2443 data.message_handler_(message); |
2417 } | 2444 } |
2418 } | 2445 } |
2419 | 2446 |
2420 | 2447 |
2421 // Puts a command coming from the public API on the queue. Creates | 2448 // Puts a command coming from the public API on the queue. Creates |
2422 // a copy of the command string managed by the debugger. Up to this | 2449 // a copy of the command string managed by the debugger. Up to this |
2423 // point, the command data was managed by the API client. Called | 2450 // point, the command data was managed by the API client. Called |
2424 // by the API client thread. | 2451 // by the API client thread. |
2425 void Debugger::ProcessCommand(Vector<const uint16_t> command, | 2452 void Debugger::ProcessCommand(Vector<const uint16_t> command, |
2426 v8::Debug::ClientData* client_data) { | 2453 v8::Debug::ClientData* client_data) { |
2427 // Need to cast away const. | 2454 // Need to cast away const. |
2428 CommandMessage message = CommandMessage::New( | 2455 CommandMessage message = CommandMessage::New( |
2429 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), | 2456 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), |
2430 command.length()), | 2457 command.length()), |
2431 client_data); | 2458 client_data); |
2432 Logger::DebugTag("Put command on command_queue."); | 2459 Logger::DebugTag("Put command on command_queue."); |
2433 command_queue_.Put(message); | 2460 DebuggerData& data = v8_context()->debugger_data_; |
2434 command_received_->Signal(); | 2461 data.command_queue_.Put(message); |
| 2462 data.command_received_->Signal(); |
2435 | 2463 |
2436 // Set the debug command break flag to have the command processed. | 2464 // Set the debug command break flag to have the command processed. |
2437 if (!Debug::InDebugger()) { | 2465 if (!Debug::InDebugger()) { |
2438 StackGuard::DebugCommand(); | 2466 StackGuard::DebugCommand(); |
2439 } | 2467 } |
2440 | 2468 |
2441 if (Debugger::debug_message_dispatch_handler_ != NULL) { | 2469 if (data.debug_message_dispatch_handler_ != NULL) { |
2442 Debugger::debug_message_dispatch_handler_(); | 2470 data.debug_message_dispatch_handler_(); |
2443 } | 2471 } |
2444 } | 2472 } |
2445 | 2473 |
2446 | 2474 |
2447 bool Debugger::HasCommands() { | 2475 bool Debugger::HasCommands() { |
2448 return !command_queue_.IsEmpty(); | 2476 return !v8_context()->debugger_data_.command_queue_.IsEmpty(); |
2449 } | 2477 } |
2450 | 2478 |
2451 | 2479 |
2452 bool Debugger::IsDebuggerActive() { | 2480 bool Debugger::IsDebuggerActive() { |
2453 ScopedLock with(debugger_access_); | 2481 DebuggerData& data = v8_context()->debugger_data_; |
| 2482 ScopedLock with(data.debugger_access_); |
2454 | 2483 |
2455 return message_handler_ != NULL || !event_listener_.is_null(); | 2484 return data.message_handler_ != NULL || !data.event_listener_.is_null(); |
2456 } | 2485 } |
2457 | 2486 |
2458 | 2487 |
2459 Handle<Object> Debugger::Call(Handle<JSFunction> fun, | 2488 Handle<Object> Debugger::Call(Handle<JSFunction> fun, |
2460 Handle<Object> data, | 2489 Handle<Object> data, |
2461 bool* pending_exception) { | 2490 bool* pending_exception) { |
2462 // When calling functions in the debugger prevent it from beeing unloaded. | 2491 // When calling functions in the debugger prevent it from beeing unloaded. |
2463 Debugger::never_unload_debugger_ = true; | 2492 v8_context()->debugger_data_.never_unload_debugger_ = true; |
2464 | 2493 |
2465 // Enter the debugger. | 2494 // Enter the debugger. |
2466 EnterDebugger debugger; | 2495 EnterDebugger debugger; |
2467 if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) { | 2496 if (debugger.FailedToEnter() || !debugger.HasJavaScriptFrames()) { |
2468 return Factory::undefined_value(); | 2497 return Factory::undefined_value(); |
2469 } | 2498 } |
2470 | 2499 |
2471 // Create the execution state. | 2500 // Create the execution state. |
2472 bool caught_exception = false; | 2501 bool caught_exception = false; |
2473 Handle<Object> exec_state = MakeExecutionState(&caught_exception); | 2502 Handle<Object> exec_state = MakeExecutionState(&caught_exception); |
2474 if (caught_exception) { | 2503 if (caught_exception) { |
2475 return Factory::undefined_value(); | 2504 return Factory::undefined_value(); |
2476 } | 2505 } |
2477 | 2506 |
2478 static const int kArgc = 2; | 2507 static const int kArgc = 2; |
2479 Object** argv[kArgc] = { exec_state.location(), data.location() }; | 2508 Object** argv[kArgc] = { exec_state.location(), data.location() }; |
2480 Handle<Object> result = Execution::Call(fun, Factory::undefined_value(), | 2509 Handle<Object> result = Execution::Call(fun, Factory::undefined_value(), |
2481 kArgc, argv, pending_exception); | 2510 kArgc, argv, pending_exception); |
2482 return result; | 2511 return result; |
2483 } | 2512 } |
2484 | 2513 |
2485 | 2514 |
2486 bool Debugger::StartAgent(const char* name, int port) { | 2515 bool Debugger::StartAgent(const char* name, int port) { |
2487 if (Socket::Setup()) { | 2516 if (Socket::Setup()) { |
2488 agent_ = new DebuggerAgent(name, port); | 2517 DebuggerData& data = v8_context()->debugger_data_; |
2489 agent_->Start(); | 2518 data.agent_ = new DebuggerAgent(name, port); |
| 2519 data.agent_->Start(); |
2490 return true; | 2520 return true; |
2491 } | 2521 } |
2492 | 2522 |
2493 return false; | 2523 return false; |
2494 } | 2524 } |
2495 | 2525 |
2496 | 2526 |
2497 void Debugger::StopAgent() { | 2527 void Debugger::StopAgent() { |
2498 if (agent_ != NULL) { | 2528 DebuggerData& data = v8_context()->debugger_data_; |
2499 agent_->Shutdown(); | 2529 if (data.agent_ != NULL) { |
2500 agent_->Join(); | 2530 data.agent_->Shutdown(); |
2501 delete agent_; | 2531 data.agent_->Join(); |
2502 agent_ = NULL; | 2532 delete data.agent_; |
| 2533 data.agent_ = NULL; |
2503 } | 2534 } |
2504 } | 2535 } |
2505 | 2536 |
2506 | 2537 |
2507 void Debugger::WaitForAgent() { | 2538 void Debugger::WaitForAgent() { |
2508 if (agent_ != NULL) | 2539 DebuggerData& data = v8_context()->debugger_data_; |
2509 agent_->WaitUntilListening(); | 2540 if (data.agent_ != NULL) |
| 2541 data.agent_->WaitUntilListening(); |
2510 } | 2542 } |
2511 | 2543 |
2512 MessageImpl MessageImpl::NewEvent(DebugEvent event, | 2544 MessageImpl MessageImpl::NewEvent(DebugEvent event, |
2513 bool running, | 2545 bool running, |
2514 Handle<JSObject> exec_state, | 2546 Handle<JSObject> exec_state, |
2515 Handle<JSObject> event_data) { | 2547 Handle<JSObject> event_data) { |
2516 MessageImpl message(true, event, running, | 2548 MessageImpl message(true, event, running, |
2517 exec_state, event_data, Handle<String>(), NULL); | 2549 exec_state, event_data, Handle<String>(), NULL); |
2518 return message; | 2550 return message; |
2519 } | 2551 } |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2725 | 2757 |
2726 | 2758 |
2727 void LockingCommandMessageQueue::Clear() { | 2759 void LockingCommandMessageQueue::Clear() { |
2728 ScopedLock sl(lock_); | 2760 ScopedLock sl(lock_); |
2729 queue_.Clear(); | 2761 queue_.Clear(); |
2730 } | 2762 } |
2731 | 2763 |
2732 #endif // ENABLE_DEBUGGER_SUPPORT | 2764 #endif // ENABLE_DEBUGGER_SUPPORT |
2733 | 2765 |
2734 } } // namespace v8::internal | 2766 } } // namespace v8::internal |
OLD | NEW |