Commit 8cd72a71 authored by Hannes Payer's avatar Hannes Payer Committed by Commit Bot

[heap] Reland register executable MemoryChunks.

Bug: chromium:774108,v8:6792
Change-Id: I4736b86ad5bd5e0777dc7a121023c4ed34d69fb0
Reviewed-on: https://chromium-review.googlesource.com/873170
Commit-Queue: Hannes Payer <hpayer@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50683}
parent 8432d381
......@@ -626,6 +626,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();
......@@ -640,6 +641,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();
......
......@@ -2658,6 +2658,7 @@ class AlwaysAllocateScope {
Heap* heap_;
};
// The CodeSpaceMemoryModificationScope can only be used by the main thread.
class CodeSpaceMemoryModificationScope {
public:
explicit inline CodeSpaceMemoryModificationScope(Heap* heap);
......@@ -2667,6 +2668,9 @@ class CodeSpaceMemoryModificationScope {
Heap* heap_;
};
// The CodePageMemoryModificationScope does not check if tansitions to
// writeable and back to executable are actually allowed, i.e. the MemoryChunk
// was registered to be executable. It can be used by concurrent threads.
class CodePageMemoryModificationScope {
public:
explicit inline CodePageMemoryModificationScope(MemoryChunk* chunk);
......
......@@ -826,8 +826,13 @@ MemoryChunk* MemoryAllocator::AllocateChunk(size_t reserve_area_size,
owner);
}
return MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
executable, owner, &reservation);
MemoryChunk* chunk =
MemoryChunk::Initialize(heap, base, chunk_size, area_start, area_end,
executable, owner, &reservation);
if (chunk->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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment