[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:
parent
852bdba4bf
commit
e97daee2e5
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user