blob: 9c27c51b8feadea6cfc8c7e655669f1a3bc9dd10 [file] [log] [blame] [edit]
// 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_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_
#define V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_
#include "include/v8-platform.h"
#include "src/base/base-export.h"
#include "src/base/compiler-specific.h"
#include "src/base/platform/mutex.h"
#include "src/base/region-allocator.h"
#include "src/base/virtual-address-space.h"
namespace v8 {
namespace base {
/**
* Emulates a virtual address subspace.
*
* This class is (optionally) backed by a page allocation and emulates a virtual
* address space that is potentially larger than that mapping. It generally
* first attempts to satisfy page allocation requests from its backing mapping,
* but will also attempt to obtain new page mappings inside the unmapped space
* through page allocation hints if necessary.
*
* Caveat: an emulated subspace violates the invariant that page allocations in
* an address space will never end up inside a child space and so does not
* provide the same security gurarantees.
*/
class V8_BASE_EXPORT EmulatedVirtualAddressSubspace final
: public NON_EXPORTED_BASE(::v8::VirtualAddressSpace) {
public:
// Construct an emulated virtual address subspace of the specified total size,
// potentially backed by a page allocation from the parent space. The newly
// created instance takes ownership of the page allocation (if any) and frees
// it during destruction.
EmulatedVirtualAddressSubspace(v8::VirtualAddressSpace* parent_space,
Address base, size_t mapped_size,
size_t total_size);
~EmulatedVirtualAddressSubspace() 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;
Address AllocateSharedPages(Address hint, size_t size,
PagePermissions permissions,
PlatformSharedMemoryHandle handle,
uint64_t offset) override;
void FreeSharedPages(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;
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 permissions) override;
bool DiscardSystemPages(Address address, size_t size) override;
bool DecommitPages(Address address, size_t size) override;
private:
size_t mapped_size() const { return mapped_size_; }
size_t unmapped_size() const { return size() - mapped_size_; }
Address mapped_base() const { return base(); }
Address unmapped_base() const { return base() + mapped_size_; }
bool Contains(Address outer_start, size_t outer_size, Address inner_start,
size_t inner_size) const {
return (inner_start >= outer_start) &&
((inner_start + inner_size) <= (outer_start + outer_size));
}
bool Contains(Address addr, size_t length) const {
return Contains(base(), size(), addr, length);
}
bool MappedRegionContains(Address addr, size_t length) const {
return Contains(mapped_base(), mapped_size(), addr, length);
}
bool UnmappedRegionContains(Address addr, size_t length) const {
return Contains(unmapped_base(), unmapped_size(), addr, length);
}
// Helper function to define a limit for the size of allocations in the
// unmapped region. This limit makes it possible to estimate the expected
// runtime of some loops in the Allocate methods.
bool IsUsableSizeForUnmappedRegion(size_t size) const {
return size <= (unmapped_size() / 2);
}
// Size of the mapped region located at the beginning of this address space.
const size_t mapped_size_;
// Pointer to the parent space from which the backing pages were allocated.
// Must be kept alive by the owner of this instance.
v8::VirtualAddressSpace* parent_space_;
// Mutex guarding the non-threadsafe RegionAllocator and
// RandomNumberGenerator.
Mutex mutex_;
// RegionAllocator to manage the page allocation and divide it into further
// regions as necessary.
RegionAllocator region_allocator_;
// Random number generator for generating random addresses.
RandomNumberGenerator rng_;
};
} // namespace base
} // namespace v8
#endif // V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_