Index: runtime/vm/pages.cc |
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc |
index 06f15b31e3c6951d9f4ea5532f14ce8aa61cced1..6144a616093a080fa69baa81c53888020b57a57f 100644 |
--- a/runtime/vm/pages.cc |
+++ b/runtime/vm/pages.cc |
@@ -115,7 +115,8 @@ void HeapPage::WriteProtect(bool read_only) { |
prot = VirtualMemory::kReadWrite; |
} |
} |
- memory_->Protect(prot); |
+ bool status = memory_->Protect(prot); |
+ ASSERT(status); |
} |
@@ -153,7 +154,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; |
@@ -219,7 +227,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) && |
@@ -432,6 +441,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_); |
@@ -481,6 +506,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; |