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

Side by Side Diff: vm/pages.cc

Issue 11186013: - Do not bump allocate in old-space pages. Always use (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « vm/pages.h ('k') | no next file » | 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/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 13 matching lines...) Expand all
24 "Print free list statistics after a GC"); 24 "Print free list statistics after a GC");
25 25
26 HeapPage* HeapPage::Initialize(VirtualMemory* memory, bool is_executable) { 26 HeapPage* HeapPage::Initialize(VirtualMemory* memory, bool is_executable) {
27 ASSERT(memory->size() > VirtualMemory::PageSize()); 27 ASSERT(memory->size() > VirtualMemory::PageSize());
28 memory->Commit(is_executable); 28 memory->Commit(is_executable);
29 29
30 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address()); 30 HeapPage* result = reinterpret_cast<HeapPage*>(memory->address());
31 result->memory_ = memory; 31 result->memory_ = memory;
32 result->next_ = NULL; 32 result->next_ = NULL;
33 result->used_ = 0; 33 result->used_ = 0;
34 result->top_ = result->first_object_start();
35 return result; 34 return result;
36 } 35 }
37 36
38 37
39 HeapPage* HeapPage::Allocate(intptr_t size, bool is_executable) { 38 HeapPage* HeapPage::Allocate(intptr_t size, bool is_executable) {
40 VirtualMemory* memory = 39 VirtualMemory* memory =
41 VirtualMemory::ReserveAligned(size, PageSpace::kPageAlignment); 40 VirtualMemory::ReserveAligned(size, PageSpace::kPageAlignment);
42 return Initialize(memory, is_executable); 41 return Initialize(memory, is_executable);
43 } 42 }
44 43
45 44
46 void HeapPage::Deallocate() { 45 void HeapPage::Deallocate() {
47 // The memory for this object will become unavailable after the delete below. 46 // The memory for this object will become unavailable after the delete below.
48 delete memory_; 47 delete memory_;
49 } 48 }
50 49
51 50
52 void HeapPage::VisitObjects(ObjectVisitor* visitor) const { 51 void HeapPage::VisitObjects(ObjectVisitor* visitor) const {
53 uword obj_addr = first_object_start(); 52 uword obj_addr = object_start();
54 uword end_addr = top(); 53 uword end_addr = object_end();
55 while (obj_addr < end_addr) { 54 while (obj_addr < end_addr) {
56 RawObject* raw_obj = RawObject::FromAddr(obj_addr); 55 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
57 visitor->VisitObject(raw_obj); 56 visitor->VisitObject(raw_obj);
58 obj_addr += raw_obj->Size(); 57 obj_addr += raw_obj->Size();
59 } 58 }
60 ASSERT(obj_addr == end_addr); 59 ASSERT(obj_addr == end_addr);
61 } 60 }
62 61
63 62
64 void HeapPage::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 63 void HeapPage::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
65 uword obj_addr = first_object_start(); 64 uword obj_addr = object_start();
66 uword end_addr = top(); 65 uword end_addr = object_end();
67 while (obj_addr < end_addr) { 66 while (obj_addr < end_addr) {
68 RawObject* raw_obj = RawObject::FromAddr(obj_addr); 67 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
69 obj_addr += raw_obj->VisitPointers(visitor); 68 obj_addr += raw_obj->VisitPointers(visitor);
70 } 69 }
71 ASSERT(obj_addr == end_addr); 70 ASSERT(obj_addr == end_addr);
72 } 71 }
73 72
74 73
75 RawObject* HeapPage::FindObject(FindObjectVisitor* visitor) const { 74 RawObject* HeapPage::FindObject(FindObjectVisitor* visitor) const {
76 uword obj_addr = first_object_start(); 75 uword obj_addr = object_start();
77 uword end_addr = top(); 76 uword end_addr = object_end();
78 while (obj_addr < end_addr) { 77 while (obj_addr < end_addr) {
79 RawObject* raw_obj = RawObject::FromAddr(obj_addr); 78 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
80 if (raw_obj->FindObject(visitor)) { 79 if (raw_obj->FindObject(visitor)) {
81 return raw_obj; // Found object, return it. 80 return raw_obj; // Found object, return it.
82 } 81 }
83 obj_addr += raw_obj->Size(); 82 obj_addr += raw_obj->Size();
84 } 83 }
85 ASSERT(obj_addr == end_addr); 84 ASSERT(obj_addr == end_addr);
86 return Object::null(); 85 return Object::null();
87 } 86 }
88 87
89 88
90 void HeapPage::WriteProtect(bool read_only) { 89 void HeapPage::WriteProtect(bool read_only) {
91 memory_->Protect( 90 memory_->Protect(
92 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite); 91 read_only ? VirtualMemory::kReadOnly : VirtualMemory::kReadWrite);
93 } 92 }
94 93
95 94
96 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity, bool is_executable) 95 PageSpace::PageSpace(Heap* heap, intptr_t max_capacity, bool is_executable)
97 : freelist_(), 96 : freelist_(),
98 heap_(heap), 97 heap_(heap),
99 pages_(NULL), 98 pages_(NULL),
100 pages_tail_(NULL), 99 pages_tail_(NULL),
101 large_pages_(NULL), 100 large_pages_(NULL),
102 bump_page_(NULL),
103 max_capacity_(max_capacity), 101 max_capacity_(max_capacity),
104 capacity_(0), 102 capacity_(0),
105 in_use_(0), 103 in_use_(0),
106 count_(0), 104 count_(0),
107 is_executable_(is_executable), 105 is_executable_(is_executable),
108 sweeping_(false), 106 sweeping_(false),
109 page_space_controller_(FLAG_heap_growth_space_ratio, 107 page_space_controller_(FLAG_heap_growth_space_ratio,
110 FLAG_heap_growth_rate, 108 FLAG_heap_growth_rate,
111 FLAG_heap_growth_time_ratio) { 109 FLAG_heap_growth_time_ratio) {
112 } 110 }
113 111
114 112
115 PageSpace::~PageSpace() { 113 PageSpace::~PageSpace() {
116 FreePages(pages_); 114 FreePages(pages_);
117 FreePages(large_pages_); 115 FreePages(large_pages_);
118 } 116 }
119 117
120 118
121 intptr_t PageSpace::LargePageSizeFor(intptr_t size) { 119 intptr_t PageSpace::LargePageSizeFor(intptr_t size) {
122 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage), 120 intptr_t page_size = Utils::RoundUp(size + sizeof(HeapPage),
123 VirtualMemory::PageSize()); 121 VirtualMemory::PageSize());
124 return page_size; 122 return page_size;
125 } 123 }
126 124
127 125
128 void PageSpace::AllocatePage() { 126 HeapPage* PageSpace::AllocatePage() {
129 HeapPage* page = HeapPage::Allocate(kPageSize, is_executable_); 127 HeapPage* page = HeapPage::Allocate(kPageSize, is_executable_);
130 if (pages_ == NULL) { 128 if (pages_ == NULL) {
131 pages_ = page; 129 pages_ = page;
132 } else { 130 } else {
133 pages_tail_->set_next(page); 131 pages_tail_->set_next(page);
134 } 132 }
135 pages_tail_ = page; 133 pages_tail_ = page;
136 bump_page_ = NULL; // Reenable scanning of pages for bump allocation.
137 capacity_ += kPageSize; 134 capacity_ += kPageSize;
135 page->set_object_end(page->memory_->end());
136 return page;
138 } 137 }
139 138
140 139
141 HeapPage* PageSpace::AllocateLargePage(intptr_t size) { 140 HeapPage* PageSpace::AllocateLargePage(intptr_t size) {
142 intptr_t page_size = LargePageSizeFor(size); 141 intptr_t page_size = LargePageSizeFor(size);
143 HeapPage* page = HeapPage::Allocate(page_size, is_executable_); 142 HeapPage* page = HeapPage::Allocate(page_size, is_executable_);
144 page->set_next(large_pages_); 143 page->set_next(large_pages_);
145 large_pages_ = page; 144 large_pages_ = page;
146 capacity_ += page_size; 145 capacity_ += page_size;
146 // Only one object in this page.
147 page->set_object_end(page->object_start() + size);
147 return page; 148 return page;
148 } 149 }
149 150
150 151
151 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) { 152 void PageSpace::FreePage(HeapPage* page, HeapPage* previous_page) {
152 capacity_ -= page->memory_->size(); 153 capacity_ -= page->memory_->size();
153 // Remove the page from the list. 154 // Remove the page from the list.
154 if (previous_page != NULL) { 155 if (previous_page != NULL) {
155 previous_page->set_next(page->next()); 156 previous_page->set_next(page->next());
156 } else { 157 } else {
(...skipping 22 matching lines...) Expand all
179 void PageSpace::FreePages(HeapPage* pages) { 180 void PageSpace::FreePages(HeapPage* pages) {
180 HeapPage* page = pages; 181 HeapPage* page = pages;
181 while (page != NULL) { 182 while (page != NULL) {
182 HeapPage* next = page->next(); 183 HeapPage* next = page->next();
183 page->Deallocate(); 184 page->Deallocate();
184 page = next; 185 page = next;
185 } 186 }
186 } 187 }
187 188
188 189
189 uword PageSpace::TryBumpAllocate(intptr_t size) {
190 if (pages_tail_ == NULL) {
191 return 0;
192 }
193 uword result = pages_tail_->TryBumpAllocate(size);
194 if (result != 0) {
195 return result;
196 }
197 if (bump_page_ == NULL) {
198 // The bump page has not yet been used: Start at the beginning of the list.
199 bump_page_ = pages_;
200 }
201 // The last page has already been attempted above.
202 while (bump_page_ != pages_tail_) {
203 ASSERT(bump_page_->next() != NULL);
204 result = bump_page_->TryBumpAllocate(size);
205 if (result != 0) {
206 return result;
207 }
208 bump_page_ = bump_page_->next();
209 }
210 // Ran through all of the pages trying to bump allocate: Give up.
211 return 0;
212 }
213
214
215 uword PageSpace::TryAllocate(intptr_t size) { 190 uword PageSpace::TryAllocate(intptr_t size) {
216 return TryAllocate(size, kControlGrowth); 191 return TryAllocate(size, kControlGrowth);
217 } 192 }
218 193
219 194
220 uword PageSpace::TryAllocate(intptr_t size, GrowthPolicy growth_policy) { 195 uword PageSpace::TryAllocate(intptr_t size, GrowthPolicy growth_policy) {
221 ASSERT(size >= kObjectAlignment); 196 ASSERT(size >= kObjectAlignment);
222 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 197 ASSERT(Utils::IsAligned(size, kObjectAlignment));
223 uword result = 0; 198 uword result = 0;
224 if (size < kAllocatablePageSize) { 199 if (size < kAllocatablePageSize) {
225 result = freelist_.TryAllocate(size); 200 result = freelist_.TryAllocate(size);
226 if (result == 0) { 201 if ((result == 0) &&
227 result = TryBumpAllocate(size); 202 (page_space_controller_.CanGrowPageSpace(size) ||
228 if ((result == 0) && 203 growth_policy == kForceGrowth) &&
229 (page_space_controller_.CanGrowPageSpace(size) || 204 CanIncreaseCapacity(kPageSize)) {
230 growth_policy == kForceGrowth) && 205 HeapPage* page = AllocatePage();
231 CanIncreaseCapacity(kPageSize)) { 206 ASSERT(page != NULL);
232 AllocatePage(); 207 // Start of the newly allocated page is the allocated object.
233 result = TryBumpAllocate(size); 208 result = page->object_start();
234 ASSERT(result != 0); 209 // Enqueue the remainder in the free list.
235 } 210 uword free_start = result + size;
211 freelist_.Free(free_start, page->object_end() - free_start);
236 } 212 }
237 } else { 213 } else {
238 // Large page allocation. 214 // Large page allocation.
239 intptr_t page_size = LargePageSizeFor(size); 215 intptr_t page_size = LargePageSizeFor(size);
240 if (page_size < size) { 216 if (page_size < size) {
241 // On overflow we fail to allocate. 217 // On overflow we fail to allocate.
242 return 0; 218 return 0;
243 } 219 }
244 if (CanIncreaseCapacity(page_size)) { 220 if (CanIncreaseCapacity(page_size)) {
245 HeapPage* page = AllocateLargePage(size); 221 HeapPage* page = AllocateLargePage(size);
246 if (page != NULL) { 222 if (page != NULL) {
247 result = page->top(); 223 result = page->object_start();
248 page->set_top(result + size);
249 } 224 }
250 } 225 }
251 } 226 }
252 if (result != 0) { 227 if (result != 0) {
253 in_use_ += size; 228 in_use_ += size;
254 } 229 }
230 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
255 return result; 231 return result;
256 } 232 }
257 233
258 234
259 bool PageSpace::Contains(uword addr) const { 235 bool PageSpace::Contains(uword addr) const {
260 HeapPage* page = pages_; 236 HeapPage* page = pages_;
261 while (page != NULL) { 237 while (page != NULL) {
262 if (page->Contains(addr)) { 238 if (page->Contains(addr)) {
263 return true; 239 return true;
264 } 240 }
265 page = page->next(); 241 page = page->next();
266 } 242 }
267 243
268 page = large_pages_; 244 page = large_pages_;
269 while (page != NULL) { 245 while (page != NULL) {
270 if (page->Contains(addr)) { 246 if (page->Contains(addr)) {
271 return true; 247 return true;
272 } 248 }
273 page = page->next(); 249 page = page->next();
274 } 250 }
275 return false; 251 return false;
276 } 252 }
277 253
278 254
279 void PageSpace::StartEndAddress(uword* start, uword* end) const { 255 void PageSpace::StartEndAddress(uword* start, uword* end) const {
280 ASSERT(pages_ != NULL || large_pages_ != NULL); 256 ASSERT(pages_ != NULL || large_pages_ != NULL);
281 *start = static_cast<uword>(~0); 257 *start = static_cast<uword>(~0);
282 *end = 0; 258 *end = 0;
283 for (HeapPage* page = pages_; page != NULL; page = page->next()) { 259 for (HeapPage* page = pages_; page != NULL; page = page->next()) {
284 *start = Utils::Minimum(*start, page->start()); 260 *start = Utils::Minimum(*start, page->object_start());
285 *end = Utils::Maximum(*end, page->end()); 261 *end = Utils::Maximum(*end, page->object_end());
286 } 262 }
287 for (HeapPage* page = large_pages_; page != NULL; page = page->next()) { 263 for (HeapPage* page = large_pages_; page != NULL; page = page->next()) {
288 *start = Utils::Minimum(*start, page->start()); 264 *start = Utils::Minimum(*start, page->object_start());
289 *end = Utils::Maximum(*end, page->end()); 265 *end = Utils::Maximum(*end, page->object_end());
290 } 266 }
291 ASSERT(*start != static_cast<uword>(~0)); 267 ASSERT(*start != static_cast<uword>(~0));
292 ASSERT(*end != 0); 268 ASSERT(*end != 0);
293 } 269 }
294 270
295 271
296 void PageSpace::VisitObjects(ObjectVisitor* visitor) const { 272 void PageSpace::VisitObjects(ObjectVisitor* visitor) const {
297 HeapPage* page = pages_; 273 HeapPage* page = pages_;
298 while (page != NULL) { 274 while (page != NULL) {
299 page->VisitObjects(visitor); 275 page->VisitObjects(visitor);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 } 378 }
403 Timer timer(true, "MarkSweep"); 379 Timer timer(true, "MarkSweep");
404 timer.Start(); 380 timer.Start();
405 int64_t start = OS::GetCurrentTimeMillis(); 381 int64_t start = OS::GetCurrentTimeMillis();
406 382
407 // Mark all reachable old-gen objects. 383 // Mark all reachable old-gen objects.
408 GCMarker marker(heap_); 384 GCMarker marker(heap_);
409 marker.MarkObjects(isolate, this, invoke_api_callbacks); 385 marker.MarkObjects(isolate, this, invoke_api_callbacks);
410 386
411 // Reset the bump allocation page to unused. 387 // Reset the bump allocation page to unused.
412 bump_page_ = NULL;
413 // Reset the freelists and setup sweeping. 388 // Reset the freelists and setup sweeping.
414 freelist_.Reset(); 389 freelist_.Reset();
415 GCSweeper sweeper(heap_); 390 GCSweeper sweeper(heap_);
416 intptr_t in_use = 0; 391 intptr_t in_use = 0;
417 392
418 HeapPage* prev_page = NULL; 393 HeapPage* prev_page = NULL;
419 HeapPage* page = pages_; 394 HeapPage* page = pages_;
420 while (page != NULL) { 395 while (page != NULL) {
421 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_); 396 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_);
422 HeapPage* next_page = page->next(); 397 HeapPage* next_page = page->next();
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 return 0; 576 return 0;
602 } else { 577 } else {
603 ASSERT(total_time >= gc_time); 578 ASSERT(total_time >= gc_time);
604 int result= static_cast<int>((static_cast<double>(gc_time) / 579 int result= static_cast<int>((static_cast<double>(gc_time) /
605 static_cast<double>(total_time)) * 100); 580 static_cast<double>(total_time)) * 100);
606 return result; 581 return result;
607 } 582 }
608 } 583 }
609 584
610 } // namespace dart 585 } // namespace dart
OLDNEW
« no previous file with comments | « vm/pages.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698