V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
bounded-page-allocator.cc
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 #include "src/base/bounded-page-allocator.h"
6 
7 namespace v8 {
8 namespace base {
9 
10 BoundedPageAllocator::BoundedPageAllocator(v8::PageAllocator* page_allocator,
11  Address start, size_t size,
12  size_t allocate_page_size)
13  : allocate_page_size_(allocate_page_size),
14  commit_page_size_(page_allocator->CommitPageSize()),
15  page_allocator_(page_allocator),
16  region_allocator_(start, size, allocate_page_size_) {
17  CHECK_NOT_NULL(page_allocator);
18  CHECK(IsAligned(allocate_page_size, page_allocator->AllocatePageSize()));
19  CHECK(IsAligned(allocate_page_size_, commit_page_size_));
20 }
21 
22 BoundedPageAllocator::Address BoundedPageAllocator::begin() const {
23  return region_allocator_.begin();
24 }
25 
26 size_t BoundedPageAllocator::size() const { return region_allocator_.size(); }
27 
28 void* BoundedPageAllocator::AllocatePages(void* hint, size_t size,
29  size_t alignment,
31  MutexGuard guard(&mutex_);
32  CHECK(IsAligned(alignment, region_allocator_.page_size()));
33 
34  // Region allocator does not support alignments bigger than it's own
35  // allocation alignment.
36  CHECK_LE(alignment, allocate_page_size_);
37 
38  // TODO(ishell): Consider using randomized version here.
39  Address address = region_allocator_.AllocateRegion(size);
40  if (address == RegionAllocator::kAllocationFailure) {
41  return nullptr;
42  }
43  CHECK(page_allocator_->SetPermissions(reinterpret_cast<void*>(address), size,
44  access));
45  return reinterpret_cast<void*>(address);
46 }
47 
48 bool BoundedPageAllocator::AllocatePagesAt(Address address, size_t size,
50  CHECK(IsAligned(address, allocate_page_size_));
51  CHECK(IsAligned(size, allocate_page_size_));
52  CHECK(region_allocator_.contains(address, size));
53 
54  if (!region_allocator_.AllocateRegionAt(address, size)) {
55  return false;
56  }
57  CHECK(page_allocator_->SetPermissions(reinterpret_cast<void*>(address), size,
58  access));
59  return true;
60 }
61 
62 bool BoundedPageAllocator::FreePages(void* raw_address, size_t size) {
63  MutexGuard guard(&mutex_);
64 
65  Address address = reinterpret_cast<Address>(raw_address);
66  size_t freed_size = region_allocator_.FreeRegion(address);
67  if (freed_size != size) return false;
68  CHECK(page_allocator_->SetPermissions(raw_address, size,
69  PageAllocator::kNoAccess));
70  return true;
71 }
72 
73 bool BoundedPageAllocator::ReleasePages(void* raw_address, size_t size,
74  size_t new_size) {
75  Address address = reinterpret_cast<Address>(raw_address);
76  CHECK(IsAligned(address, allocate_page_size_));
77 
78  DCHECK_LT(new_size, size);
79  DCHECK(IsAligned(size - new_size, commit_page_size_));
80 
81  // Check if we freed any allocatable pages by this release.
82  size_t allocated_size = RoundUp(size, allocate_page_size_);
83  size_t new_allocated_size = RoundUp(new_size, allocate_page_size_);
84 
85 #ifdef DEBUG
86  {
87  // There must be an allocated region at given |address| of a size not
88  // smaller than |size|.
89  MutexGuard guard(&mutex_);
90  CHECK_EQ(allocated_size, region_allocator_.CheckRegion(address));
91  }
92 #endif
93 
94  if (new_allocated_size < allocated_size) {
95  MutexGuard guard(&mutex_);
96  region_allocator_.TrimRegion(address, new_allocated_size);
97  }
98 
99  // Keep the region in "used" state just uncommit some pages.
100  Address free_address = address + new_size;
101  size_t free_size = size - new_size;
102  return page_allocator_->SetPermissions(reinterpret_cast<void*>(free_address),
103  free_size, PageAllocator::kNoAccess);
104 }
105 
106 bool BoundedPageAllocator::SetPermissions(void* address, size_t size,
107  PageAllocator::Permission access) {
108  DCHECK(IsAligned(reinterpret_cast<Address>(address), commit_page_size_));
109  DCHECK(IsAligned(size, commit_page_size_));
110  DCHECK(region_allocator_.contains(reinterpret_cast<Address>(address), size));
111  return page_allocator_->SetPermissions(address, size, access);
112 }
113 
114 bool BoundedPageAllocator::DiscardSystemPages(void* address, size_t size) {
115  return page_allocator_->DiscardSystemPages(address, size);
116 }
117 
118 } // namespace base
119 } // namespace v8
bool SetPermissions(void *address, size_t size, Permission access) override
bool ReleasePages(void *address, size_t size, size_t new_size) override
void * AllocatePages(void *hint, size_t size, size_t alignment, Permission access) override
bool DiscardSystemPages(void *address, size_t size) override
Definition: libplatform.h:13
virtual size_t AllocatePageSize()=0
bool FreePages(void *address, size_t size) override