blob: 52268e65b8bd0549e2cc35db9b619a6c05e333d8 [file] [log] [blame]
// Copyright 2021 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_VIRTUAL_ADDRESS_SPACE_H_
#define V8_BASE_VIRTUAL_ADDRESS_SPACE_H_
#include "include/v8-platform.h"
#include "src/base/base-export.h"
#include "src/base/compiler-specific.h"
#include "src/base/platform/platform.h"
#include "src/base/region-allocator.h"
namespace v8 {
namespace base {
using Address = uintptr_t;
constexpr Address kNullAddress = 0;
class VirtualAddressSubspace;
/*
* Common parent class to implement deletion of subspaces.
*/
class VirtualAddressSpaceBase
: public NON_EXPORTED_BASE(::v8::VirtualAddressSpace) {
public:
using VirtualAddressSpace::VirtualAddressSpace;
private:
friend VirtualAddressSubspace;
// Called by a subspace during destruction. Responsible for freeing the
// address space reservation and any other data associated with the subspace
// in the parent space.
virtual void FreeSubspace(VirtualAddressSubspace* subspace) = 0;
};
/*
* Helper routine to determine whether one set of page permissions (the lhs) is
* a subset of another one (the rhs).
*/
V8_BASE_EXPORT bool IsSubset(PagePermissions lhs, PagePermissions rhs);
/*
* The virtual address space of the current process. Conceptionally, there
* should only be one such "root" instance. However, in practice there is no
* issue with having multiple instances as the actual resources are managed by
* the OS kernel.
*/
class V8_BASE_EXPORT VirtualAddressSpace : public VirtualAddressSpaceBase {
public:
VirtualAddressSpace();
~VirtualAddressSpace() override = default;
void SetRandomSeed(int64_t seed) override;
Address RandomPageAddress() override;
Address AllocatePages(Address hint, size_t size, size_t alignment,
PagePermissions access) override;
void FreePages(Address address, size_t size) override;
bool SetPagePermissions(Address address, size_t size,
PagePermissions access) override;
bool AllocateGuardRegion(Address address, size_t size) override;
void FreeGuardRegion(Address address, size_t size) override;
Address AllocateSharedPages(Address hint, size_t size,
PagePermissions permissions,
PlatformSharedMemoryHandle handle,
uint64_t offset) override;
void FreeSharedPages(Address address, size_t size) override;
bool CanAllocateSubspaces() override;
std::unique_ptr<v8::VirtualAddressSpace> AllocateSubspace(
Address hint, size_t size, size_t alignment,
PagePermissions max_page_permissions) override;
bool RecommitPages(Address address, size_t size,
PagePermissions access) override;
bool DiscardSystemPages(Address address, size_t size) override;
bool DecommitPages(Address address, size_t size) override;
private:
void FreeSubspace(VirtualAddressSubspace* subspace) override;
};
/*
* A subspace of a parent virtual address space. This represents a reserved
* contiguous region of virtual address space in the current process.
*/
class V8_BASE_EXPORT VirtualAddressSubspace : public VirtualAddressSpaceBase {
public:
~VirtualAddressSubspace() override;
void SetRandomSeed(int64_t seed) override;
Address RandomPageAddress() override;
Address AllocatePages(Address hint, size_t size, size_t alignment,
PagePermissions permissions) override;
void FreePages(Address address, size_t size) override;
bool SetPagePermissions(Address address, size_t size,
PagePermissions permissions) override;
bool AllocateGuardRegion(Address address, size_t size) override;
void FreeGuardRegion(Address address, size_t size) override;
Address AllocateSharedPages(Address hint, size_t size,
PagePermissions permissions,
PlatformSharedMemoryHandle handle,
uint64_t offset) override;
void FreeSharedPages(Address address, size_t size) override;
bool CanAllocateSubspaces() override { return true; }
std::unique_ptr<v8::VirtualAddressSpace> AllocateSubspace(
Address hint, size_t size, size_t alignment,
PagePermissions max_page_permissions) override;
bool RecommitPages(Address address, size_t size,
PagePermissions permissions) override;
bool DiscardSystemPages(Address address, size_t size) override;
bool DecommitPages(Address address, size_t size) override;
private:
// The VirtualAddressSpace class creates instances of this class when
// allocating sub spaces.
friend class v8::base::VirtualAddressSpace;
void FreeSubspace(VirtualAddressSubspace* subspace) override;
VirtualAddressSubspace(AddressSpaceReservation reservation,
VirtualAddressSpaceBase* parent_space,
PagePermissions max_page_permissions);
// The address space reservation backing this subspace.
AddressSpaceReservation reservation_;
// Mutex guarding the non-threadsafe RegionAllocator and
// RandomNumberGenerator.
Mutex mutex_;
// RegionAllocator to manage the virtual address reservation and divide it
// into further regions as necessary.
RegionAllocator region_allocator_;
// Random number generator for generating random addresses.
RandomNumberGenerator rng_;
// Pointer to the parent space. Must be kept alive by the owner of this
// instance during its lifetime.
VirtualAddressSpaceBase* parent_space_;
};
} // namespace base
} // namespace v8
#endif // V8_BASE_VIRTUAL_ADDRESS_SPACE_H_