| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
| 6 | 6 |
| 7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 compacting_ = evacuation_candidates_.length() > 0; | 304 compacting_ = evacuation_candidates_.length() > 0; |
| 305 } | 305 } |
| 306 | 306 |
| 307 return compacting_; | 307 return compacting_; |
| 308 } | 308 } |
| 309 | 309 |
| 310 | 310 |
| 311 void MarkCompactCollector::ClearInvalidStoreAndSlotsBufferEntries() { | 311 void MarkCompactCollector::ClearInvalidStoreAndSlotsBufferEntries() { |
| 312 { | 312 { |
| 313 GCTracer::Scope gc_scope(heap()->tracer(), | 313 GCTracer::Scope gc_scope(heap()->tracer(), |
| 314 GCTracer::Scope::MC_STORE_BUFFER_CLEAR); | 314 GCTracer::Scope::MC_CLEAR_STORE_BUFFER); |
| 315 heap_->store_buffer()->ClearInvalidStoreBufferEntries(); | 315 heap_->store_buffer()->ClearInvalidStoreBufferEntries(); |
| 316 } | 316 } |
| 317 | 317 |
| 318 { | 318 { |
| 319 GCTracer::Scope gc_scope(heap()->tracer(), | 319 GCTracer::Scope gc_scope(heap()->tracer(), |
| 320 GCTracer::Scope::MC_SLOTS_BUFFER_CLEAR); | 320 GCTracer::Scope::MC_CLEAR_SLOTS_BUFFER); |
| 321 int number_of_pages = evacuation_candidates_.length(); | 321 int number_of_pages = evacuation_candidates_.length(); |
| 322 for (int i = 0; i < number_of_pages; i++) { | 322 for (int i = 0; i < number_of_pages; i++) { |
| 323 Page* p = evacuation_candidates_[i]; | 323 Page* p = evacuation_candidates_[i]; |
| 324 SlotsBuffer::RemoveInvalidSlots(heap_, p->slots_buffer()); | 324 SlotsBuffer::RemoveInvalidSlots(heap_, p->slots_buffer()); |
| 325 } | 325 } |
| 326 } | 326 } |
| 327 #ifdef VERIFY_HEAP |
| 328 if (FLAG_verify_heap) { |
| 329 VerifyValidStoreAndSlotsBufferEntries(); |
| 330 } |
| 331 #endif |
| 327 } | 332 } |
| 328 | 333 |
| 329 | 334 |
| 330 #ifdef VERIFY_HEAP | 335 #ifdef VERIFY_HEAP |
| 331 static void VerifyValidSlotsBufferEntries(Heap* heap, PagedSpace* space) { | 336 static void VerifyValidSlotsBufferEntries(Heap* heap, PagedSpace* space) { |
| 332 PageIterator it(space); | 337 PageIterator it(space); |
| 333 while (it.has_next()) { | 338 while (it.has_next()) { |
| 334 Page* p = it.next(); | 339 Page* p = it.next(); |
| 335 SlotsBuffer::VerifySlots(heap, p->slots_buffer()); | 340 SlotsBuffer::VerifySlots(heap, p->slots_buffer()); |
| 336 } | 341 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 357 // Make sure that Prepare() has been called. The individual steps below will | 362 // Make sure that Prepare() has been called. The individual steps below will |
| 358 // update the state as they proceed. | 363 // update the state as they proceed. |
| 359 DCHECK(state_ == PREPARE_GC); | 364 DCHECK(state_ == PREPARE_GC); |
| 360 | 365 |
| 361 MarkLiveObjects(); | 366 MarkLiveObjects(); |
| 362 | 367 |
| 363 DCHECK(heap_->incremental_marking()->IsStopped()); | 368 DCHECK(heap_->incremental_marking()->IsStopped()); |
| 364 | 369 |
| 365 ClearNonLiveReferences(); | 370 ClearNonLiveReferences(); |
| 366 | 371 |
| 367 ClearWeakCollections(); | |
| 368 | |
| 369 #ifdef VERIFY_HEAP | 372 #ifdef VERIFY_HEAP |
| 370 if (FLAG_verify_heap) { | 373 if (FLAG_verify_heap) { |
| 371 VerifyMarking(heap_); | 374 VerifyMarking(heap_); |
| 372 } | 375 } |
| 373 #endif | 376 #endif |
| 374 | 377 |
| 375 ClearInvalidStoreAndSlotsBufferEntries(); | |
| 376 | |
| 377 #ifdef VERIFY_HEAP | |
| 378 if (FLAG_verify_heap) { | |
| 379 VerifyValidStoreAndSlotsBufferEntries(); | |
| 380 } | |
| 381 #endif | |
| 382 | |
| 383 SweepSpaces(); | 378 SweepSpaces(); |
| 384 | 379 |
| 380 EvacuateNewSpaceAndCandidates(); |
| 381 |
| 385 Finish(); | 382 Finish(); |
| 386 | |
| 387 if (marking_parity_ == EVEN_MARKING_PARITY) { | |
| 388 marking_parity_ = ODD_MARKING_PARITY; | |
| 389 } else { | |
| 390 DCHECK(marking_parity_ == ODD_MARKING_PARITY); | |
| 391 marking_parity_ = EVEN_MARKING_PARITY; | |
| 392 } | |
| 393 } | 383 } |
| 394 | 384 |
| 395 | 385 |
| 396 #ifdef VERIFY_HEAP | 386 #ifdef VERIFY_HEAP |
| 397 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { | 387 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { |
| 398 PageIterator it(space); | 388 PageIterator it(space); |
| 399 | 389 |
| 400 while (it.has_next()) { | 390 while (it.has_next()) { |
| 401 Page* p = it.next(); | 391 Page* p = it.next(); |
| 402 CHECK(p->markbits()->IsClean()); | 392 CHECK(p->markbits()->IsClean()); |
| (...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 860 | 850 |
| 861 #ifdef VERIFY_HEAP | 851 #ifdef VERIFY_HEAP |
| 862 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 852 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
| 863 VerifyMarkbitsAreClean(); | 853 VerifyMarkbitsAreClean(); |
| 864 } | 854 } |
| 865 #endif | 855 #endif |
| 866 } | 856 } |
| 867 | 857 |
| 868 | 858 |
| 869 void MarkCompactCollector::Finish() { | 859 void MarkCompactCollector::Finish() { |
| 860 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_FINISH); |
| 861 |
| 862 // The hashing of weak_object_to_code_table is no longer valid. |
| 863 heap()->weak_object_to_code_table()->Rehash( |
| 864 heap()->isolate()->factory()->undefined_value()); |
| 865 |
| 866 // Clear the marking state of live large objects. |
| 867 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); |
| 868 |
| 870 #ifdef DEBUG | 869 #ifdef DEBUG |
| 871 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 870 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
| 872 state_ = IDLE; | 871 state_ = IDLE; |
| 873 #endif | 872 #endif |
| 873 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); |
| 874 |
| 874 // The stub cache is not traversed during GC; clear the cache to | 875 // The stub cache is not traversed during GC; clear the cache to |
| 875 // force lazy re-initialization of it. This must be done after the | 876 // force lazy re-initialization of it. This must be done after the |
| 876 // GC, because it relies on the new address of certain old space | 877 // GC, because it relies on the new address of certain old space |
| 877 // objects (empty string, illegal builtin). | 878 // objects (empty string, illegal builtin). |
| 878 isolate()->stub_cache()->Clear(); | 879 isolate()->stub_cache()->Clear(); |
| 879 | 880 |
| 880 if (have_code_to_deoptimize_) { | 881 if (have_code_to_deoptimize_) { |
| 881 // Some code objects were marked for deoptimization during the GC. | 882 // Some code objects were marked for deoptimization during the GC. |
| 882 Deoptimizer::DeoptimizeMarkedCode(isolate()); | 883 Deoptimizer::DeoptimizeMarkedCode(isolate()); |
| 883 have_code_to_deoptimize_ = false; | 884 have_code_to_deoptimize_ = false; |
| 884 } | 885 } |
| 885 | 886 |
| 886 heap_->incremental_marking()->ClearIdleMarkingDelayCounter(); | 887 heap_->incremental_marking()->ClearIdleMarkingDelayCounter(); |
| 888 |
| 889 if (marking_parity_ == EVEN_MARKING_PARITY) { |
| 890 marking_parity_ = ODD_MARKING_PARITY; |
| 891 } else { |
| 892 DCHECK(marking_parity_ == ODD_MARKING_PARITY); |
| 893 marking_parity_ = EVEN_MARKING_PARITY; |
| 894 } |
| 887 } | 895 } |
| 888 | 896 |
| 889 | 897 |
| 890 // ------------------------------------------------------------------------- | 898 // ------------------------------------------------------------------------- |
| 891 // Phase 1: tracing and marking live objects. | 899 // Phase 1: tracing and marking live objects. |
| 892 // before: all objects are in normal state. | 900 // before: all objects are in normal state. |
| 893 // after: a live object's map pointer is marked as '00'. | 901 // after: a live object's map pointer is marked as '00'. |
| 894 | 902 |
| 895 // Marking all live objects in the heap as part of mark-sweep or mark-compact | 903 // Marking all live objects in the heap as part of mark-sweep or mark-compact |
| 896 // collection. Before marking, all objects are in their normal state. After | 904 // collection. Before marking, all objects are in their normal state. After |
| (...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1962 | 1970 |
| 1963 { | 1971 { |
| 1964 GCTracer::Scope gc_scope(heap()->tracer(), | 1972 GCTracer::Scope gc_scope(heap()->tracer(), |
| 1965 GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); | 1973 GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); |
| 1966 PrepareForCodeFlushing(); | 1974 PrepareForCodeFlushing(); |
| 1967 } | 1975 } |
| 1968 | 1976 |
| 1969 RootMarkingVisitor root_visitor(heap()); | 1977 RootMarkingVisitor root_visitor(heap()); |
| 1970 | 1978 |
| 1971 { | 1979 { |
| 1972 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOT); | 1980 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS); |
| 1973 MarkRoots(&root_visitor); | 1981 MarkRoots(&root_visitor); |
| 1974 } | |
| 1975 | |
| 1976 { | |
| 1977 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_TOPOPT); | |
| 1978 ProcessTopOptimizedFrame(&root_visitor); | 1982 ProcessTopOptimizedFrame(&root_visitor); |
| 1979 } | 1983 } |
| 1980 | 1984 |
| 1981 { | 1985 { |
| 1982 GCTracer::Scope gc_scope(heap()->tracer(), | 1986 GCTracer::Scope gc_scope(heap()->tracer(), |
| 1983 GCTracer::Scope::MC_MARK_WEAK_CLOSURE); | 1987 GCTracer::Scope::MC_MARK_WEAK_CLOSURE); |
| 1984 | 1988 |
| 1985 // The objects reachable from the roots are marked, yet unreachable | 1989 // The objects reachable from the roots are marked, yet unreachable |
| 1986 // objects are unmarked. Mark objects reachable due to host | 1990 // objects are unmarked. Mark objects reachable due to host |
| 1987 // application specific logic or through Harmony weak maps. | 1991 // application specific logic or through Harmony weak maps. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2001 ProcessMarkingDeque(); | 2005 ProcessMarkingDeque(); |
| 2002 | 2006 |
| 2003 // Repeat Harmony weak maps marking to mark unmarked objects reachable from | 2007 // Repeat Harmony weak maps marking to mark unmarked objects reachable from |
| 2004 // the weak roots we just marked as pending destruction. | 2008 // the weak roots we just marked as pending destruction. |
| 2005 // | 2009 // |
| 2006 // We only process harmony collections, as all object groups have been fully | 2010 // We only process harmony collections, as all object groups have been fully |
| 2007 // processed and no weakly reachable node can discover new objects groups. | 2011 // processed and no weakly reachable node can discover new objects groups. |
| 2008 ProcessEphemeralMarking(&root_visitor, true); | 2012 ProcessEphemeralMarking(&root_visitor, true); |
| 2009 } | 2013 } |
| 2010 | 2014 |
| 2011 AfterMarking(); | |
| 2012 | |
| 2013 if (FLAG_print_cumulative_gc_stat) { | 2015 if (FLAG_print_cumulative_gc_stat) { |
| 2014 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 2016 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
| 2015 start_time); | 2017 start_time); |
| 2016 } | 2018 } |
| 2019 if (FLAG_track_gc_object_stats) { |
| 2020 if (FLAG_trace_gc_object_stats) { |
| 2021 heap()->object_stats_->TraceObjectStats(); |
| 2022 } |
| 2023 heap()->object_stats_->CheckpointObjectStats(); |
| 2024 } |
| 2017 } | 2025 } |
| 2018 | 2026 |
| 2019 | 2027 |
| 2020 void MarkCompactCollector::AfterMarking() { | 2028 void MarkCompactCollector::ClearNonLiveReferences() { |
| 2029 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
| 2030 |
| 2021 { | 2031 { |
| 2022 GCTracer::Scope gc_scope(heap()->tracer(), | 2032 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2023 GCTracer::Scope::MC_MARK_STRING_TABLE); | 2033 GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
| 2024 | 2034 |
| 2025 // Prune the string table removing all strings only pointed to by the | 2035 // Prune the string table removing all strings only pointed to by the |
| 2026 // string table. Cannot use string_table() here because the string | 2036 // string table. Cannot use string_table() here because the string |
| 2027 // table is marked. | 2037 // table is marked. |
| 2028 StringTable* string_table = heap()->string_table(); | 2038 StringTable* string_table = heap()->string_table(); |
| 2029 InternalizedStringTableCleaner internalized_visitor(heap()); | 2039 InternalizedStringTableCleaner internalized_visitor(heap()); |
| 2030 string_table->IterateElements(&internalized_visitor); | 2040 string_table->IterateElements(&internalized_visitor); |
| 2031 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); | 2041 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); |
| 2032 | 2042 |
| 2033 ExternalStringTableCleaner external_visitor(heap()); | 2043 ExternalStringTableCleaner external_visitor(heap()); |
| 2034 heap()->external_string_table_.Iterate(&external_visitor); | 2044 heap()->external_string_table_.Iterate(&external_visitor); |
| 2035 heap()->external_string_table_.CleanUp(); | 2045 heap()->external_string_table_.CleanUp(); |
| 2036 } | 2046 } |
| 2037 | 2047 |
| 2038 { | 2048 { |
| 2039 GCTracer::Scope gc_scope(heap()->tracer(), | 2049 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2040 GCTracer::Scope::MC_MARK_WEAK_REFERENCES); | 2050 GCTracer::Scope::MC_CLEAR_WEAK_LISTS); |
| 2041 | |
| 2042 // Process the weak references. | 2051 // Process the weak references. |
| 2043 MarkCompactWeakObjectRetainer mark_compact_object_retainer; | 2052 MarkCompactWeakObjectRetainer mark_compact_object_retainer; |
| 2044 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); | 2053 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); |
| 2045 } | 2054 } |
| 2046 | 2055 |
| 2047 { | 2056 { |
| 2048 GCTracer::Scope gc_scope(heap()->tracer(), | 2057 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2049 GCTracer::Scope::MC_MARK_GLOBAL_HANDLES); | 2058 GCTracer::Scope::MC_CLEAR_GLOBAL_HANDLES); |
| 2050 | 2059 |
| 2051 // Remove object groups after marking phase. | 2060 // Remove object groups after marking phase. |
| 2052 heap()->isolate()->global_handles()->RemoveObjectGroups(); | 2061 heap()->isolate()->global_handles()->RemoveObjectGroups(); |
| 2053 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); | 2062 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); |
| 2054 } | 2063 } |
| 2055 | 2064 |
| 2056 // Flush code from collected candidates. | 2065 // Flush code from collected candidates. |
| 2057 if (is_code_flushing_enabled()) { | 2066 if (is_code_flushing_enabled()) { |
| 2058 GCTracer::Scope gc_scope(heap()->tracer(), | 2067 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2059 GCTracer::Scope::MC_MARK_CODE_FLUSH); | 2068 GCTracer::Scope::MC_CLEAR_CODE_FLUSH); |
| 2060 code_flusher_->ProcessCandidates(); | 2069 code_flusher_->ProcessCandidates(); |
| 2061 } | 2070 } |
| 2062 | 2071 |
| 2063 if (FLAG_track_gc_object_stats) { | |
| 2064 if (FLAG_trace_gc_object_stats) { | |
| 2065 heap()->object_stats_->TraceObjectStats(); | |
| 2066 } | |
| 2067 heap()->object_stats_->CheckpointObjectStats(); | |
| 2068 } | |
| 2069 } | |
| 2070 | |
| 2071 | |
| 2072 void MarkCompactCollector::ClearNonLiveReferences() { | |
| 2073 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | |
| 2074 | 2072 |
| 2075 DependentCode* dependent_code_list; | 2073 DependentCode* dependent_code_list; |
| 2076 Object* non_live_map_list; | 2074 Object* non_live_map_list; |
| 2077 ClearWeakCells(&non_live_map_list, &dependent_code_list); | 2075 ClearWeakCells(&non_live_map_list, &dependent_code_list); |
| 2078 | 2076 |
| 2079 { | 2077 { |
| 2080 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAP); | 2078 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAPS); |
| 2081 ClearSimpleMapTransitions(non_live_map_list); | 2079 ClearSimpleMapTransitions(non_live_map_list); |
| 2082 ClearFullMapTransitions(); | 2080 ClearFullMapTransitions(); |
| 2083 } | 2081 } |
| 2084 | 2082 |
| 2085 MarkDependentCodeForDeoptimization(dependent_code_list); | 2083 MarkDependentCodeForDeoptimization(dependent_code_list); |
| 2084 |
| 2085 ClearWeakCollections(); |
| 2086 |
| 2087 ClearInvalidStoreAndSlotsBufferEntries(); |
| 2086 } | 2088 } |
| 2087 | 2089 |
| 2088 | 2090 |
| 2089 void MarkCompactCollector::MarkDependentCodeForDeoptimization( | 2091 void MarkCompactCollector::MarkDependentCodeForDeoptimization( |
| 2090 DependentCode* list_head) { | 2092 DependentCode* list_head) { |
| 2091 GCTracer::Scope gc_scope(heap()->tracer(), | 2093 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2092 GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | 2094 GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); |
| 2093 | |
| 2094 Isolate* isolate = this->isolate(); | 2095 Isolate* isolate = this->isolate(); |
| 2095 DependentCode* current = list_head; | 2096 DependentCode* current = list_head; |
| 2096 while (current->length() > 0) { | 2097 while (current->length() > 0) { |
| 2097 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 2098 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( |
| 2098 isolate, DependentCode::kWeakCodeGroup); | 2099 isolate, DependentCode::kWeakCodeGroup); |
| 2099 current = current->next_link(); | 2100 current = current->next_link(); |
| 2100 } | 2101 } |
| 2101 | 2102 |
| 2102 WeakHashTable* table = heap_->weak_object_to_code_table(); | 2103 WeakHashTable* table = heap_->weak_object_to_code_table(); |
| 2103 uint32_t capacity = table->Capacity(); | 2104 uint32_t capacity = table->Capacity(); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2279 descriptors->GetEnumCache(), to_trim); | 2280 descriptors->GetEnumCache(), to_trim); |
| 2280 | 2281 |
| 2281 if (!descriptors->HasEnumIndicesCache()) return; | 2282 if (!descriptors->HasEnumIndicesCache()) return; |
| 2282 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); | 2283 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); |
| 2283 heap_->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(enum_indices_cache, | 2284 heap_->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(enum_indices_cache, |
| 2284 to_trim); | 2285 to_trim); |
| 2285 } | 2286 } |
| 2286 | 2287 |
| 2287 | 2288 |
| 2288 void MarkCompactCollector::ProcessWeakCollections() { | 2289 void MarkCompactCollector::ProcessWeakCollections() { |
| 2289 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 2290 GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); | |
| 2291 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2290 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2292 while (weak_collection_obj != Smi::FromInt(0)) { | 2291 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2293 JSWeakCollection* weak_collection = | 2292 JSWeakCollection* weak_collection = |
| 2294 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2293 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2295 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); | 2294 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
| 2296 if (weak_collection->table()->IsHashTable()) { | 2295 if (weak_collection->table()->IsHashTable()) { |
| 2297 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2296 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
| 2298 for (int i = 0; i < table->Capacity(); i++) { | 2297 for (int i = 0; i < table->Capacity(); i++) { |
| 2299 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2298 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
| 2300 Object** key_slot = | 2299 Object** key_slot = |
| 2301 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); | 2300 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); |
| 2302 RecordSlot(table, key_slot, *key_slot); | 2301 RecordSlot(table, key_slot, *key_slot); |
| 2303 Object** value_slot = | 2302 Object** value_slot = |
| 2304 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); | 2303 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); |
| 2305 MarkCompactMarkingVisitor::MarkObjectByPointer(this, table, | 2304 MarkCompactMarkingVisitor::MarkObjectByPointer(this, table, |
| 2306 value_slot); | 2305 value_slot); |
| 2307 } | 2306 } |
| 2308 } | 2307 } |
| 2309 } | 2308 } |
| 2310 weak_collection_obj = weak_collection->next(); | 2309 weak_collection_obj = weak_collection->next(); |
| 2311 } | 2310 } |
| 2312 } | 2311 } |
| 2313 | 2312 |
| 2314 | 2313 |
| 2315 void MarkCompactCollector::ClearWeakCollections() { | 2314 void MarkCompactCollector::ClearWeakCollections() { |
| 2316 GCTracer::Scope gc_scope(heap()->tracer(), | 2315 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2317 GCTracer::Scope::MC_WEAKCOLLECTION_CLEAR); | 2316 GCTracer::Scope::MC_CLEAR_WEAK_COLLECTIONS); |
| 2318 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2317 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2319 while (weak_collection_obj != Smi::FromInt(0)) { | 2318 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2320 JSWeakCollection* weak_collection = | 2319 JSWeakCollection* weak_collection = |
| 2321 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2320 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2322 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); | 2321 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
| 2323 if (weak_collection->table()->IsHashTable()) { | 2322 if (weak_collection->table()->IsHashTable()) { |
| 2324 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2323 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
| 2325 for (int i = 0; i < table->Capacity(); i++) { | 2324 for (int i = 0; i < table->Capacity(); i++) { |
| 2326 HeapObject* key = HeapObject::cast(table->KeyAt(i)); | 2325 HeapObject* key = HeapObject::cast(table->KeyAt(i)); |
| 2327 if (!MarkCompactCollector::IsMarked(key)) { | 2326 if (!MarkCompactCollector::IsMarked(key)) { |
| 2328 table->RemoveEntry(i); | 2327 table->RemoveEntry(i); |
| 2329 } | 2328 } |
| 2330 } | 2329 } |
| 2331 } | 2330 } |
| 2332 weak_collection_obj = weak_collection->next(); | 2331 weak_collection_obj = weak_collection->next(); |
| 2333 weak_collection->set_next(heap()->undefined_value()); | 2332 weak_collection->set_next(heap()->undefined_value()); |
| 2334 } | 2333 } |
| 2335 heap()->set_encountered_weak_collections(Smi::FromInt(0)); | 2334 heap()->set_encountered_weak_collections(Smi::FromInt(0)); |
| 2336 } | 2335 } |
| 2337 | 2336 |
| 2338 | 2337 |
| 2339 void MarkCompactCollector::AbortWeakCollections() { | 2338 void MarkCompactCollector::AbortWeakCollections() { |
| 2340 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 2341 GCTracer::Scope::MC_WEAKCOLLECTION_ABORT); | |
| 2342 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2339 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2343 while (weak_collection_obj != Smi::FromInt(0)) { | 2340 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2344 JSWeakCollection* weak_collection = | 2341 JSWeakCollection* weak_collection = |
| 2345 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2342 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2346 weak_collection_obj = weak_collection->next(); | 2343 weak_collection_obj = weak_collection->next(); |
| 2347 weak_collection->set_next(heap()->undefined_value()); | 2344 weak_collection->set_next(heap()->undefined_value()); |
| 2348 } | 2345 } |
| 2349 heap()->set_encountered_weak_collections(Smi::FromInt(0)); | 2346 heap()->set_encountered_weak_collections(Smi::FromInt(0)); |
| 2350 } | 2347 } |
| 2351 | 2348 |
| 2352 | 2349 |
| 2353 void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list, | 2350 void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list, |
| 2354 DependentCode** dependent_code_list) { | 2351 DependentCode** dependent_code_list) { |
| 2355 Heap* heap = this->heap(); | 2352 Heap* heap = this->heap(); |
| 2356 GCTracer::Scope gc_scope(heap->tracer(), GCTracer::Scope::MC_CLEAR_WEAKCELL); | 2353 GCTracer::Scope gc_scope(heap->tracer(), |
| 2354 GCTracer::Scope::MC_CLEAR_WEAK_CELLS); |
| 2357 Object* weak_cell_obj = heap->encountered_weak_cells(); | 2355 Object* weak_cell_obj = heap->encountered_weak_cells(); |
| 2358 Object* the_hole_value = heap->the_hole_value(); | 2356 Object* the_hole_value = heap->the_hole_value(); |
| 2359 DependentCode* dependent_code_head = | 2357 DependentCode* dependent_code_head = |
| 2360 DependentCode::cast(heap->empty_fixed_array()); | 2358 DependentCode::cast(heap->empty_fixed_array()); |
| 2361 Object* non_live_map_head = Smi::FromInt(0); | 2359 Object* non_live_map_head = Smi::FromInt(0); |
| 2362 while (weak_cell_obj != Smi::FromInt(0)) { | 2360 while (weak_cell_obj != Smi::FromInt(0)) { |
| 2363 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); | 2361 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); |
| 2364 Object* next_weak_cell = weak_cell->next(); | 2362 Object* next_weak_cell = weak_cell->next(); |
| 2365 bool clear_value = true; | 2363 bool clear_value = true; |
| 2366 bool clear_next = true; | 2364 bool clear_next = true; |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3442 default: | 3440 default: |
| 3443 UNREACHABLE(); | 3441 UNREACHABLE(); |
| 3444 break; | 3442 break; |
| 3445 } | 3443 } |
| 3446 } | 3444 } |
| 3447 } | 3445 } |
| 3448 } | 3446 } |
| 3449 | 3447 |
| 3450 | 3448 |
| 3451 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 3449 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 3450 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); |
| 3452 Heap::RelocationLock relocation_lock(heap()); | 3451 Heap::RelocationLock relocation_lock(heap()); |
| 3453 | 3452 |
| 3454 { | 3453 { |
| 3455 GCTracer::Scope gc_scope(heap()->tracer(), | 3454 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3456 GCTracer::Scope::MC_SWEEP_NEWSPACE); | 3455 GCTracer::Scope::MC_EVACUATE_NEW_SPACE); |
| 3457 EvacuationScope evacuation_scope(this); | 3456 EvacuationScope evacuation_scope(this); |
| 3458 EvacuateNewSpace(); | 3457 EvacuateNewSpace(); |
| 3459 } | 3458 } |
| 3460 | 3459 |
| 3461 { | 3460 { |
| 3462 GCTracer::Scope gc_scope(heap()->tracer(), | 3461 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3463 GCTracer::Scope::MC_EVACUATE_PAGES); | 3462 GCTracer::Scope::MC_EVACUATE_CANDIDATES); |
| 3464 EvacuationScope evacuation_scope(this); | 3463 EvacuationScope evacuation_scope(this); |
| 3465 EvacuatePagesInParallel(); | 3464 EvacuatePagesInParallel(); |
| 3466 } | 3465 } |
| 3467 | 3466 |
| 3467 UpdatePointersAfterEvacuation(); |
| 3468 |
| 3468 { | 3469 { |
| 3469 GCTracer::Scope gc_scope(heap()->tracer(), | 3470 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3470 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); | 3471 GCTracer::Scope::MC_EVACUATE_CLEAN_UP); |
| 3472 // After updating all pointers, we can finally sweep the aborted pages, |
| 3473 // effectively overriding any forward pointers. |
| 3474 SweepAbortedPages(); |
| 3475 |
| 3476 // EvacuateNewSpaceAndCandidates iterates over new space objects and for |
| 3477 // ArrayBuffers either re-registers them as live or promotes them. This is |
| 3478 // needed to properly free them. |
| 3479 heap()->array_buffer_tracker()->FreeDead(false); |
| 3480 |
| 3481 // Deallocate evacuated candidate pages. |
| 3482 ReleaseEvacuationCandidates(); |
| 3483 } |
| 3484 |
| 3485 #ifdef VERIFY_HEAP |
| 3486 if (FLAG_verify_heap && !sweeping_in_progress_) { |
| 3487 VerifyEvacuation(heap()); |
| 3488 } |
| 3489 #endif |
| 3490 } |
| 3491 |
| 3492 |
| 3493 void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
| 3494 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3495 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
| 3496 { |
| 3497 GCTracer::Scope gc_scope( |
| 3498 heap()->tracer(), |
| 3499 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); |
| 3471 UpdateSlotsRecordedIn(migration_slots_buffer_); | 3500 UpdateSlotsRecordedIn(migration_slots_buffer_); |
| 3472 if (FLAG_trace_fragmentation_verbose) { | 3501 if (FLAG_trace_fragmentation_verbose) { |
| 3473 PrintF(" migration slots buffer: %d\n", | 3502 PrintF(" migration slots buffer: %d\n", |
| 3474 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | 3503 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); |
| 3475 } | 3504 } |
| 3476 slots_buffer_allocator_->DeallocateChain(&migration_slots_buffer_); | 3505 slots_buffer_allocator_->DeallocateChain(&migration_slots_buffer_); |
| 3477 DCHECK(migration_slots_buffer_ == NULL); | 3506 DCHECK(migration_slots_buffer_ == NULL); |
| 3478 | 3507 |
| 3479 // TODO(hpayer): Process the slots buffers in parallel. This has to be done | 3508 // TODO(hpayer): Process the slots buffers in parallel. This has to be done |
| 3480 // after evacuation of all pages finishes. | 3509 // after evacuation of all pages finishes. |
| 3481 int buffers = evacuation_slots_buffers_.length(); | 3510 int buffers = evacuation_slots_buffers_.length(); |
| 3482 for (int i = 0; i < buffers; i++) { | 3511 for (int i = 0; i < buffers; i++) { |
| 3483 SlotsBuffer* buffer = evacuation_slots_buffers_[i]; | 3512 SlotsBuffer* buffer = evacuation_slots_buffers_[i]; |
| 3484 UpdateSlotsRecordedIn(buffer); | 3513 UpdateSlotsRecordedIn(buffer); |
| 3485 slots_buffer_allocator_->DeallocateChain(&buffer); | 3514 slots_buffer_allocator_->DeallocateChain(&buffer); |
| 3486 } | 3515 } |
| 3487 evacuation_slots_buffers_.Rewind(0); | 3516 evacuation_slots_buffers_.Rewind(0); |
| 3488 } | 3517 } |
| 3489 | 3518 |
| 3490 // Second pass: find pointers to new space and update them. | 3519 // Second pass: find pointers to new space and update them. |
| 3491 PointersUpdatingVisitor updating_visitor(heap()); | 3520 PointersUpdatingVisitor updating_visitor(heap()); |
| 3492 | 3521 |
| 3493 { | 3522 { |
| 3494 GCTracer::Scope gc_scope(heap()->tracer(), | 3523 GCTracer::Scope gc_scope( |
| 3495 GCTracer::Scope::MC_UPDATE_NEW_TO_NEW_POINTERS); | 3524 heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
| 3496 // Update pointers in to space. | 3525 // Update pointers in to space. |
| 3497 SemiSpaceIterator to_it(heap()->new_space()); | 3526 SemiSpaceIterator to_it(heap()->new_space()); |
| 3498 for (HeapObject* object = to_it.Next(); object != NULL; | 3527 for (HeapObject* object = to_it.Next(); object != NULL; |
| 3499 object = to_it.Next()) { | 3528 object = to_it.Next()) { |
| 3500 Map* map = object->map(); | 3529 Map* map = object->map(); |
| 3501 object->IterateBody(map->instance_type(), object->SizeFromMap(map), | 3530 object->IterateBody(map->instance_type(), object->SizeFromMap(map), |
| 3502 &updating_visitor); | 3531 &updating_visitor); |
| 3503 } | 3532 } |
| 3504 } | |
| 3505 | |
| 3506 { | |
| 3507 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3508 GCTracer::Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS); | |
| 3509 // Update roots. | 3533 // Update roots. |
| 3510 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3534 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 3511 } | |
| 3512 | 3535 |
| 3513 { | |
| 3514 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3515 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); | |
| 3516 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), | 3536 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), |
| 3517 &Heap::ScavengeStoreBufferCallback); | 3537 &Heap::ScavengeStoreBufferCallback); |
| 3518 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 3538 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
| 3519 } | 3539 } |
| 3520 | 3540 |
| 3521 int npages = evacuation_candidates_.length(); | 3541 int npages = evacuation_candidates_.length(); |
| 3522 { | 3542 { |
| 3523 GCTracer::Scope gc_scope( | 3543 GCTracer::Scope gc_scope( |
| 3524 heap()->tracer(), | 3544 heap()->tracer(), |
| 3525 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); | 3545 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED); |
| 3526 for (int i = 0; i < npages; i++) { | 3546 for (int i = 0; i < npages; i++) { |
| 3527 Page* p = evacuation_candidates_[i]; | 3547 Page* p = evacuation_candidates_[i]; |
| 3528 DCHECK(p->IsEvacuationCandidate() || | 3548 DCHECK(p->IsEvacuationCandidate() || |
| 3529 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3549 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
| 3530 | 3550 |
| 3531 if (p->IsEvacuationCandidate()) { | 3551 if (p->IsEvacuationCandidate()) { |
| 3532 UpdateSlotsRecordedIn(p->slots_buffer()); | 3552 UpdateSlotsRecordedIn(p->slots_buffer()); |
| 3533 if (FLAG_trace_fragmentation_verbose) { | 3553 if (FLAG_trace_fragmentation_verbose) { |
| 3534 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), | 3554 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), |
| 3535 SlotsBuffer::SizeOfChain(p->slots_buffer())); | 3555 SlotsBuffer::SizeOfChain(p->slots_buffer())); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3577 default: | 3597 default: |
| 3578 UNREACHABLE(); | 3598 UNREACHABLE(); |
| 3579 break; | 3599 break; |
| 3580 } | 3600 } |
| 3581 } | 3601 } |
| 3582 } | 3602 } |
| 3583 } | 3603 } |
| 3584 | 3604 |
| 3585 { | 3605 { |
| 3586 GCTracer::Scope gc_scope(heap()->tracer(), | 3606 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3587 GCTracer::Scope::MC_UPDATE_MISC_POINTERS); | 3607 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); |
| 3588 heap_->string_table()->Iterate(&updating_visitor); | 3608 heap_->string_table()->Iterate(&updating_visitor); |
| 3589 | 3609 |
| 3590 // Update pointers from external string table. | 3610 // Update pointers from external string table. |
| 3591 heap_->UpdateReferencesInExternalStringTable( | 3611 heap_->UpdateReferencesInExternalStringTable( |
| 3592 &UpdateReferenceInExternalStringTableEntry); | 3612 &UpdateReferenceInExternalStringTableEntry); |
| 3593 | 3613 |
| 3594 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3614 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 3595 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); | 3615 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); |
| 3596 } | 3616 } |
| 3597 | |
| 3598 { | |
| 3599 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3600 GCTracer::Scope::MC_SWEEP_ABORTED); | |
| 3601 // After updating all pointers, we can finally sweep the aborted pages, | |
| 3602 // effectively overriding any forward pointers. | |
| 3603 SweepAbortedPages(); | |
| 3604 } | |
| 3605 | |
| 3606 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); | |
| 3607 | |
| 3608 // The hashing of weak_object_to_code_table is no longer valid. | |
| 3609 heap()->weak_object_to_code_table()->Rehash( | |
| 3610 heap()->isolate()->factory()->undefined_value()); | |
| 3611 } | 3617 } |
| 3612 | 3618 |
| 3613 | 3619 |
| 3614 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { | 3620 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { |
| 3615 int npages = evacuation_candidates_.length(); | 3621 int npages = evacuation_candidates_.length(); |
| 3616 for (int i = 0; i < npages; i++) { | 3622 for (int i = 0; i < npages; i++) { |
| 3617 Page* p = evacuation_candidates_[i]; | 3623 Page* p = evacuation_candidates_[i]; |
| 3618 if (!p->IsEvacuationCandidate()) continue; | 3624 if (!p->IsEvacuationCandidate()) continue; |
| 3619 p->Unlink(); | 3625 p->Unlink(); |
| 3620 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3626 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3827 | 3833 |
| 3828 #ifdef DEBUG | 3834 #ifdef DEBUG |
| 3829 state_ = SWEEP_SPACES; | 3835 state_ = SWEEP_SPACES; |
| 3830 #endif | 3836 #endif |
| 3831 | 3837 |
| 3832 MoveEvacuationCandidatesToEndOfPagesList(); | 3838 MoveEvacuationCandidatesToEndOfPagesList(); |
| 3833 | 3839 |
| 3834 { | 3840 { |
| 3835 { | 3841 { |
| 3836 GCTracer::Scope sweep_scope(heap()->tracer(), | 3842 GCTracer::Scope sweep_scope(heap()->tracer(), |
| 3837 GCTracer::Scope::MC_SWEEP_OLDSPACE); | 3843 GCTracer::Scope::MC_SWEEP_OLD); |
| 3838 SweepSpace(heap()->old_space(), CONCURRENT_SWEEPING); | 3844 SweepSpace(heap()->old_space(), CONCURRENT_SWEEPING); |
| 3839 } | 3845 } |
| 3840 { | 3846 { |
| 3841 GCTracer::Scope sweep_scope(heap()->tracer(), | 3847 GCTracer::Scope sweep_scope(heap()->tracer(), |
| 3842 GCTracer::Scope::MC_SWEEP_CODE); | 3848 GCTracer::Scope::MC_SWEEP_CODE); |
| 3843 SweepSpace(heap()->code_space(), CONCURRENT_SWEEPING); | 3849 SweepSpace(heap()->code_space(), CONCURRENT_SWEEPING); |
| 3844 } | 3850 } |
| 3845 { | 3851 { |
| 3846 GCTracer::Scope sweep_scope(heap()->tracer(), | 3852 GCTracer::Scope sweep_scope(heap()->tracer(), |
| 3847 GCTracer::Scope::MC_SWEEP_MAP); | 3853 GCTracer::Scope::MC_SWEEP_MAP); |
| 3848 SweepSpace(heap()->map_space(), CONCURRENT_SWEEPING); | 3854 SweepSpace(heap()->map_space(), CONCURRENT_SWEEPING); |
| 3849 } | 3855 } |
| 3850 sweeping_in_progress_ = true; | 3856 sweeping_in_progress_ = true; |
| 3851 if (heap()->concurrent_sweeping_enabled()) { | 3857 if (heap()->concurrent_sweeping_enabled()) { |
| 3852 StartSweeperThreads(); | 3858 StartSweeperThreads(); |
| 3853 } | 3859 } |
| 3854 } | 3860 } |
| 3855 | 3861 |
| 3856 // Deallocate unmarked large objects. | 3862 // Deallocate unmarked large objects. |
| 3857 heap_->lo_space()->FreeUnmarkedObjects(); | 3863 heap_->lo_space()->FreeUnmarkedObjects(); |
| 3858 | 3864 |
| 3859 // Give pages that are queued to be freed back to the OS. Invalid store | 3865 // Give pages that are queued to be freed back to the OS. Invalid store |
| 3860 // buffer entries are already filter out. We can just release the memory. | 3866 // buffer entries are already filter out. We can just release the memory. |
| 3861 heap()->FreeQueuedChunks(); | 3867 heap()->FreeQueuedChunks(); |
| 3862 | 3868 |
| 3863 EvacuateNewSpaceAndCandidates(); | |
| 3864 | |
| 3865 // EvacuateNewSpaceAndCandidates iterates over new space objects and for | |
| 3866 // ArrayBuffers either re-registers them as live or promotes them. This is | |
| 3867 // needed to properly free them. | |
| 3868 heap()->array_buffer_tracker()->FreeDead(false); | |
| 3869 | |
| 3870 // Clear the marking state of live large objects. | |
| 3871 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); | |
| 3872 | |
| 3873 // Deallocate evacuated candidate pages. | |
| 3874 ReleaseEvacuationCandidates(); | |
| 3875 | |
| 3876 if (FLAG_print_cumulative_gc_stat) { | 3869 if (FLAG_print_cumulative_gc_stat) { |
| 3877 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 3870 heap_->tracer()->AddSweepingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
| 3878 start_time); | 3871 start_time); |
| 3879 } | 3872 } |
| 3880 | |
| 3881 #ifdef VERIFY_HEAP | |
| 3882 if (FLAG_verify_heap && !sweeping_in_progress_) { | |
| 3883 VerifyEvacuation(heap()); | |
| 3884 } | |
| 3885 #endif | |
| 3886 } | 3873 } |
| 3887 | 3874 |
| 3888 | 3875 |
| 3889 void MarkCompactCollector::ParallelSweepSpaceComplete(PagedSpace* space) { | 3876 void MarkCompactCollector::ParallelSweepSpaceComplete(PagedSpace* space) { |
| 3890 PageIterator it(space); | 3877 PageIterator it(space); |
| 3891 while (it.has_next()) { | 3878 while (it.has_next()) { |
| 3892 Page* p = it.next(); | 3879 Page* p = it.next(); |
| 3893 if (p->parallel_sweeping_state().Value() == | 3880 if (p->parallel_sweeping_state().Value() == |
| 3894 MemoryChunk::kSweepingFinalize) { | 3881 MemoryChunk::kSweepingFinalize) { |
| 3895 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingDone); | 3882 p->parallel_sweeping_state().SetValue(MemoryChunk::kSweepingDone); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3974 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3961 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3975 if (Marking::IsBlack(mark_bit)) { | 3962 if (Marking::IsBlack(mark_bit)) { |
| 3976 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3963 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3977 RecordRelocSlot(&rinfo, target); | 3964 RecordRelocSlot(&rinfo, target); |
| 3978 } | 3965 } |
| 3979 } | 3966 } |
| 3980 } | 3967 } |
| 3981 | 3968 |
| 3982 } // namespace internal | 3969 } // namespace internal |
| 3983 } // namespace v8 | 3970 } // namespace v8 |
| OLD | NEW |