v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
page-memory.h
Go to the documentation of this file.
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_HEAP_CPPGC_PAGE_MEMORY_H_
6#define V8_HEAP_CPPGC_PAGE_MEMORY_H_
7
8#include <map>
9#include <memory>
10#include <unordered_map>
11#include <vector>
12
14#include "src/base/macros.h"
18
19namespace cppgc {
20namespace internal {
21
23 public:
24 MemoryRegion() = default;
25 MemoryRegion(Address base, size_t size) : base_(base), size_(size) {
26 DCHECK(base);
27 DCHECK_LT(0u, size);
28 }
29
30 Address base() const { return base_; }
31 size_t size() const { return size_; }
32 Address end() const { return base_ + size_; }
33
34 bool Contains(ConstAddress addr) const {
35 return (reinterpret_cast<uintptr_t>(addr) -
36 reinterpret_cast<uintptr_t>(base_)) < size_;
37 }
38
39 bool Contains(const MemoryRegion& other) const {
40 return base_ <= other.base() && other.end() <= end();
41 }
42
43 private:
44 Address base_ = nullptr;
45 size_t size_ = 0;
46};
47
49 public:
52
53 const MemoryRegion region() const { return reserved_region_; }
54
55 // Lookup writeable base for an |address| that's contained in
56 // PageMemoryRegion.
57 inline Address Lookup(ConstAddress address) const {
58 const MemoryRegion memory_region = region();
59 return memory_region.Contains(address) ? memory_region.base() : nullptr;
60 }
61
62 PageAllocator& allocator() const { return allocator_; }
63
64 // Disallow copy/move.
67
68 void UnprotectForTesting();
69
70 private:
73};
74
75// A PageMemoryRegionTree is a binary search tree of PageMemoryRegions sorted
76// by reserved base addresses.
77//
78// The tree does not keep its elements alive but merely provides indexing
79// capabilities.
81 public:
84
85 void Add(PageMemoryRegion*);
86 void Remove(PageMemoryRegion*);
87
88 inline PageMemoryRegion* Lookup(ConstAddress) const;
89
90 private:
91 std::map<ConstAddress, PageMemoryRegion*> set_;
92};
93
94// A pool of PageMemory objects represented by the writeable base addresses.
95// TODO (v8:14390): Consider sharing the page-pool across multiple threads.
97 public:
98 // Adds a new entry to the pool.
99 void Add(PageMemoryRegion*);
100 // Takes a new entry entry from the pool or nullptr in case the pool is empty.
101 PageMemoryRegion* Take();
102
103 // Returns the number of entries pooled.
104 size_t pooled() const { return pool_.size(); }
105 // Memory in the pool which is neither discarded nor decommitted, i.e. the
106 // actual cost of pooled memory.
107 size_t PooledMemory() const;
108
109 void ReleasePooledPages(PageAllocator& allocator);
110
111 auto& get_raw_pool_for_testing() { return pool_; }
112
113 void SetDecommitPooledPages(bool value) { decommit_pooled_pages_ = value; }
114 static constexpr bool kDefaultDecommitPooledPage = false;
115
116 private:
117 // The pool of pages that are not returned to the OS. Bounded by
118 // `primary_pool_capacity_`.
121 : region(region) {}
123 // When a page enters the pool, it's from the heap, so it's neither
124 // decommitted nor discarded.
125 bool is_decommitted = false;
126 bool is_discarded = false;
127 };
128 std::vector<PooledPageMemoryRegion> pool_;
129 bool decommit_pooled_pages_ = kDefaultDecommitPooledPage;
130};
131
132// A backend that is used for allocating and freeing normal and large pages.
133//
134// Internally maintains a set of PageMemoryRegions. The backend keeps its used
135// regions alive.
137 public:
138 PageBackend(PageAllocator& normal_page_allocator,
139 PageAllocator& large_page_allocator);
141
142 // Allocates a normal page from the backend.
143 //
144 // Returns the writeable base of the region.
145 Address TryAllocateNormalPageMemory();
146
147 // Returns normal page memory back to the backend. Expects the
148 // |writeable_base| returned by |AllocateNormalMemory()|.
149 void FreeNormalPageMemory(Address writeable_base);
150
151 // Allocates a large page from the backend.
152 //
153 // Returns the writeable base of the region.
154 Address TryAllocateLargePageMemory(size_t size);
155
156 // Returns large page memory back to the backend. Expects the |writeable_base|
157 // returned by |AllocateLargePageMemory()|.
158 void FreeLargePageMemory(Address writeable_base);
159
160 // Returns the writeable base if |address| is contained in a valid page
161 // memory.
162 inline Address Lookup(ConstAddress) const;
163
164 // Disallow copy/move.
165 PageBackend(const PageBackend&) = delete;
167
168 void ReleasePooledPages();
169
171 return page_memory_region_tree_;
172 }
173
174 NormalPageMemoryPool& page_pool() { return page_pool_; }
175
176 private:
177 // Guards against concurrent uses of `Lookup()`.
181
182 // A PageMemoryRegion for a normal page is kept alive by the
183 // `normal_page_memory_regions_` and as such is always present there.
184 // It's present in:
185 // - `page_pool_` when it's not used (and available for allocation),
186 // - `page_memory_region_tree_` when used (i.e. allocated).
189 std::unordered_map<PageMemoryRegion*, std::unique_ptr<PageMemoryRegion>>
191 std::unordered_map<PageMemoryRegion*, std::unique_ptr<PageMemoryRegion>>
193};
194
196 auto it = set_.upper_bound(address);
197 // This check also covers set_.size() > 0, since for empty container it is
198 // guaranteed that begin() == end().
199 if (it == set_.begin()) {
200 return nullptr;
201 }
202 auto* result = std::next(it, -1)->second;
203 if (address < result->region().end()) {
204 return result;
205 }
206 return nullptr;
207}
208
212 return pmr ? pmr->Lookup(address) : nullptr;
213}
214
215} // namespace internal
216} // namespace cppgc
217
218#endif // V8_HEAP_CPPGC_PAGE_MEMORY_H_
RegisterAllocator * allocator_
bool Contains(const MemoryRegion &other) const
Definition page-memory.h:39
MemoryRegion(Address base, size_t size)
Definition page-memory.h:25
bool Contains(ConstAddress addr) const
Definition page-memory.h:34
std::vector< PooledPageMemoryRegion > pool_
PageBackend & operator=(const PageBackend &)=delete
PageBackend(const PageBackend &)=delete
NormalPageMemoryPool & page_pool()
PageAllocator & normal_page_allocator_
std::unordered_map< PageMemoryRegion *, std::unique_ptr< PageMemoryRegion > > normal_page_memory_regions_
PageMemoryRegionTree & get_page_memory_region_tree_for_testing()
PageMemoryRegionTree page_memory_region_tree_
Address Lookup(ConstAddress) const
std::unordered_map< PageMemoryRegion *, std::unique_ptr< PageMemoryRegion > > large_page_memory_regions_
PageAllocator & large_page_allocator_
NormalPageMemoryPool page_pool_
std::map< ConstAddress, PageMemoryRegion * > set_
Definition page-memory.h:91
PageMemoryRegion * Lookup(ConstAddress) const
PageAllocator & allocator() const
Definition page-memory.h:62
PageMemoryRegion(const PageMemoryRegion &)=delete
const MemoryRegion reserved_region_
Definition page-memory.h:72
const MemoryRegion region() const
Definition page-memory.h:53
Address Lookup(ConstAddress address) const
Definition page-memory.h:57
PageMemoryRegion & operator=(const PageMemoryRegion &)=delete
const int size_
Definition assembler.cc:132
int end
ZoneVector< RpoNumber > & result
uint8_t * Address
Definition globals.h:17
const uint8_t * ConstAddress
Definition globals.h:18
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define V8_EXPORT_PRIVATE
Definition macros.h:460
std::unique_ptr< ValueMirror > value