Commit 51224eab authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ptr-compr] Explicitly pass v8::PageAllocator instance to helper functions.

... like AllocatePage[s](), FreePages() and SetPermissions().
This CL also changes base::PageAllocator to cache AllocatePageSize and CommitPageSize
values returned by the OS.
This is a necessary cleanup before introducing BoundedPageAllocator.

Bug: v8:8096
Change-Id: Ifb7cdd2caa6a1b029ce0fca6545c61df9d281be2
Reviewed-on: https://chromium-review.googlesource.com/1209343Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55690}
parent 98bdaf98
......@@ -57,15 +57,17 @@ struct InitializePageAllocator {
static base::LazyInstance<v8::PageAllocator*, InitializePageAllocator>::type
page_allocator = LAZY_INSTANCE_INITIALIZER;
v8::PageAllocator* GetPageAllocator() { return page_allocator.Get(); }
// We will attempt allocation this many times. After each failure, we call
// OnCriticalMemoryPressure to try to free some memory.
const int kAllocationTries = 2;
} // namespace
v8::PageAllocator* GetPlatformPageAllocator() {
DCHECK_NOT_NULL(page_allocator.Get());
return page_allocator.Get();
}
void* Malloced::New(size_t size) {
void* result = AllocWithRetry(size);
if (result == nullptr) {
......@@ -131,26 +133,31 @@ void AlignedFree(void *ptr) {
#endif
}
size_t AllocatePageSize() { return GetPageAllocator()->AllocatePageSize(); }
size_t AllocatePageSize() {
return GetPlatformPageAllocator()->AllocatePageSize();
}
size_t CommitPageSize() { return GetPageAllocator()->CommitPageSize(); }
size_t CommitPageSize() { return GetPlatformPageAllocator()->CommitPageSize(); }
void SetRandomMmapSeed(int64_t seed) {
GetPageAllocator()->SetRandomMmapSeed(seed);
GetPlatformPageAllocator()->SetRandomMmapSeed(seed);
}
void* GetRandomMmapAddr() { return GetPageAllocator()->GetRandomMmapAddr(); }
void* GetRandomMmapAddr() {
return GetPlatformPageAllocator()->GetRandomMmapAddr();
}
void* AllocatePages(void* address, size_t size, size_t alignment,
void* AllocatePages(v8::PageAllocator* page_allocator, void* address,
size_t size, size_t alignment,
PageAllocator::Permission access) {
DCHECK_NOT_NULL(page_allocator);
DCHECK_EQ(address, AlignedAddress(address, alignment));
DCHECK_EQ(0UL, size & (GetPageAllocator()->AllocatePageSize() - 1));
DCHECK_EQ(0UL, size & (page_allocator->AllocatePageSize() - 1));
void* result = nullptr;
for (int i = 0; i < kAllocationTries; ++i) {
result =
GetPageAllocator()->AllocatePages(address, size, alignment, access);
result = page_allocator->AllocatePages(address, size, alignment, access);
if (result != nullptr) break;
size_t request_size = size + alignment - AllocatePageSize();
size_t request_size = size + alignment - page_allocator->AllocatePageSize();
if (!OnCriticalMemoryPressure(request_size)) break;
}
#if defined(LEAK_SANITIZER)
......@@ -161,9 +168,11 @@ void* AllocatePages(void* address, size_t size, size_t alignment,
return result;
}
bool FreePages(void* address, const size_t size) {
DCHECK_EQ(0UL, size & (GetPageAllocator()->AllocatePageSize() - 1));
bool result = GetPageAllocator()->FreePages(address, size);
bool FreePages(v8::PageAllocator* page_allocator, void* address,
const size_t size) {
DCHECK_NOT_NULL(page_allocator);
DCHECK_EQ(0UL, size & (page_allocator->AllocatePageSize() - 1));
bool result = page_allocator->FreePages(address, size);
#if defined(LEAK_SANITIZER)
if (result) {
__lsan_unregister_root_region(address, size);
......@@ -172,9 +181,11 @@ bool FreePages(void* address, const size_t size) {
return result;
}
bool ReleasePages(void* address, size_t size, size_t new_size) {
bool ReleasePages(v8::PageAllocator* page_allocator, void* address, size_t size,
size_t new_size) {
DCHECK_NOT_NULL(page_allocator);
DCHECK_LT(new_size, size);
bool result = GetPageAllocator()->ReleasePages(address, size, new_size);
bool result = page_allocator->ReleasePages(address, size, new_size);
#if defined(LEAK_SANITIZER)
if (result) {
__lsan_unregister_root_region(address, size);
......@@ -184,15 +195,18 @@ bool ReleasePages(void* address, size_t size, size_t new_size) {
return result;
}
bool SetPermissions(void* address, size_t size,
PageAllocator::Permission access) {
return GetPageAllocator()->SetPermissions(address, size, access);
bool SetPermissions(v8::PageAllocator* page_allocator, void* address,
size_t size, PageAllocator::Permission access) {
DCHECK_NOT_NULL(page_allocator);
return page_allocator->SetPermissions(address, size, access);
}
byte* AllocatePage(void* address, size_t* allocated) {
size_t page_size = AllocatePageSize();
void* result =
AllocatePages(address, page_size, page_size, PageAllocator::kReadWrite);
byte* AllocatePage(v8::PageAllocator* page_allocator, void* address,
size_t* allocated) {
DCHECK_NOT_NULL(page_allocator);
size_t page_size = page_allocator->AllocatePageSize();
void* result = AllocatePages(page_allocator, address, page_size, page_size,
PageAllocator::kReadWrite);
if (result != nullptr) *allocated = page_size;
return static_cast<byte*>(result);
}
......@@ -206,14 +220,19 @@ bool OnCriticalMemoryPressure(size_t length) {
return true;
}
VirtualMemory::VirtualMemory() : address_(kNullAddress), size_(0) {}
VirtualMemory::VirtualMemory()
: page_allocator_(GetPlatformPageAllocator()),
address_(kNullAddress),
size_(0) {}
VirtualMemory::VirtualMemory(size_t size, void* hint, size_t alignment)
: address_(kNullAddress), size_(0) {
size_t page_size = AllocatePageSize();
: page_allocator_(GetPlatformPageAllocator()),
address_(kNullAddress),
size_(0) {
size_t page_size = page_allocator_->AllocatePageSize();
size_t alloc_size = RoundUp(size, page_size);
address_ = reinterpret_cast<Address>(
AllocatePages(hint, alloc_size, alignment, PageAllocator::kNoAccess));
address_ = reinterpret_cast<Address>(AllocatePages(
page_allocator_, hint, alloc_size, alignment, PageAllocator::kNoAccess));
if (address_ != kNullAddress) {
size_ = alloc_size;
}
......@@ -233,21 +252,22 @@ void VirtualMemory::Reset() {
bool VirtualMemory::SetPermissions(Address address, size_t size,
PageAllocator::Permission access) {
CHECK(InVM(address, size));
bool result = v8::internal::SetPermissions(address, size, access);
bool result =
v8::internal::SetPermissions(page_allocator_, address, size, access);
DCHECK(result);
return result;
}
size_t VirtualMemory::Release(Address free_start) {
DCHECK(IsReserved());
DCHECK(IsAddressAligned(free_start, CommitPageSize()));
DCHECK(IsAddressAligned(free_start, page_allocator_->CommitPageSize()));
// Notice: Order is important here. The VirtualMemory object might live
// inside the allocated region.
const size_t free_size = size_ - (free_start - address_);
CHECK(InVM(free_start, free_size));
DCHECK_LT(address_, free_start);
DCHECK_LT(free_start, address_ + size_);
CHECK(ReleasePages(reinterpret_cast<void*>(address_), size_,
CHECK(ReleasePages(page_allocator_, reinterpret_cast<void*>(address_), size_,
size_ - free_size));
size_ -= free_size;
return free_size;
......@@ -263,12 +283,13 @@ void VirtualMemory::Free() {
Reset();
// FreePages expects size to be aligned to allocation granularity. Trimming
// may leave size at only commit granularity. Align it here.
CHECK(FreePages(reinterpret_cast<void*>(address),
RoundUp(size, AllocatePageSize())));
CHECK(FreePages(page_allocator_, reinterpret_cast<void*>(address),
RoundUp(size, page_allocator_->AllocatePageSize())));
}
void VirtualMemory::TakeControl(VirtualMemory* from) {
DCHECK(!IsReserved());
page_allocator_ = from->page_allocator_;
address_ = from->address_;
size_ = from->size_;
from->Reset();
......
......@@ -82,6 +82,9 @@ void* AllocWithRetry(size_t size);
void* AlignedAlloc(size_t size, size_t alignment);
void AlignedFree(void *ptr);
// Returns platfrom page allocator instance. Guaranteed to be a valid pointer.
V8_EXPORT_PRIVATE v8::PageAllocator* GetPlatformPageAllocator();
// Gets the page granularity for AllocatePages and FreePages. Addresses returned
// by AllocatePages and AllocatePage are aligned to this size.
V8_EXPORT_PRIVATE size_t AllocatePageSize();
......@@ -101,14 +104,16 @@ V8_EXPORT_PRIVATE void* GetRandomMmapAddr();
// AllocatePageSize(). Returns the address of the allocated memory, with the
// specified size and alignment, or nullptr on failure.
V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT void* AllocatePages(void* address, size_t size,
V8_WARN_UNUSED_RESULT void* AllocatePages(v8::PageAllocator* page_allocator,
void* address, size_t size,
size_t alignment,
PageAllocator::Permission access);
// Frees memory allocated by a call to AllocatePages. |address| and |size| must
// be multiples of AllocatePageSize(). Returns true on success, otherwise false.
V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT bool FreePages(void* address, const size_t size);
V8_WARN_UNUSED_RESULT bool FreePages(v8::PageAllocator* page_allocator,
void* address, const size_t size);
// Releases memory that is no longer needed. The range specified by |address|
// and |size| must be an allocated memory region. |size| and |new_size| must be
......@@ -116,7 +121,8 @@ V8_WARN_UNUSED_RESULT bool FreePages(void* address, const size_t size);
// Released memory is left in an undefined state, so it should not be accessed.
// Returns true on success, otherwise false.
V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT bool ReleasePages(void* address, size_t size,
V8_WARN_UNUSED_RESULT bool ReleasePages(v8::PageAllocator* page_allocator,
void* address, size_t size,
size_t new_size);
// Sets permissions according to |access|. |address| and |size| must be
......@@ -124,18 +130,21 @@ V8_WARN_UNUSED_RESULT bool ReleasePages(void* address, size_t size,
// cause the memory contents to be lost. Returns true on success, otherwise
// false.
V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT bool SetPermissions(void* address, size_t size,
V8_WARN_UNUSED_RESULT bool SetPermissions(v8::PageAllocator* page_allocator,
void* address, size_t size,
PageAllocator::Permission access);
inline bool SetPermissions(Address address, size_t size,
PageAllocator::Permission access) {
return SetPermissions(reinterpret_cast<void*>(address), size, access);
inline bool SetPermissions(v8::PageAllocator* page_allocator, Address address,
size_t size, PageAllocator::Permission access) {
return SetPermissions(page_allocator, reinterpret_cast<void*>(address), size,
access);
}
// Convenience function that allocates a single system page with read and write
// permissions. |address| is a hint. Returns the base address of the memory and
// the page size via |allocated| on success. Returns nullptr on failure.
V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT byte* AllocatePage(void* address, size_t* allocated);
V8_WARN_UNUSED_RESULT byte* AllocatePage(v8::PageAllocator* page_allocator,
void* address, size_t* allocated);
// Function that may release reserved memory regions to allow failed allocations
// to succeed. |length| is the amount of memory needed. Returns |true| if memory
......@@ -156,7 +165,9 @@ class V8_EXPORT_PRIVATE VirtualMemory {
// Construct a virtual memory by assigning it some already mapped address
// and size.
VirtualMemory(Address address, size_t size)
: address_(address), size_(size) {}
: page_allocator_(GetPlatformPageAllocator()),
address_(address),
size_(size) {}
// Releases the reserved memory, if any, controlled by this VirtualMemory
// object.
......@@ -168,6 +179,8 @@ class V8_EXPORT_PRIVATE VirtualMemory {
// Initialize or resets an embedded VirtualMemory object.
void Reset();
v8::PageAllocator* page_allocator() { return page_allocator_; }
// Returns the start address of the reserved memory.
// If the memory was reserved with an alignment, this address is not
// necessarily aligned. The user might need to round it up to a multiple of
......@@ -208,6 +221,8 @@ class V8_EXPORT_PRIVATE VirtualMemory {
}
private:
// Page allocator that controls the virtual memory.
v8::PageAllocator* page_allocator_;
Address address_; // Start address of the virtual memory.
size_t size_; // Size of the virtual memory.
};
......
......@@ -24,8 +24,10 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
#if defined(USE_SIMULATOR)
return stub;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return stub;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -170,7 +172,8 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif
}
......@@ -182,8 +185,10 @@ MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
#if defined(USE_SIMULATOR)
return stub;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return stub;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -259,7 +264,8 @@ MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
masm.GetCode(isolate, &desc);
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer);
#endif
}
......@@ -269,8 +275,10 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -286,7 +294,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif
}
......
......@@ -24,11 +24,9 @@ STATIC_ASSERT_ENUM(PageAllocator::kReadExecute,
#undef STATIC_ASSERT_ENUM
size_t PageAllocator::AllocatePageSize() {
return base::OS::AllocatePageSize();
}
size_t PageAllocator::CommitPageSize() { return base::OS::CommitPageSize(); }
PageAllocator::PageAllocator()
: allocate_page_size_(base::OS::AllocatePageSize()),
commit_page_size_(base::OS::CommitPageSize()) {}
void PageAllocator::SetRandomMmapSeed(int64_t seed) {
base::OS::SetRandomMmapSeed(seed);
......
......@@ -15,11 +15,12 @@ namespace base {
class V8_BASE_EXPORT PageAllocator
: public NON_EXPORTED_BASE(::v8::PageAllocator) {
public:
PageAllocator();
virtual ~PageAllocator() = default;
size_t AllocatePageSize() override;
size_t AllocatePageSize() override { return allocate_page_size_; }
size_t CommitPageSize() override;
size_t CommitPageSize() override { return commit_page_size_; }
void SetRandomMmapSeed(int64_t seed) override;
......@@ -34,6 +35,10 @@ class V8_BASE_EXPORT PageAllocator
bool SetPermissions(void* address, size_t size,
PageAllocator::Permission access) override;
private:
const size_t allocate_page_size_;
const size_t commit_page_size_;
};
} // namespace base
......
......@@ -118,18 +118,20 @@ class ShellArrayBufferAllocator : public ArrayBufferAllocatorBase {
// store their lengths as a SMI internally.
if (length >= kTwoGB) return nullptr;
size_t page_size = i::AllocatePageSize();
v8::PageAllocator* page_allocator = i::GetPlatformPageAllocator();
size_t page_size = page_allocator->AllocatePageSize();
size_t allocated = RoundUp(length, page_size);
// Rounding up could go over the limit.
if (allocated >= kTwoGB) return nullptr;
return i::AllocatePages(nullptr, allocated, page_size,
return i::AllocatePages(page_allocator, nullptr, allocated, page_size,
PageAllocator::kReadWrite);
}
void FreeVM(void* data, size_t length) {
size_t page_size = i::AllocatePageSize();
v8::PageAllocator* page_allocator = i::GetPlatformPageAllocator();
size_t page_size = page_allocator->AllocatePageSize();
size_t allocated = RoundUp(length, page_size);
CHECK(i::FreePages(data, allocated));
CHECK(i::FreePages(page_allocator, data, allocated));
}
};
......
......@@ -304,6 +304,8 @@ void CodeRangeAddressHint::NotifyFreedCodeRange(void* code_range_start,
MemoryAllocator::MemoryAllocator(Isolate* isolate, size_t capacity,
size_t code_range_size)
: isolate_(isolate),
data_page_allocator_(GetPlatformPageAllocator()),
code_page_allocator_(GetPlatformPageAllocator()),
code_range_(nullptr),
capacity_(RoundUp(capacity, Page::kPageSize)),
size_(0),
......@@ -490,7 +492,9 @@ size_t MemoryAllocator::Unmapper::CommittedBufferedMemory() {
}
bool MemoryAllocator::CommitMemory(Address base, size_t size) {
if (!SetPermissions(base, size, PageAllocator::kReadWrite)) {
// TODO(ishell): use proper page allocator
if (!SetPermissions(GetPlatformPageAllocator(), base, size,
PageAllocator::kReadWrite)) {
return false;
}
UpdateAllocatedSpaceLimits(base, base + size);
......@@ -499,7 +503,7 @@ bool MemoryAllocator::CommitMemory(Address base, size_t size) {
void MemoryAllocator::FreeMemory(VirtualMemory* reservation,
Executability executable) {
// TODO(gc) make code_range part of memory allocator?
// TODO(ishell): make code_range part of memory allocator?
// Code which is part of the code-range does not have its own VirtualMemory.
DCHECK(code_range() == nullptr ||
!code_range()->contains(reservation->address()));
......@@ -512,13 +516,13 @@ void MemoryAllocator::FreeMemory(VirtualMemory* reservation,
void MemoryAllocator::FreeMemory(Address base, size_t size,
Executability executable) {
// TODO(gc) make code_range part of memory allocator?
// TODO(ishell): make code_range part of memory allocator?
if (code_range() != nullptr && code_range()->contains(base)) {
DCHECK(executable == EXECUTABLE);
code_range()->FreeRawMemory(base, size);
} else {
DCHECK(executable == NOT_EXECUTABLE || !code_range()->valid());
CHECK(FreePages(reinterpret_cast<void*>(base), size));
CHECK(FreePages(data_page_allocator_, reinterpret_cast<void*>(base), size));
}
}
......@@ -608,8 +612,10 @@ void MemoryChunk::SetReadAndExecutable() {
size_t page_size = MemoryAllocator::GetCommitPageSize();
DCHECK(IsAddressAligned(protect_start, page_size));
size_t protect_size = RoundUp(area_size(), page_size);
CHECK(SetPermissions(protect_start, protect_size,
PageAllocator::kReadExecute));
// TODO(ishell): use reservation_.SetPermissions() once it's always
// initialized.
CHECK(SetPermissions(reservation_.page_allocator(), protect_start,
protect_size, PageAllocator::kReadExecute));
}
}
......@@ -627,8 +633,10 @@ void MemoryChunk::SetReadAndWritable() {
size_t page_size = MemoryAllocator::GetCommitPageSize();
DCHECK(IsAddressAligned(unprotect_start, page_size));
size_t unprotect_size = RoundUp(area_size(), page_size);
CHECK(SetPermissions(unprotect_start, unprotect_size,
PageAllocator::kReadWrite));
// TODO(ishell): use reservation_.SetPermissions() once it's always
// initialized.
CHECK(SetPermissions(reservation_.page_allocator(), unprotect_start,
unprotect_size, PageAllocator::kReadWrite));
}
}
......@@ -696,7 +704,9 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
size_t page_size = MemoryAllocator::GetCommitPageSize();
DCHECK(IsAddressAligned(area_start, page_size));
size_t area_size = RoundUp(area_end - area_start, page_size);
CHECK(SetPermissions(area_start, area_size,
// TODO(ishell): use reservation->SetPermissions() once it's always
// initialized.
CHECK(SetPermissions(reservation->page_allocator(), area_start, area_size,
PageAllocator::kReadWriteExecute));
}
}
......@@ -928,7 +938,7 @@ MemoryChunk* MemoryAllocator::AllocateChunk(size_t reserve_area_size,
if ((base + chunk_size) == 0u) {
CHECK(!last_chunk_.IsReserved());
last_chunk_.TakeControl(&reservation);
UncommitBlock(last_chunk_.address(), last_chunk_.size());
UncommitBlock(&last_chunk_, last_chunk_.address(), last_chunk_.size());
size_ -= chunk_size;
if (executable == EXECUTABLE) {
size_executable_ -= chunk_size;
......@@ -1128,7 +1138,8 @@ void MemoryAllocator::PerformFreeMemory(MemoryChunk* chunk) {
VirtualMemory* reservation = chunk->reserved_memory();
if (chunk->IsFlagSet(MemoryChunk::POOLED)) {
UncommitBlock(reinterpret_cast<Address>(chunk), MemoryChunk::kPageSize);
UncommitBlock(reservation, reinterpret_cast<Address>(chunk),
MemoryChunk::kPageSize);
} else {
if (reservation->IsReserved()) {
FreeMemory(reservation, chunk->executable());
......@@ -1237,9 +1248,13 @@ bool MemoryAllocator::CommitBlock(Address start, size_t size) {
return true;
}
bool MemoryAllocator::UncommitBlock(Address start, size_t size) {
if (!SetPermissions(start, size, PageAllocator::kNoAccess)) return false;
bool MemoryAllocator::UncommitBlock(VirtualMemory* reservation, Address start,
size_t size) {
// TODO(ishell): use reservation->SetPermissions() once it's always
// initialized.
if (!SetPermissions(reservation->page_allocator(), start, size,
PageAllocator::kNoAccess))
return false;
isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size));
return true;
}
......@@ -3342,7 +3357,10 @@ void ReadOnlySpace::SetPermissionsForPages(PageAllocator::Permission access) {
if (access == PageAllocator::kRead) {
page->MakeHeaderRelocatable();
}
CHECK(SetPermissions(page->address() + area_start_offset,
// TODO(ishell): use p->reserved_memory()->SetPermissions() once it's always
// initialized.
CHECK(SetPermissions(page->reserved_memory()->page_allocator(),
page->address() + area_start_offset,
page->size() - area_start_offset, access));
}
}
......
......@@ -363,7 +363,7 @@ class MemoryChunk {
+ kUIntptrSize // uintptr_t flags_
+ kPointerSize // Address area_start_
+ kPointerSize // Address area_end_
+ 2 * kPointerSize // VirtualMemory reservation_
+ 3 * kPointerSize // VirtualMemory reservation_
+ kPointerSize // Address owner_
+ kPointerSize // Heap* heap_
+ kIntptrSize // intptr_t progress_bar_
......@@ -894,6 +894,9 @@ class ReadOnlyPage : public Page {
// Clears any pointers in the header that point out of the page that would
// otherwise make the header non-relocatable.
void MakeHeaderRelocatable();
private:
friend class ReadOnlySpace;
};
class LargePage : public MemoryChunk {
......@@ -1456,7 +1459,7 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
// start is not kNullAddress, the size is greater than zero, and the
// block is contained in the initial chunk. Returns true if it succeeded
// and false otherwise.
bool UncommitBlock(Address start, size_t size);
bool UncommitBlock(VirtualMemory* reservation, Address start, size_t size);
// Zaps a contiguous block of memory [start..(start+size)[ with
// a given zap value.
......@@ -1467,6 +1470,14 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
size_t commit_size,
size_t reserved_size);
// Page allocator instance for allocating non-executable pages.
// Guaranteed to be a valid pointer.
v8::PageAllocator* data_page_allocator() { return data_page_allocator_; }
// Page allocator instance for allocating executable pages.
// Guaranteed to be a valid pointer.
v8::PageAllocator* code_page_allocator() { return code_page_allocator_; }
CodeRange* code_range() { return code_range_; }
Unmapper* unmapper() { return &unmapper_; }
......@@ -1518,6 +1529,10 @@ class V8_EXPORT_PRIVATE MemoryAllocator {
}
Isolate* isolate_;
v8::PageAllocator* data_page_allocator_;
v8::PageAllocator* code_page_allocator_;
CodeRange* code_range_;
// Maximum space size in bytes.
......
......@@ -16,8 +16,10 @@ namespace internal {
#define __ masm.
UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -39,7 +41,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
}
......@@ -131,8 +134,10 @@ class LabelConverter {
MemMoveFunction CreateMemMoveFunction(Isolate* isolate) {
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -450,7 +455,8 @@ MemMoveFunction CreateMemMoveFunction(Isolate* isolate) {
masm.GetCode(isolate, &desc);
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
// TODO(jkummerow): It would be nice to register this code creation event
// with the PROFILE / GDBJIT system.
return FUNCTION_CAST<MemMoveFunction>(buffer);
......
......@@ -51,16 +51,18 @@ void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
uint32_t* size) {
EmbeddedData d = EmbeddedData::FromIsolate(isolate);
const uint32_t page_size = static_cast<uint32_t>(AllocatePageSize());
v8::PageAllocator* page_allocator = v8::internal::GetPlatformPageAllocator();
const uint32_t page_size =
static_cast<uint32_t>(page_allocator->AllocatePageSize());
const uint32_t allocated_size = RoundUp(d.size(), page_size);
uint8_t* allocated_bytes = static_cast<uint8_t*>(
AllocatePages(GetRandomMmapAddr(), allocated_size, page_size,
PageAllocator::kReadWrite));
AllocatePages(page_allocator, isolate->heap()->GetRandomMmapAddr(),
allocated_size, page_size, PageAllocator::kReadWrite));
CHECK_NOT_NULL(allocated_bytes);
std::memcpy(allocated_bytes, d.data(), d.size());
CHECK(SetPermissions(allocated_bytes, allocated_size,
CHECK(SetPermissions(page_allocator, allocated_bytes, allocated_size,
PageAllocator::kReadExecute));
*data = allocated_bytes;
......@@ -72,8 +74,10 @@ void InstructionStream::CreateOffHeapInstructionStream(Isolate* isolate,
// static
void InstructionStream::FreeOffHeapInstructionStream(uint8_t* data,
uint32_t size) {
const uint32_t page_size = static_cast<uint32_t>(AllocatePageSize());
CHECK(FreePages(data, RoundUp(size, page_size)));
v8::PageAllocator* page_allocator = v8::internal::GetPlatformPageAllocator();
const uint32_t page_size =
static_cast<uint32_t>(page_allocator->AllocatePageSize());
CHECK(FreePages(page_allocator, data, RoundUp(size, page_size)));
}
} // namespace internal
......
......@@ -24,8 +24,10 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
defined(_MIPS_ARCH_MIPS32RX)
return stub;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -545,7 +547,8 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif
}
......@@ -555,8 +558,10 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -572,7 +577,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif
}
......
......@@ -23,9 +23,10 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
#if defined(USE_SIMULATOR)
return stub;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return stub;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -546,7 +547,8 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif
}
......@@ -556,8 +558,10 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -573,7 +577,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif
}
......
......@@ -76,7 +76,8 @@ void JSArrayBuffer::FreeBackingStore(Isolate* isolate, Allocation allocation) {
isolate->wasm_engine()->memory_tracker();
if (!memory_tracker->FreeMemoryIfIsWasmMemory(isolate,
allocation.backing_store)) {
CHECK(FreePages(allocation.allocation_base, allocation.length));
CHECK(FreePages(GetPlatformPageAllocator(), allocation.allocation_base,
allocation.length));
}
} else {
isolate->array_buffer_allocator()->Free(allocation.allocation_base,
......
......@@ -20,8 +20,10 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -41,7 +43,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif
}
......
......@@ -20,8 +20,10 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
#if defined(USE_SIMULATOR)
return nullptr;
#else
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -38,7 +40,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif
}
......
......@@ -640,6 +640,7 @@ void NativeModule::PatchJumpTable(uint32_t func_index, Address target,
}
Address NativeModule::AllocateForCode(size_t size) {
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
// This happens under a lock assumed by the caller.
size = RoundUp(size, kCodeAlignment);
AddressRange mem = free_code_space_.Allocate(size);
......@@ -660,8 +661,8 @@ Address NativeModule::AllocateForCode(size_t size) {
mem = free_code_space_.Allocate(size);
if (mem.is_empty()) return kNullAddress;
}
Address commit_start = RoundUp(mem.start, AllocatePageSize());
Address commit_end = RoundUp(mem.end, AllocatePageSize());
Address commit_start = RoundUp(mem.start, page_allocator->AllocatePageSize());
Address commit_end = RoundUp(mem.end, page_allocator->AllocatePageSize());
// {commit_start} will be either mem.start or the start of the next page.
// {commit_end} will be the start of the page after the one in which
// the allocation ends.
......@@ -683,7 +684,7 @@ Address NativeModule::AllocateForCode(size_t size) {
if (commit_end > it->end() || it->address() >= commit_end) continue;
Address start = std::max(commit_start, it->address());
size_t commit_size = static_cast<size_t>(commit_end - start);
DCHECK(IsAligned(commit_size, AllocatePageSize()));
DCHECK(IsAligned(commit_size, page_allocator->AllocatePageSize()));
if (!wasm_code_manager_->Commit(start, commit_size)) {
return kNullAddress;
}
......@@ -692,7 +693,7 @@ Address NativeModule::AllocateForCode(size_t size) {
}
#else
size_t commit_size = static_cast<size_t>(commit_end - commit_start);
DCHECK(IsAligned(commit_size, AllocatePageSize()));
DCHECK(IsAligned(commit_size, page_allocator->AllocatePageSize()));
if (!wasm_code_manager_->Commit(commit_start, commit_size)) {
return kNullAddress;
}
......@@ -783,7 +784,8 @@ bool WasmCodeManager::Commit(Address start, size_t size) {
? PageAllocator::kReadWrite
: PageAllocator::kReadWriteExecute;
bool ret = SetPermissions(start, size, permission);
bool ret =
SetPermissions(GetPlatformPageAllocator(), start, size, permission);
TRACE_HEAP("Setting rw permissions for %p:%p\n",
reinterpret_cast<void*>(start),
reinterpret_cast<void*>(start + size));
......@@ -909,6 +911,8 @@ bool NativeModule::SetExecutable(bool executable) {
if (is_executable_ == executable) return true;
TRACE_HEAP("Setting module %p as executable: %d.\n", this, executable);
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
if (FLAG_wasm_write_protect_code_memory) {
PageAllocator::Permission permission =
executable ? PageAllocator::kReadExecute : PageAllocator::kReadWrite;
......@@ -923,7 +927,8 @@ bool NativeModule::SetExecutable(bool executable) {
// committed or not.
if (can_request_more_memory_) {
for (auto& vmem : owned_code_space_) {
if (!SetPermissions(vmem.address(), vmem.size(), permission)) {
if (!SetPermissions(page_allocator, vmem.address(), vmem.size(),
permission)) {
return false;
}
TRACE_HEAP("Set %p:%p to executable:%d\n", vmem.address(), vmem.end(),
......@@ -936,8 +941,10 @@ bool NativeModule::SetExecutable(bool executable) {
for (auto& range : allocated_code_space_.ranges()) {
// allocated_code_space_ is fine-grained, so we need to
// page-align it.
size_t range_size = RoundUp(range.size(), AllocatePageSize());
if (!SetPermissions(range.start, range_size, permission)) {
size_t range_size =
RoundUp(range.size(), page_allocator->AllocatePageSize());
if (!SetPermissions(page_allocator, range.start, range_size,
permission)) {
return false;
}
TRACE_HEAP("Set %p:%p to executable:%d\n",
......
......@@ -77,8 +77,9 @@ void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
}
// The Reserve makes the whole region inaccessible by default.
*allocation_base = AllocatePages(nullptr, *allocation_length, kWasmPageSize,
PageAllocator::kNoAccess);
*allocation_base =
AllocatePages(GetPlatformPageAllocator(), nullptr, *allocation_length,
kWasmPageSize, PageAllocator::kNoAccess);
if (*allocation_base == nullptr) {
memory_tracker->ReleaseReservation(*allocation_length);
AddAllocationStatusSample(heap->isolate(), AllocationStatus::kOtherFailure);
......@@ -91,8 +92,9 @@ void* TryAllocateBackingStore(WasmMemoryTracker* memory_tracker, Heap* heap,
// Make the part we care about accessible.
if (size > 0) {
bool result = SetPermissions(memory, RoundUp(size, kWasmPageSize),
PageAllocator::kReadWrite);
bool result =
SetPermissions(GetPlatformPageAllocator(), memory,
RoundUp(size, kWasmPageSize), PageAllocator::kReadWrite);
// SetPermissions commits the extra memory, which may put us over the
// process memory limit. If so, report this as an OOM.
if (!result) {
......@@ -225,7 +227,8 @@ bool WasmMemoryTracker::FreeMemoryIfIsWasmMemory(Isolate* isolate,
const void* buffer_start) {
if (IsWasmMemory(buffer_start)) {
const AllocationData allocation = ReleaseAllocation(isolate, buffer_start);
CHECK(FreePages(allocation.allocation_base, allocation.allocation_length));
CHECK(FreePages(GetPlatformPageAllocator(), allocation.allocation_base,
allocation.allocation_length));
return true;
}
return false;
......
......@@ -904,8 +904,8 @@ MaybeHandle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
DCHECK_NOT_NULL(old_buffer->backing_store());
// If adjusting permissions fails, propagate error back to return
// failure to grow.
if (!i::SetPermissions(old_mem_start, new_size,
PageAllocator::kReadWrite)) {
if (!i::SetPermissions(GetPlatformPageAllocator(), old_mem_start,
new_size, PageAllocator::kReadWrite)) {
return {};
}
reinterpret_cast<v8::Isolate*>(isolate)
......
......@@ -15,8 +15,10 @@ namespace internal {
#define __ masm.
UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
v8::PageAllocator* page_allocator = GetPlatformPageAllocator();
size_t allocated = 0;
byte* buffer = AllocatePage(isolate->heap()->GetRandomMmapAddr(), &allocated);
byte* buffer = AllocatePage(page_allocator,
isolate->heap()->GetRandomMmapAddr(), &allocated);
if (buffer == nullptr) return nullptr;
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
......@@ -32,7 +34,8 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
Assembler::FlushICache(buffer, allocated);
CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
CHECK(SetPermissions(page_allocator, buffer, allocated,
PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
}
......
......@@ -90,6 +90,11 @@ static void VerifyMemoryChunk(Isolate* isolate, Heap* heap,
TestMemoryAllocatorScope test_allocator_scope(isolate, memory_allocator);
TestCodeRangeScope test_code_range_scope(isolate, code_range);
v8::PageAllocator* data_page_allocator =
memory_allocator->data_page_allocator();
v8::PageAllocator* code_page_allocator =
memory_allocator->code_page_allocator();
size_t header_size = (executable == EXECUTABLE)
? MemoryAllocator::CodePageGuardStartOffset()
: MemoryChunk::kObjectStartOffset;
......@@ -100,12 +105,13 @@ static void VerifyMemoryChunk(Isolate* isolate, Heap* heap,
reserve_area_size, commit_area_size, executable, space);
size_t alignment = code_range != nullptr && code_range->valid()
? MemoryChunk::kAlignment
: CommitPageSize();
: code_page_allocator->CommitPageSize();
size_t reserved_size =
((executable == EXECUTABLE))
? RoundUp(header_size + guard_size + reserve_area_size + guard_size,
alignment)
: RoundUp(header_size + reserve_area_size, CommitPageSize());
: RoundUp(header_size + reserve_area_size,
data_page_allocator->CommitPageSize());
CHECK(memory_chunk->size() == reserved_size);
CHECK(memory_chunk->area_start() <
memory_chunk->address() + memory_chunk->size());
......
......@@ -17,7 +17,8 @@ static inline uint8_t* AllocateAssemblerBuffer(
size_t page_size = v8::internal::AllocatePageSize();
size_t alloc_size = RoundUp(requested, page_size);
void* result = v8::internal::AllocatePages(
address, alloc_size, page_size, v8::PageAllocator::kReadWriteExecute);
GetPlatformPageAllocator(), address, alloc_size, page_size,
v8::PageAllocator::kReadWriteExecute);
CHECK(result);
*allocated = alloc_size;
return static_cast<uint8_t*>(result);
......@@ -25,8 +26,9 @@ static inline uint8_t* AllocateAssemblerBuffer(
static inline void MakeAssemblerBufferExecutable(uint8_t* buffer,
size_t allocated) {
bool result = v8::internal::SetPermissions(buffer, allocated,
v8::PageAllocator::kReadExecute);
bool result =
v8::internal::SetPermissions(GetPlatformPageAllocator(), buffer,
allocated, v8::PageAllocator::kReadExecute);
CHECK(result);
// Flush the instruction cache as part of making the buffer executable.
......@@ -35,8 +37,9 @@ static inline void MakeAssemblerBufferExecutable(uint8_t* buffer,
static inline void MakeAssemblerBufferWritable(uint8_t* buffer,
size_t allocated) {
bool result = v8::internal::SetPermissions(buffer, allocated,
v8::PageAllocator::kReadWrite);
bool result =
v8::internal::SetPermissions(GetPlatformPageAllocator(), buffer,
allocated, v8::PageAllocator::kReadWrite);
CHECK(result);
}
......
......@@ -95,12 +95,14 @@ class MemoryAllocationPermissionsTest : public ::testing::Test {
void TestPermissions(PageAllocator::Permission permission, bool can_read,
bool can_write) {
const size_t page_size = AllocatePageSize();
int* buffer = static_cast<int*>(
AllocatePages(nullptr, page_size, page_size, permission));
v8::PageAllocator* page_allocator =
v8::internal::GetPlatformPageAllocator();
const size_t page_size = page_allocator->AllocatePageSize();
int* buffer = static_cast<int*>(AllocatePages(
page_allocator, nullptr, page_size, page_size, permission));
ProbeMemory(buffer, MemoryAction::kRead, can_read);
ProbeMemory(buffer, MemoryAction::kWrite, can_write);
CHECK(FreePages(buffer, page_size));
CHECK(FreePages(page_allocator, buffer, page_size));
}
};
......@@ -125,41 +127,46 @@ TEST(AllocationTest, AllocateAndFree) {
size_t page_size = v8::internal::AllocatePageSize();
CHECK_NE(0, page_size);
v8::PageAllocator* page_allocator = v8::internal::GetPlatformPageAllocator();
// A large allocation, aligned at native allocation granularity.
const size_t kAllocationSize = 1 * v8::internal::MB;
void* mem_addr = v8::internal::AllocatePages(
v8::internal::GetRandomMmapAddr(), kAllocationSize, page_size,
PageAllocator::Permission::kReadWrite);
page_allocator, page_allocator->GetRandomMmapAddr(), kAllocationSize,
page_size, PageAllocator::Permission::kReadWrite);
CHECK_NOT_NULL(mem_addr);
CHECK(v8::internal::FreePages(mem_addr, kAllocationSize));
CHECK(v8::internal::FreePages(page_allocator, mem_addr, kAllocationSize));
// A large allocation, aligned significantly beyond native granularity.
const size_t kBigAlignment = 64 * v8::internal::MB;
void* aligned_mem_addr = v8::internal::AllocatePages(
AlignedAddress(v8::internal::GetRandomMmapAddr(), kBigAlignment),
page_allocator,
AlignedAddress(page_allocator->GetRandomMmapAddr(), kBigAlignment),
kAllocationSize, kBigAlignment, PageAllocator::Permission::kReadWrite);
CHECK_NOT_NULL(aligned_mem_addr);
CHECK_EQ(aligned_mem_addr, AlignedAddress(aligned_mem_addr, kBigAlignment));
CHECK(v8::internal::FreePages(aligned_mem_addr, kAllocationSize));
CHECK(v8::internal::FreePages(page_allocator, aligned_mem_addr,
kAllocationSize));
}
TEST(AllocationTest, ReserveMemory) {
v8::PageAllocator* page_allocator = v8::internal::GetPlatformPageAllocator();
size_t page_size = v8::internal::AllocatePageSize();
const size_t kAllocationSize = 1 * v8::internal::MB;
void* mem_addr = v8::internal::AllocatePages(
v8::internal::GetRandomMmapAddr(), kAllocationSize, page_size,
PageAllocator::Permission::kReadWrite);
page_allocator, page_allocator->GetRandomMmapAddr(), kAllocationSize,
page_size, PageAllocator::Permission::kReadWrite);
CHECK_NE(0, page_size);
CHECK_NOT_NULL(mem_addr);
size_t commit_size = v8::internal::CommitPageSize();
CHECK(v8::internal::SetPermissions(mem_addr, commit_size,
size_t commit_size = page_allocator->CommitPageSize();
CHECK(v8::internal::SetPermissions(page_allocator, mem_addr, commit_size,
PageAllocator::Permission::kReadWrite));
// Check whether we can write to memory.
int* addr = static_cast<int*>(mem_addr);
addr[v8::internal::KB - 1] = 2;
CHECK(v8::internal::SetPermissions(mem_addr, commit_size,
CHECK(v8::internal::SetPermissions(page_allocator, mem_addr, commit_size,
PageAllocator::Permission::kNoAccess));
CHECK(v8::internal::FreePages(mem_addr, kAllocationSize));
CHECK(v8::internal::FreePages(page_allocator, mem_addr, kAllocationSize));
}
} // namespace internal
......
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