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