OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 void ScavengePointer(Object** p) { | 531 void ScavengePointer(Object** p) { |
532 Object* object = *p; | 532 Object* object = *p; |
533 if (!Heap::InNewSpace(object)) return; | 533 if (!Heap::InNewSpace(object)) return; |
534 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), | 534 Heap::ScavengeObject(reinterpret_cast<HeapObject**>(p), |
535 reinterpret_cast<HeapObject*>(object)); | 535 reinterpret_cast<HeapObject*>(object)); |
536 } | 536 } |
537 }; | 537 }; |
538 | 538 |
539 | 539 |
540 // Shared state read by the scavenge collector and set by ScavengeObject. | 540 // Shared state read by the scavenge collector and set by ScavengeObject. |
541 static Address promoted_top = NULL; | 541 static Address promoted_rear = NULL; |
542 | 542 |
543 | 543 |
544 #ifdef DEBUG | 544 #ifdef DEBUG |
545 // Visitor class to verify pointers in code or data space do not point into | 545 // Visitor class to verify pointers in code or data space do not point into |
546 // new space. | 546 // new space. |
547 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { | 547 class VerifyNonPointerSpacePointersVisitor: public ObjectVisitor { |
548 public: | 548 public: |
549 void VisitPointers(Object** start, Object**end) { | 549 void VisitPointers(Object** start, Object**end) { |
550 for (Object** current = start; current < end; current++) { | 550 for (Object** current = start; current < end; current++) { |
551 if ((*current)->IsHeapObject()) { | 551 if ((*current)->IsHeapObject()) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 // ignored here. | 599 // ignored here. |
600 new_space_.Double(); | 600 new_space_.Double(); |
601 new_space_growth_limit_ *= 2; | 601 new_space_growth_limit_ *= 2; |
602 } | 602 } |
603 | 603 |
604 // Flip the semispaces. After flipping, to space is empty, from space has | 604 // Flip the semispaces. After flipping, to space is empty, from space has |
605 // live objects. | 605 // live objects. |
606 new_space_.Flip(); | 606 new_space_.Flip(); |
607 new_space_.ResetAllocationInfo(); | 607 new_space_.ResetAllocationInfo(); |
608 | 608 |
609 // We need to sweep newly copied objects which can be in either the to space | 609 // We need to sweep newly copied objects which can be in either the |
610 // or the old space. For to space objects, we use a mark. Newly copied | 610 // to space or promoted to the old generation. For to-space |
611 // objects lie between the mark and the allocation top. For objects | 611 // objects, we treat the bottom of the to space as a queue. Newly |
612 // promoted to old space, we write their addresses downward from the top of | 612 // copied and unswept objects lie between a 'front' mark and the |
613 // the new space. Sweeping newly promoted objects requires an allocation | 613 // allocation pointer. |
614 // pointer and a mark. Note that the allocation pointer 'top' actually | |
615 // moves downward from the high address in the to space. | |
616 // | 614 // |
617 // There is guaranteed to be enough room at the top of the to space for the | 615 // Promoted objects can go into various old-generation spaces, and |
618 // addresses of promoted objects: every object promoted frees up its size in | 616 // can be allocated internally in the spaces (from the free list). |
619 // bytes from the top of the new space, and objects are at least one pointer | 617 // We treat the top of the to space as a queue of addresses of |
620 // in size. Using the new space to record promoted addresses makes the | 618 // promoted objects. The addresses of newly promoted and unswept |
621 // scavenge collector agnostic to the allocation strategy (eg, linear or | 619 // objects lie between a 'front' mark and a 'rear' mark that is |
622 // free-list) used in old space. | 620 // updated as a side effect of promoting an object. |
623 Address new_mark = new_space_.ToSpaceLow(); | 621 // |
624 Address promoted_mark = new_space_.ToSpaceHigh(); | 622 // There is guaranteed to be enough room at the top of the to space |
625 promoted_top = new_space_.ToSpaceHigh(); | 623 // for the addresses of promoted objects: every object promoted |
| 624 // frees up its size in bytes from the top of the new space, and |
| 625 // objects are at least one pointer in size. |
| 626 Address new_space_front = new_space_.ToSpaceLow(); |
| 627 Address promoted_front = new_space_.ToSpaceHigh(); |
| 628 promoted_rear = new_space_.ToSpaceHigh(); |
626 | 629 |
627 ScavengeVisitor scavenge_visitor; | 630 ScavengeVisitor scavenge_visitor; |
628 // Copy roots. | 631 // Copy roots. |
629 IterateRoots(&scavenge_visitor); | 632 IterateRoots(&scavenge_visitor); |
630 | 633 |
631 // Copy objects reachable from the old generation. By definition, there | 634 // Copy objects reachable from weak pointers. |
632 // are no intergenerational pointers in code or data spaces. | 635 GlobalHandles::IterateWeakRoots(&scavenge_visitor); |
| 636 |
| 637 // Copy objects reachable from the old generation. By definition, |
| 638 // there are no intergenerational pointers in code or data spaces. |
633 IterateRSet(old_pointer_space_, &ScavengePointer); | 639 IterateRSet(old_pointer_space_, &ScavengePointer); |
634 IterateRSet(map_space_, &ScavengePointer); | 640 IterateRSet(map_space_, &ScavengePointer); |
635 lo_space_->IterateRSet(&ScavengePointer); | 641 lo_space_->IterateRSet(&ScavengePointer); |
636 | 642 |
637 bool has_processed_weak_pointers = false; | 643 do { |
| 644 ASSERT(new_space_front <= new_space_.top()); |
| 645 ASSERT(promoted_front >= promoted_rear); |
638 | 646 |
639 while (true) { | 647 // The addresses new_space_front and new_space_.top() define a |
640 ASSERT(new_mark <= new_space_.top()); | 648 // queue of unprocessed copied objects. Process them until the |
641 ASSERT(promoted_mark >= promoted_top); | 649 // queue is empty. |
642 | 650 while (new_space_front < new_space_.top()) { |
643 // Copy objects reachable from newly copied objects. | 651 HeapObject* object = HeapObject::FromAddress(new_space_front); |
644 while (new_mark < new_space_.top() || promoted_mark > promoted_top) { | 652 object->Iterate(&scavenge_visitor); |
645 // Sweep newly copied objects in the to space. The allocation pointer | 653 new_space_front += object->Size(); |
646 // can change during sweeping. | |
647 Address previous_top = new_space_.top(); | |
648 SemiSpaceIterator new_it(new_space(), new_mark); | |
649 while (new_it.has_next()) { | |
650 new_it.next()->Iterate(&scavenge_visitor); | |
651 } | |
652 new_mark = previous_top; | |
653 | |
654 // Sweep newly copied objects in the old space. The promotion 'top' | |
655 // pointer could change during sweeping. | |
656 previous_top = promoted_top; | |
657 for (Address current = promoted_mark - kPointerSize; | |
658 current >= previous_top; | |
659 current -= kPointerSize) { | |
660 HeapObject* object = HeapObject::cast(Memory::Object_at(current)); | |
661 object->Iterate(&scavenge_visitor); | |
662 UpdateRSet(object); | |
663 } | |
664 promoted_mark = previous_top; | |
665 } | 654 } |
666 | 655 |
667 if (has_processed_weak_pointers) break; // We are done. | 656 // The addresses promoted_front and promoted_rear define a queue |
668 // Copy objects reachable from weak pointers. | 657 // of unprocessed addresses of promoted objects. Process them |
669 GlobalHandles::IterateWeakRoots(&scavenge_visitor); | 658 // until the queue is empty. |
670 has_processed_weak_pointers = true; | 659 while (promoted_front > promoted_rear) { |
671 } | 660 promoted_front -= kPointerSize; |
| 661 HeapObject* object = |
| 662 HeapObject::cast(Memory::Object_at(promoted_front)); |
| 663 object->Iterate(&scavenge_visitor); |
| 664 UpdateRSet(object); |
| 665 } |
| 666 |
| 667 // Take another spin if there are now unswept objects in new space |
| 668 // (there are currently no more unswept promoted objects). |
| 669 } while (new_space_front < new_space_.top()); |
672 | 670 |
673 // Set age mark. | 671 // Set age mark. |
674 new_space_.set_age_mark(new_mark); | 672 new_space_.set_age_mark(new_space_.top()); |
675 | 673 |
676 LOG(ResourceEvent("scavenge", "end")); | 674 LOG(ResourceEvent("scavenge", "end")); |
677 | 675 |
678 gc_state_ = NOT_IN_GC; | 676 gc_state_ = NOT_IN_GC; |
679 } | 677 } |
680 | 678 |
681 | 679 |
682 void Heap::ClearRSetRange(Address start, int size_in_bytes) { | 680 void Heap::ClearRSetRange(Address start, int size_in_bytes) { |
683 uint32_t start_bit; | 681 uint32_t start_bit; |
684 Address start_word_address = | 682 Address start_word_address = |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
885 if (ShouldBePromoted(object->address(), object_size)) { | 883 if (ShouldBePromoted(object->address(), object_size)) { |
886 OldSpace* target_space = Heap::TargetSpace(object); | 884 OldSpace* target_space = Heap::TargetSpace(object); |
887 ASSERT(target_space == Heap::old_pointer_space_ || | 885 ASSERT(target_space == Heap::old_pointer_space_ || |
888 target_space == Heap::old_data_space_); | 886 target_space == Heap::old_data_space_); |
889 Object* result = target_space->AllocateRaw(object_size); | 887 Object* result = target_space->AllocateRaw(object_size); |
890 if (!result->IsFailure()) { | 888 if (!result->IsFailure()) { |
891 *p = MigrateObject(object, HeapObject::cast(result), object_size); | 889 *p = MigrateObject(object, HeapObject::cast(result), object_size); |
892 if (target_space == Heap::old_pointer_space_) { | 890 if (target_space == Heap::old_pointer_space_) { |
893 // Record the object's address at the top of the to space, to allow | 891 // Record the object's address at the top of the to space, to allow |
894 // it to be swept by the scavenger. | 892 // it to be swept by the scavenger. |
895 promoted_top -= kPointerSize; | 893 promoted_rear -= kPointerSize; |
896 Memory::Object_at(promoted_top) = *p; | 894 Memory::Object_at(promoted_rear) = *p; |
897 } else { | 895 } else { |
898 #ifdef DEBUG | 896 #ifdef DEBUG |
899 // Objects promoted to the data space should not have pointers to | 897 // Objects promoted to the data space should not have pointers to |
900 // new space. | 898 // new space. |
901 VerifyNonPointerSpacePointersVisitor v; | 899 VerifyNonPointerSpacePointersVisitor v; |
902 (*p)->Iterate(&v); | 900 (*p)->Iterate(&v); |
903 #endif | 901 #endif |
904 } | 902 } |
905 return; | 903 return; |
906 } | 904 } |
(...skipping 2490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3397 #ifdef DEBUG | 3395 #ifdef DEBUG |
3398 bool Heap::GarbageCollectionGreedyCheck() { | 3396 bool Heap::GarbageCollectionGreedyCheck() { |
3399 ASSERT(FLAG_gc_greedy); | 3397 ASSERT(FLAG_gc_greedy); |
3400 if (Bootstrapper::IsActive()) return true; | 3398 if (Bootstrapper::IsActive()) return true; |
3401 if (disallow_allocation_failure()) return true; | 3399 if (disallow_allocation_failure()) return true; |
3402 return CollectGarbage(0, NEW_SPACE); | 3400 return CollectGarbage(0, NEW_SPACE); |
3403 } | 3401 } |
3404 #endif | 3402 #endif |
3405 | 3403 |
3406 } } // namespace v8::internal | 3404 } } // namespace v8::internal |
OLD | NEW |