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

Side by Side Diff: runtime/vm/pages.cc

Issue 1541073002: Implement safepointing of threads (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix-typo Created 4 years, 10 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 | « runtime/vm/os_thread.h ('k') | runtime/vm/parser.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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/pages.h" 5 #include "vm/pages.h"
6 6
7 #include "platform/assert.h" 7 #include "platform/assert.h"
8 #include "vm/compiler_stats.h" 8 #include "vm/compiler_stats.h"
9 #include "vm/gc_marker.h" 9 #include "vm/gc_marker.h"
10 #include "vm/gc_sweeper.h" 10 #include "vm/gc_sweeper.h"
11 #include "vm/lockers.h" 11 #include "vm/lockers.h"
12 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/os_thread.h" 13 #include "vm/os_thread.h"
14 #include "vm/thread_registry.h" 14 #include "vm/safepoint.h"
15 #include "vm/verified_memory.h" 15 #include "vm/verified_memory.h"
16 #include "vm/virtual_memory.h" 16 #include "vm/virtual_memory.h"
17 17
18 namespace dart { 18 namespace dart {
19 19
20 DEFINE_FLAG(int, heap_growth_rate, 0, 20 DEFINE_FLAG(int, heap_growth_rate, 0,
21 "The max number of pages the heap can grow at a time"); 21 "The max number of pages the heap can grow at a time");
22 DEFINE_FLAG(int, old_gen_growth_space_ratio, 20, 22 DEFINE_FLAG(int, old_gen_growth_space_ratio, 20,
23 "The desired maximum percentage of free space after old gen GC"); 23 "The desired maximum percentage of free space after old gen GC");
24 DEFINE_FLAG(int, old_gen_growth_time_ratio, 3, 24 DEFINE_FLAG(int, old_gen_growth_time_ratio, 3,
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
784 if (page->type() == HeapPage::kExecutable) { 784 if (page->type() == HeapPage::kExecutable) {
785 page->WriteProtect(read_only); 785 page->WriteProtect(read_only);
786 } 786 }
787 page = page->next(); 787 page = page->next();
788 } 788 }
789 } 789 }
790 } 790 }
791 791
792 792
793 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 793 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
794 Thread* thread = Thread::Current();
794 Isolate* isolate = heap_->isolate(); 795 Isolate* isolate = heap_->isolate();
795 ASSERT(isolate == Isolate::Current()); 796 ASSERT(isolate == Isolate::Current());
796 797
797 // Wait for pending tasks to complete and then account for the driver task. 798 // Wait for pending tasks to complete and then account for the driver task.
798 { 799 {
799 MonitorLocker locker(tasks_lock()); 800 MonitorLocker locker(tasks_lock());
800 while (tasks() > 0) { 801 while (tasks() > 0) {
801 locker.Wait(); 802 locker.WaitWithSafepointCheck(thread);
802 } 803 }
803 set_tasks(1); 804 set_tasks(1);
804 } 805 }
805 // Ensure that all threads for this isolate are at a safepoint (either stopped 806 // Ensure that all threads for this isolate are at a safepoint (either
806 // or in native code). If two threads are racing at this point, the loser 807 // stopped or in native code). We have guards around Newgen GC and oldgen GC
807 // will continue with its collection after waiting for the winner to complete. 808 // to ensure that if two threads are racing to collect at the same time the
808 // TODO(koda): Consider moving SafepointThreads into allocation failure/retry 809 // loser skips collection and goes straight to allocation.
809 // logic to avoid needless collections. 810 {
810 isolate->thread_registry()->SafepointThreads(); 811 SafepointOperationScope safepoint_scope(thread);
811 812
812 // Perform various cleanup that relies on no tasks interfering. 813 // Perform various cleanup that relies on no tasks interfering.
813 isolate->class_table()->FreeOldTables(); 814 isolate->class_table()->FreeOldTables();
814 815
815 NoSafepointScope no_safepoints; 816 NoSafepointScope no_safepoints;
816 817
817 if (FLAG_print_free_list_before_gc) { 818 if (FLAG_print_free_list_before_gc) {
818 OS::Print("Data Freelist (before GC):\n"); 819 OS::Print("Data Freelist (before GC):\n");
819 freelist_[HeapPage::kData].Print(); 820 freelist_[HeapPage::kData].Print();
820 OS::Print("Executable Freelist (before GC):\n"); 821 OS::Print("Executable Freelist (before GC):\n");
821 freelist_[HeapPage::kExecutable].Print(); 822 freelist_[HeapPage::kExecutable].Print();
822 } 823 }
823 824
824 if (FLAG_verify_before_gc) {
825 OS::PrintErr("Verifying before marking...");
826 heap_->VerifyGC();
827 OS::PrintErr(" done.\n");
828 }
829
830 const int64_t start = OS::GetCurrentTimeMicros();
831
832 // Make code pages writable.
833 WriteProtectCode(false);
834
835 // Save old value before GCMarker visits the weak persistent handles.
836 SpaceUsage usage_before = GetCurrentUsage();
837
838 // Mark all reachable old-gen objects.
839 bool collect_code = FLAG_collect_code && ShouldCollectCode();
840 GCMarker marker(heap_);
841 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
842 usage_.used_in_words = marker.marked_words();
843
844 int64_t mid1 = OS::GetCurrentTimeMicros();
845
846 // Abandon the remainder of the bump allocation block.
847 AbandonBumpAllocation();
848 // Reset the freelists and setup sweeping.
849 freelist_[HeapPage::kData].Reset();
850 freelist_[HeapPage::kExecutable].Reset();
851
852 int64_t mid2 = OS::GetCurrentTimeMicros();
853 int64_t mid3 = 0;
854
855 {
856 if (FLAG_verify_before_gc) { 825 if (FLAG_verify_before_gc) {
857 OS::PrintErr("Verifying before sweeping..."); 826 OS::PrintErr("Verifying before marking...");
858 heap_->VerifyGC(kAllowMarked); 827 heap_->VerifyGC();
859 OS::PrintErr(" done.\n"); 828 OS::PrintErr(" done.\n");
860 } 829 }
861 GCSweeper sweeper;
862 830
863 // During stop-the-world phases we should use bulk lock when adding elements 831 const int64_t start = OS::GetCurrentTimeMicros();
864 // to the free list.
865 MutexLocker mld(freelist_[HeapPage::kData].mutex());
866 MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
867 832
868 // Large and executable pages are always swept immediately. 833 // Make code pages writable.
869 HeapPage* prev_page = NULL; 834 WriteProtectCode(false);
870 HeapPage* page = large_pages_; 835
871 while (page != NULL) { 836 // Save old value before GCMarker visits the weak persistent handles.
872 HeapPage* next_page = page->next(); 837 SpaceUsage usage_before = GetCurrentUsage();
873 const intptr_t words_to_end = sweeper.SweepLargePage(page); 838
874 if (words_to_end == 0) { 839 // Mark all reachable old-gen objects.
875 FreeLargePage(page, prev_page); 840 bool collect_code = FLAG_collect_code && ShouldCollectCode();
876 } else { 841 GCMarker marker(heap_);
877 TruncateLargePage(page, words_to_end << kWordSizeLog2); 842 marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
878 prev_page = page; 843 usage_.used_in_words = marker.marked_words();
844
845 int64_t mid1 = OS::GetCurrentTimeMicros();
846
847 // Abandon the remainder of the bump allocation block.
848 AbandonBumpAllocation();
849 // Reset the freelists and setup sweeping.
850 freelist_[HeapPage::kData].Reset();
851 freelist_[HeapPage::kExecutable].Reset();
852
853 int64_t mid2 = OS::GetCurrentTimeMicros();
854 int64_t mid3 = 0;
855
856 {
857 if (FLAG_verify_before_gc) {
858 OS::PrintErr("Verifying before sweeping...");
859 heap_->VerifyGC(kAllowMarked);
860 OS::PrintErr(" done.\n");
879 } 861 }
880 // Advance to the next page. 862 GCSweeper sweeper;
881 page = next_page;
882 }
883 863
884 prev_page = NULL; 864 // During stop-the-world phases we should use bulk lock when adding
885 page = exec_pages_; 865 // elements to the free list.
886 FreeList* freelist = &freelist_[HeapPage::kExecutable]; 866 MutexLocker mld(freelist_[HeapPage::kData].mutex());
887 while (page != NULL) { 867 MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
888 HeapPage* next_page = page->next();
889 bool page_in_use = sweeper.SweepPage(page, freelist, true);
890 if (page_in_use) {
891 prev_page = page;
892 } else {
893 FreePage(page, prev_page);
894 }
895 // Advance to the next page.
896 page = next_page;
897 }
898 868
899 mid3 = OS::GetCurrentTimeMicros(); 869 // Large and executable pages are always swept immediately.
900 870 HeapPage* prev_page = NULL;
901 if (!FLAG_concurrent_sweep) { 871 HeapPage* page = large_pages_;
902 // Sweep all regular sized pages now.
903 prev_page = NULL;
904 page = pages_;
905 while (page != NULL) { 872 while (page != NULL) {
906 HeapPage* next_page = page->next(); 873 HeapPage* next_page = page->next();
907 bool page_in_use = sweeper.SweepPage( 874 const intptr_t words_to_end = sweeper.SweepLargePage(page);
908 page, &freelist_[page->type()], true); 875 if (words_to_end == 0) {
876 FreeLargePage(page, prev_page);
877 } else {
878 TruncateLargePage(page, words_to_end << kWordSizeLog2);
879 prev_page = page;
880 }
881 // Advance to the next page.
882 page = next_page;
883 }
884
885 prev_page = NULL;
886 page = exec_pages_;
887 FreeList* freelist = &freelist_[HeapPage::kExecutable];
888 while (page != NULL) {
889 HeapPage* next_page = page->next();
890 bool page_in_use = sweeper.SweepPage(page, freelist, true);
909 if (page_in_use) { 891 if (page_in_use) {
910 prev_page = page; 892 prev_page = page;
911 } else { 893 } else {
912 FreePage(page, prev_page); 894 FreePage(page, prev_page);
913 } 895 }
914 // Advance to the next page. 896 // Advance to the next page.
915 page = next_page; 897 page = next_page;
916 } 898 }
917 if (FLAG_verify_after_gc) { 899
918 OS::PrintErr("Verifying after sweeping..."); 900 mid3 = OS::GetCurrentTimeMicros();
919 heap_->VerifyGC(kForbidMarked); 901
920 OS::PrintErr(" done.\n"); 902 if (!FLAG_concurrent_sweep) {
903 // Sweep all regular sized pages now.
904 prev_page = NULL;
905 page = pages_;
906 while (page != NULL) {
907 HeapPage* next_page = page->next();
908 bool page_in_use = sweeper.SweepPage(
909 page, &freelist_[page->type()], true);
910 if (page_in_use) {
911 prev_page = page;
912 } else {
913 FreePage(page, prev_page);
914 }
915 // Advance to the next page.
916 page = next_page;
917 }
918 if (FLAG_verify_after_gc) {
919 OS::PrintErr("Verifying after sweeping...");
920 heap_->VerifyGC(kForbidMarked);
921 OS::PrintErr(" done.\n");
922 }
923 } else {
924 // Start the concurrent sweeper task now.
925 GCSweeper::SweepConcurrent(
926 isolate, pages_, pages_tail_, &freelist_[HeapPage::kData]);
921 } 927 }
922 } else { 928 }
923 // Start the concurrent sweeper task now. 929
924 GCSweeper::SweepConcurrent( 930 // Make code pages read-only.
925 isolate, pages_, pages_tail_, &freelist_[HeapPage::kData]); 931 WriteProtectCode(true);
932
933 int64_t end = OS::GetCurrentTimeMicros();
934
935 // Record signals for growth control. Include size of external allocations.
936 page_space_controller_.EvaluateGarbageCollection(usage_before,
937 GetCurrentUsage(),
938 start, end);
939
940 heap_->RecordTime(kMarkObjects, mid1 - start);
941 heap_->RecordTime(kResetFreeLists, mid2 - mid1);
942 heap_->RecordTime(kSweepPages, mid3 - mid2);
943 heap_->RecordTime(kSweepLargePages, end - mid3);
944
945 if (FLAG_print_free_list_after_gc) {
946 OS::Print("Data Freelist (after GC):\n");
947 freelist_[HeapPage::kData].Print();
948 OS::Print("Executable Freelist (after GC):\n");
949 freelist_[HeapPage::kExecutable].Print();
950 }
951
952 UpdateMaxUsed();
953 if (heap_ != NULL) {
954 heap_->UpdateGlobalMaxUsed();
926 } 955 }
927 } 956 }
928 957
929 // Make code pages read-only.
930 WriteProtectCode(true);
931
932 int64_t end = OS::GetCurrentTimeMicros();
933
934 // Record signals for growth control. Include size of external allocations.
935 page_space_controller_.EvaluateGarbageCollection(usage_before,
936 GetCurrentUsage(),
937 start, end);
938
939 heap_->RecordTime(kMarkObjects, mid1 - start);
940 heap_->RecordTime(kResetFreeLists, mid2 - mid1);
941 heap_->RecordTime(kSweepPages, mid3 - mid2);
942 heap_->RecordTime(kSweepLargePages, end - mid3);
943
944 if (FLAG_print_free_list_after_gc) {
945 OS::Print("Data Freelist (after GC):\n");
946 freelist_[HeapPage::kData].Print();
947 OS::Print("Executable Freelist (after GC):\n");
948 freelist_[HeapPage::kExecutable].Print();
949 }
950
951 UpdateMaxUsed();
952 if (heap_ != NULL) {
953 heap_->UpdateGlobalMaxUsed();
954 }
955
956 isolate->thread_registry()->ResumeAllThreads();
957
958 // Done, reset the task count. 958 // Done, reset the task count.
959 { 959 {
960 MonitorLocker ml(tasks_lock()); 960 MonitorLocker ml(tasks_lock());
961 set_tasks(tasks() - 1); 961 set_tasks(tasks() - 1);
962 ml.Notify(); 962 ml.Notify();
963 } 963 }
964 } 964 }
965 965
966 966
967 uword PageSpace::TryAllocateDataBumpInternal(intptr_t size, 967 uword PageSpace::TryAllocateDataBumpInternal(intptr_t size,
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 return 0; 1215 return 0;
1216 } else { 1216 } else {
1217 ASSERT(total_time >= gc_time); 1217 ASSERT(total_time >= gc_time);
1218 int result = static_cast<int>((static_cast<double>(gc_time) / 1218 int result = static_cast<int>((static_cast<double>(gc_time) /
1219 static_cast<double>(total_time)) * 100); 1219 static_cast<double>(total_time)) * 100);
1220 return result; 1220 return result;
1221 } 1221 }
1222 } 1222 }
1223 1223
1224 } // namespace dart 1224 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/os_thread.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698