OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "platform/heap/PageMemory.h" | 5 #include "platform/heap/PageMemory.h" |
6 | 6 |
7 #include "platform/heap/Heap.h" | 7 #include "platform/heap/Heap.h" |
8 #include "wtf/AddressSanitizer.h" | 8 #include "wtf/AddressSanitizer.h" |
9 #include "wtf/Assertions.h" | 9 #include "wtf/Assertions.h" |
10 #include "wtf/Atomics.h" | 10 #include "wtf/Atomics.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 while (current) { | 77 while (current) { |
78 Address base = current->m_region->base(); | 78 Address base = current->m_region->base(); |
79 if (address < base) { | 79 if (address < base) { |
80 current = current->m_left; | 80 current = current->m_left; |
81 continue; | 81 continue; |
82 } | 82 } |
83 if (address >= base + current->m_region->size()) { | 83 if (address >= base + current->m_region->size()) { |
84 current = current->m_right; | 84 current = current->m_right; |
85 continue; | 85 continue; |
86 } | 86 } |
87 ASSERT(current->m_region->contains(address)); | 87 DCHECK(current->m_region->contains(address)); |
88 return current->m_region; | 88 return current->m_region; |
89 } | 89 } |
90 return nullptr; | 90 return nullptr; |
91 } | 91 } |
92 | 92 |
93 void RegionTree::add(PageMemoryRegion* region) { | 93 void RegionTree::add(PageMemoryRegion* region) { |
94 ASSERT(region); | 94 DCHECK(region); |
95 RegionTreeNode* newTree = new RegionTreeNode(region); | 95 RegionTreeNode* newTree = new RegionTreeNode(region); |
96 MutexLocker locker(m_mutex); | 96 MutexLocker locker(m_mutex); |
97 newTree->addTo(&m_root); | 97 newTree->addTo(&m_root); |
98 } | 98 } |
99 | 99 |
100 void RegionTreeNode::addTo(RegionTreeNode** context) { | 100 void RegionTreeNode::addTo(RegionTreeNode** context) { |
101 Address base = m_region->base(); | 101 Address base = m_region->base(); |
102 for (RegionTreeNode* current = *context; current; current = *context) { | 102 for (RegionTreeNode* current = *context; current; current = *context) { |
103 ASSERT(!current->m_region->contains(base)); | 103 DCHECK(!current->m_region->contains(base)); |
104 context = (base < current->m_region->base()) ? ¤t->m_left | 104 context = (base < current->m_region->base()) ? ¤t->m_left |
105 : ¤t->m_right; | 105 : ¤t->m_right; |
106 } | 106 } |
107 *context = this; | 107 *context = this; |
108 } | 108 } |
109 | 109 |
110 void RegionTree::remove(PageMemoryRegion* region) { | 110 void RegionTree::remove(PageMemoryRegion* region) { |
111 // Deletion of large objects (and thus their regions) can happen | 111 // Deletion of large objects (and thus their regions) can happen |
112 // concurrently on sweeper threads. Removal can also happen during thread | 112 // concurrently on sweeper threads. Removal can also happen during thread |
113 // shutdown, but that case is safe. Regardless, we make all removals | 113 // shutdown, but that case is safe. Regardless, we make all removals |
114 // mutually exclusive. | 114 // mutually exclusive. |
115 MutexLocker locker(m_mutex); | 115 MutexLocker locker(m_mutex); |
116 ASSERT(region); | 116 DCHECK(region); |
117 ASSERT(m_root); | 117 DCHECK(m_root); |
118 Address base = region->base(); | 118 Address base = region->base(); |
119 RegionTreeNode** context = &m_root; | 119 RegionTreeNode** context = &m_root; |
120 RegionTreeNode* current = m_root; | 120 RegionTreeNode* current = m_root; |
121 for (; current; current = *context) { | 121 for (; current; current = *context) { |
122 if (region == current->m_region) | 122 if (region == current->m_region) |
123 break; | 123 break; |
124 context = (base < current->m_region->base()) ? ¤t->m_left | 124 context = (base < current->m_region->base()) ? ¤t->m_left |
125 : ¤t->m_right; | 125 : ¤t->m_right; |
126 } | 126 } |
127 | 127 |
128 // Shutdown via detachMainThread might not have populated the region tree. | 128 // Shutdown via detachMainThread might not have populated the region tree. |
129 if (!current) | 129 if (!current) |
130 return; | 130 return; |
131 | 131 |
132 *context = nullptr; | 132 *context = nullptr; |
133 if (current->m_left) { | 133 if (current->m_left) { |
134 current->m_left->addTo(context); | 134 current->m_left->addTo(context); |
135 current->m_left = nullptr; | 135 current->m_left = nullptr; |
136 } | 136 } |
137 if (current->m_right) { | 137 if (current->m_right) { |
138 current->m_right->addTo(context); | 138 current->m_right->addTo(context); |
139 current->m_right = nullptr; | 139 current->m_right = nullptr; |
140 } | 140 } |
141 delete current; | 141 delete current; |
142 } | 142 } |
143 | 143 |
144 PageMemory::PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable) | 144 PageMemory::PageMemory(PageMemoryRegion* reserved, const MemoryRegion& writable) |
145 : m_reserved(reserved), m_writable(writable) { | 145 : m_reserved(reserved), m_writable(writable) { |
146 ASSERT(reserved->contains(writable)); | 146 DCHECK(reserved->contains(writable)); |
147 | 147 |
148 // Register the writable area of the memory as part of the LSan root set. | 148 // Register the writable area of the memory as part of the LSan root set. |
149 // Only the writable area is mapped and can contain C++ objects. Those | 149 // Only the writable area is mapped and can contain C++ objects. Those |
150 // C++ objects can contain pointers to objects outside of the heap and | 150 // C++ objects can contain pointers to objects outside of the heap and |
151 // should therefore be part of the LSan root set. | 151 // should therefore be part of the LSan root set. |
152 __lsan_register_root_region(m_writable.base(), m_writable.size()); | 152 __lsan_register_root_region(m_writable.base(), m_writable.size()); |
153 } | 153 } |
154 | 154 |
155 PageMemory* PageMemory::setupPageMemoryInRegion(PageMemoryRegion* region, | 155 PageMemory* PageMemory::setupPageMemoryInRegion(PageMemoryRegion* region, |
156 size_t pageOffset, | 156 size_t pageOffset, |
157 size_t payloadSize) { | 157 size_t payloadSize) { |
158 // Setup the payload one guard page into the page memory. | 158 // Setup the payload one guard page into the page memory. |
159 Address payloadAddress = region->base() + pageOffset + blinkGuardPageSize; | 159 Address payloadAddress = region->base() + pageOffset + blinkGuardPageSize; |
160 return new PageMemory(region, MemoryRegion(payloadAddress, payloadSize)); | 160 return new PageMemory(region, MemoryRegion(payloadAddress, payloadSize)); |
161 } | 161 } |
162 | 162 |
163 static size_t roundToOsPageSize(size_t size) { | 163 static size_t roundToOsPageSize(size_t size) { |
164 return (size + WTF::kSystemPageSize - 1) & ~(WTF::kSystemPageSize - 1); | 164 return (size + WTF::kSystemPageSize - 1) & ~(WTF::kSystemPageSize - 1); |
165 } | 165 } |
166 | 166 |
167 PageMemory* PageMemory::allocate(size_t payloadSize, RegionTree* regionTree) { | 167 PageMemory* PageMemory::allocate(size_t payloadSize, RegionTree* regionTree) { |
168 ASSERT(payloadSize > 0); | 168 DCHECK_GT(payloadSize, 0UL); |
169 | 169 |
170 // Virtual memory allocation routines operate in OS page sizes. | 170 // Virtual memory allocation routines operate in OS page sizes. |
171 // Round up the requested size to nearest os page size. | 171 // Round up the requested size to nearest os page size. |
172 payloadSize = roundToOsPageSize(payloadSize); | 172 payloadSize = roundToOsPageSize(payloadSize); |
173 | 173 |
174 // Overallocate by 2 times OS page size to have space for a | 174 // Overallocate by 2 times OS page size to have space for a |
175 // guard page at the beginning and end of blink heap page. | 175 // guard page at the beginning and end of blink heap page. |
176 size_t allocationSize = payloadSize + 2 * blinkGuardPageSize; | 176 size_t allocationSize = payloadSize + 2 * blinkGuardPageSize; |
177 PageMemoryRegion* pageMemoryRegion = | 177 PageMemoryRegion* pageMemoryRegion = |
178 PageMemoryRegion::allocateLargePage(allocationSize, regionTree); | 178 PageMemoryRegion::allocateLargePage(allocationSize, regionTree); |
179 PageMemory* storage = | 179 PageMemory* storage = |
180 setupPageMemoryInRegion(pageMemoryRegion, 0, payloadSize); | 180 setupPageMemoryInRegion(pageMemoryRegion, 0, payloadSize); |
181 RELEASE_ASSERT(storage->commit()); | 181 CHECK(storage->commit()); |
182 return storage; | 182 return storage; |
183 } | 183 } |
184 | 184 |
185 } // namespace blink | 185 } // namespace blink |
OLD | NEW |