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

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
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);
siva 2012/07/19 17:36:06 This verification doesn't quite ensure that the st
Ivan Posva 2012/07/20 15:37:46 Discussed offline: Suggestion would work and has t
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
240 void Scavenger::IterateRoots(Isolate* isolate, 281 void Scavenger::IterateRoots(Isolate* isolate,
241 ObjectPointerVisitor* visitor, 282 ScavengerVisitor* visitor,
242 bool visit_prologue_weak_persistent_handles) { 283 bool visit_prologue_weak_persistent_handles) {
284 // Iterating though the store buffers.
siva 2012/07/19 17:36:06 spelling!!
Ivan Posva 2012/07/20 15:37:46 Done.
285 visitor->VisitingOldPointers(true);
286 // Grab the deduplication sets out of the store buffer.
287 StoreBuffer::DedupSet* pending = isolate->store_buffer()->DedupSets();
288 intptr_t entries = 0;
289 intptr_t duplicates = 0;
290 while (pending != NULL) {
291 StoreBuffer::DedupSet* next = pending->next();
292 HashSet* set = pending->set();
293 intptr_t count = set->Count();
294 intptr_t size = set->Size();
295 intptr_t handled = 0;
296 entries += count;
297 for (intptr_t i = 0; i < size; i++) {
298 RawObject** pointer = reinterpret_cast<RawObject**>(set->At(i));
299 if (pointer != NULL) {
300 RawObject* value = *pointer;
301 // Skip entries that have been overwritten with Smis.
302 if (value->IsHeapObject()) {
303 if (from_->Contains(RawObject::ToAddr(value))) {
304 visitor->VisitPointer(pointer);
305 } else {
306 duplicates++;
307 }
308 }
309 handled++;
310 if (handled == count) {
311 break;
312 }
313 }
314 }
315 delete pending;
316 pending = next;
317 }
318 if (FLAG_verbose_gc) {
319 OS::PrintErr("StoreBuffer: %d, %d (entries, dups)\n",
320 entries, duplicates);
321 }
322 StoreBufferBlock* block = isolate->store_buffer_block();
323 entries = block->Count();
324 duplicates = 0;
325 for (intptr_t i = 0; i < entries; i++) {
326 RawObject** pointer = reinterpret_cast<RawObject**>(block->At(i));
327 if (from_->Contains(RawObject::ToAddr(*pointer))) {
328 visitor->VisitPointer(pointer);
329 } else {
330 duplicates++;
331 }
332 }
siva 2012/07/19 17:36:06 Instead of processing this StoreBufferBlock separa
Ivan Posva 2012/07/20 15:37:46 The number of addresses visited here is limited so
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
243 isolate->VisitObjectPointers(visitor, 340 isolate->VisitObjectPointers(visitor,
244 visit_prologue_weak_persistent_handles, 341 visit_prologue_weak_persistent_handles,
245 StackFrameIterator::kDontValidateFrames); 342 StackFrameIterator::kDontValidateFrames);
246 heap_->IterateOldPointers(visitor);
247 } 343 }
248 344
249 345
250 bool Scavenger::IsUnreachable(RawObject** p) { 346 bool Scavenger::IsUnreachable(RawObject** p) {
251 RawObject* raw_obj = *p; 347 RawObject* raw_obj = *p;
252 if (!raw_obj->IsHeapObject()) { 348 if (!raw_obj->IsHeapObject()) {
253 return false; 349 return false;
254 } 350 }
255 if (!raw_obj->IsNewObject()) { 351 if (!raw_obj->IsNewObject()) {
256 return false; 352 return false;
257 } 353 }
258 uword raw_addr = RawObject::ToAddr(raw_obj); 354 uword raw_addr = RawObject::ToAddr(raw_obj);
259 if (!from_->Contains(raw_addr)) { 355 if (!from_->Contains(raw_addr)) {
260 return false; 356 return false;
261 } 357 }
262 uword header = *reinterpret_cast<uword*>(raw_addr); 358 uword header = *reinterpret_cast<uword*>(raw_addr);
263 if (IsForwarding(header)) { 359 if (IsForwarding(header)) {
264 uword new_addr = ForwardedAddr(header); 360 uword new_addr = ForwardedAddr(header);
265 *p = RawObject::FromAddr(new_addr); 361 *p = RawObject::FromAddr(new_addr);
266 return false; 362 return false;
267 } 363 }
268 return true; 364 return true;
269 } 365 }
270 366
271 367
272 void Scavenger::IterateWeakReferences(Isolate* isolate, 368 void Scavenger::IterateWeakReferences(Isolate* isolate,
273 ObjectPointerVisitor* visitor) { 369 ScavengerVisitor* visitor) {
274 ApiState* state = isolate->api_state(); 370 ApiState* state = isolate->api_state();
275 ASSERT(state != NULL); 371 ASSERT(state != NULL);
276 while (true) { 372 while (true) {
277 WeakReference* queue = state->delayed_weak_references(); 373 WeakReference* queue = state->delayed_weak_references();
278 if (queue == NULL) { 374 if (queue == NULL) {
279 // The delay queue is empty therefore no clean-up is required. 375 // The delay queue is empty therefore no clean-up is required.
280 return; 376 return;
281 } 377 }
282 state->set_delayed_weak_references(NULL); 378 state->set_delayed_weak_references(NULL);
283 while (queue != NULL) { 379 while (queue != NULL) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 418
323 419
324 void Scavenger::IterateWeakRoots(Isolate* isolate, 420 void Scavenger::IterateWeakRoots(Isolate* isolate,
325 HandleVisitor* visitor, 421 HandleVisitor* visitor,
326 bool visit_prologue_weak_persistent_handles) { 422 bool visit_prologue_weak_persistent_handles) {
327 isolate->VisitWeakPersistentHandles(visitor, 423 isolate->VisitWeakPersistentHandles(visitor,
328 visit_prologue_weak_persistent_handles); 424 visit_prologue_weak_persistent_handles);
329 } 425 }
330 426
331 427
332 void Scavenger::ProcessToSpace(ObjectPointerVisitor* visitor) { 428 void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) {
333 // Iterate until all work has been drained. 429 // Iterate until all work has been drained.
334 while ((resolved_top_ < top_) || PromotedStackHasMore()) { 430 while ((resolved_top_ < top_) || PromotedStackHasMore()) {
335 while (resolved_top_ < top_) { 431 while (resolved_top_ < top_) {
336 RawObject* raw_obj = RawObject::FromAddr(resolved_top_); 432 RawObject* raw_obj = RawObject::FromAddr(resolved_top_);
337 resolved_top_ += raw_obj->VisitPointers(visitor); 433 resolved_top_ += raw_obj->VisitPointers(visitor);
338 } 434 }
435 visitor->VisitingOldPointers(true);
339 while (PromotedStackHasMore()) { 436 while (PromotedStackHasMore()) {
340 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack()); 437 RawObject* raw_object = RawObject::FromAddr(PopFromPromotedStack());
341 // Resolve or copy all objects referred to by the current object. This 438 // 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 439 // can potentially push more objects on this stack as well as add more
343 // objects to be resolved in the to space. 440 // objects to be resolved in the to space.
344 raw_object->VisitPointers(visitor); 441 raw_object->VisitPointers(visitor);
345 } 442 }
443 visitor->VisitingOldPointers(false);
346 } 444 }
347 } 445 }
348 446
349 447
350 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const { 448 void Scavenger::VisitObjectPointers(ObjectPointerVisitor* visitor) const {
351 uword cur = FirstObjectStart(); 449 uword cur = FirstObjectStart();
352 while (cur < top_) { 450 while (cur < top_) {
353 RawObject* raw_obj = RawObject::FromAddr(cur); 451 RawObject* raw_obj = RawObject::FromAddr(cur);
354 cur += raw_obj->VisitPointers(visitor); 452 cur += raw_obj->VisitPointers(visitor);
355 } 453 }
(...skipping 24 matching lines...) Expand all
380 had_promotion_failure_ = false; 478 had_promotion_failure_ = false;
381 Isolate* isolate = Isolate::Current(); 479 Isolate* isolate = Isolate::Current();
382 NoHandleScope no_handles(isolate); 480 NoHandleScope no_handles(isolate);
383 481
384 if (FLAG_verify_before_gc) { 482 if (FLAG_verify_before_gc) {
385 OS::PrintErr("Verifying before Scavenge..."); 483 OS::PrintErr("Verifying before Scavenge...");
386 heap_->Verify(); 484 heap_->Verify();
387 OS::PrintErr(" done.\n"); 485 OS::PrintErr(" done.\n");
388 } 486 }
389 487
488 if (FLAG_verbose_gc) {
489 OS::PrintErr("Start scavenge\n");
490 }
390 Timer timer(FLAG_verbose_gc, "Scavenge"); 491 Timer timer(FLAG_verbose_gc, "Scavenge");
391 timer.Start(); 492 timer.Start();
392 // Setup the visitor and run a scavenge. 493 // Setup the visitor and run a scavenge.
393 ScavengerVisitor visitor(isolate, this); 494 ScavengerVisitor visitor(isolate, this);
394 Prologue(isolate, invoke_api_callbacks); 495 Prologue(isolate, invoke_api_callbacks);
395 IterateRoots(isolate, &visitor, !invoke_api_callbacks); 496 IterateRoots(isolate, &visitor, !invoke_api_callbacks);
396 ProcessToSpace(&visitor); 497 ProcessToSpace(&visitor);
397 IterateWeakReferences(isolate, &visitor); 498 IterateWeakReferences(isolate, &visitor);
398 ScavengerWeakVisitor weak_visitor(this); 499 ScavengerWeakVisitor weak_visitor(this);
399 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks); 500 IterateWeakRoots(isolate, &weak_visitor, invoke_api_callbacks);
400 Epilogue(isolate, invoke_api_callbacks); 501 Epilogue(isolate, invoke_api_callbacks);
401 timer.Stop(); 502 timer.Stop();
402 if (FLAG_verbose_gc) { 503 if (FLAG_verbose_gc) {
403 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime()); 504 OS::PrintErr("Scavenge[%d]: %dus\n", count_, timer.TotalElapsedTime());
404 } 505 }
405 506
406 if (FLAG_verify_after_gc) { 507 if (FLAG_verify_after_gc) {
407 OS::PrintErr("Verifying after Scavenge..."); 508 OS::PrintErr("Verifying after Scavenge...");
408 heap_->Verify(); 509 heap_->Verify();
409 OS::PrintErr(" done.\n"); 510 OS::PrintErr(" done.\n");
410 } 511 }
411 512
412 count_++; 513 count_++;
413 // Done scavenging. Reset the marker. 514 // Done scavenging. Reset the marker.
414 ASSERT(scavenging_); 515 ASSERT(scavenging_);
415 scavenging_ = false; 516 scavenging_ = false;
416 } 517 }
417 518
418 } // namespace dart 519 } // namespace dart
OLDNEW
« no previous file with comments | « vm/scavenger.h ('k') | vm/store_buffer.h » ('j') | vm/store_buffer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698