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

Unified 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, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/os_thread.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/pages.cc
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 5d5df0e2d559398f7494b34059206646c3399233..0397b2ae5332e17bc040f4594ba791885e793729 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -11,7 +11,7 @@
#include "vm/lockers.h"
#include "vm/object.h"
#include "vm/os_thread.h"
-#include "vm/thread_registry.h"
+#include "vm/safepoint.h"
#include "vm/verified_memory.h"
#include "vm/virtual_memory.h"
@@ -791,6 +791,7 @@ void PageSpace::WriteProtectCode(bool read_only) {
void PageSpace::MarkSweep(bool invoke_api_callbacks) {
+ Thread* thread = Thread::Current();
Isolate* isolate = heap_->isolate();
ASSERT(isolate == Isolate::Current());
@@ -798,114 +799,95 @@ void PageSpace::MarkSweep(bool invoke_api_callbacks) {
{
MonitorLocker locker(tasks_lock());
while (tasks() > 0) {
- locker.Wait();
+ locker.WaitWithSafepointCheck(thread);
}
set_tasks(1);
}
- // Ensure that all threads for this isolate are at a safepoint (either stopped
- // or in native code). If two threads are racing at this point, the loser
- // will continue with its collection after waiting for the winner to complete.
- // TODO(koda): Consider moving SafepointThreads into allocation failure/retry
- // logic to avoid needless collections.
- isolate->thread_registry()->SafepointThreads();
-
- // Perform various cleanup that relies on no tasks interfering.
- isolate->class_table()->FreeOldTables();
-
- NoSafepointScope no_safepoints;
-
- if (FLAG_print_free_list_before_gc) {
- OS::Print("Data Freelist (before GC):\n");
- freelist_[HeapPage::kData].Print();
- OS::Print("Executable Freelist (before GC):\n");
- freelist_[HeapPage::kExecutable].Print();
- }
+ // Ensure that all threads for this isolate are at a safepoint (either
+ // stopped or in native code). We have guards around Newgen GC and oldgen GC
+ // to ensure that if two threads are racing to collect at the same time the
+ // loser skips collection and goes straight to allocation.
+ {
+ SafepointOperationScope safepoint_scope(thread);
- if (FLAG_verify_before_gc) {
- OS::PrintErr("Verifying before marking...");
- heap_->VerifyGC();
- OS::PrintErr(" done.\n");
- }
+ // Perform various cleanup that relies on no tasks interfering.
+ isolate->class_table()->FreeOldTables();
- const int64_t start = OS::GetCurrentTimeMicros();
+ NoSafepointScope no_safepoints;
- // Make code pages writable.
- WriteProtectCode(false);
+ if (FLAG_print_free_list_before_gc) {
+ OS::Print("Data Freelist (before GC):\n");
+ freelist_[HeapPage::kData].Print();
+ OS::Print("Executable Freelist (before GC):\n");
+ freelist_[HeapPage::kExecutable].Print();
+ }
- // Save old value before GCMarker visits the weak persistent handles.
- SpaceUsage usage_before = GetCurrentUsage();
+ if (FLAG_verify_before_gc) {
+ OS::PrintErr("Verifying before marking...");
+ heap_->VerifyGC();
+ OS::PrintErr(" done.\n");
+ }
- // Mark all reachable old-gen objects.
- bool collect_code = FLAG_collect_code && ShouldCollectCode();
- GCMarker marker(heap_);
- marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
- usage_.used_in_words = marker.marked_words();
+ const int64_t start = OS::GetCurrentTimeMicros();
- int64_t mid1 = OS::GetCurrentTimeMicros();
+ // Make code pages writable.
+ WriteProtectCode(false);
- // Abandon the remainder of the bump allocation block.
- AbandonBumpAllocation();
- // Reset the freelists and setup sweeping.
- freelist_[HeapPage::kData].Reset();
- freelist_[HeapPage::kExecutable].Reset();
+ // Save old value before GCMarker visits the weak persistent handles.
+ SpaceUsage usage_before = GetCurrentUsage();
- int64_t mid2 = OS::GetCurrentTimeMicros();
- int64_t mid3 = 0;
+ // Mark all reachable old-gen objects.
+ bool collect_code = FLAG_collect_code && ShouldCollectCode();
+ GCMarker marker(heap_);
+ marker.MarkObjects(isolate, this, invoke_api_callbacks, collect_code);
+ usage_.used_in_words = marker.marked_words();
- {
- if (FLAG_verify_before_gc) {
- OS::PrintErr("Verifying before sweeping...");
- heap_->VerifyGC(kAllowMarked);
- OS::PrintErr(" done.\n");
- }
- GCSweeper sweeper;
+ int64_t mid1 = OS::GetCurrentTimeMicros();
- // During stop-the-world phases we should use bulk lock when adding elements
- // to the free list.
- MutexLocker mld(freelist_[HeapPage::kData].mutex());
- MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
+ // Abandon the remainder of the bump allocation block.
+ AbandonBumpAllocation();
+ // Reset the freelists and setup sweeping.
+ freelist_[HeapPage::kData].Reset();
+ freelist_[HeapPage::kExecutable].Reset();
- // Large and executable pages are always swept immediately.
- HeapPage* prev_page = NULL;
- HeapPage* page = large_pages_;
- while (page != NULL) {
- HeapPage* next_page = page->next();
- const intptr_t words_to_end = sweeper.SweepLargePage(page);
- if (words_to_end == 0) {
- FreeLargePage(page, prev_page);
- } else {
- TruncateLargePage(page, words_to_end << kWordSizeLog2);
- prev_page = page;
- }
- // Advance to the next page.
- page = next_page;
- }
+ int64_t mid2 = OS::GetCurrentTimeMicros();
+ int64_t mid3 = 0;
- prev_page = NULL;
- page = exec_pages_;
- FreeList* freelist = &freelist_[HeapPage::kExecutable];
- while (page != NULL) {
- HeapPage* next_page = page->next();
- bool page_in_use = sweeper.SweepPage(page, freelist, true);
- if (page_in_use) {
- prev_page = page;
- } else {
- FreePage(page, prev_page);
+ {
+ if (FLAG_verify_before_gc) {
+ OS::PrintErr("Verifying before sweeping...");
+ heap_->VerifyGC(kAllowMarked);
+ OS::PrintErr(" done.\n");
}
- // Advance to the next page.
- page = next_page;
- }
+ GCSweeper sweeper;
- mid3 = OS::GetCurrentTimeMicros();
+ // During stop-the-world phases we should use bulk lock when adding
+ // elements to the free list.
+ MutexLocker mld(freelist_[HeapPage::kData].mutex());
+ MutexLocker mle(freelist_[HeapPage::kExecutable].mutex());
+
+ // Large and executable pages are always swept immediately.
+ HeapPage* prev_page = NULL;
+ HeapPage* page = large_pages_;
+ while (page != NULL) {
+ HeapPage* next_page = page->next();
+ const intptr_t words_to_end = sweeper.SweepLargePage(page);
+ if (words_to_end == 0) {
+ FreeLargePage(page, prev_page);
+ } else {
+ TruncateLargePage(page, words_to_end << kWordSizeLog2);
+ prev_page = page;
+ }
+ // Advance to the next page.
+ page = next_page;
+ }
- if (!FLAG_concurrent_sweep) {
- // Sweep all regular sized pages now.
prev_page = NULL;
- page = pages_;
+ page = exec_pages_;
+ FreeList* freelist = &freelist_[HeapPage::kExecutable];
while (page != NULL) {
HeapPage* next_page = page->next();
- bool page_in_use = sweeper.SweepPage(
- page, &freelist_[page->type()], true);
+ bool page_in_use = sweeper.SweepPage(page, freelist, true);
if (page_in_use) {
prev_page = page;
} else {
@@ -914,47 +896,65 @@ void PageSpace::MarkSweep(bool invoke_api_callbacks) {
// Advance to the next page.
page = next_page;
}
- if (FLAG_verify_after_gc) {
- OS::PrintErr("Verifying after sweeping...");
- heap_->VerifyGC(kForbidMarked);
- OS::PrintErr(" done.\n");
+
+ mid3 = OS::GetCurrentTimeMicros();
+
+ if (!FLAG_concurrent_sweep) {
+ // Sweep all regular sized pages now.
+ prev_page = NULL;
+ page = pages_;
+ while (page != NULL) {
+ HeapPage* next_page = page->next();
+ bool page_in_use = sweeper.SweepPage(
+ page, &freelist_[page->type()], true);
+ if (page_in_use) {
+ prev_page = page;
+ } else {
+ FreePage(page, prev_page);
+ }
+ // Advance to the next page.
+ page = next_page;
+ }
+ if (FLAG_verify_after_gc) {
+ OS::PrintErr("Verifying after sweeping...");
+ heap_->VerifyGC(kForbidMarked);
+ OS::PrintErr(" done.\n");
+ }
+ } else {
+ // Start the concurrent sweeper task now.
+ GCSweeper::SweepConcurrent(
+ isolate, pages_, pages_tail_, &freelist_[HeapPage::kData]);
}
- } else {
- // Start the concurrent sweeper task now.
- GCSweeper::SweepConcurrent(
- isolate, pages_, pages_tail_, &freelist_[HeapPage::kData]);
}
- }
- // Make code pages read-only.
- WriteProtectCode(true);
+ // Make code pages read-only.
+ WriteProtectCode(true);
- int64_t end = OS::GetCurrentTimeMicros();
+ int64_t end = OS::GetCurrentTimeMicros();
- // Record signals for growth control. Include size of external allocations.
- page_space_controller_.EvaluateGarbageCollection(usage_before,
- GetCurrentUsage(),
- start, end);
+ // Record signals for growth control. Include size of external allocations.
+ page_space_controller_.EvaluateGarbageCollection(usage_before,
+ GetCurrentUsage(),
+ start, end);
- heap_->RecordTime(kMarkObjects, mid1 - start);
- heap_->RecordTime(kResetFreeLists, mid2 - mid1);
- heap_->RecordTime(kSweepPages, mid3 - mid2);
- heap_->RecordTime(kSweepLargePages, end - mid3);
+ heap_->RecordTime(kMarkObjects, mid1 - start);
+ heap_->RecordTime(kResetFreeLists, mid2 - mid1);
+ heap_->RecordTime(kSweepPages, mid3 - mid2);
+ heap_->RecordTime(kSweepLargePages, end - mid3);
- if (FLAG_print_free_list_after_gc) {
- OS::Print("Data Freelist (after GC):\n");
- freelist_[HeapPage::kData].Print();
- OS::Print("Executable Freelist (after GC):\n");
- freelist_[HeapPage::kExecutable].Print();
- }
+ if (FLAG_print_free_list_after_gc) {
+ OS::Print("Data Freelist (after GC):\n");
+ freelist_[HeapPage::kData].Print();
+ OS::Print("Executable Freelist (after GC):\n");
+ freelist_[HeapPage::kExecutable].Print();
+ }
- UpdateMaxUsed();
- if (heap_ != NULL) {
- heap_->UpdateGlobalMaxUsed();
+ UpdateMaxUsed();
+ if (heap_ != NULL) {
+ heap_->UpdateGlobalMaxUsed();
+ }
}
- isolate->thread_registry()->ResumeAllThreads();
-
// Done, reset the task count.
{
MonitorLocker ml(tasks_lock());
« 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