Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: src/global-handles.cc

Issue 1209403005: Let the second pass phantom callbacks run in a separate task on the foreground thread. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Run second pass callbacks synchronously when GC is forced. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/global-handles.h ('k') | src/heap/heap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/global-handles.h ('k') | src/heap/heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698