| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 12 matching lines...) Expand all Loading... |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "compilation-cache.h" | 30 #include "compilation-cache.h" |
| 31 #include "execution.h" | 31 #include "execution.h" |
| 32 #include "heap-profiler.h" | 32 #include "heap-profiler.h" |
| 33 #include "gdb-jit.h" |
| 33 #include "global-handles.h" | 34 #include "global-handles.h" |
| 34 #include "ic-inl.h" | 35 #include "ic-inl.h" |
| 36 #include "liveobjectlist-inl.h" |
| 35 #include "mark-compact.h" | 37 #include "mark-compact.h" |
| 36 #include "objects-visiting.h" | 38 #include "objects-visiting.h" |
| 37 #include "stub-cache.h" | 39 #include "stub-cache.h" |
| 38 | 40 |
| 39 namespace v8 { | 41 namespace v8 { |
| 40 namespace internal { | 42 namespace internal { |
| 41 | 43 |
| 42 // ------------------------------------------------------------------------- | 44 // ------------------------------------------------------------------------- |
| 43 // MarkCompactCollector | 45 // MarkCompactCollector |
| 44 | 46 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 ASSERT(!FLAG_always_compact || !FLAG_never_compact); | 119 ASSERT(!FLAG_always_compact || !FLAG_never_compact); |
| 118 | 120 |
| 119 compacting_collection_ = | 121 compacting_collection_ = |
| 120 FLAG_always_compact || force_compaction_ || compact_on_next_gc_; | 122 FLAG_always_compact || force_compaction_ || compact_on_next_gc_; |
| 121 compact_on_next_gc_ = false; | 123 compact_on_next_gc_ = false; |
| 122 | 124 |
| 123 if (FLAG_never_compact) compacting_collection_ = false; | 125 if (FLAG_never_compact) compacting_collection_ = false; |
| 124 if (!HEAP->map_space()->MapPointersEncodable()) | 126 if (!HEAP->map_space()->MapPointersEncodable()) |
| 125 compacting_collection_ = false; | 127 compacting_collection_ = false; |
| 126 if (FLAG_collect_maps) CreateBackPointers(); | 128 if (FLAG_collect_maps) CreateBackPointers(); |
| 129 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 130 if (FLAG_gdbjit) { |
| 131 // If GDBJIT interface is active disable compaction. |
| 132 compacting_collection_ = false; |
| 133 } |
| 134 #endif |
| 127 | 135 |
| 128 PagedSpaces spaces; | 136 PagedSpaces spaces; |
| 129 for (PagedSpace* space = spaces.next(); | 137 for (PagedSpace* space = spaces.next(); |
| 130 space != NULL; space = spaces.next()) { | 138 space != NULL; space = spaces.next()) { |
| 131 space->PrepareForMarkCompact(compacting_collection_); | 139 space->PrepareForMarkCompact(compacting_collection_); |
| 132 } | 140 } |
| 133 | 141 |
| 134 #ifdef DEBUG | 142 #ifdef DEBUG |
| 135 live_bytes_ = 0; | 143 live_bytes_ = 0; |
| 136 live_young_objects_size_ = 0; | 144 live_young_objects_size_ = 0; |
| (...skipping 1563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 EncodeFreeRegion(free_start, static_cast<int>(current - free_start)); | 1708 EncodeFreeRegion(free_start, static_cast<int>(current - free_start)); |
| 1701 is_prev_alive = true; | 1709 is_prev_alive = true; |
| 1702 } | 1710 } |
| 1703 } else { // Non-live object. | 1711 } else { // Non-live object. |
| 1704 object_size = object->Size(); | 1712 object_size = object->Size(); |
| 1705 ProcessNonLive(object); | 1713 ProcessNonLive(object); |
| 1706 if (is_prev_alive) { // Transition from live to non-live. | 1714 if (is_prev_alive) { // Transition from live to non-live. |
| 1707 free_start = current; | 1715 free_start = current; |
| 1708 is_prev_alive = false; | 1716 is_prev_alive = false; |
| 1709 } | 1717 } |
| 1718 LiveObjectList::ProcessNonLive(object); |
| 1710 } | 1719 } |
| 1711 } | 1720 } |
| 1712 | 1721 |
| 1713 // If we ended on a free region, mark it. | 1722 // If we ended on a free region, mark it. |
| 1714 if (!is_prev_alive) { | 1723 if (!is_prev_alive) { |
| 1715 EncodeFreeRegion(free_start, static_cast<int>(end - free_start)); | 1724 EncodeFreeRegion(free_start, static_cast<int>(end - free_start)); |
| 1716 } | 1725 } |
| 1717 } | 1726 } |
| 1718 | 1727 |
| 1719 | 1728 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1931 // Promotion failed. Just migrate object to another semispace. | 1940 // Promotion failed. Just migrate object to another semispace. |
| 1932 // Allocation cannot fail at this point: semispaces are of equal size. | 1941 // Allocation cannot fail at this point: semispaces are of equal size. |
| 1933 Object* target = space->AllocateRaw(size)->ToObjectUnchecked(); | 1942 Object* target = space->AllocateRaw(size)->ToObjectUnchecked(); |
| 1934 | 1943 |
| 1935 MigrateObject(heap, | 1944 MigrateObject(heap, |
| 1936 HeapObject::cast(target)->address(), | 1945 HeapObject::cast(target)->address(), |
| 1937 current, | 1946 current, |
| 1938 size, | 1947 size, |
| 1939 false); | 1948 false); |
| 1940 } else { | 1949 } else { |
| 1950 // Process the dead object before we write a NULL into its header. |
| 1951 LiveObjectList::ProcessNonLive(object); |
| 1952 |
| 1941 size = object->Size(); | 1953 size = object->Size(); |
| 1942 Memory::Address_at(current) = NULL; | 1954 Memory::Address_at(current) = NULL; |
| 1943 } | 1955 } |
| 1944 } | 1956 } |
| 1945 | 1957 |
| 1946 // Second pass: find pointers to new space and update them. | 1958 // Second pass: find pointers to new space and update them. |
| 1947 PointersToNewGenUpdatingVisitor updating_visitor(heap); | 1959 PointersToNewGenUpdatingVisitor updating_visitor(heap); |
| 1948 | 1960 |
| 1949 // Update pointers in to space. | 1961 // Update pointers in to space. |
| 1950 Address current = space->bottom(); | 1962 Address current = space->bottom(); |
| 1951 while (current < space->top()) { | 1963 while (current < space->top()) { |
| 1952 HeapObject* object = HeapObject::FromAddress(current); | 1964 HeapObject* object = HeapObject::FromAddress(current); |
| 1953 current += | 1965 current += |
| 1954 StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(), | 1966 StaticPointersToNewGenUpdatingVisitor::IterateBody(object->map(), |
| 1955 object); | 1967 object); |
| 1956 } | 1968 } |
| 1957 | 1969 |
| 1958 // Update roots. | 1970 // Update roots. |
| 1959 heap->IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE); | 1971 heap->IterateRoots(&updating_visitor, VISIT_ALL_IN_SCAVENGE); |
| 1972 LiveObjectList::IterateElements(&updating_visitor); |
| 1960 | 1973 |
| 1961 // Update pointers in old spaces. | 1974 // Update pointers in old spaces. |
| 1962 heap->IterateDirtyRegions(heap->old_pointer_space(), | 1975 heap->IterateDirtyRegions(heap->old_pointer_space(), |
| 1963 &Heap::IteratePointersInDirtyRegion, | 1976 &Heap::IteratePointersInDirtyRegion, |
| 1964 &UpdatePointerToNewGen, | 1977 &UpdatePointerToNewGen, |
| 1965 heap->WATERMARK_SHOULD_BE_VALID); | 1978 heap->WATERMARK_SHOULD_BE_VALID); |
| 1966 | 1979 |
| 1967 heap->lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen); | 1980 heap->lo_space()->IterateDirtyRegions(&UpdatePointerToNewGen); |
| 1968 | 1981 |
| 1969 // Update pointers from cells. | 1982 // Update pointers from cells. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2037 static_cast<int>(current - free_start), | 2050 static_cast<int>(current - free_start), |
| 2038 true); | 2051 true); |
| 2039 is_previous_alive = true; | 2052 is_previous_alive = true; |
| 2040 } | 2053 } |
| 2041 } else { | 2054 } else { |
| 2042 heap->mark_compact_collector()->ReportDeleteIfNeeded(object); | 2055 heap->mark_compact_collector()->ReportDeleteIfNeeded(object); |
| 2043 if (is_previous_alive) { // Transition from live to free. | 2056 if (is_previous_alive) { // Transition from live to free. |
| 2044 free_start = current; | 2057 free_start = current; |
| 2045 is_previous_alive = false; | 2058 is_previous_alive = false; |
| 2046 } | 2059 } |
| 2060 LiveObjectList::ProcessNonLive(object); |
| 2047 } | 2061 } |
| 2048 // The object is now unmarked for the call to Size() at the top of the | 2062 // The object is now unmarked for the call to Size() at the top of the |
| 2049 // loop. | 2063 // loop. |
| 2050 } | 2064 } |
| 2051 | 2065 |
| 2052 bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop()) | 2066 bool page_is_empty = (p->ObjectAreaStart() == p->AllocationTop()) |
| 2053 || (!is_previous_alive && free_start == p->ObjectAreaStart()); | 2067 || (!is_previous_alive && free_start == p->ObjectAreaStart()); |
| 2054 | 2068 |
| 2055 if (page_is_empty) { | 2069 if (page_is_empty) { |
| 2056 // This page is empty. Check whether we are in the middle of | 2070 // This page is empty. Check whether we are in the middle of |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2217 | 2231 |
| 2218 #ifdef DEBUG | 2232 #ifdef DEBUG |
| 2219 CheckNoMapsToEvacuate(); | 2233 CheckNoMapsToEvacuate(); |
| 2220 #endif | 2234 #endif |
| 2221 } | 2235 } |
| 2222 | 2236 |
| 2223 void UpdateMapPointersInRoots() { | 2237 void UpdateMapPointersInRoots() { |
| 2224 MapUpdatingVisitor map_updating_visitor; | 2238 MapUpdatingVisitor map_updating_visitor; |
| 2225 heap_->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG); | 2239 heap_->IterateRoots(&map_updating_visitor, VISIT_ONLY_STRONG); |
| 2226 heap_->isolate_->global_handles()->IterateWeakRoots(&map_updating_visitor); | 2240 heap_->isolate_->global_handles()->IterateWeakRoots(&map_updating_visitor); |
| 2241 LiveObjectList::IterateElements(&map_updating_visitor); |
| 2227 } | 2242 } |
| 2228 | 2243 |
| 2229 void UpdateMapPointersInPagedSpace(PagedSpace* space) { | 2244 void UpdateMapPointersInPagedSpace(PagedSpace* space) { |
| 2230 ASSERT(space != heap_->map_space()); | 2245 ASSERT(space != heap_->map_space()); |
| 2231 | 2246 |
| 2232 PageIterator it(space, PageIterator::PAGES_IN_USE); | 2247 PageIterator it(space, PageIterator::PAGES_IN_USE); |
| 2233 while (it.has_next()) { | 2248 while (it.has_next()) { |
| 2234 Page* p = it.next(); | 2249 Page* p = it.next(); |
| 2235 UpdateMapPointersInRange(heap_, p->ObjectAreaStart(), p->AllocationTop()); | 2250 UpdateMapPointersInRange(heap_, p->ObjectAreaStart(), p->AllocationTop()); |
| 2236 } | 2251 } |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2589 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); | 2604 ASSERT(state_ == ENCODE_FORWARDING_ADDRESSES); |
| 2590 state_ = UPDATE_POINTERS; | 2605 state_ = UPDATE_POINTERS; |
| 2591 #endif | 2606 #endif |
| 2592 UpdatingVisitor updating_visitor(heap_); | 2607 UpdatingVisitor updating_visitor(heap_); |
| 2593 heap_->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); | 2608 heap_->IterateRoots(&updating_visitor, VISIT_ONLY_STRONG); |
| 2594 heap_->isolate_->global_handles()->IterateWeakRoots(&updating_visitor); | 2609 heap_->isolate_->global_handles()->IterateWeakRoots(&updating_visitor); |
| 2595 | 2610 |
| 2596 // Update the pointer to the head of the weak list of global contexts. | 2611 // Update the pointer to the head of the weak list of global contexts. |
| 2597 updating_visitor.VisitPointer(&heap_->global_contexts_list_); | 2612 updating_visitor.VisitPointer(&heap_->global_contexts_list_); |
| 2598 | 2613 |
| 2614 LiveObjectList::IterateElements(&updating_visitor); |
| 2615 |
| 2599 int live_maps_size = IterateLiveObjects( | 2616 int live_maps_size = IterateLiveObjects( |
| 2600 heap_->map_space(), &MarkCompactCollector::UpdatePointersInOldObject); | 2617 heap_->map_space(), &MarkCompactCollector::UpdatePointersInOldObject); |
| 2601 int live_pointer_olds_size = IterateLiveObjects( | 2618 int live_pointer_olds_size = IterateLiveObjects( |
| 2602 heap_->old_pointer_space(), | 2619 heap_->old_pointer_space(), |
| 2603 &MarkCompactCollector::UpdatePointersInOldObject); | 2620 &MarkCompactCollector::UpdatePointersInOldObject); |
| 2604 int live_data_olds_size = IterateLiveObjects( | 2621 int live_data_olds_size = IterateLiveObjects( |
| 2605 heap_->old_data_space(), | 2622 heap_->old_data_space(), |
| 2606 &MarkCompactCollector::UpdatePointersInOldObject); | 2623 &MarkCompactCollector::UpdatePointersInOldObject); |
| 2607 int live_codes_size = IterateLiveObjects( | 2624 int live_codes_size = IterateLiveObjects( |
| 2608 heap_->code_space(), &MarkCompactCollector::UpdatePointersInOldObject); | 2625 heap_->code_space(), &MarkCompactCollector::UpdatePointersInOldObject); |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2984 code_flusher_ = new CodeFlusher(heap_->isolate()); | 3001 code_flusher_ = new CodeFlusher(heap_->isolate()); |
| 2985 } else { | 3002 } else { |
| 2986 if (code_flusher_ == NULL) return; | 3003 if (code_flusher_ == NULL) return; |
| 2987 delete code_flusher_; | 3004 delete code_flusher_; |
| 2988 code_flusher_ = NULL; | 3005 code_flusher_ = NULL; |
| 2989 } | 3006 } |
| 2990 } | 3007 } |
| 2991 | 3008 |
| 2992 | 3009 |
| 2993 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) { | 3010 void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) { |
| 3011 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 3012 if (obj->IsCode()) { |
| 3013 GDBJITInterface::RemoveCode(reinterpret_cast<Code*>(obj)); |
| 3014 } |
| 3015 #endif |
| 2994 #ifdef ENABLE_LOGGING_AND_PROFILING | 3016 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 2995 if (obj->IsCode()) { | 3017 if (obj->IsCode()) { |
| 2996 PROFILE(CodeDeleteEvent(obj->address())); | 3018 PROFILE(CodeDeleteEvent(obj->address())); |
| 2997 } else if (obj->IsJSFunction()) { | 3019 } else if (obj->IsJSFunction()) { |
| 2998 PROFILE(FunctionDeleteEvent(obj->address())); | 3020 PROFILE(FunctionDeleteEvent(obj->address())); |
| 2999 } | 3021 } |
| 3000 #endif | 3022 #endif |
| 3001 } | 3023 } |
| 3002 | 3024 |
| 3003 | 3025 |
| 3004 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) { | 3026 int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) { |
| 3005 MapWord map_word = obj->map_word(); | 3027 MapWord map_word = obj->map_word(); |
| 3006 map_word.ClearMark(); | 3028 map_word.ClearMark(); |
| 3007 return obj->SizeFromMap(map_word.ToMap()); | 3029 return obj->SizeFromMap(map_word.ToMap()); |
| 3008 } | 3030 } |
| 3009 | 3031 |
| 3010 | 3032 |
| 3011 void MarkCompactCollector::Initialize() { | 3033 void MarkCompactCollector::Initialize() { |
| 3012 StaticPointersToNewGenUpdatingVisitor::Initialize(); | 3034 StaticPointersToNewGenUpdatingVisitor::Initialize(); |
| 3013 StaticMarkingVisitor::Initialize(); | 3035 StaticMarkingVisitor::Initialize(); |
| 3014 } | 3036 } |
| 3015 | 3037 |
| 3016 | 3038 |
| 3017 } } // namespace v8::internal | 3039 } } // namespace v8::internal |
| OLD | NEW |