Commit 699144a2 authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

[Memory] Add PageAllocator concept to v8::Platform.

- Adds abstract base class PageAllocator, defined in v8-platform.h. Adds
  GetPageAllocator method to v8::Platform.
- Implements a DefaultPageAllocator, implemented in terms of base::OS
  page allocation methods.

Bug: chromium:756050
Cq-Include-Trybots: master.tryserver.chromium.linux:linux_chromium_rel_ng
Change-Id: Iece0b261a07294a49c30ac25e848dc39cb1a32e2
Reviewed-on: https://chromium-review.googlesource.com/809778
Commit-Queue: Bill Budge <bbudge@chromium.org>
Reviewed-by: 's avatarHannes Payer <hpayer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50282}
parent efdbc429
...@@ -2525,6 +2525,8 @@ v8_component("v8_libbase") { ...@@ -2525,6 +2525,8 @@ v8_component("v8_libbase") {
"src/base/once.cc", "src/base/once.cc",
"src/base/once.h", "src/base/once.h",
"src/base/optional.h", "src/base/optional.h",
"src/base/page-allocator.cc",
"src/base/page-allocator.h",
"src/base/platform/condition-variable.cc", "src/base/platform/condition-variable.cc",
"src/base/platform/condition-variable.h", "src/base/platform/condition-variable.h",
"src/base/platform/elapsed-timer.h", "src/base/platform/elapsed-timer.h",
......
...@@ -157,6 +157,74 @@ class TracingController { ...@@ -157,6 +157,74 @@ class TracingController {
virtual void RemoveTraceStateObserver(TraceStateObserver*) {} virtual void RemoveTraceStateObserver(TraceStateObserver*) {}
}; };
/**
* A V8 page memory allocator.
*
* Can be implemented by an embedder to manage large host OS allocations.
*/
class PageAllocator {
public:
virtual ~PageAllocator() = default;
/**
* Gets the page granularity for AllocatePages and FreePages. Addresses and
* lengths for those calls should be multiples of AllocatePageSize().
*/
virtual size_t AllocatePageSize() = 0;
/**
* Gets the page granularity for SetPermissions and ReleasePages. Addresses
* and lengths for those calls should be multiples of CommitPageSize().
*/
virtual size_t CommitPageSize() = 0;
/**
* Sets the random seed so that GetRandomMmapAddr() will generate repeatable
* sequences of random mmap addresses.
*/
virtual void SetRandomMmapSeed(int64_t seed) = 0;
/**
* Returns a randomized address, suitable for memory allocation under ASLR.
* The address will be aligned to AllocatePageSize.
*/
virtual void* GetRandomMmapAddr() = 0;
/**
* Memory permissions.
*/
enum Permission {
kNoAccess,
kReadWrite,
// TODO(hpayer): Remove this flag. Memory should never be rwx.
kReadWriteExecute,
kReadExecute
};
/**
* Allocates memory in range with the given alignment and permission.
*/
virtual void* AllocatePages(void* address, size_t length, size_t alignment,
Permission permissions) = 0;
/**
* Frees memory in a range that was allocated by a call to AllocatePages.
*/
virtual bool FreePages(void* address, size_t length) = 0;
/**
* Releases memory in a range that was allocated by a call to AllocatePages.
*/
virtual bool ReleasePages(void* address, size_t length,
size_t new_length) = 0;
/**
* Sets permissions on pages in an allocated range.
*/
virtual bool SetPermissions(void* address, size_t length,
Permission permissions) = 0;
};
/** /**
* V8 Platform abstraction layer. * V8 Platform abstraction layer.
* *
...@@ -177,6 +245,14 @@ class Platform { ...@@ -177,6 +245,14 @@ class Platform {
virtual ~Platform() = default; virtual ~Platform() = default;
/**
* Allows the embedder to manage large memory allocations.
*/
virtual PageAllocator* GetPageAllocator() {
// TODO(bbudge) Make this abstract after all embedders implement this.
return nullptr;
}
/** /**
* Enables the embedder to respond in cases where V8 can't allocate large * Enables the embedder to respond in cases where V8 can't allocate large
* blocks of memory. V8 retries the failed allocation once after calling this * blocks of memory. V8 retries the failed allocation once after calling this
...@@ -184,7 +260,12 @@ class Platform { ...@@ -184,7 +260,12 @@ class Platform {
* error. * error.
* Embedder overrides of this function must NOT call back into V8. * Embedder overrides of this function must NOT call back into V8.
*/ */
virtual void OnCriticalMemoryPressure() {} virtual void OnCriticalMemoryPressure() {
// TODO(bbudge) Change this method by adding a failed_allocation_size
// parameter, and to return a bool. This will allow embedders to manage a
// reserve, rather than simply release it all on a failure.
// See crbug.com/634547.
}
/** /**
* Gets the number of threads that are used to execute background tasks. Is * Gets the number of threads that are used to execute background tasks. Is
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
#include <stdlib.h> // For free, malloc. #include <stdlib.h> // For free, malloc.
#include "src/base/bits.h" #include "src/base/bits.h"
#include "src/base/lazy-instance.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/utils.h" #include "src/utils.h"
#include "src/v8.h" #include "src/v8.h"
...@@ -38,6 +40,26 @@ void* AlignedAllocInternal(size_t size, size_t alignment) { ...@@ -38,6 +40,26 @@ void* AlignedAllocInternal(size_t size, size_t alignment) {
return ptr; return ptr;
} }
// TODO(bbudge) Simplify this once all embedders implement a page allocator.
struct InitializePageAllocator {
static void Construct(void* page_allocator_ptr_arg) {
auto page_allocator_ptr =
reinterpret_cast<v8::PageAllocator**>(page_allocator_ptr_arg);
v8::PageAllocator* page_allocator =
V8::GetCurrentPlatform()->GetPageAllocator();
if (page_allocator == nullptr) {
static v8::base::PageAllocator default_allocator;
page_allocator = &default_allocator;
}
*page_allocator_ptr = page_allocator;
}
};
static base::LazyInstance<v8::PageAllocator*, InitializePageAllocator>::type
page_allocator = LAZY_INSTANCE_INITIALIZER;
v8::PageAllocator* GetPageAllocator() { return page_allocator.Get(); }
} // namespace } // namespace
void* Malloced::New(size_t size) { void* Malloced::New(size_t size) {
...@@ -103,109 +125,59 @@ void AlignedFree(void *ptr) { ...@@ -103,109 +125,59 @@ void AlignedFree(void *ptr) {
#endif #endif
} }
#define STATIC_ASSERT_ENUM(a, b) \ size_t AllocatePageSize() { return GetPageAllocator()->AllocatePageSize(); }
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enum: " #a)
STATIC_ASSERT_ENUM(MemoryPermission::kNoAccess,
base::OS::MemoryPermission::kNoAccess);
STATIC_ASSERT_ENUM(MemoryPermission::kReadWrite,
base::OS::MemoryPermission::kReadWrite);
STATIC_ASSERT_ENUM(MemoryPermission::kReadWriteExecute,
base::OS::MemoryPermission::kReadWriteExecute);
STATIC_ASSERT_ENUM(MemoryPermission::kReadExecute,
base::OS::MemoryPermission::kReadExecute);
#undef STATIC_ASSERT_ENUM
// Default Memory Manager.
// TODO(bbudge) Move this to libplatform.
class DefaultMemoryManager {
public:
static size_t AllocatePageSize() { return base::OS::AllocatePageSize(); }
static size_t CommitPageSize() { return base::OS::CommitPageSize(); }
static void SetRandomMmapSeed(int64_t seed) {
base::OS::SetRandomMmapSeed(seed);
}
static void* GetRandomMmapAddr() { return base::OS::GetRandomMmapAddr(); }
static void* AllocatePages(void* address, size_t size, size_t alignment,
MemoryPermission access) {
void* result =
base::OS::Allocate(address, size, alignment,
static_cast<base::OS::MemoryPermission>(access));
#if defined(LEAK_SANITIZER)
if (result != nullptr) {
__lsan_register_root_region(result, size);
}
#endif
return result;
}
static bool FreePages(void* address, const size_t size) {
bool result = base::OS::Free(address, size);
#if defined(LEAK_SANITIZER)
if (result) {
__lsan_unregister_root_region(address, size);
}
#endif
return result;
}
static bool ReleasePages(void* address, size_t size, size_t new_size) {
DCHECK_LT(new_size, size);
bool result = base::OS::Release(reinterpret_cast<byte*>(address) + new_size,
size - new_size);
#if defined(LEAK_SANITIZER)
if (result) {
__lsan_unregister_root_region(address, size);
__lsan_register_root_region(address, new_size);
}
#endif
return result;
}
static bool SetPermissions(void* address, size_t size, size_t CommitPageSize() { return GetPageAllocator()->CommitPageSize(); }
MemoryPermission access) {
return base::OS::SetPermissions(
address, size, static_cast<base::OS::MemoryPermission>(access));
}
};
size_t AllocatePageSize() { return DefaultMemoryManager::AllocatePageSize(); }
size_t CommitPageSize() { return DefaultMemoryManager::CommitPageSize(); }
void SetRandomMmapSeed(int64_t seed) { void SetRandomMmapSeed(int64_t seed) {
DefaultMemoryManager::SetRandomMmapSeed(seed); GetPageAllocator()->SetRandomMmapSeed(seed);
} }
void* GetRandomMmapAddr() { return DefaultMemoryManager::GetRandomMmapAddr(); } void* GetRandomMmapAddr() { return GetPageAllocator()->GetRandomMmapAddr(); }
void* AllocatePages(void* address, size_t size, size_t alignment, void* AllocatePages(void* address, size_t size, size_t alignment,
MemoryPermission access) { PageAllocator::Permission access) {
return DefaultMemoryManager::AllocatePages(address, size, alignment, access); void* result =
GetPageAllocator()->AllocatePages(address, size, alignment, access);
#if defined(LEAK_SANITIZER)
if (result != nullptr) {
__lsan_register_root_region(result, size);
}
#endif
return result;
} }
bool FreePages(void* address, const size_t size) { bool FreePages(void* address, const size_t size) {
return DefaultMemoryManager::FreePages(address, size); bool result = GetPageAllocator()->FreePages(address, size);
#if defined(LEAK_SANITIZER)
if (result) {
__lsan_unregister_root_region(address, size);
}
#endif
return result;
} }
bool ReleasePages(void* address, size_t size, size_t new_size) { bool ReleasePages(void* address, size_t size, size_t new_size) {
return DefaultMemoryManager::ReleasePages(address, size, new_size); DCHECK_LT(new_size, size);
bool result = GetPageAllocator()->ReleasePages(address, size, new_size);
#if defined(LEAK_SANITIZER)
if (result) {
__lsan_unregister_root_region(address, size);
__lsan_register_root_region(address, new_size);
}
#endif
return result;
} }
bool SetPermissions(void* address, size_t size, MemoryPermission access) { bool SetPermissions(void* address, size_t size,
return DefaultMemoryManager::SetPermissions(address, size, access); PageAllocator::Permission access) {
return GetPageAllocator()->SetPermissions(address, size, access);
} }
byte* AllocatePage(void* address, size_t* allocated) { byte* AllocatePage(void* address, size_t* allocated) {
size_t page_size = AllocatePageSize(); size_t page_size = AllocatePageSize();
void* result = AllocatePages(address, page_size, page_size, void* result =
MemoryPermission::kReadWrite); AllocatePages(address, page_size, page_size, PageAllocator::kReadWrite);
if (result != nullptr) *allocated = page_size; if (result != nullptr) *allocated = page_size;
return static_cast<byte*>(result); return static_cast<byte*>(result);
} }
...@@ -217,7 +189,7 @@ VirtualMemory::VirtualMemory(size_t size, void* hint, size_t alignment) ...@@ -217,7 +189,7 @@ VirtualMemory::VirtualMemory(size_t size, void* hint, size_t alignment)
size_t page_size = AllocatePageSize(); size_t page_size = AllocatePageSize();
size_t alloc_size = RoundUp(size, page_size); size_t alloc_size = RoundUp(size, page_size);
address_ = address_ =
AllocatePages(hint, alloc_size, alignment, MemoryPermission::kNoAccess); AllocatePages(hint, alloc_size, alignment, PageAllocator::kNoAccess);
if (address_ != nullptr) { if (address_ != nullptr) {
size_ = alloc_size; size_ = alloc_size;
} }
...@@ -235,7 +207,7 @@ void VirtualMemory::Reset() { ...@@ -235,7 +207,7 @@ void VirtualMemory::Reset() {
} }
bool VirtualMemory::SetPermissions(void* address, size_t size, bool VirtualMemory::SetPermissions(void* address, size_t size,
MemoryPermission access) { PageAllocator::Permission access) {
CHECK(InVM(address, size)); CHECK(InVM(address, size));
bool result = v8::internal::SetPermissions(address, size, access); bool result = v8::internal::SetPermissions(address, size, access);
DCHECK(result); DCHECK(result);
......
...@@ -76,15 +76,6 @@ class FreeStoreAllocationPolicy { ...@@ -76,15 +76,6 @@ class FreeStoreAllocationPolicy {
void* AlignedAlloc(size_t size, size_t alignment); void* AlignedAlloc(size_t size, size_t alignment);
void AlignedFree(void *ptr); void AlignedFree(void *ptr);
// These must be in sync with the permissions in base/platform/platform.h.
enum class MemoryPermission {
kNoAccess,
kReadWrite,
// TODO(hpayer): Remove this flag. Memory should never be rwx.
kReadWriteExecute,
kReadExecute
};
// Gets the page granularity for AllocatePages and FreePages. Addresses returned // Gets the page granularity for AllocatePages and FreePages. Addresses returned
// by AllocatePages and AllocatePage are aligned to this size. // by AllocatePages and AllocatePage are aligned to this size.
V8_EXPORT_PRIVATE size_t AllocatePageSize(); V8_EXPORT_PRIVATE size_t AllocatePageSize();
...@@ -92,7 +83,8 @@ V8_EXPORT_PRIVATE size_t AllocatePageSize(); ...@@ -92,7 +83,8 @@ V8_EXPORT_PRIVATE size_t AllocatePageSize();
// Gets the granularity at which the permissions and release calls can be made. // Gets the granularity at which the permissions and release calls can be made.
V8_EXPORT_PRIVATE size_t CommitPageSize(); V8_EXPORT_PRIVATE size_t CommitPageSize();
// Sets the random seed for repeatable sequences of random mmap addresses. // Sets the random seed so that GetRandomMmapAddr() will generate repeatable
// sequences of random mmap addresses.
V8_EXPORT_PRIVATE void SetRandomMmapSeed(int64_t seed); V8_EXPORT_PRIVATE void SetRandomMmapSeed(int64_t seed);
// Generate a random address to be used for hinting allocation calls. // Generate a random address to be used for hinting allocation calls.
...@@ -105,7 +97,7 @@ V8_EXPORT_PRIVATE void* GetRandomMmapAddr(); ...@@ -105,7 +97,7 @@ V8_EXPORT_PRIVATE void* GetRandomMmapAddr();
V8_EXPORT_PRIVATE V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT void* AllocatePages(void* address, size_t size, V8_WARN_UNUSED_RESULT void* AllocatePages(void* address, size_t size,
size_t alignment, size_t alignment,
MemoryPermission access); PageAllocator::Permission access);
// Frees memory allocated by a call to AllocatePages. |address| and |size| must // Frees memory allocated by a call to AllocatePages. |address| and |size| must
// be multiples of AllocatePageSize(). Returns true on success, otherwise false. // be multiples of AllocatePageSize(). Returns true on success, otherwise false.
...@@ -127,7 +119,7 @@ V8_WARN_UNUSED_RESULT bool ReleasePages(void* address, size_t size, ...@@ -127,7 +119,7 @@ V8_WARN_UNUSED_RESULT bool ReleasePages(void* address, size_t size,
// false. // false.
V8_EXPORT_PRIVATE V8_EXPORT_PRIVATE
V8_WARN_UNUSED_RESULT bool SetPermissions(void* address, size_t size, V8_WARN_UNUSED_RESULT bool SetPermissions(void* address, size_t size,
MemoryPermission access); PageAllocator::Permission access);
// Convenience function that allocates a single system page with read and write // 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 // permissions. |address| is a hint. Returns the base address of the memory and
...@@ -183,7 +175,8 @@ class V8_EXPORT_PRIVATE VirtualMemory { ...@@ -183,7 +175,8 @@ class V8_EXPORT_PRIVATE VirtualMemory {
// Sets permissions according to the access argument. address and size must be // Sets permissions according to the access argument. address and size must be
// multiples of CommitPageSize(). Returns true on success, otherwise false. // multiples of CommitPageSize(). Returns true on success, otherwise false.
bool SetPermissions(void* address, size_t size, MemoryPermission access); bool SetPermissions(void* address, size_t size,
PageAllocator::Permission access);
// Releases memory after |free_start|. Returns the number of bytes released. // Releases memory after |free_start|. Returns the number of bytes released.
size_t Release(void* free_start); size_t Release(void* free_start);
......
...@@ -508,7 +508,7 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { ...@@ -508,7 +508,7 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
size_t page_size = i::AllocatePageSize(); size_t page_size = i::AllocatePageSize();
size_t allocated = RoundUp(length, page_size); size_t allocated = RoundUp(length, page_size);
void* address = i::AllocatePages(i::GetRandomMmapAddr(), allocated, void* address = i::AllocatePages(i::GetRandomMmapAddr(), allocated,
page_size, i::MemoryPermission::kNoAccess); page_size, PageAllocator::kNoAccess);
return address; return address;
} }
...@@ -532,10 +532,10 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { ...@@ -532,10 +532,10 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
v8::ArrayBuffer::Allocator::Protection protection) { v8::ArrayBuffer::Allocator::Protection protection) {
DCHECK(protection == v8::ArrayBuffer::Allocator::Protection::kNoAccess || DCHECK(protection == v8::ArrayBuffer::Allocator::Protection::kNoAccess ||
protection == v8::ArrayBuffer::Allocator::Protection::kReadWrite); protection == v8::ArrayBuffer::Allocator::Protection::kReadWrite);
i::MemoryPermission permission = PageAllocator::Permission permission =
(protection == v8::ArrayBuffer::Allocator::Protection::kReadWrite) (protection == v8::ArrayBuffer::Allocator::Protection::kReadWrite)
? i::MemoryPermission::kReadWrite ? PageAllocator::kReadWrite
: i::MemoryPermission::kNoAccess; : PageAllocator::kNoAccess;
CHECK(i::SetPermissions(data, length, permission)); CHECK(i::SetPermissions(data, length, permission));
} }
}; };
......
...@@ -169,7 +169,7 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, ...@@ -169,7 +169,7 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer); return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif #endif
} }
...@@ -258,7 +258,7 @@ MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function( ...@@ -258,7 +258,7 @@ MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
masm.GetCode(isolate, &desc); masm.GetCode(isolate, &desc);
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer); return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer);
#endif #endif
} }
...@@ -285,7 +285,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -285,7 +285,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif #endif
} }
......
include_rules = [ include_rules = [
"-include", "-include",
"+include/v8config.h", "+include/v8config.h",
"+include/v8-platform.h",
"-src", "-src",
"+src/base", "+src/base",
] ]
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h"
namespace v8 {
namespace base {
#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enum: " #a)
STATIC_ASSERT_ENUM(PageAllocator::kNoAccess,
base::OS::MemoryPermission::kNoAccess);
STATIC_ASSERT_ENUM(PageAllocator::kReadWrite,
base::OS::MemoryPermission::kReadWrite);
STATIC_ASSERT_ENUM(PageAllocator::kReadWriteExecute,
base::OS::MemoryPermission::kReadWriteExecute);
STATIC_ASSERT_ENUM(PageAllocator::kReadExecute,
base::OS::MemoryPermission::kReadExecute);
#undef STATIC_ASSERT_ENUM
size_t PageAllocator::AllocatePageSize() {
return base::OS::AllocatePageSize();
}
size_t PageAllocator::CommitPageSize() { return base::OS::CommitPageSize(); }
void PageAllocator::SetRandomMmapSeed(int64_t seed) {
base::OS::SetRandomMmapSeed(seed);
}
void* PageAllocator::GetRandomMmapAddr() {
return base::OS::GetRandomMmapAddr();
}
void* PageAllocator::AllocatePages(void* address, size_t size, size_t alignment,
PageAllocator::Permission access) {
return base::OS::Allocate(address, size, alignment,
static_cast<base::OS::MemoryPermission>(access));
}
bool PageAllocator::FreePages(void* address, size_t size) {
return base::OS::Free(address, size);
}
bool PageAllocator::ReleasePages(void* address, size_t size, size_t new_size) {
DCHECK_LT(new_size, size);
return base::OS::Release(reinterpret_cast<uint8_t*>(address) + new_size,
size - new_size);
}
bool PageAllocator::SetPermissions(void* address, size_t size,
PageAllocator::Permission access) {
return base::OS::SetPermissions(
address, size, static_cast<base::OS::MemoryPermission>(access));
}
} // namespace base
} // namespace v8
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_BASE_PAGE_ALLOCATOR_H_
#define V8_BASE_PAGE_ALLOCATOR_H_
#include "include/v8-platform.h"
#include "src/base/base-export.h"
#include "src/base/compiler-specific.h"
namespace v8 {
namespace base {
class V8_BASE_EXPORT PageAllocator
: public NON_EXPORTED_BASE(::v8::PageAllocator) {
public:
virtual ~PageAllocator() = default;
size_t AllocatePageSize() override;
size_t CommitPageSize() override;
void SetRandomMmapSeed(int64_t seed) override;
void* GetRandomMmapAddr() override;
void* AllocatePages(void* address, size_t size, size_t alignment,
PageAllocator::Permission access) override;
bool FreePages(void* address, size_t size) override;
bool ReleasePages(void* address, size_t size, size_t new_size) override;
bool SetPermissions(void* address, size_t size,
PageAllocator::Permission access) override;
};
} // namespace base
} // namespace v8
#endif // V8_BASE_PAGE_ALLOCATOR_H_
...@@ -37,11 +37,6 @@ ...@@ -37,11 +37,6 @@
namespace v8 { namespace v8 {
namespace internal {
// TODO(bbudge) Move this to libplatform.
class DefaultMemoryManager;
} // namespace internal
namespace base { namespace base {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -99,10 +94,9 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) { ...@@ -99,10 +94,9 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
#endif // V8_NO_FAST_TLS #endif // V8_NO_FAST_TLS
class PageAllocator;
class TimezoneCache; class TimezoneCache;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// OS // OS
// //
...@@ -161,9 +155,8 @@ class V8_BASE_EXPORT OS { ...@@ -161,9 +155,8 @@ class V8_BASE_EXPORT OS {
static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...); static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args); static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
// OS memory management API. Except for testing, use the equivalent API in // Memory permissions. These should be kept in sync with the ones in
// v8::internal (src/allocation.h). // v8::PageAllocator.
enum class MemoryPermission { enum class MemoryPermission {
kNoAccess, kNoAccess,
kReadWrite, kReadWrite,
...@@ -256,7 +249,7 @@ class V8_BASE_EXPORT OS { ...@@ -256,7 +249,7 @@ class V8_BASE_EXPORT OS {
// These classes use the private memory management API below. // These classes use the private memory management API below.
friend class MemoryMappedFile; friend class MemoryMappedFile;
friend class PosixMemoryMappedFile; friend class PosixMemoryMappedFile;
friend class v8::internal::DefaultMemoryManager; friend class v8::base::PageAllocator;
static size_t AllocatePageSize(); static size_t AllocatePageSize();
......
...@@ -148,7 +148,7 @@ class ShellArrayBufferAllocator : public ArrayBufferAllocatorBase { ...@@ -148,7 +148,7 @@ class ShellArrayBufferAllocator : public ArrayBufferAllocatorBase {
// Rounding up could go over the limit. // Rounding up could go over the limit.
if (allocated >= kTwoGB) return nullptr; if (allocated >= kTwoGB) return nullptr;
return i::AllocatePages(nullptr, allocated, page_size, return i::AllocatePages(nullptr, allocated, page_size,
i::MemoryPermission::kReadWrite); PageAllocator::kReadWrite);
} }
void FreeVM(void* data, size_t length) { void FreeVM(void* data, size_t length) {
......
...@@ -131,7 +131,7 @@ bool CodeRange::SetUp(size_t requested) { ...@@ -131,7 +131,7 @@ bool CodeRange::SetUp(size_t requested) {
// the beginning of an executable space. // the beginning of an executable space.
if (reserved_area > 0) { if (reserved_area > 0) {
if (!reservation.SetPermissions(base, reserved_area, if (!reservation.SetPermissions(base, reserved_area,
MemoryPermission::kReadWrite)) PageAllocator::kReadWrite))
return false; return false;
base += reserved_area; base += reserved_area;
...@@ -226,7 +226,7 @@ bool CodeRange::CommitRawMemory(Address start, size_t length) { ...@@ -226,7 +226,7 @@ bool CodeRange::CommitRawMemory(Address start, size_t length) {
bool CodeRange::UncommitRawMemory(Address start, size_t length) { bool CodeRange::UncommitRawMemory(Address start, size_t length) {
return virtual_memory_.SetPermissions(start, length, return virtual_memory_.SetPermissions(start, length,
MemoryPermission::kNoAccess); PageAllocator::kNoAccess);
} }
...@@ -234,7 +234,7 @@ void CodeRange::FreeRawMemory(Address address, size_t length) { ...@@ -234,7 +234,7 @@ void CodeRange::FreeRawMemory(Address address, size_t length) {
DCHECK(IsAddressAligned(address, MemoryChunk::kAlignment)); DCHECK(IsAddressAligned(address, MemoryChunk::kAlignment));
base::LockGuard<base::Mutex> guard(&code_range_mutex_); base::LockGuard<base::Mutex> guard(&code_range_mutex_);
free_list_.emplace_back(address, length); free_list_.emplace_back(address, length);
virtual_memory_.SetPermissions(address, length, MemoryPermission::kNoAccess); virtual_memory_.SetPermissions(address, length, PageAllocator::kNoAccess);
} }
bool CodeRange::ReserveBlock(const size_t requested_size, FreeBlock* block) { bool CodeRange::ReserveBlock(const size_t requested_size, FreeBlock* block) {
...@@ -398,7 +398,7 @@ int MemoryAllocator::Unmapper::NumberOfChunks() { ...@@ -398,7 +398,7 @@ int MemoryAllocator::Unmapper::NumberOfChunks() {
bool MemoryAllocator::CommitMemory(Address base, size_t size, bool MemoryAllocator::CommitMemory(Address base, size_t size,
Executability executable) { Executability executable) {
if (!SetPermissions(base, size, MemoryPermission::kReadWrite)) { if (!SetPermissions(base, size, PageAllocator::kReadWrite)) {
return false; return false;
} }
UpdateAllocatedSpaceLimits(base, base + size); UpdateAllocatedSpaceLimits(base, base + size);
...@@ -460,7 +460,7 @@ Address MemoryAllocator::AllocateAlignedMemory( ...@@ -460,7 +460,7 @@ Address MemoryAllocator::AllocateAlignedMemory(
} }
} else { } else {
if (reservation.SetPermissions(base, commit_size, if (reservation.SetPermissions(base, commit_size,
MemoryPermission::kReadWrite)) { PageAllocator::kReadWrite)) {
UpdateAllocatedSpaceLimits(base, base + commit_size); UpdateAllocatedSpaceLimits(base, base + commit_size);
} else { } else {
base = nullptr; base = nullptr;
...@@ -525,7 +525,7 @@ void MemoryChunk::SetReadAndExecutable() { ...@@ -525,7 +525,7 @@ void MemoryChunk::SetReadAndExecutable() {
DCHECK(IsAddressAligned(protect_start, page_size)); DCHECK(IsAddressAligned(protect_start, page_size));
size_t protect_size = RoundUp(area_size(), page_size); size_t protect_size = RoundUp(area_size(), page_size);
CHECK(SetPermissions(protect_start, protect_size, CHECK(SetPermissions(protect_start, protect_size,
MemoryPermission::kReadExecute)); PageAllocator::kReadExecute));
} }
} }
...@@ -544,7 +544,7 @@ void MemoryChunk::SetReadAndWritable() { ...@@ -544,7 +544,7 @@ void MemoryChunk::SetReadAndWritable() {
DCHECK(IsAddressAligned(unprotect_start, page_size)); DCHECK(IsAddressAligned(unprotect_start, page_size));
size_t unprotect_size = RoundUp(area_size(), page_size); size_t unprotect_size = RoundUp(area_size(), page_size);
CHECK(SetPermissions(unprotect_start, unprotect_size, CHECK(SetPermissions(unprotect_start, unprotect_size,
MemoryPermission::kReadWrite)); PageAllocator::kReadWrite));
} }
} }
...@@ -599,7 +599,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size, ...@@ -599,7 +599,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
DCHECK(IsAddressAligned(area_start, page_size)); DCHECK(IsAddressAligned(area_start, page_size));
size_t area_size = RoundUp(area_end - area_start, page_size); size_t area_size = RoundUp(area_end - area_start, page_size);
CHECK(SetPermissions(area_start, area_size, CHECK(SetPermissions(area_start, area_size,
MemoryPermission::kReadWriteExecute)); PageAllocator::kReadWriteExecute));
} }
} }
...@@ -939,7 +939,7 @@ void MemoryAllocator::PartialFreeMemory(MemoryChunk* chunk, Address start_free, ...@@ -939,7 +939,7 @@ void MemoryAllocator::PartialFreeMemory(MemoryChunk* chunk, Address start_free,
DCHECK_EQ(chunk->address() + chunk->size(), DCHECK_EQ(chunk->address() + chunk->size(),
chunk->area_end() + CodePageGuardSize()); chunk->area_end() + CodePageGuardSize());
reservation->SetPermissions(chunk->area_end_, page_size, reservation->SetPermissions(chunk->area_end_, page_size,
MemoryPermission::kNoAccess); PageAllocator::kNoAccess);
} }
// On e.g. Windows, a reservation may be larger than a page and releasing // On e.g. Windows, a reservation may be larger than a page and releasing
// partially starting at |start_free| will also release the potentially // partially starting at |start_free| will also release the potentially
...@@ -1091,7 +1091,7 @@ bool MemoryAllocator::CommitBlock(Address start, size_t size, ...@@ -1091,7 +1091,7 @@ bool MemoryAllocator::CommitBlock(Address start, size_t size,
bool MemoryAllocator::UncommitBlock(Address start, size_t size) { bool MemoryAllocator::UncommitBlock(Address start, size_t size) {
if (!SetPermissions(start, size, MemoryPermission::kNoAccess)) return false; if (!SetPermissions(start, size, PageAllocator::kNoAccess)) return false;
isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size)); isolate_->counters()->memory_allocated()->Decrement(static_cast<int>(size));
return true; return true;
} }
...@@ -1158,24 +1158,23 @@ bool MemoryAllocator::CommitExecutableMemory(VirtualMemory* vm, Address start, ...@@ -1158,24 +1158,23 @@ bool MemoryAllocator::CommitExecutableMemory(VirtualMemory* vm, Address start,
const Address code_area = start + code_area_offset; const Address code_area = start + code_area_offset;
const Address post_guard_page = start + reserved_size - guard_size; const Address post_guard_page = start + reserved_size - guard_size;
// Commit the non-executable header, from start to pre-code guard page. // Commit the non-executable header, from start to pre-code guard page.
if (vm->SetPermissions(start, pre_guard_offset, if (vm->SetPermissions(start, pre_guard_offset, PageAllocator::kReadWrite)) {
MemoryPermission::kReadWrite)) {
// Create the pre-code guard page, following the header. // Create the pre-code guard page, following the header.
if (vm->SetPermissions(pre_guard_page, page_size, if (vm->SetPermissions(pre_guard_page, page_size,
MemoryPermission::kNoAccess)) { PageAllocator::kNoAccess)) {
// Commit the executable code body. // Commit the executable code body.
if (vm->SetPermissions(code_area, commit_size - pre_guard_offset, if (vm->SetPermissions(code_area, commit_size - pre_guard_offset,
MemoryPermission::kReadWrite)) { PageAllocator::kReadWrite)) {
// Create the post-code guard page. // Create the post-code guard page.
if (vm->SetPermissions(post_guard_page, page_size, if (vm->SetPermissions(post_guard_page, page_size,
MemoryPermission::kNoAccess)) { PageAllocator::kNoAccess)) {
UpdateAllocatedSpaceLimits(start, code_area + commit_size); UpdateAllocatedSpaceLimits(start, code_area + commit_size);
return true; return true;
} }
vm->SetPermissions(code_area, commit_size, MemoryPermission::kNoAccess); vm->SetPermissions(code_area, commit_size, PageAllocator::kNoAccess);
} }
} }
vm->SetPermissions(start, pre_guard_offset, MemoryPermission::kNoAccess); vm->SetPermissions(start, pre_guard_offset, PageAllocator::kNoAccess);
} }
return false; return false;
} }
......
...@@ -58,7 +58,7 @@ void StoreBuffer::SetUp() { ...@@ -58,7 +58,7 @@ void StoreBuffer::SetUp() {
if (!reservation.SetPermissions(reinterpret_cast<Address>(start_[0]), if (!reservation.SetPermissions(reinterpret_cast<Address>(start_[0]),
kStoreBufferSize * kStoreBuffers, kStoreBufferSize * kStoreBuffers,
MemoryPermission::kReadWrite)) { PageAllocator::kReadWrite)) {
V8::FatalProcessOutOfMemory("StoreBuffer::SetUp"); V8::FatalProcessOutOfMemory("StoreBuffer::SetUp");
} }
current_ = 0; current_ = 0;
......
...@@ -38,7 +38,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -38,7 +38,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
} }
...@@ -449,7 +449,7 @@ MemMoveFunction CreateMemMoveFunction(Isolate* isolate) { ...@@ -449,7 +449,7 @@ MemMoveFunction CreateMemMoveFunction(Isolate* isolate) {
masm.GetCode(isolate, &desc); masm.GetCode(isolate, &desc);
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
// TODO(jkummerow): It would be nice to register this code creation event // TODO(jkummerow): It would be nice to register this code creation event
// with the PROFILE / GDBJIT system. // with the PROFILE / GDBJIT system.
return FUNCTION_CAST<MemMoveFunction>(buffer); return FUNCTION_CAST<MemMoveFunction>(buffer);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "include/libplatform/libplatform.h" #include "include/libplatform/libplatform.h"
#include "src/base/debug/stack_trace.h" #include "src/base/debug/stack_trace.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/base/platform/time.h" #include "src/base/platform/time.h"
#include "src/base/sys-info.h" #include "src/base/sys-info.h"
...@@ -84,6 +85,7 @@ DefaultPlatform::DefaultPlatform( ...@@ -84,6 +85,7 @@ DefaultPlatform::DefaultPlatform(
: thread_pool_size_(0), : thread_pool_size_(0),
idle_task_support_(idle_task_support), idle_task_support_(idle_task_support),
tracing_controller_(std::move(tracing_controller)), tracing_controller_(std::move(tracing_controller)),
page_allocator_(new v8::base::PageAllocator()),
time_function_for_testing_(nullptr) { time_function_for_testing_(nullptr) {
if (!tracing_controller_) { if (!tracing_controller_) {
tracing::TracingController* controller = new tracing::TracingController(); tracing::TracingController* controller = new tracing::TracingController();
...@@ -254,5 +256,9 @@ Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() { ...@@ -254,5 +256,9 @@ Platform::StackTracePrinter DefaultPlatform::GetStackTracePrinter() {
return PrintStackTrace; return PrintStackTrace;
} }
v8::PageAllocator* DefaultPlatform::GetPageAllocator() {
return page_allocator_.get();
}
} // namespace platform } // namespace platform
} // namespace v8 } // namespace v8
...@@ -27,6 +27,7 @@ class Thread; ...@@ -27,6 +27,7 @@ class Thread;
class WorkerThread; class WorkerThread;
class DefaultForegroundTaskRunner; class DefaultForegroundTaskRunner;
class DefaultBackgroundTaskRunner; class DefaultBackgroundTaskRunner;
class DefaultPageAllocator;
class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) { class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
public: public:
...@@ -70,6 +71,7 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) { ...@@ -70,6 +71,7 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
double CurrentClockTimeMillis() override; double CurrentClockTimeMillis() override;
v8::TracingController* GetTracingController() override; v8::TracingController* GetTracingController() override;
StackTracePrinter GetStackTracePrinter() override; StackTracePrinter GetStackTracePrinter() override;
v8::PageAllocator* GetPageAllocator() override;
private: private:
static const int kMaxThreadPoolSize; static const int kMaxThreadPoolSize;
...@@ -82,6 +84,7 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) { ...@@ -82,6 +84,7 @@ class V8_PLATFORM_EXPORT DefaultPlatform : public NON_EXPORTED_BASE(Platform) {
foreground_task_runner_map_; foreground_task_runner_map_;
std::unique_ptr<TracingController> tracing_controller_; std::unique_ptr<TracingController> tracing_controller_;
std::unique_ptr<PageAllocator> page_allocator_;
TimeFunction time_function_for_testing_; TimeFunction time_function_for_testing_;
DISALLOW_COPY_AND_ASSIGN(DefaultPlatform); DISALLOW_COPY_AND_ASSIGN(DefaultPlatform);
......
...@@ -544,7 +544,7 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, ...@@ -544,7 +544,7 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer); return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif #endif
} }
...@@ -571,7 +571,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -571,7 +571,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif #endif
} }
......
...@@ -545,7 +545,7 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate, ...@@ -545,7 +545,7 @@ MemCopyUint8Function CreateMemCopyUint8Function(Isolate* isolate,
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<MemCopyUint8Function>(buffer); return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif #endif
} }
...@@ -572,7 +572,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -572,7 +572,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif #endif
} }
......
...@@ -40,7 +40,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -40,7 +40,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
!RelocInfo::RequiresRelocation(isolate, desc)); !RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif #endif
} }
......
...@@ -37,7 +37,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -37,7 +37,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
!RelocInfo::RequiresRelocation(isolate, desc)); !RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
#endif #endif
} }
......
...@@ -1913,6 +1913,8 @@ ...@@ -1913,6 +1913,8 @@
'base/once.cc', 'base/once.cc',
'base/once.h', 'base/once.h',
'base/optional.h', 'base/optional.h',
'base/page-allocator.cc',
'base/page-allocator.h',
'base/platform/elapsed-timer.h', 'base/platform/elapsed-timer.h',
'base/platform/time.cc', 'base/platform/time.cc',
'base/platform/time.h', 'base/platform/time.h',
......
...@@ -693,7 +693,7 @@ bool WasmCodeManager::Commit(Address start, size_t size) { ...@@ -693,7 +693,7 @@ bool WasmCodeManager::Commit(Address start, size_t size) {
remaining_uncommitted_.Increment(size); remaining_uncommitted_.Increment(size);
return false; return false;
} }
bool ret = SetPermissions(start, size, MemoryPermission::kReadWrite); bool ret = SetPermissions(start, size, PageAllocator::kReadWrite);
TRACE_HEAP("Setting rw permissions for %p:%p\n", TRACE_HEAP("Setting rw permissions for %p:%p\n",
reinterpret_cast<void*>(start), reinterpret_cast<void*>(start),
reinterpret_cast<void*>(start + size)); reinterpret_cast<void*>(start + size));
...@@ -794,8 +794,8 @@ bool NativeModule::SetExecutable(bool executable) { ...@@ -794,8 +794,8 @@ bool NativeModule::SetExecutable(bool executable) {
if (is_executable_ == executable) return true; if (is_executable_ == executable) return true;
TRACE_HEAP("Setting module %zu as executable: %d.\n", instance_id, TRACE_HEAP("Setting module %zu as executable: %d.\n", instance_id,
executable); executable);
MemoryPermission permission = executable ? MemoryPermission::kReadExecute PageAllocator::Permission permission =
: MemoryPermission::kReadWrite; executable ? PageAllocator::kReadExecute : PageAllocator::kReadWrite;
#if V8_OS_WIN #if V8_OS_WIN
// On windows, we need to switch permissions per separate virtual memory // On windows, we need to switch permissions per separate virtual memory
......
...@@ -31,7 +31,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) { ...@@ -31,7 +31,7 @@ UnaryMathFunctionWithIsolate CreateSqrtFunction(Isolate* isolate) {
DCHECK(!RelocInfo::RequiresRelocation(isolate, desc)); DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
Assembler::FlushICache(isolate, buffer, allocated); Assembler::FlushICache(isolate, buffer, allocated);
CHECK(SetPermissions(buffer, allocated, MemoryPermission::kReadExecute)); CHECK(SetPermissions(buffer, allocated, PageAllocator::kReadExecute));
return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer); return FUNCTION_CAST<UnaryMathFunctionWithIsolate>(buffer);
} }
......
...@@ -574,8 +574,7 @@ static inline uint8_t* AllocateAssemblerBuffer( ...@@ -574,8 +574,7 @@ static inline uint8_t* AllocateAssemblerBuffer(
size_t page_size = v8::internal::AllocatePageSize(); size_t page_size = v8::internal::AllocatePageSize();
size_t alloc_size = RoundUp(requested, page_size); size_t alloc_size = RoundUp(requested, page_size);
void* result = v8::internal::AllocatePages( void* result = v8::internal::AllocatePages(
nullptr, alloc_size, page_size, nullptr, alloc_size, page_size, v8::PageAllocator::kReadWriteExecute);
v8::internal::MemoryPermission::kReadWriteExecute);
CHECK(result); CHECK(result);
*allocated = alloc_size; *allocated = alloc_size;
return static_cast<uint8_t*>(result); return static_cast<uint8_t*>(result);
...@@ -583,8 +582,8 @@ static inline uint8_t* AllocateAssemblerBuffer( ...@@ -583,8 +582,8 @@ static inline uint8_t* AllocateAssemblerBuffer(
static inline void MakeAssemblerBufferExecutable(uint8_t* buffer, static inline void MakeAssemblerBufferExecutable(uint8_t* buffer,
size_t allocated) { size_t allocated) {
bool result = v8::internal::SetPermissions( bool result = v8::internal::SetPermissions(buffer, allocated,
buffer, allocated, v8::internal::MemoryPermission::kReadExecute); v8::PageAllocator::kReadExecute);
CHECK(result); CHECK(result);
} }
...@@ -681,6 +680,10 @@ class ManualGCScope { ...@@ -681,6 +680,10 @@ class ManualGCScope {
class TestPlatform : public v8::Platform { class TestPlatform : public v8::Platform {
public: public:
// v8::Platform implementation. // v8::Platform implementation.
v8::PageAllocator* GetPageAllocator() override {
return old_platform_->GetPageAllocator();
}
void OnCriticalMemoryPressure() override { void OnCriticalMemoryPressure() override {
old_platform_->OnCriticalMemoryPressure(); old_platform_->OnCriticalMemoryPressure();
} }
......
...@@ -93,7 +93,7 @@ class MemoryAllocationPermissionsTest : public ::testing::Test { ...@@ -93,7 +93,7 @@ class MemoryAllocationPermissionsTest : public ::testing::Test {
} }
} }
void TestPermissions(v8::internal::MemoryPermission permission, bool can_read, void TestPermissions(PageAllocator::Permission permission, bool can_read,
bool can_write) { bool can_write) {
const size_t page_size = AllocatePageSize(); const size_t page_size = AllocatePageSize();
int* buffer = static_cast<int*>( int* buffer = static_cast<int*>(
...@@ -109,9 +109,9 @@ sigjmp_buf MemoryAllocationPermissionsTest::continuation_; ...@@ -109,9 +109,9 @@ sigjmp_buf MemoryAllocationPermissionsTest::continuation_;
} // namespace } // namespace
TEST_F(MemoryAllocationPermissionsTest, DoTest) { TEST_F(MemoryAllocationPermissionsTest, DoTest) {
TestPermissions(MemoryPermission::kNoAccess, false, false); TestPermissions(PageAllocator::Permission::kNoAccess, false, false);
TestPermissions(MemoryPermission::kReadWrite, true, true); TestPermissions(PageAllocator::Permission::kReadWrite, true, true);
TestPermissions(MemoryPermission::kReadWriteExecute, true, true); TestPermissions(PageAllocator::Permission::kReadWriteExecute, true, true);
} }
#endif // V8_OS_POSIX #endif // V8_OS_POSIX
...@@ -127,7 +127,7 @@ TEST(AllocationTest, AllocateAndFree) { ...@@ -127,7 +127,7 @@ TEST(AllocationTest, AllocateAndFree) {
const size_t kAllocationSize = 1 * v8::internal::MB; const size_t kAllocationSize = 1 * v8::internal::MB;
void* mem_addr = v8::internal::AllocatePages( void* mem_addr = v8::internal::AllocatePages(
v8::internal::GetRandomMmapAddr(), kAllocationSize, page_size, v8::internal::GetRandomMmapAddr(), kAllocationSize, page_size,
v8::internal::MemoryPermission::kReadWrite); PageAllocator::Permission::kReadWrite);
CHECK_NOT_NULL(mem_addr); CHECK_NOT_NULL(mem_addr);
CHECK(v8::internal::FreePages(mem_addr, kAllocationSize)); CHECK(v8::internal::FreePages(mem_addr, kAllocationSize));
...@@ -135,7 +135,7 @@ TEST(AllocationTest, AllocateAndFree) { ...@@ -135,7 +135,7 @@ TEST(AllocationTest, AllocateAndFree) {
const size_t kBigAlignment = 64 * v8::internal::MB; const size_t kBigAlignment = 64 * v8::internal::MB;
void* aligned_mem_addr = v8::internal::AllocatePages( void* aligned_mem_addr = v8::internal::AllocatePages(
v8::internal::GetRandomMmapAddr(), kAllocationSize, kBigAlignment, v8::internal::GetRandomMmapAddr(), kAllocationSize, kBigAlignment,
v8::internal::MemoryPermission::kReadWrite); PageAllocator::Permission::kReadWrite);
CHECK_NOT_NULL(aligned_mem_addr); CHECK_NOT_NULL(aligned_mem_addr);
CHECK_EQ(aligned_mem_addr, AlignedAddress(aligned_mem_addr, kBigAlignment)); CHECK_EQ(aligned_mem_addr, AlignedAddress(aligned_mem_addr, kBigAlignment));
CHECK(v8::internal::FreePages(aligned_mem_addr, kAllocationSize)); CHECK(v8::internal::FreePages(aligned_mem_addr, kAllocationSize));
...@@ -146,17 +146,17 @@ TEST(AllocationTest, ReserveMemory) { ...@@ -146,17 +146,17 @@ TEST(AllocationTest, ReserveMemory) {
const size_t kAllocationSize = 1 * v8::internal::MB; const size_t kAllocationSize = 1 * v8::internal::MB;
void* mem_addr = v8::internal::AllocatePages( void* mem_addr = v8::internal::AllocatePages(
v8::internal::GetRandomMmapAddr(), kAllocationSize, page_size, v8::internal::GetRandomMmapAddr(), kAllocationSize, page_size,
v8::internal::MemoryPermission::kReadWrite); PageAllocator::Permission::kReadWrite);
CHECK_NE(0, page_size); CHECK_NE(0, page_size);
CHECK_NOT_NULL(mem_addr); CHECK_NOT_NULL(mem_addr);
size_t commit_size = v8::internal::CommitPageSize(); size_t commit_size = v8::internal::CommitPageSize();
CHECK(v8::internal::SetPermissions( CHECK(v8::internal::SetPermissions(mem_addr, commit_size,
mem_addr, commit_size, v8::internal::MemoryPermission::kReadWrite)); PageAllocator::Permission::kReadWrite));
// Check whether we can write to memory. // Check whether we can write to memory.
int* addr = static_cast<int*>(mem_addr); int* addr = static_cast<int*>(mem_addr);
addr[v8::internal::KB - 1] = 2; addr[v8::internal::KB - 1] = 2;
CHECK(v8::internal::SetPermissions( CHECK(v8::internal::SetPermissions(mem_addr, commit_size,
mem_addr, commit_size, v8::internal::MemoryPermission::kNoAccess)); PageAllocator::Permission::kNoAccess));
CHECK(v8::internal::FreePages(mem_addr, kAllocationSize)); CHECK(v8::internal::FreePages(mem_addr, kAllocationSize));
} }
......
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