[heap] Register executable MemoryChunks.

Bug: chromium:774108,v8:6792
Change-Id: If0ff62b959b74b7be4e00b04d7a734ab95b8ecb6
Reviewed-on: https://chromium-review.googlesource.com/867040
Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Hannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50610}
This commit is contained in:
Hannes Payer 2018-01-16 09:22:42 +01:00 committed by Commit Bot
parent 852bdba4bf
commit e97daee2e5
3 changed files with 35 additions and 2 deletions

View File

@ -624,6 +624,7 @@ CodeSpaceMemoryModificationScope::CodeSpaceMemoryModificationScope(Heap* heap)
LargePage* page = heap_->lo_space()->first_page();
while (page != nullptr) {
if (page->IsFlagSet(MemoryChunk::IS_EXECUTABLE)) {
CHECK(heap_->memory_allocator()->IsMemoryChunkExecutable(page));
page->SetReadAndWritable();
}
page = page->next_page();
@ -638,6 +639,7 @@ CodeSpaceMemoryModificationScope::~CodeSpaceMemoryModificationScope() {
LargePage* page = heap_->lo_space()->first_page();
while (page != nullptr) {
if (page->IsFlagSet(MemoryChunk::IS_EXECUTABLE)) {
CHECK(heap_->memory_allocator()->IsMemoryChunkExecutable(page));
page->SetReadAndExecutable();
}
page = page->next_page();
@ -654,12 +656,14 @@ CodePageMemoryModificationScope::CodePageMemoryModificationScope(
DCHECK(chunk_->owner()->identity() == CODE_SPACE ||
(chunk_->owner()->identity() == LO_SPACE &&
chunk_->IsFlagSet(MemoryChunk::IS_EXECUTABLE)));
CHECK(chunk_->heap()->memory_allocator()->IsMemoryChunkExecutable(chunk_));
chunk_->SetReadAndWritable();
}
}
CodePageMemoryModificationScope::~CodePageMemoryModificationScope() {
if (scope_active_) {
CHECK(chunk_->heap()->memory_allocator()->IsMemoryChunkExecutable(chunk_));
chunk_->SetReadAndExecutable();
}
}

View File

@ -826,8 +826,13 @@ MemoryChunk* MemoryAllocator::AllocateChunk(size_t reserve_area_size,
owner);
}
return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
MemoryChunk* chunk =
MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
executable, owner, &reservation);
if (executable) RegisterExecutableMemoryChunk(chunk);
return chunk;
}
void Page::ResetAllocatedBytes() { allocated_bytes_ = area_size(); }
@ -970,6 +975,8 @@ void MemoryAllocator::PreFreeMemory(MemoryChunk* chunk) {
}
chunk->SetFlag(MemoryChunk::PRE_FREED);
if (chunk->executable()) UnregisterExecutableMemoryChunk(chunk);
}
@ -1722,6 +1729,7 @@ void PagedSpace::ReleasePage(Page* page) {
void PagedSpace::SetReadAndExecutable() {
DCHECK(identity() == CODE_SPACE);
for (Page* page : *this) {
CHECK(heap_->memory_allocator()->IsMemoryChunkExecutable(page));
page->SetReadAndExecutable();
}
}
@ -1729,6 +1737,7 @@ void PagedSpace::SetReadAndExecutable() {
void PagedSpace::SetReadAndWritable() {
DCHECK(identity() == CODE_SPACE);
for (Page* page : *this) {
CHECK(heap_->memory_allocator()->IsMemoryChunkExecutable(page));
page->SetReadAndWritable();
}
}

View File

@ -1359,6 +1359,12 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
// and false otherwise.
bool CommitBlock(Address start, size_t size, Executability executable);
// Checks if an allocated MemoryChunk was intended to be used for executable
// memory.
bool IsMemoryChunkExecutable(MemoryChunk* chunk) {
return executable_memory_.find(chunk) != executable_memory_.end();
}
// Uncommit a contiguous block of memory [start..(start+size)[.
// start is not nullptr, the size is greater than zero, and the
// block is contained in the initial chunk. Returns true if it succeeded
@ -1409,6 +1415,17 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
} while ((high > ptr) && !highest_ever_allocated_.TrySetValue(ptr, high));
}
void RegisterExecutableMemoryChunk(MemoryChunk* chunk) {
DCHECK(chunk->IsFlagSet(MemoryChunk::IS_EXECUTABLE));
DCHECK_EQ(executable_memory_.find(chunk), executable_memory_.end());
executable_memory_.insert(chunk);
}
void UnregisterExecutableMemoryChunk(MemoryChunk* chunk) {
DCHECK_NE(executable_memory_.find(chunk), executable_memory_.end());
executable_memory_.erase(chunk);
}
Isolate* isolate_;
CodeRange* code_range_;
@ -1431,6 +1448,9 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
VirtualMemory last_chunk_;
Unmapper unmapper_;
// Data structure to remember allocated executable memory chunks.
std::unordered_set<MemoryChunk*> executable_memory_;
friend class heap::TestCodeRangeScope;
DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator);