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

Side by Side Diff: vm/scavenger.cc

Issue 10797021: - Start using the collected store buffer entries to find (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 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 | Annotate | Revision Log
« no previous file with comments | « vm/scavenger.h ('k') | vm/store_buffer.h » ('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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/scavenger.h" 5 #include "vm/scavenger.h"
6 6
7 #include "vm/dart.h" 7 #include "vm/dart.h"
8 #include "vm/dart_api_state.h" 8 #include "vm/dart_api_state.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/object.h" 10 #include "vm/object.h"
11 #include "vm/stack_frame.h" 11 #include "vm/stack_frame.h"
12 #include "vm/store_buffer.h"
12 #include "vm/verifier.h" 13 #include "vm/verifier.h"
13 #include "vm/visitor.h" 14 #include "vm/visitor.h"
14 15
15 namespace dart { 16 namespace dart {
16 17
17 // Scavenger uses RawObject::kFreeBit to distinguish forwaded and non-forwarded 18 // Scavenger uses RawObject::kFreeBit to distinguish forwaded and non-forwarded
18 // objects because scavenger can never encounter free list element during 19 // objects because scavenger can never encounter free list element during
19 // evacuation and thus all objects scavenger encounters have 20 // evacuation and thus all objects scavenger encounters have
20 // kFreeBit cleared. 21 // kFreeBit cleared.
21 enum { 22 enum {
(...skipping 22 matching lines...) Expand all
44 *reinterpret_cast<uword*>(orignal) = target | kForwarded; 45 *reinterpret_cast<uword*>(orignal) = target | kForwarded;
45 } 46 }
46 47
47 48
48 class ScavengerVisitor : public ObjectPointerVisitor { 49 class ScavengerVisitor : public ObjectPointerVisitor {
49 public: 50 public:
50 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger) 51 explicit ScavengerVisitor(Isolate* isolate, Scavenger* scavenger)
51 : ObjectPointerVisitor(isolate), 52 : ObjectPointerVisitor(isolate),
52 scavenger_(scavenger), 53 scavenger_(scavenger),
53 heap_(scavenger->heap_), 54 heap_(scavenger->heap_),
54 vm_heap_(Dart::vm_isolate()->heap()) {} 55 vm_heap_(Dart::vm_isolate()->heap()),
56 visiting_old_pointers_(false) {}
55 57
56 void VisitPointers(RawObject** first, RawObject** last) { 58 void VisitPointers(RawObject** first, RawObject** last) {
57 for (RawObject** current = first; current <= last; current++) { 59 for (RawObject** current = first; current <= last; current++) {
58 ScavengePointer(current); 60 ScavengePointer(current);
59 } 61 }
60 } 62 }
61 63
64 void VisitingOldPointers(bool value) { visiting_old_pointers_ = value; }
65
62 private: 66 private:
63 void UpdateStoreBuffer(RawObject** p, RawObject* obj) { 67 void UpdateStoreBuffer(RawObject** p, RawObject* obj) {
64 // TODO(iposva): Implement store buffers. 68 uword ptr = reinterpret_cast<uword>(p);
69 ASSERT(obj->IsHeapObject());
70 ASSERT(!scavenger_->Contains(ptr));
71 ASSERT(!heap_->CodeContains(ptr));
72 ASSERT(heap_->Contains(ptr));
73 // If the newly written object is not a new object, drop it immediately.
74 if (!obj->IsNewObject()) return;
75 isolate()->store_buffer()->AddPointer(ptr);
65 } 76 }
66 77
67 void ScavengePointer(RawObject** p) { 78 void ScavengePointer(RawObject** p) {
68 RawObject* raw_obj = *p; 79 RawObject* raw_obj = *p;
69 80
70 // Fast exit if the raw object is a Smi or an old object. 81 // Fast exit if the raw object is a Smi or an old object.
71 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) { 82 if (!raw_obj->IsHeapObject() || raw_obj->IsOldObject()) {
72 return; 83 return;
73 } 84 }
74 85
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 memmove(reinterpret_cast<void*>(new_addr), 131 memmove(reinterpret_cast<void*>(new_addr),
121 reinterpret_cast<void*>(raw_addr), 132 reinterpret_cast<void*>(raw_addr),
122 size); 133 size);
123 // Remember forwarding address. 134 // Remember forwarding address.
124 ForwardTo(raw_addr, new_addr); 135 ForwardTo(raw_addr, new_addr);
125 } 136 }
126 // Update the reference. 137 // Update the reference.
127 RawObject* new_obj = RawObject::FromAddr(new_addr); 138 RawObject* new_obj = RawObject::FromAddr(new_addr);
128 *p = new_obj; 139 *p = new_obj;
129 // Update the store buffer as needed. 140 // Update the store buffer as needed.
130 UpdateStoreBuffer(p, new_obj); 141 if (visiting_old_pointers_) {
142 UpdateStoreBuffer(p, new_obj);
143 }
131 } 144 }
132 145
133 Scavenger* scavenger_; 146 Scavenger* scavenger_;
134 Heap* heap_; 147 Heap* heap_;
135 Heap* vm_heap_; 148 Heap* vm_heap_;
136 149
150 bool visiting_old_pointers_;
151
137 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor); 152 DISALLOW_COPY_AND_ASSIGN(ScavengerVisitor);
138 }; 153 };
139 154
140 155
141 class ScavengerWeakVisitor : public HandleVisitor { 156 class ScavengerWeakVisitor : public HandleVisitor {
142 public: 157 public:
143 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) { 158 explicit ScavengerWeakVisitor(Scavenger* scavenger) : scavenger_(scavenger) {
144 } 159 }
145 160
146 void VisitHandle(uword addr) { 161 void VisitHandle(uword addr) {
147 FinalizablePersistentHandle* handle = 162 FinalizablePersistentHandle* handle =
148 reinterpret_cast<FinalizablePersistentHandle*>(addr); 163 reinterpret_cast<FinalizablePersistentHandle*>(addr);
149 RawObject** p = reinterpret_cast<RawObject**>(handle); 164 RawObject** p = reinterpret_cast<RawObject**>(handle);
150 if (scavenger_->IsUnreachable(p)) { 165 if (scavenger_->IsUnreachable(p)) {
151 FinalizablePersistentHandle::Finalize(handle); 166 FinalizablePersistentHandle::Finalize(handle);
152 } 167 }
153 } 168 }
154 169
155 private: 170 private:
156 Scavenger* scavenger_; 171 Scavenger* scavenger_;
157 172
158 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor); 173 DISALLOW_COPY_AND_ASSIGN(ScavengerWeakVisitor);
159 }; 174 };
160 175
161 176
177 // Visitor used to verify that all old->new references have been added to the
178 // StoreBuffers.
179 class VerifyStoreBufferPointerVisitor : public ObjectPointerVisitor {
180 public:
181 VerifyStoreBufferPointerVisitor(Isolate* isolate, MemoryRegion* to)
182 : ObjectPointerVisitor(isolate), to_(to) {}
183
184 void VisitPointers(RawObject** first, RawObject** last) {
185 for (RawObject** current = first; current <= last; current++) {
186 RawObject* obj = *current;
187 if (obj->IsHeapObject() && obj->IsNewObject()) {
188 ASSERT(to_->Contains(RawObject::ToAddr(obj)));
189 }
190 }
191 }
192
193 private:
194 MemoryRegion* to_;
195
196 DISALLOW_COPY_AND_ASSIGN(VerifyStoreBufferPointerVisitor);
197 };
198
199
162 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment) 200 Scavenger::Scavenger(Heap* heap, intptr_t max_capacity, uword object_alignment)
163 : heap_(heap), 201 : heap_(heap),
164 object_alignment_(object_alignment), 202 object_alignment_(object_alignment),
165 count_(0), 203 count_(0),
166 scavenging_(false) { 204 scavenging_(false) {
167 // Verify assumptions about the first word in objects which the scavenger is 205 // Verify assumptions about the first word in objects which the scavenger is
168 // going to use for forwarding pointers. 206 // going to use for forwarding pointers.
169 ASSERT(Object::tags_offset() == 0); 207 ASSERT(Object::tags_offset() == 0);
170 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit)); 208 ASSERT(kForwardingMask == (1 << RawObject::kFreeBit));
171 209
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 end_ = to_->end(); 260 end_ = to_->end();
223 } 261 }
224 262
225 263
226 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) { 264 void Scavenger::Epilogue(Isolate* isolate, bool invoke_api_callbacks) {
227 // All objects in the to space have been copied from the from space at this 265 // All objects in the to space have been copied from the from space at this
228 // moment. 266 // moment.
229 survivor_end_ = top_; 267 survivor_end_ = top_;
230 268
231 #if defined(DEBUG) 269 #if defined(DEBUG)
270 VerifyStoreBufferPointerVisitor verify_store_buffer_visitor(isolate, to_);
271 heap_->IterateOldPointers(&verify_store_buffer_visitor);
272
232 memset(from_->pointer(), 0xf3, from_->size()); 273 memset(from_->pointer(), 0xf3, from_->size());
233 #endif // defined(DEBUG) 274 #endif // defined(DEBUG)
234 if (invoke_api_callbacks) { 275 if (invoke_api_callbacks) {
235 isolate->gc_epilogue_callbacks().Invoke(); 276 isolate->gc_epilogue_callbacks().Invoke();
236 } 277 }
237 } 278 }
238 279
239 280
281 void Scavenger::IterateStoreBuffers(Isolate* isolate,
282 ScavengerVisitor* visitor) {
283 // Iterating through the store buffers.
284 visitor->VisitingOldPointers(true);
285 // Grab the deduplication sets out of the store buffer.
286 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets();
287 intptr_t entries = 0;
288 intptr_t duplicates = 0;
289 while (pending != NULL) {
290 StoreBuffer::DedupSet* next = pending->next();
291 HashSet* set = pending->set();
292 intptr_t count = set->Count();
293 intptr_t size = set->Size();
294 intptr_t handled = 0;
295 entries += count;
296 for (intptr_t i = 0; i < size; i++) {
297 RawObject** pointer = reinterpret_cast<RawObject**>(set->At(i));
298 if (pointer != NULL) {
299 RawObject* value = *pointer;
300 // Skip entries that have been overwritten with Smis.
301 if (value->IsHeapObject()) {
302 if (from_->Contains(RawObject::ToAddr(value))) {
303 visitor->VisitPointer(pointer);
304 } else {
305 duplicates++;
306 }
307 }
308 handled++;
309 if (handled == count) {
310 break;
311 }
312 }
313 }
314 delete pending;
315 pending = next;
316 }
317 if (FLAG_verbose_gc) {
318 OS::PrintErr("StoreBuffer: %d, %d (entries, dups)\n",
319 entries, duplicates);
320 }
321 StoreBufferBlock* block = isolate->store_buffer_block();
322 entries = block->Count();
323 duplicates = 0;
324 for (intptr_t i = 0; i < entries; i++) {
325 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i));
326 if (from_->Contains(RawObject::ToAddr(*pointer))) {
327 visitor->VisitPointer(pointer);
328 } else {
329 duplicates++;
330 }
331 }
332 block->Reset();
333 if (FLAG_verbose_gc) {
334 OS::PrintErr("StoreBufferBlock: %d, %d (entries, dups)\n",
335 entries, duplicates);
336 }
337 // Done iterating through the store buffers.
338 visitor->VisitingOldPointers(false);
339 }
340
341
240 void Scavenger::IterateRoots(Isolate* isolate, 342 void Scavenger::IterateRoots(Isolate* isolate,
241 ObjectPointerVisitor* visitor, 343 ScavengerVisitor* visitor,
242 bool visit_prologue_weak_persistent_handles) { 344 bool visit_prologue_weak_persistent_handles) {
345 IterateStoreBuffers(isolate, visitor);
243 isolate->VisitObjectPointers(visitor, 346 isolate->VisitObjectPointers(visitor,
244 visit_prologue_weak_persistent_handles, 347 visit_prologue_weak_persistent_handles,
245 StackFrameIterator::kDontValidateFrames); 348 StackFrameIterator::kDontValidateFrames);
246 heap_->IterateOldPointers(visitor);
247 } 349 }
248 350
249 351
250 bool Scavenger::IsUnreachable(RawObject** p) { 352 bool Scavenger::IsUnreachable(RawObject** p) {
251 RawObject* raw_obj = *p; 353 RawObject* raw_obj = *p;
252 if (!raw_obj->IsHeapObject()) { 354 if (!raw_obj->IsHeapObject()) {
253 return false; 355 return false;
254 } 356 }
255 if (!raw_obj->IsNewObject()) { 357 if (!raw_obj->IsNewObject()) {
256 return false; 358 return false;
257 } 359 }
258 uword raw_addr = RawObject::ToAddr(raw_obj); 360 uword raw_addr = RawObject::ToAddr(raw_obj);
259 if (!from_->Contains(raw_addr)) { 361 if (!from_->Contains(raw_addr)) {
260 return false; 362 return false;
261 } 363 }
262 uword header = *reinterpret_cast<uword*>(raw_addr); 364 uword header = *reinterpret_cast<uword*>(raw_addr);
263 if (IsForwarding(header)) { 365 if (IsForwarding(header)) {
264 uword new_addr = ForwardedAddr(header); 366 uword new_addr = ForwardedAddr(header);
265 *p = RawObject::FromAddr(new_addr); 367 *p = RawObject::FromAddr(new_addr);
266 return false; 368 return false;
267 } 369 }
268 return true; 370 return true;
269 } 371 }
270 372
271 373
272 void Scavenger::IterateWeakReferences(Isolate* isolate, 374 void Scavenger::IterateWeakReferences(Isolate* isolate,
273 ObjectPointerVisitor* visitor) { 375 ScavengerVisitor* visitor) {
274 ApiState* state = isolate->api_state(); 376 ApiState* state = isolate->api_state();
275 ASSERT(state != NULL); 377 ASSERT(state != NULL);
276 while (true) { 378 while (true) {
277 WeakReference* queue = state->delayed_weak_references(); 379 WeakReference* queue = state->delayed_weak_references();
278 if (queue == NULL) { 380 if (queue == NULL) {
279 // The delay queue is empty therefore no clean-up is required. 381 // The delay queue is empty therefore no clean-up is required.
280 return; 382 return;
281 } 383 }
282 state->set_delayed_weak_references(NULL); 384 state->set_delayed_weak_references(NULL);
283 while (queue != NULL) { 385 while (queue != NULL) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 424
323 425
324 void Scavenger::IterateWeakRoots(Isolate* isolate, 426 void Scavenger::IterateWeakRoots(Isolate* isolate,
325 HandleVisitor* visitor, 427 HandleVisitor* visitor,
326 bool visit_prologue_weak_persistent_handles) { 428 bool visit_prologue_weak_persistent_handles) {
327 isolate->VisitWeakPersistentHandles(visitor, 429 isolate->VisitWeakPersistentHandles(visitor,
328 visit_prologue_weak_persistent_handles); 430 visit_prologue_weak_persistent_handles);
329 } 431 }
330 432
331 433
332 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { 434 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) {
333 // Iterate until all work has been drained. 435 // Iterate until all work has been drained.
334 while ((resolved_top_ < top_) || PromotedStackHasMore()) { 436 while ((resolved_top_ < top_) || PromotedStackHasMore()) {
335 while (resolved_top_ < top_) { 437 while (resolved_top_ < top_) {
336 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); 438 RawObject* raw_obj = RawObject::FromAddr(resolved_top_);
337 resolved_top_ += raw_obj->VisitPointers(visitor); 439 resolved_top_ += raw_obj->VisitPointers(visitor);
338 } 440 }
441 visitor->VisitingOldPointers(true);
339 while (PromotedStackHasMore()) { 442 while (PromotedStackHasMore()) {
340 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); 443 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack());
341 // Resolve or copy all objects referred to by the current object. This 444 // Resolve or copy all objects referred to by the current object. This
342 // can potentially push more objects on this stack as well as add more 445 // can potentially push more objects on this stack as well as add more
343 // objects to be resolved in the to space. 446 // objects to be resolved in the to space.
344 raw_object->VisitPointers(visitor); 447 raw_object->VisitPointers(visitor);
345 } 448 }
449 visitor->VisitingOldPointers(false);
346 } 450 }
347 } 451 }
348 452
349 453
350 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 454 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
351 uword cur = FirstObjectStart(); 455 uword cur = FirstObjectStart();
352 while (cur < top_) { 456 while (cur < top_) {
353 RawObject* raw_obj = RawObject::FromAddr(cur); 457 RawObject* raw_obj = RawObject::FromAddr(cur);
354 cur += raw_obj->VisitPointers(visitor); 458 cur += raw_obj->VisitPointers(visitor);
355 } 459 }
(...skipping 24 matching lines...) Expand all
380 had_promotion_failure_ = false; 484 had_promotion_failure_ = false;
381 Isolate* isolate = Isolate::Current(); 485 Isolate* isolate = Isolate::Current();
382 NoHandleScope no_handles(isolate); 486 NoHandleScope no_handles(isolate);
383 487
384 if (FLAG_verify_before_gc) { 488 if (FLAG_verify_before_gc) {
385 OS::PrintErr("Verifying before Scavenge..."); 489 OS::PrintErr("Verifying before Scavenge...");
386 heap_->Verify(); 490 heap_->Verify();
387 OS::PrintErr(" done.\n"); 491 OS::PrintErr(" done.\n");
388 } 492 }
389 493
494 if (FLAG_verbose_gc) {
495 OS::PrintErr("Start scavenge\n");
496 }
390 Timer timer(FLAG_verbose_gc, "Scavenge"); 497 Timer timer(FLAG_verbose_gc, "Scavenge");
391 timer.Start(); 498 timer.Start();
392 // Setup the visitor and run a scavenge. 499 // Setup the visitor and run a scavenge.
393 ScavengerVisitor visitor(isolate, this); 500 ScavengerVisitor visitor(isolate, this);
394 Prologue(isolate, invoke_api_callbacks); 501 Prologue(isolate, invoke_api_callbacks);
395 IterateRoots(isolate, &visitor, !invoke_api_callbacks); 502 IterateRoots(isolate, &visitor, !invoke_api_callbacks);
396 ProcessToSpace(&visitor); 503 ProcessToSpace(&visitor);
397 IterateWeakReferences(isolate, &visitor); 504 IterateWeakReferences(isolate, &visitor);
398 ScavengerWeakVisitor weak_visitor(this); 505 ScavengerWeakVisitor weak_visitor(this);
399 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); 506 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks);
400 Epilogue(isolate, invoke_api_callbacks); 507 Epilogue(isolate, invoke_api_callbacks);
401 timer.Stop(); 508 timer.Stop();
402 if (FLAG_verbose_gc) { 509 if (FLAG_verbose_gc) {
403 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); 510 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime());
404 } 511 }
405 512
406 if (FLAG_verify_after_gc) { 513 if (FLAG_verify_after_gc) {
407 OS::PrintErr("Verifying after Scavenge..."); 514 OS::PrintErr("Verifying after Scavenge...");
408 heap_->Verify(); 515 heap_->Verify();
409 OS::PrintErr(" done.\n"); 516 OS::PrintErr(" done.\n");
410 } 517 }
411 518
412 count_++; 519 count_++;
413 // Done scavenging. Reset the marker. 520 // Done scavenging. Reset the marker.
414 ASSERT(scavenging_); 521 ASSERT(scavenging_);
415 scavenging_ = false; 522 scavenging_ = false;
416 } 523 }
417 524
418 } // namespace dart 525 } // namespace dart
OLDNEW
« no previous file with comments | « vm/scavenger.h ('k') | vm/store_buffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698