| 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 |