V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
region-allocator.h
1 // Copyright 2018 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_BASE_REGION_ALLOCATOR_H_
6 #define V8_BASE_REGION_ALLOCATOR_H_
7 
8 #include <set>
9 
10 #include "src/base/address-region.h"
11 #include "src/base/utils/random-number-generator.h"
12 #include "testing/gtest/include/gtest/gtest_prod.h" // nogncheck
13 
14 namespace v8 {
15 namespace base {
16 
17 // Helper class for managing used/free regions within [address, address+size)
18 // region. Minimum allocation unit is |page_size|. Requested allocation size
19 // is rounded up to |page_size|.
20 // The region allocation algorithm implements best-fit with coalescing strategy:
21 // it tries to find a smallest suitable free region upon allocation and tries
22 // to merge region with its neighbors upon freeing.
23 //
24 // This class does not perform any actual region reservation.
25 // Not thread-safe.
26 class V8_BASE_EXPORT RegionAllocator final {
27  public:
28  typedef uintptr_t Address;
29 
30  static constexpr Address kAllocationFailure = static_cast<Address>(-1);
31 
32  RegionAllocator(Address address, size_t size, size_t page_size);
33  ~RegionAllocator();
34 
35  // Allocates region of |size| (must be |page_size|-aligned). Returns
36  // the address of the region on success or kAllocationFailure.
37  Address AllocateRegion(size_t size);
38  // Same as above but tries to randomize the region displacement.
39  Address AllocateRegion(RandomNumberGenerator* rng, size_t size);
40 
41  // Allocates region of |size| at |requested_address| if it's free. Both the
42  // address and the size must be |page_size|-aligned. On success returns
43  // true.
44  // This kind of allocation is supposed to be used during setup phase to mark
45  // certain regions as used or for randomizing regions displacement.
46  bool AllocateRegionAt(Address requested_address, size_t size);
47 
48  // Frees region at given |address|, returns the size of the region.
49  // There must be a used region starting at given address otherwise nothing
50  // will be freed and 0 will be returned.
51  size_t FreeRegion(Address address) { return TrimRegion(address, 0); }
52 
53  // Decreases size of the previously allocated region at |address|, returns
54  // freed size. |new_size| must be |page_size|-aligned and
55  // less than or equal to current region's size. Setting new size to zero
56  // frees the region.
57  size_t TrimRegion(Address address, size_t new_size);
58 
59  // If there is a used region starting at given address returns its size
60  // otherwise 0.
61  size_t CheckRegion(Address address);
62 
63  // Returns true if there are no pages allocated in given region.
64  bool IsFree(Address address, size_t size);
65 
66  Address begin() const { return whole_region_.begin(); }
67  Address end() const { return whole_region_.end(); }
68  size_t size() const { return whole_region_.size(); }
69 
70  bool contains(Address address) const {
71  return whole_region_.contains(address);
72  }
73 
74  bool contains(Address address, size_t size) const {
75  return whole_region_.contains(address, size);
76  }
77 
78  // Total size of not yet aquired regions.
79  size_t free_size() const { return free_size_; }
80 
81  // The alignment of the allocated region's addresses and granularity of
82  // the allocated region's sizes.
83  size_t page_size() const { return page_size_; }
84 
85  void Print(std::ostream& os) const;
86 
87  private:
88  class Region : public AddressRegion {
89  public:
90  Region(Address address, size_t size, bool is_used)
91  : AddressRegion(address, size), is_used_(is_used) {}
92 
93  bool is_used() const { return is_used_; }
94  void set_is_used(bool used) { is_used_ = used; }
95 
96  void Print(std::ostream& os) const;
97 
98  private:
99  bool is_used_;
100  };
101 
102  // The whole region.
103  const Region whole_region_;
104 
105  // Number of |page_size_| in the whole region.
106  const size_t region_size_in_pages_;
107 
108  // If the free size is less than this value - stop trying to randomize the
109  // allocation addresses.
110  const size_t max_load_for_randomization_;
111 
112  // Size of all free regions.
113  size_t free_size_;
114 
115  // Minimum region size. Must be a pow of 2.
116  const size_t page_size_;
117 
118  struct AddressEndOrder {
119  bool operator()(const Region* a, const Region* b) const {
120  return a->end() < b->end();
121  }
122  };
123  // All regions ordered by addresses.
124  typedef std::set<Region*, AddressEndOrder> AllRegionsSet;
125  AllRegionsSet all_regions_;
126 
127  struct SizeAddressOrder {
128  bool operator()(const Region* a, const Region* b) const {
129  if (a->size() != b->size()) return a->size() < b->size();
130  return a->begin() < b->begin();
131  }
132  };
133  // Free regions ordered by sizes and addresses.
134  std::set<Region*, SizeAddressOrder> free_regions_;
135 
136  // Returns region containing given address or nullptr.
137  AllRegionsSet::iterator FindRegion(Address address);
138 
139  // Adds given region to the set of free regions.
140  void FreeListAddRegion(Region* region);
141 
142  // Finds best-fit free region for given size.
143  Region* FreeListFindRegion(size_t size);
144 
145  // Removes given region from the set of free regions.
146  void FreeListRemoveRegion(Region* region);
147 
148  // Splits given |region| into two: one of |new_size| size and a new one
149  // having the rest. The new region is returned.
150  Region* Split(Region* region, size_t new_size);
151 
152  // For two coalescing regions merges |next| to |prev| and deletes |next|.
153  void Merge(AllRegionsSet::iterator prev_iter,
154  AllRegionsSet::iterator next_iter);
155 
156  FRIEND_TEST(RegionAllocatorTest, AllocateRegionRandom);
157  FRIEND_TEST(RegionAllocatorTest, Fragmentation);
158  FRIEND_TEST(RegionAllocatorTest, FindRegion);
159  FRIEND_TEST(RegionAllocatorTest, Contains);
160 
161  DISALLOW_COPY_AND_ASSIGN(RegionAllocator);
162 };
163 
164 } // namespace base
165 } // namespace v8
166 
167 #endif // V8_BASE_REGION_ALLOCATOR_H_
Definition: libplatform.h:13