Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: runtime/vm/pages.cc

Issue 2974233002: VM: Re-format to use at most one newline between functions (Closed)
Patch Set: Rebase and merge Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/pages_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/pages.h" 5 #include "vm/pages.h"
6 6
7 #include "platform/address_sanitizer.h" 7 #include "platform/address_sanitizer.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/compiler_stats.h" 9 #include "vm/compiler_stats.h"
10 #include "vm/gc_marker.h" 10 #include "vm/gc_marker.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 ASSERT(result != NULL); 71 ASSERT(result != NULL);
72 result->memory_ = memory; 72 result->memory_ = memory;
73 result->next_ = NULL; 73 result->next_ = NULL;
74 result->type_ = type; 74 result->type_ = type;
75 75
76 LSAN_REGISTER_ROOT_REGION(result, sizeof(*result)); 76 LSAN_REGISTER_ROOT_REGION(result, sizeof(*result));
77 77
78 return result; 78 return result;
79 } 79 }
80 80
81
82 HeapPage* HeapPage::Allocate(intptr_t size_in_words, 81 HeapPage* HeapPage::Allocate(intptr_t size_in_words,
83 PageType type, 82 PageType type,
84 const char* name) { 83 const char* name) {
85 VirtualMemory* memory = 84 VirtualMemory* memory =
86 VirtualMemory::Reserve(size_in_words << kWordSizeLog2); 85 VirtualMemory::Reserve(size_in_words << kWordSizeLog2);
87 if (memory == NULL) { 86 if (memory == NULL) {
88 return NULL; 87 return NULL;
89 } 88 }
90 HeapPage* result = Initialize(memory, type, name); 89 HeapPage* result = Initialize(memory, type, name);
91 if (result == NULL) { 90 if (result == NULL) {
92 delete memory; // Release reservation to OS. 91 delete memory; // Release reservation to OS.
93 return NULL; 92 return NULL;
94 } 93 }
95 return result; 94 return result;
96 } 95 }
97 96
98
99 void HeapPage::Deallocate() { 97 void HeapPage::Deallocate() {
100 bool image_page = is_image_page(); 98 bool image_page = is_image_page();
101 99
102 if (!image_page) { 100 if (!image_page) {
103 LSAN_UNREGISTER_ROOT_REGION(this, sizeof(*this)); 101 LSAN_UNREGISTER_ROOT_REGION(this, sizeof(*this));
104 } 102 }
105 103
106 // For a regular heap pages, the memory for this object will become 104 // For a regular heap pages, the memory for this object will become
107 // unavailable after the delete below. 105 // unavailable after the delete below.
108 delete memory_; 106 delete memory_;
109 107
110 // For a heap page from a snapshot, the HeapPage object lives in the malloc 108 // For a heap page from a snapshot, the HeapPage object lives in the malloc
111 // heap rather than the page itself. 109 // heap rather than the page itself.
112 if (image_page) { 110 if (image_page) {
113 free(this); 111 free(this);
114 } 112 }
115 } 113 }
116 114
117
118 void HeapPage::VisitObjects(ObjectVisitor* visitor) const { 115 void HeapPage::VisitObjects(ObjectVisitor* visitor) const {
119 NoSafepointScope no_safepoint; 116 NoSafepointScope no_safepoint;
120 uword obj_addr = object_start(); 117 uword obj_addr = object_start();
121 uword end_addr = object_end(); 118 uword end_addr = object_end();
122 while (obj_addr < end_addr) { 119 while (obj_addr < end_addr) {
123 RawObject* raw_obj = RawObject::FromAddr(obj_addr); 120 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
124 visitor->VisitObject(raw_obj); 121 visitor->VisitObject(raw_obj);
125 obj_addr += raw_obj->Size(); 122 obj_addr += raw_obj->Size();
126 } 123 }
127 ASSERT(obj_addr == end_addr); 124 ASSERT(obj_addr == end_addr);
128 } 125 }
129 126
130
131 void HeapPage::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 127 void HeapPage::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
132 NoSafepointScope no_safepoint; 128 NoSafepointScope no_safepoint;
133 uword obj_addr = object_start(); 129 uword obj_addr = object_start();
134 uword end_addr = object_end(); 130 uword end_addr = object_end();
135 while (obj_addr < end_addr) { 131 while (obj_addr < end_addr) {
136 RawObject* raw_obj = RawObject::FromAddr(obj_addr); 132 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
137 obj_addr += raw_obj->VisitPointers(visitor); 133 obj_addr += raw_obj->VisitPointers(visitor);
138 } 134 }
139 ASSERT(obj_addr == end_addr); 135 ASSERT(obj_addr == end_addr);
140 } 136 }
141 137
142
143 RawObject* HeapPage::FindObject(FindObjectVisitor* visitor) const { 138 RawObject* HeapPage::FindObject(FindObjectVisitor* visitor) const {
144 uword obj_addr = object_start(); 139 uword obj_addr = object_start();
145 uword end_addr = object_end(); 140 uword end_addr = object_end();
146 if (visitor->VisitRange(obj_addr, end_addr)) { 141 if (visitor->VisitRange(obj_addr, end_addr)) {
147 while (obj_addr < end_addr) { 142 while (obj_addr < end_addr) {
148 RawObject* raw_obj = RawObject::FromAddr(obj_addr); 143 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
149 uword next_obj_addr = obj_addr + raw_obj->Size(); 144 uword next_obj_addr = obj_addr + raw_obj->Size();
150 if (visitor->VisitRange(obj_addr, next_obj_addr) && 145 if (visitor->VisitRange(obj_addr, next_obj_addr) &&
151 raw_obj->FindObject(visitor)) { 146 raw_obj->FindObject(visitor)) {
152 return raw_obj; // Found object, return it. 147 return raw_obj; // Found object, return it.
153 } 148 }
154 obj_addr = next_obj_addr; 149 obj_addr = next_obj_addr;
155 } 150 }
156 ASSERT(obj_addr == end_addr); 151 ASSERT(obj_addr == end_addr);
157 } 152 }
158 return Object::null(); 153 return Object::null();
159 } 154 }
160 155
161
162 void HeapPage::WriteProtect(bool read_only) { 156 void HeapPage::WriteProtect(bool read_only) {
163 ASSERT(!is_image_page()); 157 ASSERT(!is_image_page());
164 158
165 VirtualMemory::Protection prot; 159 VirtualMemory::Protection prot;
166 if (read_only) { 160 if (read_only) {
167 if (type_ == kExecutable) { 161 if (type_ == kExecutable) {
168 prot = VirtualMemory::kReadExecute; 162 prot = VirtualMemory::kReadExecute;
169 } else { 163 } else {
170 prot = VirtualMemory::kReadOnly; 164 prot = VirtualMemory::kReadOnly;
171 } 165 }
172 } else { 166 } else {
173 prot = VirtualMemory::kReadWrite; 167 prot = VirtualMemory::kReadWrite;
174 } 168 }
175 bool status = memory_->Protect(prot); 169 bool status = memory_->Protect(prot);
176 ASSERT(status); 170 ASSERT(status);
177 } 171 }
178 172
179
180 PageSpace::PageSpace(Heap* heap, 173 PageSpace::PageSpace(Heap* heap,
181 intptr_t max_capacity_in_words, 174 intptr_t max_capacity_in_words,
182 intptr_t max_external_in_words) 175 intptr_t max_external_in_words)
183 : freelist_(), 176 : freelist_(),
184 heap_(heap), 177 heap_(heap),
185 pages_lock_(new Mutex()), 178 pages_lock_(new Mutex()),
186 pages_(NULL), 179 pages_(NULL),
187 pages_tail_(NULL), 180 pages_tail_(NULL),
188 exec_pages_(NULL), 181 exec_pages_(NULL),
189 exec_pages_tail_(NULL), 182 exec_pages_tail_(NULL),
(...skipping 11 matching lines...) Expand all
201 FLAG_old_gen_growth_space_ratio, 194 FLAG_old_gen_growth_space_ratio,
202 FLAG_old_gen_growth_rate, 195 FLAG_old_gen_growth_rate,
203 FLAG_old_gen_growth_time_ratio), 196 FLAG_old_gen_growth_time_ratio),
204 gc_time_micros_(0), 197 gc_time_micros_(0),
205 collections_(0) { 198 collections_(0) {
206 // We aren't holding the lock but no one can reference us yet. 199 // We aren't holding the lock but no one can reference us yet.
207 UpdateMaxCapacityLocked(); 200 UpdateMaxCapacityLocked();
208 UpdateMaxUsed(); 201 UpdateMaxUsed();
209 } 202 }
210 203
211
212 PageSpace::~PageSpace() { 204 PageSpace::~PageSpace() {
213 { 205 {
214 MonitorLocker ml(tasks_lock()); 206 MonitorLocker ml(tasks_lock());
215 while (tasks() > 0) { 207 while (tasks() > 0) {
216 ml.Wait(); 208 ml.Wait();
217 } 209 }
218 } 210 }
219 FreePages(pages_); 211 FreePages(pages_);
220 FreePages(exec_pages_); 212 FreePages(exec_pages_);
221 FreePages(large_pages_); 213 FreePages(large_pages_);
222 delete pages_lock_; 214 delete pages_lock_;
223 delete tasks_lock_; 215 delete tasks_lock_;
224 } 216 }
225 217
226
227 intptr_t PageSpace::LargePageSizeInWordsFor(intptr_t size) { 218 intptr_t PageSpace::LargePageSizeInWordsFor(intptr_t size) {
228 intptr_t page_size = Utils::RoundUp(size + HeapPage::ObjectStartOffset(), 219 intptr_t page_size = Utils::RoundUp(size + HeapPage::ObjectStartOffset(),
229 VirtualMemory::PageSize()); 220 VirtualMemory::PageSize());
230 return page_size >> kWordSizeLog2; 221 return page_size >> kWordSizeLog2;
231 } 222 }
232 223
233
234 HeapPage* PageSpace::AllocatePage(HeapPage::PageType type) { 224 HeapPage* PageSpace::AllocatePage(HeapPage::PageType type) {
235 const bool is_exec = (type == HeapPage::kExecutable); 225 const bool is_exec = (type == HeapPage::kExecutable);
236 const intptr_t kVmNameSize = 128; 226 const intptr_t kVmNameSize = 128;
237 char vm_name[kVmNameSize]; 227 char vm_name[kVmNameSize];
238 Heap::RegionName(heap_, is_exec ? Heap::kCode : Heap::kOld, vm_name, 228 Heap::RegionName(heap_, is_exec ? Heap::kCode : Heap::kOld, vm_name,
239 kVmNameSize); 229 kVmNameSize);
240 HeapPage* page = HeapPage::Allocate(kPageSizeInWords, type, vm_name); 230 HeapPage* page = HeapPage::Allocate(kPageSizeInWords, type, vm_name);
241 if (page == NULL) { 231 if (page == NULL) {
242 return NULL; 232 return NULL;
243 } 233 }
(...skipping 22 matching lines...) Expand all
266 exec_pages_tail_->WriteProtect(true); 256 exec_pages_tail_->WriteProtect(true);
267 } 257 }
268 } 258 }
269 exec_pages_tail_ = page; 259 exec_pages_tail_ = page;
270 } 260 }
271 IncreaseCapacityInWordsLocked(kPageSizeInWords); 261 IncreaseCapacityInWordsLocked(kPageSizeInWords);
272 page->set_object_end(page->memory_->end()); 262 page->set_object_end(page->memory_->end());
273 return page; 263 return page;
274 } 264 }
275 265
276
277 HeapPage* PageSpace::AllocateLargePage(intptr_t size, HeapPage::PageType type) { 266 HeapPage* PageSpace::AllocateLargePage(intptr_t size, HeapPage::PageType type) {
278 const bool is_exec = (type == HeapPage::kExecutable); 267 const bool is_exec = (type == HeapPage::kExecutable);
279 const intptr_t page_size_in_words = LargePageSizeInWordsFor(size); 268 const intptr_t page_size_in_words = LargePageSizeInWordsFor(size);
280 const intptr_t kVmNameSize = 128; 269 const intptr_t kVmNameSize = 128;
281 char vm_name[kVmNameSize]; 270 char vm_name[kVmNameSize];
282 Heap::RegionName(heap_, is_exec ? Heap::kCode : Heap::kOld, vm_name, 271 Heap::RegionName(heap_, is_exec ? Heap::kCode : Heap::kOld, vm_name,
283 kVmNameSize); 272 kVmNameSize);
284 HeapPage* page = HeapPage::Allocate(page_size_in_words, type, vm_name); 273 HeapPage* page = HeapPage::Allocate(page_size_in_words, type, vm_name);
285 if (page == NULL) { 274 if (page == NULL) {
286 return NULL; 275 return NULL;
287 } 276 }
288 page->set_next(large_pages_); 277 page->set_next(large_pages_);
289 large_pages_ = page; 278 large_pages_ = page;
290 IncreaseCapacityInWords(page_size_in_words); 279 IncreaseCapacityInWords(page_size_in_words);
291 // Only one object in this page (at least until String::MakeExternal or 280 // Only one object in this page (at least until String::MakeExternal or
292 // Array::MakeFixedLength is called). 281 // Array::MakeFixedLength is called).
293 page->set_object_end(page->object_start() + size); 282 page->set_object_end(page->object_start() + size);
294 return page; 283 return page;
295 } 284 }
296 285
297
298 void PageSpace::TruncateLargePage(HeapPage* page, 286 void PageSpace::TruncateLargePage(HeapPage* page,
299 intptr_t new_object_size_in_bytes) { 287 intptr_t new_object_size_in_bytes) {
300 const intptr_t old_object_size_in_bytes = 288 const intptr_t old_object_size_in_bytes =
301 page->object_end() - page->object_start(); 289 page->object_end() - page->object_start();
302 ASSERT(new_object_size_in_bytes <= old_object_size_in_bytes); 290 ASSERT(new_object_size_in_bytes <= old_object_size_in_bytes);
303 const intptr_t new_page_size_in_words = 291 const intptr_t new_page_size_in_words =
304 LargePageSizeInWordsFor(new_object_size_in_bytes); 292 LargePageSizeInWordsFor(new_object_size_in_bytes);
305 VirtualMemory* memory = page->memory_; 293 VirtualMemory* memory = page->memory_;
306 const intptr_t old_page_size_in_words = (memory->size() >> kWordSizeLog2); 294 const intptr_t old_page_size_in_words = (memory->size() >> kWordSizeLog2);
307 if (new_page_size_in_words < old_page_size_in_words) { 295 if (new_page_size_in_words < old_page_size_in_words) {
308 memory->Truncate(new_page_size_in_words << kWordSizeLog2); 296 memory->Truncate(new_page_size_in_words << kWordSizeLog2);
309 IncreaseCapacityInWords(new_page_size_in_words - old_page_size_in_words); 297 IncreaseCapacityInWords(new_page_size_in_words - old_page_size_in_words);
310 page->set_object_end(page->object_start() + new_object_size_in_bytes); 298 page->set_object_end(page->object_start() + new_object_size_in_bytes);
311 } 299 }
312 } 300 }
313 301
314
315 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) { 302 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) {
316 bool is_exec = (page->type() == HeapPage::kExecutable); 303 bool is_exec = (page->type() == HeapPage::kExecutable);
317 { 304 {
318 MutexLocker ml(pages_lock_); 305 MutexLocker ml(pages_lock_);
319 IncreaseCapacityInWordsLocked(-(page->memory_->size() >> kWordSizeLog2)); 306 IncreaseCapacityInWordsLocked(-(page->memory_->size() >> kWordSizeLog2));
320 if (!is_exec) { 307 if (!is_exec) {
321 // Remove the page from the list of data pages. 308 // Remove the page from the list of data pages.
322 if (previous_page != NULL) { 309 if (previous_page != NULL) {
323 previous_page->set_next(page->next()); 310 previous_page->set_next(page->next());
324 } else { 311 } else {
(...skipping 11 matching lines...) Expand all
336 } 323 }
337 if (page == exec_pages_tail_) { 324 if (page == exec_pages_tail_) {
338 exec_pages_tail_ = previous_page; 325 exec_pages_tail_ = previous_page;
339 } 326 }
340 } 327 }
341 } 328 }
342 // TODO(iposva): Consider adding to a pool of empty pages. 329 // TODO(iposva): Consider adding to a pool of empty pages.
343 page->Deallocate(); 330 page->Deallocate();
344 } 331 }
345 332
346
347 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) { 333 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) {
348 IncreaseCapacityInWords(-(page->memory_->size() >> kWordSizeLog2)); 334 IncreaseCapacityInWords(-(page->memory_->size() >> kWordSizeLog2));
349 // Remove the page from the list. 335 // Remove the page from the list.
350 if (previous_page != NULL) { 336 if (previous_page != NULL) {
351 previous_page->set_next(page->next()); 337 previous_page->set_next(page->next());
352 } else { 338 } else {
353 large_pages_ = page->next(); 339 large_pages_ = page->next();
354 } 340 }
355 page->Deallocate(); 341 page->Deallocate();
356 } 342 }
357 343
358
359 void PageSpace::FreePages(HeapPage* pages) { 344 void PageSpace::FreePages(HeapPage* pages) {
360 HeapPage* page = pages; 345 HeapPage* page = pages;
361 while (page != NULL) { 346 while (page != NULL) {
362 HeapPage* next = page->next(); 347 HeapPage* next = page->next();
363 page->Deallocate(); 348 page->Deallocate();
364 page = next; 349 page = next;
365 } 350 }
366 } 351 }
367 352
368
369 uword PageSpace::TryAllocateInFreshPage(intptr_t size, 353 uword PageSpace::TryAllocateInFreshPage(intptr_t size,
370 HeapPage::PageType type, 354 HeapPage::PageType type,
371 GrowthPolicy growth_policy, 355 GrowthPolicy growth_policy,
372 bool is_locked) { 356 bool is_locked) {
373 ASSERT(size < kAllocatablePageSize); 357 ASSERT(size < kAllocatablePageSize);
374 uword result = 0; 358 uword result = 0;
375 SpaceUsage after_allocation = GetCurrentUsage(); 359 SpaceUsage after_allocation = GetCurrentUsage();
376 after_allocation.used_in_words += size >> kWordSizeLog2; 360 after_allocation.used_in_words += size >> kWordSizeLog2;
377 // Can we grow by one page? 361 // Can we grow by one page?
378 after_allocation.capacity_in_words += kPageSizeInWords; 362 after_allocation.capacity_in_words += kPageSizeInWords;
(...skipping 16 matching lines...) Expand all
395 if (is_locked) { 379 if (is_locked) {
396 freelist_[type].FreeLocked(free_start, free_size); 380 freelist_[type].FreeLocked(free_start, free_size);
397 } else { 381 } else {
398 freelist_[type].Free(free_start, free_size); 382 freelist_[type].Free(free_start, free_size);
399 } 383 }
400 } 384 }
401 } 385 }
402 return result; 386 return result;
403 } 387 }
404 388
405
406 uword PageSpace::TryAllocateInternal(intptr_t size, 389 uword PageSpace::TryAllocateInternal(intptr_t size,
407 HeapPage::PageType type, 390 HeapPage::PageType type,
408 GrowthPolicy growth_policy, 391 GrowthPolicy growth_policy,
409 bool is_protected, 392 bool is_protected,
410 bool is_locked) { 393 bool is_locked) {
411 ASSERT(size >= kObjectAlignment); 394 ASSERT(size >= kObjectAlignment);
412 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 395 ASSERT(Utils::IsAligned(size, kObjectAlignment));
413 uword result = 0; 396 uword result = 0;
414 if (size < kAllocatablePageSize) { 397 if (size < kAllocatablePageSize) {
415 if (is_locked) { 398 if (is_locked) {
(...skipping 27 matching lines...) Expand all
443 // Note: usage_.capacity_in_words is increased by AllocateLargePage. 426 // Note: usage_.capacity_in_words is increased by AllocateLargePage.
444 AtomicOperations::IncrementBy(&(usage_.used_in_words), 427 AtomicOperations::IncrementBy(&(usage_.used_in_words),
445 (size >> kWordSizeLog2)); 428 (size >> kWordSizeLog2));
446 } 429 }
447 } 430 }
448 } 431 }
449 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset); 432 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
450 return result; 433 return result;
451 } 434 }
452 435
453
454 void PageSpace::AcquireDataLock() { 436 void PageSpace::AcquireDataLock() {
455 freelist_[HeapPage::kData].mutex()->Lock(); 437 freelist_[HeapPage::kData].mutex()->Lock();
456 } 438 }
457 439
458
459 void PageSpace::ReleaseDataLock() { 440 void PageSpace::ReleaseDataLock() {
460 freelist_[HeapPage::kData].mutex()->Unlock(); 441 freelist_[HeapPage::kData].mutex()->Unlock();
461 } 442 }
462 443
463
464 void PageSpace::AllocateExternal(intptr_t size) { 444 void PageSpace::AllocateExternal(intptr_t size) {
465 intptr_t size_in_words = size >> kWordSizeLog2; 445 intptr_t size_in_words = size >> kWordSizeLog2;
466 AtomicOperations::IncrementBy(&(usage_.external_in_words), size_in_words); 446 AtomicOperations::IncrementBy(&(usage_.external_in_words), size_in_words);
467 // TODO(koda): Control growth. 447 // TODO(koda): Control growth.
468 } 448 }
469 449
470
471 void PageSpace::FreeExternal(intptr_t size) { 450 void PageSpace::FreeExternal(intptr_t size) {
472 intptr_t size_in_words = size >> kWordSizeLog2; 451 intptr_t size_in_words = size >> kWordSizeLog2;
473 AtomicOperations::DecrementBy(&(usage_.external_in_words), size_in_words); 452 AtomicOperations::DecrementBy(&(usage_.external_in_words), size_in_words);
474 } 453 }
475 454
476
477 // Provides exclusive access to all pages, and ensures they are walkable. 455 // Provides exclusive access to all pages, and ensures they are walkable.
478 class ExclusivePageIterator : ValueObject { 456 class ExclusivePageIterator : ValueObject {
479 public: 457 public:
480 explicit ExclusivePageIterator(const PageSpace* space) 458 explicit ExclusivePageIterator(const PageSpace* space)
481 : space_(space), ml_(space->pages_lock_) { 459 : space_(space), ml_(space->pages_lock_) {
482 space_->MakeIterable(); 460 space_->MakeIterable();
483 page_ = space_->pages_; 461 page_ = space_->pages_;
484 if (page_ == NULL) { 462 if (page_ == NULL) {
485 page_ = space_->exec_pages_; 463 page_ = space_->exec_pages_;
486 if (page_ == NULL) { 464 if (page_ == NULL) {
487 page_ = space_->large_pages_; 465 page_ = space_->large_pages_;
488 } 466 }
489 } 467 }
490 } 468 }
491 HeapPage* page() const { return page_; } 469 HeapPage* page() const { return page_; }
492 bool Done() const { return page_ == NULL; } 470 bool Done() const { return page_ == NULL; }
493 void Advance() { 471 void Advance() {
494 ASSERT(!Done()); 472 ASSERT(!Done());
495 page_ = space_->NextPageAnySize(page_); 473 page_ = space_->NextPageAnySize(page_);
496 } 474 }
497 475
498 private: 476 private:
499 const PageSpace* space_; 477 const PageSpace* space_;
500 MutexLocker ml_; 478 MutexLocker ml_;
501 NoSafepointScope no_safepoint; 479 NoSafepointScope no_safepoint;
502 HeapPage* page_; 480 HeapPage* page_;
503 }; 481 };
504 482
505
506 // Provides exclusive access to code pages, and ensures they are walkable. 483 // Provides exclusive access to code pages, and ensures they are walkable.
507 // NOTE: This does not iterate over large pages which can contain code. 484 // NOTE: This does not iterate over large pages which can contain code.
508 class ExclusiveCodePageIterator : ValueObject { 485 class ExclusiveCodePageIterator : ValueObject {
509 public: 486 public:
510 explicit ExclusiveCodePageIterator(const PageSpace* space) 487 explicit ExclusiveCodePageIterator(const PageSpace* space)
511 : space_(space), ml_(space->pages_lock_) { 488 : space_(space), ml_(space->pages_lock_) {
512 space_->MakeIterable(); 489 space_->MakeIterable();
513 page_ = space_->exec_pages_; 490 page_ = space_->exec_pages_;
514 } 491 }
515 HeapPage* page() const { return page_; } 492 HeapPage* page() const { return page_; }
516 bool Done() const { return page_ == NULL; } 493 bool Done() const { return page_ == NULL; }
517 void Advance() { 494 void Advance() {
518 ASSERT(!Done()); 495 ASSERT(!Done());
519 page_ = page_->next(); 496 page_ = page_->next();
520 } 497 }
521 498
522 private: 499 private:
523 const PageSpace* space_; 500 const PageSpace* space_;
524 MutexLocker ml_; 501 MutexLocker ml_;
525 NoSafepointScope no_safepoint; 502 NoSafepointScope no_safepoint;
526 HeapPage* page_; 503 HeapPage* page_;
527 }; 504 };
528 505
529
530 // Provides exclusive access to large pages, and ensures they are walkable. 506 // Provides exclusive access to large pages, and ensures they are walkable.
531 class ExclusiveLargePageIterator : ValueObject { 507 class ExclusiveLargePageIterator : ValueObject {
532 public: 508 public:
533 explicit ExclusiveLargePageIterator(const PageSpace* space) 509 explicit ExclusiveLargePageIterator(const PageSpace* space)
534 : space_(space), ml_(space->pages_lock_) { 510 : space_(space), ml_(space->pages_lock_) {
535 space_->MakeIterable(); 511 space_->MakeIterable();
536 page_ = space_->large_pages_; 512 page_ = space_->large_pages_;
537 } 513 }
538 HeapPage* page() const { return page_; } 514 HeapPage* page() const { return page_; }
539 bool Done() const { return page_ == NULL; } 515 bool Done() const { return page_ == NULL; }
540 void Advance() { 516 void Advance() {
541 ASSERT(!Done()); 517 ASSERT(!Done());
542 page_ = page_->next(); 518 page_ = page_->next();
543 } 519 }
544 520
545 private: 521 private:
546 const PageSpace* space_; 522 const PageSpace* space_;
547 MutexLocker ml_; 523 MutexLocker ml_;
548 NoSafepointScope no_safepoint; 524 NoSafepointScope no_safepoint;
549 HeapPage* page_; 525 HeapPage* page_;
550 }; 526 };
551 527
552
553 void PageSpace::MakeIterable() const { 528 void PageSpace::MakeIterable() const {
554 // Assert not called from concurrent sweeper task. 529 // Assert not called from concurrent sweeper task.
555 // TODO(koda): Use thread/task identity when implemented. 530 // TODO(koda): Use thread/task identity when implemented.
556 ASSERT(Isolate::Current()->heap() != NULL); 531 ASSERT(Isolate::Current()->heap() != NULL);
557 if (bump_top_ < bump_end_) { 532 if (bump_top_ < bump_end_) {
558 FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_); 533 FreeListElement::AsElement(bump_top_, bump_end_ - bump_top_);
559 } 534 }
560 } 535 }
561 536
562
563 void PageSpace::AbandonBumpAllocation() { 537 void PageSpace::AbandonBumpAllocation() {
564 if (bump_top_ < bump_end_) { 538 if (bump_top_ < bump_end_) {
565 freelist_[HeapPage::kData].Free(bump_top_, bump_end_ - bump_top_); 539 freelist_[HeapPage::kData].Free(bump_top_, bump_end_ - bump_top_);
566 bump_top_ = 0; 540 bump_top_ = 0;
567 bump_end_ = 0; 541 bump_end_ = 0;
568 } 542 }
569 } 543 }
570 544
571
572 void PageSpace::UpdateMaxCapacityLocked() { 545 void PageSpace::UpdateMaxCapacityLocked() {
573 if (heap_ == NULL) { 546 if (heap_ == NULL) {
574 // Some unit tests. 547 // Some unit tests.
575 return; 548 return;
576 } 549 }
577 ASSERT(heap_ != NULL); 550 ASSERT(heap_ != NULL);
578 ASSERT(heap_->isolate() != NULL); 551 ASSERT(heap_->isolate() != NULL);
579 Isolate* isolate = heap_->isolate(); 552 Isolate* isolate = heap_->isolate();
580 isolate->GetHeapOldCapacityMaxMetric()->SetValue( 553 isolate->GetHeapOldCapacityMaxMetric()->SetValue(
581 static_cast<int64_t>(usage_.capacity_in_words) * kWordSize); 554 static_cast<int64_t>(usage_.capacity_in_words) * kWordSize);
582 } 555 }
583 556
584
585 void PageSpace::UpdateMaxUsed() { 557 void PageSpace::UpdateMaxUsed() {
586 if (heap_ == NULL) { 558 if (heap_ == NULL) {
587 // Some unit tests. 559 // Some unit tests.
588 return; 560 return;
589 } 561 }
590 ASSERT(heap_ != NULL); 562 ASSERT(heap_ != NULL);
591 ASSERT(heap_->isolate() != NULL); 563 ASSERT(heap_->isolate() != NULL);
592 Isolate* isolate = heap_->isolate(); 564 Isolate* isolate = heap_->isolate();
593 isolate->GetHeapOldUsedMaxMetric()->SetValue(UsedInWords() * kWordSize); 565 isolate->GetHeapOldUsedMaxMetric()->SetValue(UsedInWords() * kWordSize);
594 } 566 }
595 567
596
597 bool PageSpace::Contains(uword addr) const { 568 bool PageSpace::Contains(uword addr) const {
598 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 569 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
599 if (it.page()->Contains(addr)) { 570 if (it.page()->Contains(addr)) {
600 return true; 571 return true;
601 } 572 }
602 } 573 }
603 return false; 574 return false;
604 } 575 }
605 576
606
607 bool PageSpace::Contains(uword addr, HeapPage::PageType type) const { 577 bool PageSpace::Contains(uword addr, HeapPage::PageType type) const {
608 if (type == HeapPage::kExecutable) { 578 if (type == HeapPage::kExecutable) {
609 // Fast path executable pages. 579 // Fast path executable pages.
610 for (ExclusiveCodePageIterator it(this); !it.Done(); it.Advance()) { 580 for (ExclusiveCodePageIterator it(this); !it.Done(); it.Advance()) {
611 if (it.page()->Contains(addr)) { 581 if (it.page()->Contains(addr)) {
612 return true; 582 return true;
613 } 583 }
614 } 584 }
615 // Large pages can be executable, walk them too. 585 // Large pages can be executable, walk them too.
616 for (ExclusiveLargePageIterator it(this); !it.Done(); it.Advance()) { 586 for (ExclusiveLargePageIterator it(this); !it.Done(); it.Advance()) {
617 if ((it.page()->type() == type) && it.page()->Contains(addr)) { 587 if ((it.page()->type() == type) && it.page()->Contains(addr)) {
618 return true; 588 return true;
619 } 589 }
620 } 590 }
621 return false; 591 return false;
622 } 592 }
623 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 593 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
624 if ((it.page()->type() == type) && it.page()->Contains(addr)) { 594 if ((it.page()->type() == type) && it.page()->Contains(addr)) {
625 return true; 595 return true;
626 } 596 }
627 } 597 }
628 return false; 598 return false;
629 } 599 }
630 600
631
632 bool PageSpace::DataContains(uword addr) const { 601 bool PageSpace::DataContains(uword addr) const {
633 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 602 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
634 if ((it.page()->type() != HeapPage::kExecutable) && 603 if ((it.page()->type() != HeapPage::kExecutable) &&
635 it.page()->Contains(addr)) { 604 it.page()->Contains(addr)) {
636 return true; 605 return true;
637 } 606 }
638 } 607 }
639 return false; 608 return false;
640 } 609 }
641 610
642
643 void PageSpace::AddRegionsToObjectSet(ObjectSet* set) const { 611 void PageSpace::AddRegionsToObjectSet(ObjectSet* set) const {
644 ASSERT((pages_ != NULL) || (exec_pages_ != NULL) || (large_pages_ != NULL)); 612 ASSERT((pages_ != NULL) || (exec_pages_ != NULL) || (large_pages_ != NULL));
645 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 613 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
646 set->AddRegion(it.page()->object_start(), it.page()->object_end()); 614 set->AddRegion(it.page()->object_start(), it.page()->object_end());
647 } 615 }
648 } 616 }
649 617
650
651 void PageSpace::VisitObjects(ObjectVisitor* visitor) const { 618 void PageSpace::VisitObjects(ObjectVisitor* visitor) const {
652 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 619 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
653 it.page()->VisitObjects(visitor); 620 it.page()->VisitObjects(visitor);
654 } 621 }
655 } 622 }
656 623
657
658 void PageSpace::VisitObjectsNoImagePages(ObjectVisitor* visitor) const { 624 void PageSpace::VisitObjectsNoImagePages(ObjectVisitor* visitor) const {
659 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 625 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
660 if (!it.page()->is_image_page()) { 626 if (!it.page()->is_image_page()) {
661 it.page()->VisitObjects(visitor); 627 it.page()->VisitObjects(visitor);
662 } 628 }
663 } 629 }
664 } 630 }
665 631
666
667 void PageSpace::VisitObjectsImagePages(ObjectVisitor* visitor) const { 632 void PageSpace::VisitObjectsImagePages(ObjectVisitor* visitor) const {
668 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 633 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
669 if (it.page()->is_image_page()) { 634 if (it.page()->is_image_page()) {
670 it.page()->VisitObjects(visitor); 635 it.page()->VisitObjects(visitor);
671 } 636 }
672 } 637 }
673 } 638 }
674 639
675
676 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 640 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
677 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 641 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
678 it.page()->VisitObjectPointers(visitor); 642 it.page()->VisitObjectPointers(visitor);
679 } 643 }
680 } 644 }
681 645
682
683 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor, 646 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor,
684 HeapPage::PageType type) const { 647 HeapPage::PageType type) const {
685 if (type == HeapPage::kExecutable) { 648 if (type == HeapPage::kExecutable) {
686 // Fast path executable pages. 649 // Fast path executable pages.
687 for (ExclusiveCodePageIterator it(this); !it.Done(); it.Advance()) { 650 for (ExclusiveCodePageIterator it(this); !it.Done(); it.Advance()) {
688 RawObject* obj = it.page()->FindObject(visitor); 651 RawObject* obj = it.page()->FindObject(visitor);
689 if (obj != Object::null()) { 652 if (obj != Object::null()) {
690 return obj; 653 return obj;
691 } 654 }
692 } 655 }
(...skipping 13 matching lines...) Expand all
706 if (it.page()->type() == type) { 669 if (it.page()->type() == type) {
707 RawObject* obj = it.page()->FindObject(visitor); 670 RawObject* obj = it.page()->FindObject(visitor);
708 if (obj != Object::null()) { 671 if (obj != Object::null()) {
709 return obj; 672 return obj;
710 } 673 }
711 } 674 }
712 } 675 }
713 return Object::null(); 676 return Object::null();
714 } 677 }
715 678
716
717 void PageSpace::WriteProtect(bool read_only) { 679 void PageSpace::WriteProtect(bool read_only) {
718 if (read_only) { 680 if (read_only) {
719 // Avoid MakeIterable trying to write to the heap. 681 // Avoid MakeIterable trying to write to the heap.
720 AbandonBumpAllocation(); 682 AbandonBumpAllocation();
721 } 683 }
722 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) { 684 for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
723 if (!it.page()->is_image_page()) { 685 if (!it.page()->is_image_page()) {
724 it.page()->WriteProtect(read_only); 686 it.page()->WriteProtect(read_only);
725 } 687 }
726 } 688 }
727 } 689 }
728 690
729
730 #ifndef PRODUCT 691 #ifndef PRODUCT
731 void PageSpace::PrintToJSONObject(JSONObject* object) const { 692 void PageSpace::PrintToJSONObject(JSONObject* object) const {
732 if (!FLAG_support_service) { 693 if (!FLAG_support_service) {
733 return; 694 return;
734 } 695 }
735 Isolate* isolate = Isolate::Current(); 696 Isolate* isolate = Isolate::Current();
736 ASSERT(isolate != NULL); 697 ASSERT(isolate != NULL);
737 JSONObject space(object, "old"); 698 JSONObject space(object, "old");
738 space.AddProperty("type", "HeapSpace"); 699 space.AddProperty("type", "HeapSpace");
739 space.AddProperty("name", "old"); 700 space.AddProperty("name", "old");
740 space.AddProperty("vmName", "PageSpace"); 701 space.AddProperty("vmName", "PageSpace");
741 space.AddProperty("collections", collections()); 702 space.AddProperty("collections", collections());
742 space.AddProperty64("used", UsedInWords() * kWordSize); 703 space.AddProperty64("used", UsedInWords() * kWordSize);
743 space.AddProperty64("capacity", CapacityInWords() * kWordSize); 704 space.AddProperty64("capacity", CapacityInWords() * kWordSize);
744 space.AddProperty64("external", ExternalInWords() * kWordSize); 705 space.AddProperty64("external", ExternalInWords() * kWordSize);
745 space.AddProperty("time", MicrosecondsToSeconds(gc_time_micros())); 706 space.AddProperty("time", MicrosecondsToSeconds(gc_time_micros()));
746 if (collections() > 0) { 707 if (collections() > 0) {
747 int64_t run_time = isolate->UptimeMicros(); 708 int64_t run_time = isolate->UptimeMicros();
748 run_time = Utils::Maximum(run_time, static_cast<int64_t>(0)); 709 run_time = Utils::Maximum(run_time, static_cast<int64_t>(0));
749 double run_time_millis = MicrosecondsToMilliseconds(run_time); 710 double run_time_millis = MicrosecondsToMilliseconds(run_time);
750 double avg_time_between_collections = 711 double avg_time_between_collections =
751 run_time_millis / static_cast<double>(collections()); 712 run_time_millis / static_cast<double>(collections());
752 space.AddProperty("avgCollectionPeriodMillis", 713 space.AddProperty("avgCollectionPeriodMillis",
753 avg_time_between_collections); 714 avg_time_between_collections);
754 } else { 715 } else {
755 space.AddProperty("avgCollectionPeriodMillis", 0.0); 716 space.AddProperty("avgCollectionPeriodMillis", 0.0);
756 } 717 }
757 } 718 }
758 719
759
760 class HeapMapAsJSONVisitor : public ObjectVisitor { 720 class HeapMapAsJSONVisitor : public ObjectVisitor {
761 public: 721 public:
762 explicit HeapMapAsJSONVisitor(JSONArray* array) : array_(array) {} 722 explicit HeapMapAsJSONVisitor(JSONArray* array) : array_(array) {}
763 virtual void VisitObject(RawObject* obj) { 723 virtual void VisitObject(RawObject* obj) {
764 array_->AddValue(obj->Size() / kObjectAlignment); 724 array_->AddValue(obj->Size() / kObjectAlignment);
765 array_->AddValue(obj->GetClassId()); 725 array_->AddValue(obj->GetClassId());
766 } 726 }
767 727
768 private: 728 private:
769 JSONArray* array_; 729 JSONArray* array_;
770 }; 730 };
771 731
772
773 void PageSpace::PrintHeapMapToJSONStream(Isolate* isolate, 732 void PageSpace::PrintHeapMapToJSONStream(Isolate* isolate,
774 JSONStream* stream) const { 733 JSONStream* stream) const {
775 if (!FLAG_support_service) { 734 if (!FLAG_support_service) {
776 return; 735 return;
777 } 736 }
778 JSONObject heap_map(stream); 737 JSONObject heap_map(stream);
779 heap_map.AddProperty("type", "HeapMap"); 738 heap_map.AddProperty("type", "HeapMap");
780 heap_map.AddProperty("freeClassId", static_cast<intptr_t>(kFreeListElement)); 739 heap_map.AddProperty("freeClassId", static_cast<intptr_t>(kFreeListElement));
781 heap_map.AddProperty("unitSizeBytes", 740 heap_map.AddProperty("unitSizeBytes",
782 static_cast<intptr_t>(kObjectAlignment)); 741 static_cast<intptr_t>(kObjectAlignment));
(...skipping 23 matching lines...) Expand all
806 page_container.AddPropertyF("objectStart", "0x%" Px "", 765 page_container.AddPropertyF("objectStart", "0x%" Px "",
807 page->object_start()); 766 page->object_start());
808 JSONArray page_map(&page_container, "objects"); 767 JSONArray page_map(&page_container, "objects");
809 HeapMapAsJSONVisitor printer(&page_map); 768 HeapMapAsJSONVisitor printer(&page_map);
810 page->VisitObjects(&printer); 769 page->VisitObjects(&printer);
811 } 770 }
812 } 771 }
813 } 772 }
814 #endif // PRODUCT 773 #endif // PRODUCT
815 774
816
817 bool PageSpace::ShouldCollectCode() { 775 bool PageSpace::ShouldCollectCode() {
818 // Try to collect code if enough time has passed since the last attempt. 776 // Try to collect code if enough time has passed since the last attempt.
819 const int64_t start = OS::GetCurrentMonotonicMicros(); 777 const int64_t start = OS::GetCurrentMonotonicMicros();
820 const int64_t last_code_collection_in_us = 778 const int64_t last_code_collection_in_us =
821 page_space_controller_.last_code_collection_in_us(); 779 page_space_controller_.last_code_collection_in_us();
822 780
823 if ((start - last_code_collection_in_us) > 781 if ((start - last_code_collection_in_us) >
824 FLAG_code_collection_interval_in_us) { 782 FLAG_code_collection_interval_in_us) {
825 if (FLAG_log_code_drop) { 783 if (FLAG_log_code_drop) {
826 OS::Print("Trying to detach code.\n"); 784 OS::Print("Trying to detach code.\n");
827 } 785 }
828 page_space_controller_.set_last_code_collection_in_us(start); 786 page_space_controller_.set_last_code_collection_in_us(start);
829 return true; 787 return true;
830 } 788 }
831 return false; 789 return false;
832 } 790 }
833 791
834
835 void PageSpace::WriteProtectCode(bool read_only) { 792 void PageSpace::WriteProtectCode(bool read_only) {
836 if (FLAG_write_protect_code) { 793 if (FLAG_write_protect_code) {
837 MutexLocker ml(pages_lock_); 794 MutexLocker ml(pages_lock_);
838 NoSafepointScope no_safepoint; 795 NoSafepointScope no_safepoint;
839 // No need to go through all of the data pages first. 796 // No need to go through all of the data pages first.
840 HeapPage* page = exec_pages_; 797 HeapPage* page = exec_pages_;
841 while (page != NULL) { 798 while (page != NULL) {
842 ASSERT(page->type() == HeapPage::kExecutable); 799 ASSERT(page->type() == HeapPage::kExecutable);
843 if (!page->is_image_page()) { 800 if (!page->is_image_page()) {
844 page->WriteProtect(read_only); 801 page->WriteProtect(read_only);
845 } 802 }
846 page = page->next(); 803 page = page->next();
847 } 804 }
848 page = large_pages_; 805 page = large_pages_;
849 while (page != NULL) { 806 while (page != NULL) {
850 if (page->type() == HeapPage::kExecutable && !page->is_image_page()) { 807 if (page->type() == HeapPage::kExecutable && !page->is_image_page()) {
851 page->WriteProtect(read_only); 808 page->WriteProtect(read_only);
852 } 809 }
853 page = page->next(); 810 page = page->next();
854 } 811 }
855 } 812 }
856 } 813 }
857 814
858
859 void PageSpace::MarkSweep(bool invoke_api_callbacks) { 815 void PageSpace::MarkSweep(bool invoke_api_callbacks) {
860 Thread* thread = Thread::Current(); 816 Thread* thread = Thread::Current();
861 Isolate* isolate = heap_->isolate(); 817 Isolate* isolate = heap_->isolate();
862 ASSERT(isolate == Isolate::Current()); 818 ASSERT(isolate == Isolate::Current());
863 819
864 const int64_t pre_wait_for_sweepers = OS::GetCurrentMonotonicMicros(); 820 const int64_t pre_wait_for_sweepers = OS::GetCurrentMonotonicMicros();
865 821
866 // Wait for pending tasks to complete and then account for the driver task. 822 // Wait for pending tasks to complete and then account for the driver task.
867 { 823 {
868 MonitorLocker locker(tasks_lock()); 824 MonitorLocker locker(tasks_lock());
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 } 985 }
1030 986
1031 // Done, reset the task count. 987 // Done, reset the task count.
1032 { 988 {
1033 MonitorLocker ml(tasks_lock()); 989 MonitorLocker ml(tasks_lock());
1034 set_tasks(tasks() - 1); 990 set_tasks(tasks() - 1);
1035 ml.NotifyAll(); 991 ml.NotifyAll();
1036 } 992 }
1037 } 993 }
1038 994
1039
1040 uword PageSpace::TryAllocateDataBumpInternal(intptr_t size, 995 uword PageSpace::TryAllocateDataBumpInternal(intptr_t size,
1041 GrowthPolicy growth_policy, 996 GrowthPolicy growth_policy,
1042 bool is_locked) { 997 bool is_locked) {
1043 ASSERT(size >= kObjectAlignment); 998 ASSERT(size >= kObjectAlignment);
1044 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 999 ASSERT(Utils::IsAligned(size, kObjectAlignment));
1045 intptr_t remaining = bump_end_ - bump_top_; 1000 intptr_t remaining = bump_end_ - bump_top_;
1046 if (remaining < size) { 1001 if (remaining < size) {
1047 // Checking this first would be logical, but needlessly slow. 1002 // Checking this first would be logical, but needlessly slow.
1048 if (size >= kAllocatablePageSize) { 1003 if (size >= kAllocatablePageSize) {
1049 return is_locked ? TryAllocateDataLocked(size, growth_policy) 1004 return is_locked ? TryAllocateDataLocked(size, growth_policy)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 #ifdef DEBUG 1036 #ifdef DEBUG
1082 if (bump_top_ < bump_end_) { 1037 if (bump_top_ < bump_end_) {
1083 // Fail fast if we try to walk the remaining block. 1038 // Fail fast if we try to walk the remaining block.
1084 COMPILE_ASSERT(kIllegalCid == 0); 1039 COMPILE_ASSERT(kIllegalCid == 0);
1085 *reinterpret_cast<uword*>(bump_top_) = 0; 1040 *reinterpret_cast<uword*>(bump_top_) = 0;
1086 } 1041 }
1087 #endif // DEBUG 1042 #endif // DEBUG
1088 return result; 1043 return result;
1089 } 1044 }
1090 1045
1091
1092 uword PageSpace::TryAllocateDataBump(intptr_t size, 1046 uword PageSpace::TryAllocateDataBump(intptr_t size,
1093 GrowthPolicy growth_policy) { 1047 GrowthPolicy growth_policy) {
1094 return TryAllocateDataBumpInternal(size, growth_policy, false); 1048 return TryAllocateDataBumpInternal(size, growth_policy, false);
1095 } 1049 }
1096 1050
1097
1098 uword PageSpace::TryAllocateDataBumpLocked(intptr_t size, 1051 uword PageSpace::TryAllocateDataBumpLocked(intptr_t size,
1099 GrowthPolicy growth_policy) { 1052 GrowthPolicy growth_policy) {
1100 return TryAllocateDataBumpInternal(size, growth_policy, true); 1053 return TryAllocateDataBumpInternal(size, growth_policy, true);
1101 } 1054 }
1102 1055
1103
1104 uword PageSpace::TryAllocatePromoLocked(intptr_t size, 1056 uword PageSpace::TryAllocatePromoLocked(intptr_t size,
1105 GrowthPolicy growth_policy) { 1057 GrowthPolicy growth_policy) {
1106 FreeList* freelist = &freelist_[HeapPage::kData]; 1058 FreeList* freelist = &freelist_[HeapPage::kData];
1107 uword result = freelist->TryAllocateSmallLocked(size); 1059 uword result = freelist->TryAllocateSmallLocked(size);
1108 if (result != 0) { 1060 if (result != 0) {
1109 AtomicOperations::IncrementBy(&(usage_.used_in_words), 1061 AtomicOperations::IncrementBy(&(usage_.used_in_words),
1110 (size >> kWordSizeLog2)); 1062 (size >> kWordSizeLog2));
1111 return result; 1063 return result;
1112 } 1064 }
1113 result = TryAllocateDataBumpLocked(size, growth_policy); 1065 result = TryAllocateDataBumpLocked(size, growth_policy);
1114 if (result != 0) return result; 1066 if (result != 0) return result;
1115 return TryAllocateDataLocked(size, growth_policy); 1067 return TryAllocateDataLocked(size, growth_policy);
1116 } 1068 }
1117 1069
1118
1119 void PageSpace::SetupImagePage(void* pointer, uword size, bool is_executable) { 1070 void PageSpace::SetupImagePage(void* pointer, uword size, bool is_executable) {
1120 // Setup a HeapPage so precompiled Instructions can be traversed. 1071 // Setup a HeapPage so precompiled Instructions can be traversed.
1121 // Instructions are contiguous at [pointer, pointer + size). HeapPage 1072 // Instructions are contiguous at [pointer, pointer + size). HeapPage
1122 // expects to find objects at [memory->start() + ObjectStartOffset, 1073 // expects to find objects at [memory->start() + ObjectStartOffset,
1123 // memory->end()). 1074 // memory->end()).
1124 uword offset = HeapPage::ObjectStartOffset(); 1075 uword offset = HeapPage::ObjectStartOffset();
1125 pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset); 1076 pointer = reinterpret_cast<void*>(reinterpret_cast<uword>(pointer) - offset);
1126 size += offset; 1077 size += offset;
1127 1078
1128 VirtualMemory* memory = VirtualMemory::ForImagePage(pointer, size); 1079 VirtualMemory* memory = VirtualMemory::ForImagePage(pointer, size);
(...skipping 22 matching lines...) Expand all
1151 (*tail)->WriteProtect(false); 1102 (*tail)->WriteProtect(false);
1152 } 1103 }
1153 (*tail)->set_next(page); 1104 (*tail)->set_next(page);
1154 if (is_executable && FLAG_write_protect_code && !(*tail)->is_image_page()) { 1105 if (is_executable && FLAG_write_protect_code && !(*tail)->is_image_page()) {
1155 (*tail)->WriteProtect(true); 1106 (*tail)->WriteProtect(true);
1156 } 1107 }
1157 } 1108 }
1158 (*tail) = page; 1109 (*tail) = page;
1159 } 1110 }
1160 1111
1161
1162 PageSpaceController::PageSpaceController(Heap* heap, 1112 PageSpaceController::PageSpaceController(Heap* heap,
1163 int heap_growth_ratio, 1113 int heap_growth_ratio,
1164 int heap_growth_max, 1114 int heap_growth_max,
1165 int garbage_collection_time_ratio) 1115 int garbage_collection_time_ratio)
1166 : heap_(heap), 1116 : heap_(heap),
1167 is_enabled_(false), 1117 is_enabled_(false),
1168 grow_heap_(heap_growth_max / 2), 1118 grow_heap_(heap_growth_max / 2),
1169 heap_growth_ratio_(heap_growth_ratio), 1119 heap_growth_ratio_(heap_growth_ratio),
1170 desired_utilization_((100.0 - heap_growth_ratio) / 100.0), 1120 desired_utilization_((100.0 - heap_growth_ratio) / 100.0),
1171 heap_growth_max_(heap_growth_max), 1121 heap_growth_max_(heap_growth_max),
1172 garbage_collection_time_ratio_(garbage_collection_time_ratio), 1122 garbage_collection_time_ratio_(garbage_collection_time_ratio),
1173 last_code_collection_in_us_(OS::GetCurrentMonotonicMicros()) {} 1123 last_code_collection_in_us_(OS::GetCurrentMonotonicMicros()) {}
1174 1124
1175
1176 PageSpaceController::~PageSpaceController() {} 1125 PageSpaceController::~PageSpaceController() {}
1177 1126
1178
1179 bool PageSpaceController::NeedsGarbageCollection(SpaceUsage after) const { 1127 bool PageSpaceController::NeedsGarbageCollection(SpaceUsage after) const {
1180 if (!is_enabled_) { 1128 if (!is_enabled_) {
1181 return false; 1129 return false;
1182 } 1130 }
1183 if (heap_growth_ratio_ == 100) { 1131 if (heap_growth_ratio_ == 100) {
1184 return false; 1132 return false;
1185 } 1133 }
1186 intptr_t capacity_increase_in_words = 1134 intptr_t capacity_increase_in_words =
1187 after.capacity_in_words - last_usage_.capacity_in_words; 1135 after.capacity_in_words - last_usage_.capacity_in_words;
1188 // The concurrent sweeper might have freed more capacity than was allocated. 1136 // The concurrent sweeper might have freed more capacity than was allocated.
(...skipping 16 matching lines...) Expand all
1205 } 1153 }
1206 bool needs_gc = capacity_increase_in_pages * multiplier > grow_heap_; 1154 bool needs_gc = capacity_increase_in_pages * multiplier > grow_heap_;
1207 if (FLAG_log_growth) { 1155 if (FLAG_log_growth) {
1208 OS::PrintErr("%s: %" Pd " * %f %s %" Pd "\n", 1156 OS::PrintErr("%s: %" Pd " * %f %s %" Pd "\n",
1209 needs_gc ? "NEEDS GC" : "grow", capacity_increase_in_pages, 1157 needs_gc ? "NEEDS GC" : "grow", capacity_increase_in_pages,
1210 multiplier, needs_gc ? ">" : "<=", grow_heap_); 1158 multiplier, needs_gc ? ">" : "<=", grow_heap_);
1211 } 1159 }
1212 return needs_gc; 1160 return needs_gc;
1213 } 1161 }
1214 1162
1215
1216 void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before, 1163 void PageSpaceController::EvaluateGarbageCollection(SpaceUsage before,
1217 SpaceUsage after, 1164 SpaceUsage after,
1218 int64_t start, 1165 int64_t start,
1219 int64_t end) { 1166 int64_t end) {
1220 ASSERT(end >= start); 1167 ASSERT(end >= start);
1221 history_.AddGarbageCollectionTime(start, end); 1168 history_.AddGarbageCollectionTime(start, end);
1222 const int gc_time_fraction = history_.GarbageCollectionTimeFraction(); 1169 const int gc_time_fraction = history_.GarbageCollectionTimeFraction();
1223 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction); 1170 heap_->RecordData(PageSpace::kGCTimeFraction, gc_time_fraction);
1224 1171
1225 // Assume garbage increases linearly with allocation: 1172 // Assume garbage increases linearly with allocation:
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 1236
1290 // Limit shrinkage: allow growth by at least half the pages freed by GC. 1237 // Limit shrinkage: allow growth by at least half the pages freed by GC.
1291 const intptr_t freed_pages = 1238 const intptr_t freed_pages =
1292 (before.capacity_in_words - after.capacity_in_words) / 1239 (before.capacity_in_words - after.capacity_in_words) /
1293 PageSpace::kPageSizeInWords; 1240 PageSpace::kPageSizeInWords;
1294 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2); 1241 grow_heap_ = Utils::Maximum(grow_heap_, freed_pages / 2);
1295 heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap_); 1242 heap_->RecordData(PageSpace::kAllowedGrowth, grow_heap_);
1296 last_usage_ = after; 1243 last_usage_ = after;
1297 } 1244 }
1298 1245
1299
1300 void PageSpaceGarbageCollectionHistory::AddGarbageCollectionTime(int64_t start, 1246 void PageSpaceGarbageCollectionHistory::AddGarbageCollectionTime(int64_t start,
1301 int64_t end) { 1247 int64_t end) {
1302 Entry entry; 1248 Entry entry;
1303 entry.start = start; 1249 entry.start = start;
1304 entry.end = end; 1250 entry.end = end;
1305 history_.Add(entry); 1251 history_.Add(entry);
1306 } 1252 }
1307 1253
1308
1309 int PageSpaceGarbageCollectionHistory::GarbageCollectionTimeFraction() { 1254 int PageSpaceGarbageCollectionHistory::GarbageCollectionTimeFraction() {
1310 int64_t gc_time = 0; 1255 int64_t gc_time = 0;
1311 int64_t total_time = 0; 1256 int64_t total_time = 0;
1312 for (int i = 0; i < history_.Size() - 1; i++) { 1257 for (int i = 0; i < history_.Size() - 1; i++) {
1313 Entry current = history_.Get(i); 1258 Entry current = history_.Get(i);
1314 Entry previous = history_.Get(i + 1); 1259 Entry previous = history_.Get(i + 1);
1315 gc_time += current.end - current.start; 1260 gc_time += current.end - current.start;
1316 total_time += current.end - previous.end; 1261 total_time += current.end - previous.end;
1317 } 1262 }
1318 if (total_time == 0) { 1263 if (total_time == 0) {
1319 return 0; 1264 return 0;
1320 } else { 1265 } else {
1321 ASSERT(total_time >= gc_time); 1266 ASSERT(total_time >= gc_time);
1322 int result = static_cast<int>( 1267 int result = static_cast<int>(
1323 (static_cast<double>(gc_time) / static_cast<double>(total_time)) * 100); 1268 (static_cast<double>(gc_time) / static_cast<double>(total_time)) * 100);
1324 return result; 1269 return result;
1325 } 1270 }
1326 } 1271 }
1327 1272
1328 } // namespace dart 1273 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/pages.h ('k') | runtime/vm/pages_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698