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

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
« vm/pages.h ('K') | « 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 = first_object_start();
54 uword end_addr = top(); 53 uword end_addr = 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 = first_object_start();
66 uword end_addr = top(); 65 uword end_addr = 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 = first_object_start();
77 uword end_addr = top(); 76 uword end_addr = 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 return page;
138 } 136 }
139 137
140 138
141 HeapPage* PageSpace::AllocateLargePage(intptr_t size) { 139 HeapPage* PageSpace::AllocateLargePage(intptr_t size) {
142 intptr_t page_size = LargePageSizeFor(size); 140 intptr_t page_size = LargePageSizeFor(size);
143 HeapPage* page = HeapPage::Allocate(page_size, is_executable_); 141 HeapPage* page = HeapPage::Allocate(page_size, is_executable_);
144 page->set_next(large_pages_); 142 page->set_next(large_pages_);
145 large_pages_ = page; 143 large_pages_ = page;
146 capacity_ += page_size; 144 capacity_ += page_size;
147 return page; 145 return page;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 void PageSpace::FreePages(HeapPage* pages) { 177 void PageSpace::FreePages(HeapPage* pages) {
180 HeapPage* page = pages; 178 HeapPage* page = pages;
181 while (page != NULL) { 179 while (page != NULL) {
182 HeapPage* next = page->next(); 180 HeapPage* next = page->next();
183 page->Deallocate(); 181 page->Deallocate();
184 page = next; 182 page = next;
185 } 183 }
186 } 184 }
187 185
188 186
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) { 187 uword PageSpace::TryAllocate(intptr_t size) {
216 return TryAllocate(size, kControlGrowth); 188 return TryAllocate(size, kControlGrowth);
217 } 189 }
218 190
219 191
220 uword PageSpace::TryAllocate(intptr_t size, GrowthPolicy growth_policy) { 192 uword PageSpace::TryAllocate(intptr_t size, GrowthPolicy growth_policy) {
221 ASSERT(size >= kObjectAlignment); 193 ASSERT(size >= kObjectAlignment);
222 ASSERT(Utils::IsAligned(size, kObjectAlignment)); 194 ASSERT(Utils::IsAligned(size, kObjectAlignment));
223 uword result = 0; 195 uword result = 0;
224 if (size < kAllocatablePageSize) { 196 if (size < kAllocatablePageSize) {
225 result = freelist_.TryAllocate(size); 197 result = freelist_.TryAllocate(size);
226 if (result == 0) { 198 if ((result == 0) &&
227 result = TryBumpAllocate(size); 199 (page_space_controller_.CanGrowPageSpace(size) ||
228 if ((result == 0) && 200 growth_policy == kForceGrowth) &&
229 (page_space_controller_.CanGrowPageSpace(size) || 201 CanIncreaseCapacity(kPageSize)) {
230 growth_policy == kForceGrowth) && 202 HeapPage* page = AllocatePage();
231 CanIncreaseCapacity(kPageSize)) { 203 ASSERT(page != NULL);
232 AllocatePage(); 204 // Start of the newly allocated page is the allocated object.
233 result = TryBumpAllocate(size); 205 result = page->first_object_start();
234 ASSERT(result != 0); 206 // Enqueue the remainder in the free list.
235 } 207 uword free_start = result + size;
208 freelist_.Free(
209 free_start,
210 Utils::RoundDown(page->end() - free_start, kObjectAlignment));
236 } 211 }
237 } else { 212 } else {
238 // Large page allocation. 213 // Large page allocation.
239 intptr_t page_size = LargePageSizeFor(size); 214 intptr_t page_size = LargePageSizeFor(size);
240 if (page_size < size) { 215 if (page_size < size) {
241 // On overflow we fail to allocate. 216 // On overflow we fail to allocate.
242 return 0; 217 return 0;
243 } 218 }
244 if (CanIncreaseCapacity(page_size)) { 219 if (CanIncreaseCapacity(page_size)) {
245 HeapPage* page = AllocateLargePage(size); 220 HeapPage* page = AllocateLargePage(size);
246 if (page != NULL) { 221 if (page != NULL) {
247 result = page->top(); 222 result = page->first_object_start();
248 page->set_top(result + size);
249 } 223 }
250 } 224 }
251 } 225 }
252 if (result != 0) { 226 if (result != 0) {
253 in_use_ += size; 227 in_use_ += size;
254 } 228 }
229 ASSERT((result & kObjectAlignmentMask) == kOldObjectAlignmentOffset);
255 return result; 230 return result;
256 } 231 }
257 232
258 233
259 bool PageSpace::Contains(uword addr) const { 234 bool PageSpace::Contains(uword addr) const {
260 HeapPage* page = pages_; 235 HeapPage* page = pages_;
261 while (page != NULL) { 236 while (page != NULL) {
262 if (page->Contains(addr)) { 237 if (page->Contains(addr)) {
263 return true; 238 return true;
264 } 239 }
(...skipping 30 matching lines...) Expand all
295 270
296 void PageSpace::VisitObjects(ObjectVisitor* visitor) const { 271 void PageSpace::VisitObjects(ObjectVisitor* visitor) const {
297 HeapPage* page = pages_; 272 HeapPage* page = pages_;
298 while (page != NULL) { 273 while (page != NULL) {
299 page->VisitObjects(visitor); 274 page->VisitObjects(visitor);
300 page = page->next(); 275 page = page->next();
301 } 276 }
302 277
303 page = large_pages_; 278 page = large_pages_;
304 while (page != NULL) { 279 while (page != NULL) {
305 page->VisitObjects(visitor); 280 uword obj_addr = page->first_object_start();
cshapiro 2012/10/17 02:53:22 Why did this code have to change? This was done i
Ivan Posva 2012/10/18 17:34:21 I did not like the expansion either. Now that I ha
281 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
282 visitor->VisitObject(raw_obj);
306 page = page->next(); 283 page = page->next();
307 } 284 }
308 } 285 }
309 286
310 287
311 void PageSpace::SetPeer(RawObject* raw_obj, void* peer) { 288 void PageSpace::SetPeer(RawObject* raw_obj, void* peer) {
312 if (peer == NULL) { 289 if (peer == NULL) {
313 peer_table_.erase(raw_obj); 290 peer_table_.erase(raw_obj);
314 } else { 291 } else {
315 peer_table_[raw_obj] = peer; 292 peer_table_[raw_obj] = peer;
(...skipping 14 matching lines...) Expand all
330 307
331 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 308 void PageSpace::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
332 HeapPage* page = pages_; 309 HeapPage* page = pages_;
333 while (page != NULL) { 310 while (page != NULL) {
334 page->VisitObjectPointers(visitor); 311 page->VisitObjectPointers(visitor);
335 page = page->next(); 312 page = page->next();
336 } 313 }
337 314
338 page = large_pages_; 315 page = large_pages_;
339 while (page != NULL) { 316 while (page != NULL) {
340 page->VisitObjectPointers(visitor); 317 uword obj_addr = page->first_object_start();
cshapiro 2012/10/17 02:53:22 ditto
318 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
319 raw_obj->VisitPointers(visitor);
341 page = page->next(); 320 page = page->next();
342 } 321 }
343 } 322 }
344 323
345 324
346 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor) const { 325 RawObject* PageSpace::FindObject(FindObjectVisitor* visitor) const {
347 ASSERT(Isolate::Current()->no_gc_scope_depth() != 0); 326 ASSERT(Isolate::Current()->no_gc_scope_depth() != 0);
348 HeapPage* page = pages_; 327 HeapPage* page = pages_;
349 while (page != NULL) { 328 while (page != NULL) {
350 RawObject* obj = page->FindObject(visitor); 329 RawObject* obj = page->FindObject(visitor);
351 if (obj != Object::null()) { 330 if (obj != Object::null()) {
352 return obj; 331 return obj;
353 } 332 }
354 page = page->next(); 333 page = page->next();
355 } 334 }
356 335
357 page = large_pages_; 336 page = large_pages_;
358 while (page != NULL) { 337 while (page != NULL) {
359 RawObject* obj = page->FindObject(visitor); 338 uword obj_addr = page->first_object_start();
cshapiro 2012/10/17 02:53:22 ditto
360 if (obj != Object::null()) { 339 RawObject* raw_obj = RawObject::FromAddr(obj_addr);
361 return obj; 340 if (raw_obj->FindObject(visitor)) {
341 return raw_obj;
362 } 342 }
363 page = page->next(); 343 page = page->next();
364 } 344 }
365 return Object::null(); 345 return Object::null();
366 } 346 }
367 347
368 348
369 void PageSpace::WriteProtect(bool read_only) { 349 void PageSpace::WriteProtect(bool read_only) {
370 HeapPage* page = pages_; 350 HeapPage* page = pages_;
371 while (page != NULL) { 351 while (page != NULL) {
(...skipping 30 matching lines...) Expand all
402 } 382 }
403 Timer timer(true, "MarkSweep"); 383 Timer timer(true, "MarkSweep");
404 timer.Start(); 384 timer.Start();
405 int64_t start = OS::GetCurrentTimeMillis(); 385 int64_t start = OS::GetCurrentTimeMillis();
406 386
407 // Mark all reachable old-gen objects. 387 // Mark all reachable old-gen objects.
408 GCMarker marker(heap_); 388 GCMarker marker(heap_);
409 marker.MarkObjects(isolate, this, invoke_api_callbacks); 389 marker.MarkObjects(isolate, this, invoke_api_callbacks);
410 390
411 // Reset the bump allocation page to unused. 391 // Reset the bump allocation page to unused.
412 bump_page_ = NULL;
413 // Reset the freelists and setup sweeping. 392 // Reset the freelists and setup sweeping.
414 freelist_.Reset(); 393 freelist_.Reset();
415 GCSweeper sweeper(heap_); 394 GCSweeper sweeper(heap_);
416 intptr_t in_use = 0; 395 intptr_t in_use = 0;
417 396
418 HeapPage* prev_page = NULL; 397 HeapPage* prev_page = NULL;
419 HeapPage* page = pages_; 398 HeapPage* page = pages_;
420 while (page != NULL) { 399 while (page != NULL) {
421 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_); 400 intptr_t page_in_use = sweeper.SweepPage(page, &freelist_);
422 HeapPage* next_page = page->next(); 401 HeapPage* next_page = page->next();
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 return 0; 580 return 0;
602 } else { 581 } else {
603 ASSERT(total_time >= gc_time); 582 ASSERT(total_time >= gc_time);
604 int result= static_cast<int>((static_cast<double>(gc_time) / 583 int result= static_cast<int>((static_cast<double>(gc_time) /
605 static_cast<double>(total_time)) * 100); 584 static_cast<double>(total_time)) * 100);
606 return result; 585 return result;
607 } 586 }
608 } 587 }
609 588
610 } // namespace dart 589 } // namespace dart
OLDNEW
« vm/pages.h ('K') | « vm/pages.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698