Flutter Engine
The Flutter Engine
virtual_memory_compressed.cc
Go to the documentation of this file.
1// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
7#include "platform/utils.h"
8#include "vm/lockers.h"
9
10#if defined(DART_COMPRESSED_HEAP)
11
12namespace dart {
13
14uword VirtualMemoryCompressedHeap::base_ = 0;
15uword VirtualMemoryCompressedHeap::size_ = 0;
16uint8_t* VirtualMemoryCompressedHeap::pages_ = nullptr;
17uword VirtualMemoryCompressedHeap::minimum_free_page_id_ = 0;
18Mutex* VirtualMemoryCompressedHeap::mutex_ = nullptr;
19
20uint8_t PageMask(uword page_id) {
21 return static_cast<uint8_t>(1 << (page_id % 8));
22}
23
24bool VirtualMemoryCompressedHeap::IsPageUsed(uword page_id) {
25 if (page_id >= kCompressedHeapNumPages) return false;
26 return pages_[page_id / 8] & PageMask(page_id);
27}
28
29void VirtualMemoryCompressedHeap::SetPageUsed(uword page_id) {
30 ASSERT(page_id < kCompressedHeapNumPages);
31 pages_[page_id / 8] |= PageMask(page_id);
32}
33
34void VirtualMemoryCompressedHeap::ClearPageUsed(uword page_id) {
35 ASSERT(page_id < kCompressedHeapNumPages);
36 pages_[page_id / 8] &= ~PageMask(page_id);
37}
38
39void VirtualMemoryCompressedHeap::Init(void* compressed_heap_region,
40 size_t size) {
41 pages_ = new uint8_t[kCompressedHeapBitmapSize];
42 memset(pages_, 0, kCompressedHeapBitmapSize);
43 ASSERT(size > 0);
44 ASSERT(size <= kCompressedHeapSize);
45 for (intptr_t page_id = size / kCompressedPageSize;
46 page_id < kCompressedHeapNumPages; page_id++) {
47 SetPageUsed(page_id);
48 }
49 base_ = reinterpret_cast<uword>(compressed_heap_region);
50 size_ = size;
51 ASSERT(base_ != 0);
52 ASSERT(size_ != 0);
53 ASSERT(size_ <= kCompressedHeapSize);
54 ASSERT(Utils::IsAligned(base_, kCompressedPageSize));
55 ASSERT(Utils::IsAligned(size_, kCompressedPageSize));
56 // base_ is not necessarily 4GB-aligned, because on some systems we can't make
57 // a large enough reservation to guarantee it. Instead, we have only the
58 // weaker property that all addresses in [base_, base_ + size_) have the same
59 // same upper 32 bits, which is what we really need for compressed pointers.
60 intptr_t mask = ~(kCompressedHeapAlignment - 1);
61 ASSERT((base_ & mask) == ((base_ + size_ - 1) & mask));
62 mutex_ = new Mutex(NOT_IN_PRODUCT("compressed_heap_mutex"));
63}
64
66 delete[] pages_;
67 delete mutex_;
68 base_ = 0;
69 size_ = 0;
70 pages_ = nullptr;
71 minimum_free_page_id_ = 0;
72 mutex_ = nullptr;
73}
74
75void* VirtualMemoryCompressedHeap::GetRegion() {
76 return reinterpret_cast<void*>(base_);
77}
78
80 intptr_t alignment) {
81 ASSERT(alignment <= kCompressedHeapAlignment);
82 const intptr_t allocated_size = Utils::RoundUp(size, kCompressedPageSize);
83 uword pages = allocated_size / kCompressedPageSize;
84 uword page_alignment =
85 alignment > kCompressedPageSize ? alignment / kCompressedPageSize : 1;
86 MutexLocker ml(mutex_);
87
88 // Find a gap with enough empty pages, using the bitmap. Note that reading
89 // outside the bitmap range always returns 0, so this loop will terminate.
90 uword page_id = Utils::RoundUp(minimum_free_page_id_, page_alignment);
91 for (uword gap = 0;;) {
92 if (IsPageUsed(page_id)) {
93 gap = 0;
94 page_id = Utils::RoundUp(page_id + 1, page_alignment);
95 } else {
96 ++gap;
97 if (gap >= pages) {
98 page_id += 1 - gap;
99 break;
100 }
101 ++page_id;
102 }
103 }
104 ASSERT(page_id % page_alignment == 0);
105
106 // Make sure we're not trying to allocate past the end of the heap.
107 uword end = page_id + pages;
108 if (end > kCompressedHeapSize / kCompressedPageSize) {
109 return MemoryRegion();
110 }
111
112 // Mark all the pages in the bitmap as allocated.
113 for (uword i = page_id; i < end; ++i) {
114 ASSERT(!IsPageUsed(i));
115 SetPageUsed(i);
116 }
117
118 // Find the next free page, to speed up subsequent allocations.
119 while (IsPageUsed(minimum_free_page_id_)) {
120 ++minimum_free_page_id_;
121 }
122
123 uword address = base_ + page_id * kCompressedPageSize;
124 ASSERT(Utils::IsAligned(address, kCompressedPageSize));
125 return MemoryRegion(reinterpret_cast<void*>(address), allocated_size);
126}
127
128void VirtualMemoryCompressedHeap::Free(void* address, intptr_t size) {
129 uword start = reinterpret_cast<uword>(address);
130 ASSERT(Utils::IsAligned(start, kCompressedPageSize));
131 ASSERT(Utils::IsAligned(size, kCompressedPageSize));
132 MutexLocker ml(mutex_);
133 ASSERT(start >= base_);
134 uword page_id = (start - base_) / kCompressedPageSize;
135 uword end = page_id + size / kCompressedPageSize;
136 for (uword i = page_id; i < end; ++i) {
137 ClearPageUsed(i);
138 }
139 if (page_id < minimum_free_page_id_) {
140 minimum_free_page_id_ = page_id;
141 }
142}
143
144bool VirtualMemoryCompressedHeap::Contains(void* address) {
145 return (reinterpret_cast<uword>(address) - base_) < size_;
146}
147
148} // namespace dart
149
150#endif // defined(DART_COMPRESSED_HEAP)
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
static constexpr bool IsAligned(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:92
#define ASSERT(E)
glong glong end
void Init()
bool Contains(const Container &container, const Value &value)
Definition: dart_vm.cc:33
static void * Allocate(uword size, Zone *zone)
Definition: allocation.cc:14
uintptr_t uword
Definition: globals.h:501
static void Free(FreeList *free_list, uword address, intptr_t size, bool is_protected)
NOT_IN_PRODUCT(LibraryPtr ReloadTestScript(const char *script))
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259