Commit 33381ffd authored by Samuel Groß's avatar Samuel Groß Committed by V8 LUCI CQ

Allow customizing the RegionAllocator's split and merge operations

This change allows clients of the RegionAllocator to provide callbacks
that are invoked when regions are split or merged.
This will later be needed on Windows when a RegionAllocator is used to
manage a placeholder mapping as these need to be split and merged (using
the VirtualFree API) as well.


Bug: chromium:1218005
Change-Id: I228b41bdb43c4a9ef0db04de9b121dea6b5f12f9
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3264287
Commit-Queue: Samuel Groß <saelo@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77903}
parent 5ee6b7a7
......@@ -41,6 +41,8 @@ RegionAllocator::RegionAllocator(Address memory_region_begin,
}
RegionAllocator::~RegionAllocator() {
// TODO(chromium:1218005) either (D)CHECK that all allocated regions have
// been freed again (and thus merged into a single region) or do that now.
for (Region* region : all_regions_) {
delete region;
}
......@@ -87,6 +89,8 @@ RegionAllocator::Region* RegionAllocator::Split(Region* region,
DCHECK_NE(new_size, 0);
DCHECK_GT(region->size(), new_size);
if (on_split_) on_split_(region->begin(), new_size);
// Create new region and put it to the lists after the |region|.
DCHECK(!region->is_excluded());
RegionState state = region->state();
......@@ -112,6 +116,9 @@ void RegionAllocator::Merge(AllRegionsSet::iterator prev_iter,
Region* prev = *prev_iter;
Region* next = *next_iter;
DCHECK_EQ(prev->end(), next->begin());
if (on_merge_) on_merge_(prev->begin(), prev->size() + next->size());
prev->set_size(prev->size() + next->size());
all_regions_.erase(next_iter); // prev_iter stays valid.
......
......@@ -27,6 +27,8 @@ class V8_BASE_EXPORT RegionAllocator final {
public:
using Address = uintptr_t;
using SplitMergeCallback = std::function<void(Address start, size_t size)>;
static constexpr Address kAllocationFailure = static_cast<Address>(-1);
enum class RegionState {
......@@ -43,6 +45,27 @@ class V8_BASE_EXPORT RegionAllocator final {
RegionAllocator& operator=(const RegionAllocator&) = delete;
~RegionAllocator();
// Split and merge callbacks.
//
// These callbacks can be installed to perform additional logic when regions
// are split or merged. For example, when managing Windows placeholder
// regions, a region must be split into sub-regions (using
// VirtualFree(MEM_PRESERVE_PLACEHOLDER)) before a part of it can be replaced
// with an actual memory mapping. Similarly, multiple sub-regions must be
// merged (using VirtualFree(MEM_COALESCE_PLACEHOLDERS)) when coalescing them
// into a larger, free region again.
//
// The on_split callback is called to signal that an existing region is split
// so that [start, start+size) becomes a new region.
void set_on_split_callback(SplitMergeCallback callback) {
on_split_ = callback;
}
// The on_merge callback is called to signal that all regions in the range
// [start, start+size) are merged into a single one.
void set_on_merge_callback(SplitMergeCallback callback) {
on_merge_ = callback;
}
// Allocates region of |size| (must be |page_size|-aligned). Returns
// the address of the region on success or kAllocationFailure.
Address AllocateRegion(size_t size);
......@@ -114,9 +137,9 @@ class V8_BASE_EXPORT RegionAllocator final {
bool is_free() const { return state_ == RegionState::kFree; }
bool is_allocated() const { return state_ == RegionState::kAllocated; }
bool is_excluded() const { return state_ == RegionState::kExcluded; }
void set_state(RegionState state) { state_ = state; }
RegionState state() { return state_; }
void set_state(RegionState state) { state_ = state; }
void Print(std::ostream& os) const;
......@@ -158,6 +181,10 @@ class V8_BASE_EXPORT RegionAllocator final {
// Free regions ordered by sizes and addresses.
std::set<Region*, SizeAddressOrder> free_regions_;
// Callbacks called when regions are split or merged.
SplitMergeCallback on_split_;
SplitMergeCallback on_merge_;
// Returns region containing given address or nullptr.
AllRegionsSet::iterator FindRegion(Address address);
......
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