| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 } | 107 } |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 static void VerifyMarking(Page* p) { | 111 static void VerifyMarking(Page* p) { |
| 112 VerifyMarking(p->ObjectAreaStart(), p->ObjectAreaEnd()); | 112 VerifyMarking(p->ObjectAreaStart(), p->ObjectAreaEnd()); |
| 113 } | 113 } |
| 114 | 114 |
| 115 | 115 |
| 116 static void VerifyMarking(NewSpace* space) { | 116 static void VerifyMarking(NewSpace* space) { |
| 117 VerifyMarking(space->bottom(), space->top()); | 117 Address end = space->top(); |
| 118 NewSpacePageIterator it(space->bottom(), end); |
| 119 // The bottom position is at the start of its page. Allows us to use |
| 120 // page->body() as start of range on all pages. |
| 121 ASSERT_EQ(space->bottom(), |
| 122 NewSpacePage::FromAddress(space->bottom())->body()); |
| 123 while (it.has_next()) { |
| 124 NewSpacePage* page = it.next(); |
| 125 Address limit = it.has_next() ? page->body_limit() : end; |
| 126 VerifyMarking(page->body(), limit); |
| 127 } |
| 118 } | 128 } |
| 119 | 129 |
| 120 | 130 |
| 121 static void VerifyMarking(PagedSpace* space) { | 131 static void VerifyMarking(PagedSpace* space) { |
| 122 PageIterator it(space); | 132 PageIterator it(space); |
| 123 | 133 |
| 124 while (it.has_next()) { | 134 while (it.has_next()) { |
| 125 VerifyMarking(it.next()); | 135 VerifyMarking(it.next()); |
| 126 } | 136 } |
| 127 } | 137 } |
| (...skipping 1562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 incremental_marking->marking_deque()->ClearOverflowed(); | 1700 incremental_marking->marking_deque()->ClearOverflowed(); |
| 1691 } else { | 1701 } else { |
| 1692 // Abort any pending incremental activities e.g. incremental sweeping. | 1702 // Abort any pending incremental activities e.g. incremental sweeping. |
| 1693 incremental_marking->Abort(); | 1703 incremental_marking->Abort(); |
| 1694 } | 1704 } |
| 1695 | 1705 |
| 1696 #ifdef DEBUG | 1706 #ifdef DEBUG |
| 1697 ASSERT(state_ == PREPARE_GC); | 1707 ASSERT(state_ == PREPARE_GC); |
| 1698 state_ = MARK_LIVE_OBJECTS; | 1708 state_ = MARK_LIVE_OBJECTS; |
| 1699 #endif | 1709 #endif |
| 1700 // The to space contains live objects, the from space is used as a marking | 1710 // The to space contains live objects, a page in from space is used as a |
| 1701 // stack. | 1711 // marking stack. |
| 1702 Address marking_deque_start = heap()->new_space()->FromSpaceLow(); | 1712 Address marking_deque_start = heap()->new_space()->FromSpacePageLow(); |
| 1703 Address marking_deque_end = heap()->new_space()->FromSpaceHigh(); | 1713 Address marking_deque_end = heap()->new_space()->FromSpaceHigh(); |
| 1704 if (FLAG_force_marking_deque_overflows) { | 1714 if (FLAG_force_marking_deque_overflows) { |
| 1705 marking_deque_end = marking_deque_start + 64 * kPointerSize; | 1715 marking_deque_end = marking_deque_start + 64 * kPointerSize; |
| 1706 } | 1716 } |
| 1707 marking_deque_.Initialize(marking_deque_start, | 1717 marking_deque_.Initialize(marking_deque_start, |
| 1708 marking_deque_end); | 1718 marking_deque_end); |
| 1709 ASSERT(!marking_deque_.overflowed()); | 1719 ASSERT(!marking_deque_.overflowed()); |
| 1710 | 1720 |
| 1711 if (incremental_marking_overflowed) { | 1721 if (incremental_marking_overflowed) { |
| 1712 // There are overflowed objects left in the heap after incremental marking. | 1722 // There are overflowed objects left in the heap after incremental marking. |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 // to new space. We should clear them to avoid encountering them during next | 1930 // to new space. We should clear them to avoid encountering them during next |
| 1921 // pointer iteration. This is an issue if the store buffer overflows and we | 1931 // pointer iteration. This is an issue if the store buffer overflows and we |
| 1922 // have to scan the entire old space, including dead objects, looking for | 1932 // have to scan the entire old space, including dead objects, looking for |
| 1923 // pointers to new space. | 1933 // pointers to new space. |
| 1924 static void MigrateObject(Heap* heap, | 1934 static void MigrateObject(Heap* heap, |
| 1925 Address dst, | 1935 Address dst, |
| 1926 Address src, | 1936 Address src, |
| 1927 int size, | 1937 int size, |
| 1928 bool to_old_space) { | 1938 bool to_old_space) { |
| 1929 if (to_old_space) { | 1939 if (to_old_space) { |
| 1930 HEAP->CopyBlockToOldSpaceAndUpdateWriteBarrier(dst, src, size); | 1940 heap->CopyBlockToOldSpaceAndUpdateWriteBarrier(dst, src, size); |
| 1931 } else { | 1941 } else { |
| 1932 heap->CopyBlock(dst, src, size); | 1942 heap->CopyBlock(dst, src, size); |
| 1933 } | 1943 } |
| 1934 Memory::Address_at(src) = dst; | 1944 Memory::Address_at(src) = dst; |
| 1935 } | 1945 } |
| 1936 | 1946 |
| 1937 | 1947 |
| 1938 class StaticPointersToNewGenUpdatingVisitor : public | 1948 class StaticPointersToNewGenUpdatingVisitor : public |
| 1939 StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> { | 1949 StaticNewSpaceVisitor<StaticPointersToNewGenUpdatingVisitor> { |
| 1940 public: | 1950 public: |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2057 } | 2067 } |
| 2058 } | 2068 } |
| 2059 | 2069 |
| 2060 return false; | 2070 return false; |
| 2061 } | 2071 } |
| 2062 | 2072 |
| 2063 | 2073 |
| 2064 void MarkCompactCollector::SweepNewSpace(NewSpace* space) { | 2074 void MarkCompactCollector::SweepNewSpace(NewSpace* space) { |
| 2065 heap_->CheckNewSpaceExpansionCriteria(); | 2075 heap_->CheckNewSpaceExpansionCriteria(); |
| 2066 | 2076 |
| 2077 // Store allocation range before flipping semispaces. |
| 2067 Address from_bottom = space->bottom(); | 2078 Address from_bottom = space->bottom(); |
| 2068 Address from_top = space->top(); | 2079 Address from_top = space->top(); |
| 2069 | 2080 |
| 2070 // Flip the semispaces. After flipping, to space is empty, from space has | 2081 // Flip the semispaces. After flipping, to space is empty, from space has |
| 2071 // live objects. | 2082 // live objects. |
| 2072 space->Flip(); | 2083 space->Flip(); |
| 2073 space->ResetAllocationInfo(); | 2084 space->ResetAllocationInfo(); |
| 2074 | 2085 |
| 2075 int size = 0; | |
| 2076 int survivors_size = 0; | 2086 int survivors_size = 0; |
| 2077 | 2087 |
| 2078 // First pass: traverse all objects in inactive semispace, remove marks, | 2088 // First pass: traverse all objects in inactive semispace, remove marks, |
| 2079 // migrate live objects and write forwarding addresses. This stage puts | 2089 // migrate live objects and write forwarding addresses. This stage puts |
| 2080 // new entries in the store buffer and may cause some pages to be marked | 2090 // new entries in the store buffer and may cause some pages to be marked |
| 2081 // scan-on-scavenge. | 2091 // scan-on-scavenge. |
| 2082 for (Address current = from_bottom; current < from_top; current += size) { | 2092 SemiSpaceIterator from_it(from_bottom, from_top); |
| 2083 HeapObject* object = HeapObject::FromAddress(current); | 2093 for (HeapObject* object = from_it.Next(); |
| 2084 | 2094 object != NULL; |
| 2095 object = from_it.Next()) { |
| 2085 MarkBit mark_bit = Marking::MarkBitFrom(object); | 2096 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 2086 if (mark_bit.Get()) { | 2097 if (mark_bit.Get()) { |
| 2087 mark_bit.Clear(); | 2098 mark_bit.Clear(); |
| 2088 heap_->mark_compact_collector()->tracer()->decrement_marked_count(); | 2099 heap_->mark_compact_collector()->tracer()->decrement_marked_count(); |
| 2089 | 2100 |
| 2090 size = object->Size(); | 2101 int size = object->Size(); |
| 2091 survivors_size += size; | 2102 survivors_size += size; |
| 2092 | 2103 |
| 2093 // Aggressively promote young survivors to the old space. | 2104 // Aggressively promote young survivors to the old space. |
| 2094 if (TryPromoteObject(heap_, object, size)) { | 2105 if (TryPromoteObject(heap_, object, size)) { |
| 2095 continue; | 2106 continue; |
| 2096 } | 2107 } |
| 2097 | 2108 |
| 2098 // Promotion failed. Just migrate object to another semispace. | 2109 // Promotion failed. Just migrate object to another semispace. |
| 2099 // Allocation cannot fail at this point: semispaces are of equal size. | 2110 MaybeObject* allocation = space->AllocateRaw(size); |
| 2100 Object* target = space->AllocateRaw(size)->ToObjectUnchecked(); | 2111 if (allocation->IsFailure()) { |
| 2101 | 2112 if (!space->AddFreshPage()) { |
| 2113 // Shouldn't happen. We are sweeping linearly, and to-space |
| 2114 // has the same number of pages as from-space, so there is |
| 2115 // always room. |
| 2116 UNREACHABLE(); |
| 2117 } |
| 2118 allocation = space->AllocateRaw(size); |
| 2119 ASSERT(!allocation->IsFailure()); |
| 2120 } |
| 2121 Object* target = allocation->ToObjectUnchecked(); |
| 2102 MigrateObject(heap_, | 2122 MigrateObject(heap_, |
| 2103 HeapObject::cast(target)->address(), | 2123 HeapObject::cast(target)->address(), |
| 2104 current, | 2124 object->address(), |
| 2105 size, | 2125 size, |
| 2106 false); | 2126 false); |
| 2107 } else { | 2127 } else { |
| 2108 // Process the dead object before we write a NULL into its header. | 2128 // Process the dead object before we write a NULL into its header. |
| 2109 LiveObjectList::ProcessNonLive(object); | 2129 LiveObjectList::ProcessNonLive(object); |
| 2110 | 2130 |
| 2111 size = object->Size(); | |
| 2112 // Mark dead objects in the new space with null in their map field. | 2131 // Mark dead objects in the new space with null in their map field. |
| 2113 Memory::Address_at(current) = NULL; | 2132 Memory::Address_at(object->address()) = NULL; |
| 2114 } | 2133 } |
| 2115 } | 2134 } |
| 2116 | 2135 |
| 2117 // Second pass: find pointers to new space and update them. | 2136 // Second pass: find pointers to new space and update them. |
| 2118 PointersToNewGenUpdatingVisitor updating_visitor(heap_); | 2137 PointersToNewGenUpdatingVisitor updating_visitor(heap_); |
| 2119 | 2138 |
| 2120 // Update pointers in to space. | 2139 // Update pointers in to space. |
| 2121 Address current = space->bottom(); | 2140 SemiSpaceIterator to_it(space->bottom(), space->top()); |
| 2122 while (current < space->top()) { | 2141 for (HeapObject* object = to_it.Next(); |
| 2123 HeapObject* object = HeapObject::FromAddress(current); | 2142 object != NULL; |
| 2124 current += | 2143 object = to_it.Next()) { |
| 2125 StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(), | 2144 StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(), |
| 2126 object); | 2145 object); |
| 2127 } | 2146 } |
| 2128 | 2147 |
| 2129 // Update roots. | 2148 // Update roots. |
| 2130 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 2149 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 2131 LiveObjectList::IterateElements(&updating_visitor); | 2150 LiveObjectList::IterateElements(&updating_visitor); |
| 2132 | 2151 |
| 2133 { | 2152 { |
| 2134 StoreBufferRebuildScope scope(heap_, | 2153 StoreBufferRebuildScope scope(heap_, |
| 2135 heap_->store_buffer(), | 2154 heap_->store_buffer(), |
| 2136 &Heap::ScavengeStoreBufferCallback); | 2155 &Heap::ScavengeStoreBufferCallback); |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2713 live_objects_size += size; | 2732 live_objects_size += size; |
| 2714 } | 2733 } |
| 2715 } | 2734 } |
| 2716 return live_objects_size; | 2735 return live_objects_size; |
| 2717 } | 2736 } |
| 2718 | 2737 |
| 2719 | 2738 |
| 2720 int MarkCompactCollector::IterateLiveObjects( | 2739 int MarkCompactCollector::IterateLiveObjects( |
| 2721 NewSpace* space, LiveObjectCallback size_f) { | 2740 NewSpace* space, LiveObjectCallback size_f) { |
| 2722 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); | 2741 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); |
| 2723 return IterateLiveObjectsInRange(space->bottom(), space->top(), size_f); | 2742 int accumulator = 0; |
| 2743 Address end = space->top(); |
| 2744 NewSpacePageIterator it(space->bottom(), end); |
| 2745 // The bottom is at the start of its page. |
| 2746 ASSERT_EQ(space->bottom(), |
| 2747 NewSpacePage::FromAddress(space->bottom())->body()); |
| 2748 while (it.has_next()) { |
| 2749 NewSpacePage* page = it.next(); |
| 2750 Address start = page->body(); |
| 2751 Address limit = it.has_next() ? page->body_limit() : end; |
| 2752 accumulator += IterateLiveObjectsInRange(start, limit, size_f); |
| 2753 } |
| 2754 return accumulator; |
| 2724 } | 2755 } |
| 2725 | 2756 |
| 2726 | 2757 |
| 2727 int MarkCompactCollector::IterateLiveObjects( | 2758 int MarkCompactCollector::IterateLiveObjects( |
| 2728 PagedSpace* space, LiveObjectCallback size_f) { | 2759 PagedSpace* space, LiveObjectCallback size_f) { |
| 2729 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); | 2760 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS); |
| 2730 // TODO(gc): Do a mark-sweep first with precise sweeping. | 2761 // TODO(gc): Do a mark-sweep first with precise sweeping. |
| 2731 int total = 0; | 2762 int total = 0; |
| 2732 PageIterator it(space); | 2763 PageIterator it(space); |
| 2733 while (it.has_next()) { | 2764 while (it.has_next()) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2770 } | 2801 } |
| 2771 | 2802 |
| 2772 | 2803 |
| 2773 void MarkCompactCollector::Initialize() { | 2804 void MarkCompactCollector::Initialize() { |
| 2774 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 2805 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
| 2775 StaticMarkingVisitor::Initialize(); | 2806 StaticMarkingVisitor::Initialize(); |
| 2776 } | 2807 } |
| 2777 | 2808 |
| 2778 | 2809 |
| 2779 } } // namespace v8::internal | 2810 } } // namespace v8::internal |
| OLD | NEW |