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

Side by Side Diff: runtime/vm/gc_marker.cc

Issue 2930943002: Debug garbage collector does not correctly remove cross-gen garbage (Closed)
Patch Set: Created 3 years, 6 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
« no previous file with comments | « no previous file | runtime/vm/heap.h » ('j') | runtime/vm/heap.h » ('J')
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/gc_marker.h" 5 #include "vm/gc_marker.h"
6 6
7 #include "vm/allocation.h" 7 #include "vm/allocation.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/log.h" 10 #include "vm/log.h"
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 uword next_weak = cur_weak->ptr()->next_; 184 uword next_weak = cur_weak->ptr()->next_;
185 RawObject* raw_key = cur_weak->ptr()->key_; 185 RawObject* raw_key = cur_weak->ptr()->key_;
186 // Reset the next pointer in the weak property. 186 // Reset the next pointer in the weak property.
187 cur_weak->ptr()->next_ = 0; 187 cur_weak->ptr()->next_ = 0;
188 if (raw_key->IsMarked()) { 188 if (raw_key->IsMarked()) {
189 RawObject* raw_val = cur_weak->ptr()->value_; 189 RawObject* raw_val = cur_weak->ptr()->value_;
190 marked = marked || (raw_val->IsHeapObject() && !raw_val->IsMarked()); 190 marked = marked || (raw_val->IsHeapObject() && !raw_val->IsMarked());
191 191
192 // The key is marked so we make sure to properly visit all pointers 192 // The key is marked so we make sure to properly visit all pointers
193 // originating from this weak property. 193 // originating from this weak property.
194 VisitingOldObject(cur_weak); 194 if (cur_weak->IsOldObject()) {
195 VisitingOldObject(cur_weak);
196 } else {
197 VisitingOldObject(NULL);
198 }
195 cur_weak->VisitPointersNonvirtual(this); 199 cur_weak->VisitPointersNonvirtual(this);
196 } else { 200 } else {
197 // Requeue this weak property to be handled later. 201 // Requeue this weak property to be handled later.
198 EnqueueWeakProperty(cur_weak); 202 EnqueueWeakProperty(cur_weak);
199 } 203 }
200 // Advance to next weak property in the queue. 204 // Advance to next weak property in the queue.
201 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak); 205 cur_weak = reinterpret_cast<RawWeakProperty*>(next_weak);
202 } 206 }
203 VisitingOldObject(NULL); 207 VisitingOldObject(NULL);
204 return marked; 208 return marked;
205 } 209 }
206 210
207 void DrainMarkingStack() { 211 void DrainMarkingStack() {
208 RawObject* raw_obj = work_list_.Pop(); 212 RawObject* raw_obj = work_list_.Pop();
209 if ((raw_obj == NULL) && ProcessPendingWeakProperties()) { 213 if ((raw_obj == NULL) && ProcessPendingWeakProperties()) {
210 raw_obj = work_list_.Pop(); 214 raw_obj = work_list_.Pop();
211 } 215 }
212 216
213 if (raw_obj == NULL) { 217 if (raw_obj == NULL) {
214 ASSERT(visiting_old_object_ == NULL); 218 ASSERT(visiting_old_object_ == NULL);
215 return; 219 return;
216 } 220 }
217 do { 221 do {
218 do { 222 do {
219 // First drain the marking stacks. 223 // First drain the marking stacks.
220 VisitingOldObject(raw_obj); 224 if (raw_obj->IsOldObject()) {
225 VisitingOldObject(raw_obj);
226 } else {
227 VisitingOldObject(NULL);
228 }
229
221 const intptr_t class_id = raw_obj->GetClassId(); 230 const intptr_t class_id = raw_obj->GetClassId();
222 if (class_id != kWeakPropertyCid) { 231 if (class_id != kWeakPropertyCid) {
223 marked_bytes_ += raw_obj->VisitPointersNonvirtual(this); 232 marked_bytes_ += raw_obj->VisitPointersNonvirtual(this);
224 } else { 233 } else {
225 RawWeakProperty* raw_weak = 234 RawWeakProperty* raw_weak =
226 reinterpret_cast<RawWeakProperty*>(raw_obj); 235 reinterpret_cast<RawWeakProperty*>(raw_obj);
227 marked_bytes_ += ProcessWeakProperty(raw_weak); 236 marked_bytes_ += ProcessWeakProperty(raw_weak);
228 } 237 }
229 raw_obj = work_list_.Pop(); 238 raw_obj = work_list_.Pop();
230 } while (raw_obj != NULL); 239 } while (raw_obj != NULL);
(...skipping 16 matching lines...) Expand all
247 256
248 bool visit_function_code() const { return skipped_code_functions_ == NULL; } 257 bool visit_function_code() const { return skipped_code_functions_ == NULL; }
249 258
250 virtual void add_skipped_code_function(RawFunction* func) { 259 virtual void add_skipped_code_function(RawFunction* func) {
251 ASSERT(!visit_function_code()); 260 ASSERT(!visit_function_code());
252 skipped_code_functions_->Add(func); 261 skipped_code_functions_->Add(func);
253 } 262 }
254 263
255 void EnqueueWeakProperty(RawWeakProperty* raw_weak) { 264 void EnqueueWeakProperty(RawWeakProperty* raw_weak) {
256 ASSERT(raw_weak->IsHeapObject()); 265 ASSERT(raw_weak->IsHeapObject());
257 ASSERT(raw_weak->IsOldObject()); 266 ASSERT(raw_weak->IsOldObject());
rmacnak 2017/06/08 21:23:48 Update (visiting new-space weak properties now).
258 ASSERT(raw_weak->IsWeakProperty()); 267 ASSERT(raw_weak->IsWeakProperty());
259 ASSERT(raw_weak->IsMarked()); 268 ASSERT(raw_weak->IsMarked());
260 ASSERT(raw_weak->ptr()->next_ == 0); 269 ASSERT(raw_weak->ptr()->next_ == 0);
261 raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_); 270 raw_weak->ptr()->next_ = reinterpret_cast<uword>(delayed_weak_properties_);
262 delayed_weak_properties_ = raw_weak; 271 delayed_weak_properties_ = raw_weak;
263 } 272 }
264 273
265 intptr_t ProcessWeakProperty(RawWeakProperty* raw_weak) { 274 intptr_t ProcessWeakProperty(RawWeakProperty* raw_weak) {
266 // The fate of the weak property is determined by its key. 275 // The fate of the weak property is determined by its key.
267 RawObject* raw_key = raw_weak->ptr()->key_; 276 RawObject* raw_key = raw_weak->ptr()->key_;
268 if (raw_key->IsHeapObject() && raw_key->IsOldObject() && 277 if (raw_key->IsHeapObject() && raw_key->IsOldObject() &&
rmacnak 2017/06/08 21:23:48 Update (not all new-space objects are survivors)
269 !raw_key->IsMarked()) { 278 !raw_key->IsMarked()) {
270 // Key was white. Enqueue the weak property. 279 // Key was white. Enqueue the weak property.
271 EnqueueWeakProperty(raw_weak); 280 EnqueueWeakProperty(raw_weak);
272 return raw_weak->Size(); 281 return raw_weak->Size();
273 } 282 }
274 // Key is gray or black. Make the weak property black. 283 // Key is gray or black. Make the weak property black.
275 return raw_weak->VisitPointersNonvirtual(this); 284 return raw_weak->VisitPointersNonvirtual(this);
276 } 285 }
277 286
278 // Called when all marking is complete. 287 // Called when all marking is complete.
(...skipping 20 matching lines...) Expand all
299 308
300 void VisitingOldObject(RawObject* obj) { 309 void VisitingOldObject(RawObject* obj) {
301 ASSERT((obj == NULL) || obj->IsOldObject()); 310 ASSERT((obj == NULL) || obj->IsOldObject());
302 visiting_old_object_ = obj; 311 visiting_old_object_ = obj;
303 } 312 }
304 313
305 private: 314 private:
306 void PushMarked(RawObject* raw_obj) { 315 void PushMarked(RawObject* raw_obj) {
307 ASSERT(raw_obj->IsHeapObject()); 316 ASSERT(raw_obj->IsHeapObject());
308 ASSERT((FLAG_verify_gc_contains) 317 ASSERT((FLAG_verify_gc_contains)
309 ? page_space_->Contains(RawObject::ToAddr(raw_obj)) 318 ? ((page_space_->Contains(RawObject::ToAddr(raw_obj))) ||
319 (heap_->new_space()->Contains(RawObject::ToAddr(raw_obj))))
310 : true); 320 : true);
311 321
312 // Push the marked object on the marking stack. 322 // Push the marked object on the marking stack.
313 ASSERT(raw_obj->IsMarked()); 323 ASSERT(raw_obj->IsMarked());
314 // We acquired the mark bit => no other task is modifying the header. 324 // We acquired the mark bit => no other task is modifying the header.
315 // TODO(koda): For concurrent mutator, this needs synchronization. Consider 325 // TODO(koda): For concurrent mutator, this needs synchronization. Consider
316 // clearing these bits already in the CAS for the mark bit. 326 // clearing these bits already in the CAS for the mark bit.
317 raw_obj->ClearRememberedBitUnsynchronized(); 327 raw_obj->ClearRememberedBitUnsynchronized();
318 work_list_.Push(raw_obj); 328 work_list_.Push(raw_obj);
319 } 329 }
320 330
321 static bool TryAcquireMarkBit(RawObject* raw_obj) { 331 static bool TryAcquireMarkBit(RawObject* raw_obj) {
322 if (!sync) { 332 if (!sync) {
323 if (raw_obj->IsMarked()) return false; 333 if (raw_obj->IsMarked()) return false;
324 raw_obj->SetMarkBitUnsynchronized(); 334 raw_obj->SetMarkBitUnsynchronized();
325 return true; 335 return true;
326 } 336 }
327 return raw_obj->TryAcquireMarkBit(); 337 return raw_obj->TryAcquireMarkBit();
328 } 338 }
329 339
330 void MarkObject(RawObject* raw_obj, RawObject** p) { 340 void MarkObject(RawObject* raw_obj, RawObject** p) {
331 // Fast exit if the raw object is a Smi. 341 // Fast exit if the raw object is a Smi.
332 if (!raw_obj->IsHeapObject()) { 342 if (!raw_obj->IsHeapObject()) {
333 return; 343 return;
334 } 344 }
335 345
336 // Fast exit if the raw object is marked. 346 // Fast exit if the raw object is marked.
337 if (raw_obj->IsMarked()) { 347 if (raw_obj->IsMarked()) {
348 if (raw_obj->IsNewObject()) {
349 ProcessNewSpaceObject(raw_obj, p);
350 }
338 return; 351 return;
339 } 352 }
340 353
341 // TODO(koda): Investigate performance impact of alternative branching: 354 // TODO(koda): Investigate performance impact of alternative branching:
342 // if (smi or new) <-- can be done as single compare + conditional jump 355 // if (smi or new) <-- can be done as single compare + conditional jump
343 // if (smi) return; 356 // if (smi) return;
344 // else ... 357 // else ...
345 // if (marked) return; 358 // if (marked) return;
346 // ... 359 // ...
347 if (raw_obj->IsNewObject()) { 360 if (raw_obj->IsNewObject()) {
348 ProcessNewSpaceObject(raw_obj, p); 361 ProcessNewSpaceObject(raw_obj, p);
349 return;
350 } 362 }
351 363
352 if (!TryAcquireMarkBit(raw_obj)) { 364 if (!TryAcquireMarkBit(raw_obj)) {
353 // Already marked. 365 // Already marked.
354 return; 366 return;
355 } 367 }
356 if (RawObject::IsVariableSizeClassId(raw_obj->GetClassId())) { 368 if (RawObject::IsVariableSizeClassId(raw_obj->GetClassId())) {
357 UpdateLiveOld(raw_obj->GetClassId(), raw_obj->Size()); 369 UpdateLiveOld(raw_obj->GetClassId(), raw_obj->Size());
358 } else { 370 } else {
359 UpdateLiveOld(raw_obj->GetClassId(), 0); 371 UpdateLiveOld(raw_obj->GetClassId(), 0);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 typedef MarkingVisitorBase<true> SyncMarkingVisitor; 426 typedef MarkingVisitorBase<true> SyncMarkingVisitor;
415 427
416 428
417 static bool IsUnreachable(const RawObject* raw_obj) { 429 static bool IsUnreachable(const RawObject* raw_obj) {
418 if (!raw_obj->IsHeapObject()) { 430 if (!raw_obj->IsHeapObject()) {
419 return false; 431 return false;
420 } 432 }
421 if (raw_obj == Object::null()) { 433 if (raw_obj == Object::null()) {
422 return true; 434 return true;
423 } 435 }
424 if (!raw_obj->IsOldObject()) { 436 if (!raw_obj->IsOldObject()) {
rmacnak 2017/06/08 21:23:48 Update (not all new-space objects are survivors)
425 return false; 437 return false;
426 } 438 }
427 return !raw_obj->IsMarked(); 439 return !raw_obj->IsMarked();
428 } 440 }
429 441
430 442
431 class MarkingWeakVisitor : public HandleVisitor { 443 class MarkingWeakVisitor : public HandleVisitor {
432 public: 444 public:
433 explicit MarkingWeakVisitor(Thread* thread) : HandleVisitor(thread) {} 445 explicit MarkingWeakVisitor(Thread* thread) : HandleVisitor(thread) {}
434 446
(...skipping 30 matching lines...) Expand all
465 477
466 void GCMarker::IterateRoots(Isolate* isolate, 478 void GCMarker::IterateRoots(Isolate* isolate,
467 ObjectPointerVisitor* visitor, 479 ObjectPointerVisitor* visitor,
468 intptr_t slice_index, 480 intptr_t slice_index,
469 intptr_t num_slices) { 481 intptr_t num_slices) {
470 ASSERT(0 <= slice_index && slice_index < num_slices); 482 ASSERT(0 <= slice_index && slice_index < num_slices);
471 if ((slice_index == 0) || (num_slices <= 1)) { 483 if ((slice_index == 0) || (num_slices <= 1)) {
472 isolate->VisitObjectPointers(visitor, 484 isolate->VisitObjectPointers(visitor,
473 StackFrameIterator::kDontValidateFrames); 485 StackFrameIterator::kDontValidateFrames);
474 } 486 }
475 if ((slice_index == 1) || (num_slices <= 1)) {
476 heap_->new_space()->VisitObjectPointers(visitor);
477 }
478 487
479 // For now, we just distinguish two parts of the root set, so any remaining 488 // For now, we just distinguish two parts of the root set, so any remaining
480 // slices are empty. 489 // slices are empty.
481 } 490 }
482 491
483 492
484 void GCMarker::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) { 493 void GCMarker::IterateWeakRoots(Isolate* isolate, HandleVisitor* visitor) {
485 ApiState* state = isolate->api_state(); 494 ApiState* state = isolate->api_state();
486 ASSERT(state != NULL); 495 ASSERT(state != NULL);
487 isolate->VisitWeakPersistentHandles(visitor); 496 isolate->VisitWeakPersistentHandles(visitor);
(...skipping 21 matching lines...) Expand all
509 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor { 518 class ObjectIdRingClearPointerVisitor : public ObjectPointerVisitor {
510 public: 519 public:
511 explicit ObjectIdRingClearPointerVisitor(Isolate* isolate) 520 explicit ObjectIdRingClearPointerVisitor(Isolate* isolate)
512 : ObjectPointerVisitor(isolate) {} 521 : ObjectPointerVisitor(isolate) {}
513 522
514 523
515 void VisitPointers(RawObject** first, RawObject** last) { 524 void VisitPointers(RawObject** first, RawObject** last) {
516 for (RawObject** current = first; current <= last; current++) { 525 for (RawObject** current = first; current <= last; current++) {
517 RawObject* raw_obj = *current; 526 RawObject* raw_obj = *current;
518 ASSERT(raw_obj->IsHeapObject()); 527 ASSERT(raw_obj->IsHeapObject());
519 if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) { 528 if (raw_obj->IsOldObject() && !raw_obj->IsMarked()) {
rmacnak 2017/06/08 21:23:48 Update (not all new-space objects are survivors)
520 // Object has become garbage. Replace it will null. 529 // Object has become garbage. Replace it will null.
521 *current = Object::null(); 530 *current = Object::null();
522 } 531 }
523 } 532 }
524 } 533 }
525 }; 534 };
526 535
527 536
528 void GCMarker::ProcessObjectIdTable(Isolate* isolate) { 537 void GCMarker::ProcessObjectIdTable(Isolate* isolate) {
529 #ifndef PRODUCT 538 #ifndef PRODUCT
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 // Phase 3: Finalize results from all markers (detach code, etc.). 767 // Phase 3: Finalize results from all markers (detach code, etc.).
759 barrier.Exit(); 768 barrier.Exit();
760 } 769 }
761 ProcessWeakTables(page_space); 770 ProcessWeakTables(page_space);
762 ProcessObjectIdTable(isolate); 771 ProcessObjectIdTable(isolate);
763 } 772 }
764 Epilogue(isolate, invoke_api_callbacks); 773 Epilogue(isolate, invoke_api_callbacks);
765 } 774 }
766 775
767 } // namespace dart 776 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/heap.h » ('j') | runtime/vm/heap.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698