Index: runtime/vm/pages.cc |
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc |
index be05e9781aeae7e7e87cac7bc8e3a71eb30f778a..b6cc61fe162eb2ede2b00e8c4aba1b960d75e00e 100644 |
--- a/runtime/vm/pages.cc |
+++ b/runtime/vm/pages.cc |
@@ -111,7 +111,8 @@ void HeapPage::WriteProtect(bool read_only) { |
prot = VirtualMemory::kReadWrite; |
} |
} |
- memory_->Protect(prot); |
+ bool status = memory_->Protect(prot); |
+ ASSERT(status); |
} |
@@ -149,7 +150,14 @@ HeapPage* PageSpace::AllocatePage(HeapPage::PageType type) { |
if (pages_ == NULL) { |
pages_ = page; |
} else { |
+ const bool is_protected = (pages_tail_->type() == HeapPage::kExecutable); |
+ if (is_protected) { |
+ pages_tail_->WriteProtect(false); |
+ } |
pages_tail_->set_next(page); |
+ if (is_protected) { |
+ pages_tail_->WriteProtect(true); |
+ } |
} |
pages_tail_ = page; |
capacity_in_words_ += kPageSizeInWords; |
@@ -215,7 +223,8 @@ uword PageSpace::TryAllocate(intptr_t size, |
ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
uword result = 0; |
if (size < kAllocatablePageSize) { |
- result = freelist_[type].TryAllocate(size); |
+ const bool is_protected = (type == HeapPage::kExecutable); |
+ result = freelist_[type].TryAllocate(size, is_protected); |
if ((result == 0) && |
(page_space_controller_.CanGrowPageSpace(size) || |
growth_policy == kForceGrowth) && |
@@ -428,6 +437,22 @@ void PageSpace::MarkSweep(bool invoke_api_callbacks) { |
const int64_t start = OS::GetCurrentTimeMicros(); |
+ // Make code pages writable. |
+ HeapPage* current_page = pages_; |
+ while (current_page != NULL) { |
+ if (current_page->type() == HeapPage::kExecutable) { |
+ current_page->WriteProtect(false); |
+ } |
+ current_page = current_page->next(); |
+ } |
+ current_page = large_pages_; |
+ while (current_page != NULL) { |
+ if (current_page->type() == HeapPage::kExecutable) { |
+ current_page->WriteProtect(false); |
+ } |
+ current_page = current_page->next(); |
+ } |
+ |
// Mark all reachable old-gen objects. |
bool collect_code = FLAG_collect_code && ShouldCollectCode(); |
GCMarker marker(heap_); |
@@ -477,6 +502,22 @@ void PageSpace::MarkSweep(bool invoke_api_callbacks) { |
page = next_page; |
} |
+ // Make code pages read-only. |
+ current_page = pages_; |
+ while (current_page != NULL) { |
+ if (current_page->type() == HeapPage::kExecutable) { |
+ current_page->WriteProtect(true); |
+ } |
+ current_page = current_page->next(); |
+ } |
+ current_page = large_pages_; |
+ while (current_page != NULL) { |
+ if (current_page->type() == HeapPage::kExecutable) { |
+ current_page->WriteProtect(true); |
+ } |
+ current_page = current_page->next(); |
+ } |
+ |
// Record data and print if requested. |
intptr_t used_before_in_words = used_in_words_; |
used_in_words_ = used_in_words; |