Chromium Code Reviews| 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 |