Index: runtime/vm/pages.cc |
=================================================================== |
--- runtime/vm/pages.cc (revision 32487) |
+++ runtime/vm/pages.cc (working copy) |
@@ -31,6 +31,7 @@ |
"Emit a log message when pointers to unused code are dropped."); |
DEFINE_FLAG(bool, always_drop_code, false, |
"Always try to drop code if the function's usage counter is >= 0"); |
+DECLARE_FLAG(bool, write_protect_code); |
HeapPage* HeapPage::Initialize(VirtualMemory* memory, PageType type) { |
ASSERT(memory->size() > VirtualMemory::PageSize()); |
@@ -109,13 +110,10 @@ |
prot = VirtualMemory::kReadOnly; |
} |
} else { |
- if (executable_) { |
- prot = VirtualMemory::kReadWriteExecute; |
- } else { |
- prot = VirtualMemory::kReadWrite; |
- } |
+ prot = VirtualMemory::kReadWrite; |
} |
- memory_->Protect(prot); |
+ bool status = memory_->Protect(prot); |
+ ASSERT(status); |
} |
@@ -155,7 +153,15 @@ |
if (pages_ == NULL) { |
pages_ = page; |
} else { |
+ const bool is_protected = (pages_tail_->type() == HeapPage::kExecutable) |
+ && FLAG_write_protect_code; |
+ 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; |
@@ -221,7 +227,9 @@ |
ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
uword result = 0; |
if (size < kAllocatablePageSize) { |
- result = freelist_[type].TryAllocate(size); |
+ const bool is_protected = (type == HeapPage::kExecutable) |
+ && FLAG_write_protect_code; |
+ result = freelist_[type].TryAllocate(size, is_protected); |
if ((result == 0) && |
(page_space_controller_.CanGrowPageSpace(size) || |
growth_policy == kForceGrowth) && |
@@ -447,6 +455,24 @@ |
const int64_t start = OS::GetCurrentTimeMicros(); |
+ if (FLAG_write_protect_code) { |
+ // 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_); |
@@ -496,6 +522,24 @@ |
page = next_page; |
} |
+ if (FLAG_write_protect_code) { |
+ // Make code pages read-only. |
+ HeapPage* 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; |