OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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/global-handles.h" | 8 #include "src/global-handles.h" |
9 | 9 |
10 #include "src/vm-state-inl.h" | 10 #include "src/vm-state-inl.h" |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 block_ = block_->next_used(); | 488 block_ = block_->next_used(); |
489 } | 489 } |
490 | 490 |
491 private: | 491 private: |
492 NodeBlock* block_; | 492 NodeBlock* block_; |
493 int index_; | 493 int index_; |
494 | 494 |
495 DISALLOW_COPY_AND_ASSIGN(NodeIterator); | 495 DISALLOW_COPY_AND_ASSIGN(NodeIterator); |
496 }; | 496 }; |
497 | 497 |
| 498 class GlobalHandles::PendingPhantomCallbacksSecondPassTask : public v8::Task { |
| 499 public: |
| 500 // Takes ownership of the contents of pending_phantom_callbacks, leaving it in |
| 501 // the same state it would be after a call to Clear(). |
| 502 PendingPhantomCallbacksSecondPassTask( |
| 503 List<PendingPhantomCallback>* pending_phantom_callbacks, Isolate* isolate) |
| 504 : isolate_(isolate) { |
| 505 pending_phantom_callbacks_.Swap(pending_phantom_callbacks); |
| 506 } |
| 507 |
| 508 ~PendingPhantomCallbacksSecondPassTask() override {} |
| 509 |
| 510 void Run() override { |
| 511 InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate_); |
| 512 } |
| 513 |
| 514 private: |
| 515 List<PendingPhantomCallback> pending_phantom_callbacks_; |
| 516 Isolate* isolate_; |
| 517 |
| 518 DISALLOW_COPY_AND_ASSIGN(PendingPhantomCallbacksSecondPassTask); |
| 519 }; |
| 520 |
498 | 521 |
499 GlobalHandles::GlobalHandles(Isolate* isolate) | 522 GlobalHandles::GlobalHandles(Isolate* isolate) |
500 : isolate_(isolate), | 523 : isolate_(isolate), |
501 number_of_global_handles_(0), | 524 number_of_global_handles_(0), |
502 first_block_(NULL), | 525 first_block_(NULL), |
503 first_used_block_(NULL), | 526 first_used_block_(NULL), |
504 first_free_(NULL), | 527 first_free_(NULL), |
505 post_gc_processing_count_(0), | 528 post_gc_processing_count_(0), |
506 object_group_connections_(kObjectGroupConnectionsCapacity) {} | 529 object_group_connections_(kObjectGroupConnectionsCapacity) {} |
507 | 530 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
702 // Once the entire group has been iterated over, set the object | 725 // Once the entire group has been iterated over, set the object |
703 // group to NULL so it won't be processed again. | 726 // group to NULL so it won't be processed again. |
704 delete entry; | 727 delete entry; |
705 object_groups_.at(i) = NULL; | 728 object_groups_.at(i) = NULL; |
706 } | 729 } |
707 object_groups_.Rewind(last); | 730 object_groups_.Rewind(last); |
708 return any_group_was_visited; | 731 return any_group_was_visited; |
709 } | 732 } |
710 | 733 |
711 | 734 |
| 735 void GlobalHandles::InvokeSecondPassPhantomCallbacks( |
| 736 List<PendingPhantomCallback>* callbacks, Isolate* isolate) { |
| 737 while (callbacks->length() != 0) { |
| 738 auto callback = callbacks->RemoveLast(); |
| 739 DCHECK(callback.node() == nullptr); |
| 740 // No second pass callback required. |
| 741 if (callback.callback() == nullptr) continue; |
| 742 // Fire second pass callback |
| 743 callback.Invoke(isolate); |
| 744 } |
| 745 } |
| 746 |
| 747 |
712 int GlobalHandles::PostScavengeProcessing( | 748 int GlobalHandles::PostScavengeProcessing( |
713 const int initial_post_gc_processing_count) { | 749 const int initial_post_gc_processing_count) { |
714 int freed_nodes = 0; | 750 int freed_nodes = 0; |
715 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 751 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
716 Node* node = new_space_nodes_[i]; | 752 Node* node = new_space_nodes_[i]; |
717 DCHECK(node->is_in_new_space_list()); | 753 DCHECK(node->is_in_new_space_list()); |
718 if (!node->IsRetainer()) { | 754 if (!node->IsRetainer()) { |
719 // Free nodes do not have weak callbacks. Do not use them to compute | 755 // Free nodes do not have weak callbacks. Do not use them to compute |
720 // the freed_nodes. | 756 // the freed_nodes. |
721 continue; | 757 continue; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 } else { | 820 } else { |
785 node->set_in_new_space_list(false); | 821 node->set_in_new_space_list(false); |
786 isolate_->heap()->IncrementNodesDiedInNewSpace(); | 822 isolate_->heap()->IncrementNodesDiedInNewSpace(); |
787 } | 823 } |
788 } | 824 } |
789 new_space_nodes_.Rewind(last); | 825 new_space_nodes_.Rewind(last); |
790 new_space_nodes_.Trim(); | 826 new_space_nodes_.Trim(); |
791 } | 827 } |
792 | 828 |
793 | 829 |
794 int GlobalHandles::DispatchPendingPhantomCallbacks() { | 830 int GlobalHandles::DispatchPendingPhantomCallbacks( |
| 831 bool synchronous_second_pass) { |
795 int freed_nodes = 0; | 832 int freed_nodes = 0; |
796 { | 833 { |
797 // The initial pass callbacks must simply clear the nodes. | 834 // The initial pass callbacks must simply clear the nodes. |
798 for (auto i = pending_phantom_callbacks_.begin(); | 835 for (auto i = pending_phantom_callbacks_.begin(); |
799 i != pending_phantom_callbacks_.end(); ++i) { | 836 i != pending_phantom_callbacks_.end(); ++i) { |
800 auto callback = i; | 837 auto callback = i; |
801 // Skip callbacks that have already been processed once. | 838 // Skip callbacks that have already been processed once. |
802 if (callback->node() == nullptr) continue; | 839 if (callback->node() == nullptr) continue; |
803 callback->Invoke(isolate()); | 840 callback->Invoke(isolate()); |
804 freed_nodes++; | 841 freed_nodes++; |
805 } | 842 } |
806 } | 843 } |
807 // The second pass empties the list. | 844 if (pending_phantom_callbacks_.length() > 0) { |
808 while (pending_phantom_callbacks_.length() != 0) { | 845 if (synchronous_second_pass) { |
809 auto callback = pending_phantom_callbacks_.RemoveLast(); | 846 InvokeSecondPassPhantomCallbacks(&pending_phantom_callbacks_, isolate()); |
810 DCHECK(callback.node() == nullptr); | 847 } else { |
811 // No second pass callback required. | 848 auto* task = new PendingPhantomCallbacksSecondPassTask( |
812 if (callback.callback() == nullptr) continue; | 849 &pending_phantom_callbacks_, isolate()); |
813 // Fire second pass callback. | 850 V8::GetCurrentPlatform()->CallOnForegroundThread( |
814 callback.Invoke(isolate()); | 851 reinterpret_cast<v8::Isolate*>(isolate()), task); |
| 852 } |
815 } | 853 } |
816 pending_phantom_callbacks_.Clear(); | 854 pending_phantom_callbacks_.Clear(); |
817 return freed_nodes; | 855 return freed_nodes; |
818 } | 856 } |
819 | 857 |
820 | 858 |
821 void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) { | 859 void GlobalHandles::PendingPhantomCallback::Invoke(Isolate* isolate) { |
822 Data::Callback* callback_addr = nullptr; | 860 Data::Callback* callback_addr = nullptr; |
823 if (node_ != nullptr) { | 861 if (node_ != nullptr) { |
824 // Initialize for first pass callback. | 862 // Initialize for first pass callback. |
825 DCHECK(node_->state() == Node::NEAR_DEATH); | 863 DCHECK(node_->state() == Node::NEAR_DEATH); |
826 callback_addr = &callback_; | 864 callback_addr = &callback_; |
827 } | 865 } |
828 Data data(reinterpret_cast<v8::Isolate*>(isolate), parameter_, | 866 Data data(reinterpret_cast<v8::Isolate*>(isolate), parameter_, |
829 internal_fields_, callback_addr); | 867 internal_fields_, callback_addr); |
830 Data::Callback callback = callback_; | 868 Data::Callback callback = callback_; |
831 callback_ = nullptr; | 869 callback_ = nullptr; |
832 callback(data); | 870 callback(data); |
833 if (node_ != nullptr) { | 871 if (node_ != nullptr) { |
834 // Transition to second pass state. | 872 // Transition to second pass state. |
835 DCHECK(node_->state() == Node::FREE); | 873 DCHECK(node_->state() == Node::FREE); |
836 node_ = nullptr; | 874 node_ = nullptr; |
837 } | 875 } |
838 } | 876 } |
839 | 877 |
840 | 878 |
841 int GlobalHandles::PostGarbageCollectionProcessing(GarbageCollector collector) { | 879 int GlobalHandles::PostGarbageCollectionProcessing( |
| 880 GarbageCollector collector, const v8::GCCallbackFlags gc_callback_flags) { |
842 // Process weak global handle callbacks. This must be done after the | 881 // Process weak global handle callbacks. This must be done after the |
843 // GC is completely done, because the callbacks may invoke arbitrary | 882 // GC is completely done, because the callbacks may invoke arbitrary |
844 // API functions. | 883 // API functions. |
845 DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 884 DCHECK(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
846 const int initial_post_gc_processing_count = ++post_gc_processing_count_; | 885 const int initial_post_gc_processing_count = ++post_gc_processing_count_; |
847 int freed_nodes = 0; | 886 int freed_nodes = 0; |
848 freed_nodes += DispatchPendingPhantomCallbacks(); | 887 bool synchronous_second_pass = |
| 888 (gc_callback_flags & kGCCallbackFlagForced) != 0; |
| 889 freed_nodes += DispatchPendingPhantomCallbacks(synchronous_second_pass); |
849 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 890 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
850 // If the callbacks caused a nested GC, then return. See comment in | 891 // If the callbacks caused a nested GC, then return. See comment in |
851 // PostScavengeProcessing. | 892 // PostScavengeProcessing. |
852 return freed_nodes; | 893 return freed_nodes; |
853 } | 894 } |
854 if (collector == SCAVENGER) { | 895 if (collector == SCAVENGER) { |
855 freed_nodes += PostScavengeProcessing(initial_post_gc_processing_count); | 896 freed_nodes += PostScavengeProcessing(initial_post_gc_processing_count); |
856 } else { | 897 } else { |
857 freed_nodes += PostMarkSweepProcessing(initial_post_gc_processing_count); | 898 freed_nodes += PostMarkSweepProcessing(initial_post_gc_processing_count); |
858 } | 899 } |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1226 blocks_[block][offset] = object; | 1267 blocks_[block][offset] = object; |
1227 if (isolate->heap()->InNewSpace(object)) { | 1268 if (isolate->heap()->InNewSpace(object)) { |
1228 new_space_indices_.Add(size_); | 1269 new_space_indices_.Add(size_); |
1229 } | 1270 } |
1230 *index = size_++; | 1271 *index = size_++; |
1231 } | 1272 } |
1232 | 1273 |
1233 | 1274 |
1234 } // namespace internal | 1275 } // namespace internal |
1235 } // namespace v8 | 1276 } // namespace v8 |
OLD | NEW |