OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/freelist.h" | 5 #include "vm/freelist.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <utility> | |
9 | 8 |
10 #include "vm/bit_set.h" | 9 #include "vm/bit_set.h" |
10 #include "vm/lockers.h" | |
11 #include "vm/object.h" | 11 #include "vm/object.h" |
12 #include "vm/raw_object.h" | 12 #include "vm/raw_object.h" |
13 #include "vm/thread.h" | |
13 | 14 |
14 namespace dart { | 15 namespace dart { |
15 | 16 |
16 | 17 |
17 FreeListElement* FreeListElement::AsElement(uword addr, intptr_t size) { | 18 FreeListElement* FreeListElement::AsElement(uword addr, intptr_t size) { |
18 // Precondition: the (page containing the) header of the element is | 19 // Precondition: the (page containing the) header of the element is |
19 // writable. | 20 // writable. |
20 ASSERT(size >= kObjectAlignment); | 21 ASSERT(size >= kObjectAlignment); |
21 ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 22 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
22 | 23 |
(...skipping 19 matching lines...) Expand all Loading... | |
42 ASSERT(OFFSET_OF(FreeListElement, tags_) == Object::tags_offset()); | 43 ASSERT(OFFSET_OF(FreeListElement, tags_) == Object::tags_offset()); |
43 } | 44 } |
44 | 45 |
45 | 46 |
46 intptr_t FreeListElement::HeaderSizeFor(intptr_t size) { | 47 intptr_t FreeListElement::HeaderSizeFor(intptr_t size) { |
47 if (size == 0) return 0; | 48 if (size == 0) return 0; |
48 return ((size > RawObject::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize; | 49 return ((size > RawObject::SizeTag::kMaxSizeTag) ? 3 : 2) * kWordSize; |
49 } | 50 } |
50 | 51 |
51 | 52 |
52 FreeList::FreeList() { | 53 FreeList::FreeList() : mutex_(new Mutex()) { |
53 Reset(); | 54 Reset(); |
54 } | 55 } |
55 | 56 |
56 | 57 |
57 FreeList::~FreeList() { | 58 FreeList::~FreeList() { |
58 // Nothing to release. | 59 delete mutex_; |
59 } | 60 } |
60 | 61 |
61 | 62 |
62 uword FreeList::TryAllocate(intptr_t size, bool is_protected) { | 63 uword FreeList::TryAllocate(intptr_t size, bool is_protected) { |
64 MutexLocker ml(mutex_); | |
65 return TryAllocateLocked(size, is_protected); | |
66 } | |
67 | |
68 | |
69 uword FreeList::TryAllocateLocked(intptr_t size, bool is_protected) { | |
70 DEBUG_ASSERT(mutex_->Owner() == Isolate::Current()); | |
63 // Precondition: is_protected is false or else all free list elements are | 71 // Precondition: is_protected is false or else all free list elements are |
64 // in non-writable pages. | 72 // in non-writable pages. |
65 | 73 |
66 // Postcondition: if allocation succeeds, the allocated block is writable. | 74 // Postcondition: if allocation succeeds, the allocated block is writable. |
67 int index = IndexForSize(size); | 75 int index = IndexForSize(size); |
68 if ((index != kNumLists) && free_map_.Test(index)) { | 76 if ((index != kNumLists) && free_map_.Test(index)) { |
69 FreeListElement* element = DequeueElement(index); | 77 FreeListElement* element = DequeueElement(index); |
70 if (is_protected) { | 78 if (is_protected) { |
71 bool status = | 79 bool status = |
72 VirtualMemory::Protect(reinterpret_cast<void*>(element), | 80 VirtualMemory::Protect(reinterpret_cast<void*>(element), |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 return reinterpret_cast<uword>(current); | 167 return reinterpret_cast<uword>(current); |
160 } | 168 } |
161 previous = current; | 169 previous = current; |
162 current = current->next(); | 170 current = current->next(); |
163 } | 171 } |
164 return 0; | 172 return 0; |
165 } | 173 } |
166 | 174 |
167 | 175 |
168 void FreeList::Free(uword addr, intptr_t size) { | 176 void FreeList::Free(uword addr, intptr_t size) { |
177 MutexLocker ml(mutex_); | |
178 FreeLocked(addr, size); | |
179 } | |
180 | |
181 | |
182 void FreeList::FreeLocked(uword addr, intptr_t size) { | |
koda
2014/08/20 00:10:21
Assert that it's actually locked.
Ivan Posva
2014/08/20 03:50:53
Done.
| |
169 // Precondition required by AsElement and EnqueueElement: the (page | 183 // Precondition required by AsElement and EnqueueElement: the (page |
170 // containing the) header of the freed block should be writable. This is | 184 // containing the) header of the freed block should be writable. This is |
171 // the case when called for newly allocated pages because they are | 185 // the case when called for newly allocated pages because they are |
172 // allocated as writable. It is the case when called during GC sweeping | 186 // allocated as writable. It is the case when called during GC sweeping |
173 // because the entire heap is writable. | 187 // because the entire heap is writable. |
174 intptr_t index = IndexForSize(size); | 188 intptr_t index = IndexForSize(size); |
175 FreeListElement* element = FreeListElement::AsElement(addr, size); | 189 FreeListElement* element = FreeListElement::AsElement(addr, size); |
176 EnqueueElement(element, index); | 190 EnqueueElement(element, index); |
177 // Postcondition: the (page containing the) header is left writable. | 191 // Postcondition: the (page containing the) header is left writable. |
178 } | 192 } |
179 | 193 |
180 | 194 |
181 void FreeList::Reset() { | 195 void FreeList::Reset() { |
196 MutexLocker ml(mutex_); | |
182 free_map_.Reset(); | 197 free_map_.Reset(); |
183 for (int i = 0; i < (kNumLists + 1); i++) { | 198 for (int i = 0; i < (kNumLists + 1); i++) { |
184 free_lists_[i] = NULL; | 199 free_lists_[i] = NULL; |
185 } | 200 } |
186 } | 201 } |
187 | 202 |
188 | 203 |
189 intptr_t FreeList::IndexForSize(intptr_t size) { | 204 intptr_t FreeList::IndexForSize(intptr_t size) { |
190 ASSERT(size >= kObjectAlignment); | 205 ASSERT(size >= kObjectAlignment); |
191 ASSERT(Utils::IsAligned(size, kObjectAlignment)); | 206 ASSERT(Utils::IsAligned(size, kObjectAlignment)); |
(...skipping 21 matching lines...) Expand all Loading... | |
213 FreeListElement* next = result->next(); | 228 FreeListElement* next = result->next(); |
214 if (next == NULL && index != kNumLists) { | 229 if (next == NULL && index != kNumLists) { |
215 free_map_.Set(index, false); | 230 free_map_.Set(index, false); |
216 } | 231 } |
217 free_lists_[index] = next; | 232 free_lists_[index] = next; |
218 return result; | 233 return result; |
219 } | 234 } |
220 | 235 |
221 | 236 |
222 intptr_t FreeList::Length(int index) const { | 237 intptr_t FreeList::Length(int index) const { |
238 MutexLocker ml(mutex_); | |
223 ASSERT(index >= 0); | 239 ASSERT(index >= 0); |
224 ASSERT(index < kNumLists); | 240 ASSERT(index < kNumLists); |
225 intptr_t result = 0; | 241 intptr_t result = 0; |
226 FreeListElement* element = free_lists_[index]; | 242 FreeListElement* element = free_lists_[index]; |
227 while (element != NULL) { | 243 while (element != NULL) { |
228 ++result; | 244 ++result; |
229 element = element->next(); | 245 element = element->next(); |
230 } | 246 } |
231 return result; | 247 return result; |
232 } | 248 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 size / kObjectAlignment, | 299 size / kObjectAlignment, |
284 size, | 300 size, |
285 list_length, | 301 list_length, |
286 list_bytes / static_cast<double>(KB), | 302 list_bytes / static_cast<double>(KB), |
287 large_bytes / static_cast<double>(KB)); | 303 large_bytes / static_cast<double>(KB)); |
288 } | 304 } |
289 } | 305 } |
290 | 306 |
291 | 307 |
292 void FreeList::Print() const { | 308 void FreeList::Print() const { |
309 MutexLocker ml(mutex_); | |
293 PrintSmall(); | 310 PrintSmall(); |
294 PrintLarge(); | 311 PrintLarge(); |
295 } | 312 } |
296 | 313 |
297 | 314 |
298 void FreeList::SplitElementAfterAndEnqueue(FreeListElement* element, | 315 void FreeList::SplitElementAfterAndEnqueue(FreeListElement* element, |
299 intptr_t size, | 316 intptr_t size, |
300 bool is_protected) { | 317 bool is_protected) { |
301 // Precondition required by AsElement and EnqueueElement: either | 318 // Precondition required by AsElement and EnqueueElement: either |
302 // element->Size() == size, or else the (page containing the) header of | 319 // element->Size() == size, or else the (page containing the) header of |
(...skipping 14 matching lines...) Expand all Loading... | |
317 !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) { | 334 !VirtualMemory::InSamePage(remainder_address - 1, remainder_address)) { |
318 bool status = | 335 bool status = |
319 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address), | 336 VirtualMemory::Protect(reinterpret_cast<void*>(remainder_address), |
320 remainder_size, | 337 remainder_size, |
321 VirtualMemory::kReadExecute); | 338 VirtualMemory::kReadExecute); |
322 ASSERT(status); | 339 ASSERT(status); |
323 } | 340 } |
324 } | 341 } |
325 | 342 |
326 } // namespace dart | 343 } // namespace dart |
OLD | NEW |