| OLD | NEW |
| 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/assert.h" | 7 #include "platform/assert.h" |
| 8 #include "vm/gc_marker.h" | 8 #include "vm/gc_marker.h" |
| 9 #include "vm/gc_sweeper.h" | 9 #include "vm/gc_sweeper.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 } | 61 } |
| 62 ASSERT(obj_addr == end_addr); | 62 ASSERT(obj_addr == end_addr); |
| 63 return Object::null(); | 63 return Object::null(); |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity, bool is_executable) | 67 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity, bool is_executable) |
| 68 : freelist_(), | 68 : freelist_(), |
| 69 heap_(heap), | 69 heap_(heap), |
| 70 pages_(NULL), | 70 pages_(NULL), |
| 71 pages_tail_(NULL), |
| 71 large_pages_(NULL), | 72 large_pages_(NULL), |
| 72 bump_page_(NULL), | 73 bump_page_(NULL), |
| 73 max_capacity_(max_capacity), | 74 max_capacity_(max_capacity), |
| 74 capacity_(0), | 75 capacity_(0), |
| 75 in_use_(0), | 76 in_use_(0), |
| 76 count_(0), | 77 count_(0), |
| 77 is_executable_(is_executable), | 78 is_executable_(is_executable), |
| 78 sweeping_(false) { } | 79 sweeping_(false) { } |
| 79 | 80 |
| 80 | 81 |
| 81 PageSpace::~PageSpace() { | 82 PageSpace::~PageSpace() { |
| 82 FreePages(pages_); | 83 FreePages(pages_); |
| 83 FreePages(large_pages_); | 84 FreePages(large_pages_); |
| 84 } | 85 } |
| 85 | 86 |
| 86 | 87 |
| 87 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { | 88 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { |
| 88 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage), | 89 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage), |
| 89 VirtualMemory::PageSize()); | 90 VirtualMemory::PageSize()); |
| 90 return page_size; | 91 return page_size; |
| 91 } | 92 } |
| 92 | 93 |
| 93 | 94 |
| 94 void PageSpace::AllocatePage() { | 95 void PageSpace::AllocatePage() { |
| 95 HeapPage* page = HeapPage::Allocate(kPageSize, is_executable_); | 96 HeapPage* page = HeapPage::Allocate(kPageSize, is_executable_); |
| 96 page->set_next(pages_); | 97 if (pages_ == NULL) { |
| 97 pages_ = page; | 98 pages_ = page; |
| 99 } else { |
| 100 pages_tail_->set_next(page); |
| 101 } |
| 102 pages_tail_ = page; |
| 98 bump_page_ = NULL; // Reenable scanning of pages for bump allocation. | 103 bump_page_ = NULL; // Reenable scanning of pages for bump allocation. |
| 99 capacity_ += kPageSize; | 104 capacity_ += kPageSize; |
| 100 } | 105 } |
| 101 | 106 |
| 102 | 107 |
| 103 HeapPage* PageSpace::AllocateLargePage(intptr_t size) { | 108 HeapPage* PageSpace::AllocateLargePage(intptr_t size) { |
| 104 intptr_t page_size = LargePageSizeFor(size); | 109 intptr_t page_size = LargePageSizeFor(size); |
| 105 HeapPage* page = HeapPage::Allocate(page_size, is_executable_); | 110 HeapPage* page = HeapPage::Allocate(page_size, is_executable_); |
| 106 page->set_next(large_pages_); | 111 page->set_next(large_pages_); |
| 107 large_pages_ = page; | 112 large_pages_ = page; |
| 108 capacity_ += page_size; | 113 capacity_ += page_size; |
| 109 return page; | 114 return page; |
| 110 } | 115 } |
| 111 | 116 |
| 112 | 117 |
| 113 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) { | |
| 114 capacity_ -= page->memory_->size(); | |
| 115 // Remove the page from the list. | |
| 116 if (previous_page != NULL) { | |
| 117 previous_page->set_next(page->next()); | |
| 118 } else { | |
| 119 pages_ = page->next(); | |
| 120 } | |
| 121 // TODO(iposva): Consider adding to a pool of empty pages. | |
| 122 page->Deallocate(); | |
| 123 } | |
| 124 | |
| 125 | |
| 126 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) { | 118 void PageSpace::FreeLargePage(HeapPage* page, HeapPage* previous_page) { |
| 127 capacity_ -= page->memory_->size(); | 119 capacity_ -= page->memory_->size(); |
| 128 // Remove the page from the list. | 120 // Remove the page from the list. |
| 129 if (previous_page != NULL) { | 121 if (previous_page != NULL) { |
| 130 previous_page->set_next(page->next()); | 122 previous_page->set_next(page->next()); |
| 131 } else { | 123 } else { |
| 132 large_pages_ = page->next(); | 124 large_pages_ = page->next(); |
| 133 } | 125 } |
| 134 page->Deallocate(); | 126 page->Deallocate(); |
| 135 } | 127 } |
| 136 | 128 |
| 137 | 129 |
| 138 void PageSpace::FreePages(HeapPage* pages) { | 130 void PageSpace::FreePages(HeapPage* pages) { |
| 139 HeapPage* page = pages; | 131 HeapPage* page = pages; |
| 140 while (page != NULL) { | 132 while (page != NULL) { |
| 141 HeapPage* next = page->next(); | 133 HeapPage* next = page->next(); |
| 142 page->Deallocate(); | 134 page->Deallocate(); |
| 143 page = next; | 135 page = next; |
| 144 } | 136 } |
| 145 } | 137 } |
| 146 | 138 |
| 147 | 139 |
| 148 uword PageSpace::TryBumpAllocate(intptr_t size) { | 140 uword PageSpace::TryBumpAllocate(intptr_t size) { |
| 141 if (pages_tail_ == NULL) { |
| 142 return 0; |
| 143 } |
| 144 uword result = pages_tail_->TryBumpAllocate(size); |
| 145 if (result != 0) { |
| 146 return result; |
| 147 } |
| 149 if (bump_page_ == NULL) { | 148 if (bump_page_ == NULL) { |
| 150 // The bump page has not yet been used: Start at the beginning of the list. | 149 // The bump page has not yet been used: Start at the beginning of the list. |
| 151 bump_page_ = pages_; | 150 bump_page_ = pages_; |
| 152 } | 151 } |
| 153 while (bump_page_ != NULL) { | 152 // The last page has already been attempted above. |
| 154 uword result = bump_page_->TryBumpAllocate(size); | 153 while (bump_page_ != pages_tail_) { |
| 154 ASSERT(bump_page_->next() != NULL); |
| 155 result = bump_page_->TryBumpAllocate(size); |
| 155 if (result != 0) { | 156 if (result != 0) { |
| 156 return result; | 157 return result; |
| 157 } | 158 } |
| 158 bump_page_ = bump_page_->next(); | 159 bump_page_ = bump_page_->next(); |
| 159 } | 160 } |
| 160 // Ran through all of the pages trying to bump allocate: Give up. | 161 // Ran through all of the pages trying to bump allocate: Give up. |
| 161 return 0; | 162 return 0; |
| 162 } | 163 } |
| 163 | 164 |
| 164 | 165 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 GCMarker marker(heap_); | 277 GCMarker marker(heap_); |
| 277 marker.MarkObjects(isolate, this, invoke_api_callbacks); | 278 marker.MarkObjects(isolate, this, invoke_api_callbacks); |
| 278 | 279 |
| 279 // Reset the bump allocation page to unused. | 280 // Reset the bump allocation page to unused. |
| 280 bump_page_ = NULL; | 281 bump_page_ = NULL; |
| 281 // Reset the freelists and setup sweeping. | 282 // Reset the freelists and setup sweeping. |
| 282 freelist_.Reset(); | 283 freelist_.Reset(); |
| 283 GCSweeper sweeper(heap_); | 284 GCSweeper sweeper(heap_); |
| 284 intptr_t in_use = 0; | 285 intptr_t in_use = 0; |
| 285 | 286 |
| 286 HeapPage* prev_page = NULL; | |
| 287 HeapPage* page = pages_; | 287 HeapPage* page = pages_; |
| 288 while (page != NULL) { | 288 while (page != NULL) { |
| 289 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_); | 289 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_); |
| 290 HeapPage* next_page = page->next(); | 290 in_use += page_in_use; |
| 291 if (page_in_use == 0) { | 291 page = page->next(); |
| 292 FreePage(page, prev_page); | |
| 293 } else { | |
| 294 in_use += page_in_use; | |
| 295 prev_page = page; | |
| 296 } | |
| 297 // Advance to the next page. | |
| 298 page = next_page; | |
| 299 } | 292 } |
| 300 | 293 |
| 301 prev_page = NULL; | 294 HeapPage* prev_page = NULL; |
| 302 page = large_pages_; | 295 page = large_pages_; |
| 303 while (page != NULL) { | 296 while (page != NULL) { |
| 304 intptr_t page_in_use = sweeper.SweepLargePage(page); | 297 intptr_t page_in_use = sweeper.SweepLargePage(page); |
| 305 HeapPage* next_page = page->next(); | 298 HeapPage* next_page = page->next(); |
| 306 if (page_in_use == 0) { | 299 if (page_in_use == 0) { |
| 307 FreeLargePage(page, prev_page); | 300 FreeLargePage(page, prev_page); |
| 308 } else { | 301 } else { |
| 309 in_use += page_in_use; | 302 in_use += page_in_use; |
| 310 prev_page = page; | 303 prev_page = page; |
| 311 } | 304 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 334 OS::PrintErr(" done.\n"); | 327 OS::PrintErr(" done.\n"); |
| 335 } | 328 } |
| 336 | 329 |
| 337 count_++; | 330 count_++; |
| 338 // Done, reset the marker. | 331 // Done, reset the marker. |
| 339 ASSERT(sweeping_); | 332 ASSERT(sweeping_); |
| 340 sweeping_ = false; | 333 sweeping_ = false; |
| 341 } | 334 } |
| 342 | 335 |
| 343 } // namespace dart | 336 } // namespace dart |
| OLD | NEW |