Chromium Code Reviews| 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 } | 327 } |
| 328 | 328 |
| 329 | 329 |
| 330 #ifdef VERIFY_HEAP | 330 #ifdef VERIFY_HEAP |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 357 // Make sure that Prepare() has been called. The individual steps below will | 357 // Make sure that Prepare() has been called. The individual steps below will |
| 358 // update the state as they proceed. | 358 // update the state as they proceed. |
| 359 DCHECK(state_ == PREPARE_GC); | 359 DCHECK(state_ == PREPARE_GC); |
| 360 | 360 |
| 361 MarkLiveObjects(); | 361 MarkLiveObjects(); |
| 362 | 362 |
| 363 DCHECK(heap_->incremental_marking()->IsStopped()); | 363 DCHECK(heap_->incremental_marking()->IsStopped()); |
| 364 | 364 |
| 365 ClearNonLiveReferences(); | 365 ClearNonLiveReferences(); |
| 366 | 366 |
| 367 ClearWeakCollections(); | |
| 368 | |
| 369 #ifdef VERIFY_HEAP | 367 #ifdef VERIFY_HEAP |
|
Hannes Payer (out of office)
2015/12/11 09:27:31
It would be nice to move this one into MarkLiveObj
ulan
2015/12/11 09:35:32
It depends on ClearNonLiveReferences which removes
| |
| 370 if (FLAG_verify_heap) { | 368 if (FLAG_verify_heap) { |
| 371 VerifyMarking(heap_); | 369 VerifyMarking(heap_); |
| 372 } | 370 } |
| 373 #endif | 371 #endif |
| 374 | 372 |
| 375 ClearInvalidStoreAndSlotsBufferEntries(); | 373 MoveEvacuationCandidatesToEndOfPagesList(); |
| 376 | |
| 377 #ifdef VERIFY_HEAP | |
| 378 if (FLAG_verify_heap) { | |
| 379 VerifyValidStoreAndSlotsBufferEntries(); | |
| 380 } | |
| 381 #endif | |
| 382 | 374 |
| 383 SweepSpaces(); | 375 SweepSpaces(); |
| 384 | 376 |
| 377 EvacuateNewSpaceAndCandidates(); | |
| 378 | |
| 385 Finish(); | 379 Finish(); |
| 386 | 380 |
| 387 if (marking_parity_ == EVEN_MARKING_PARITY) { | 381 if (marking_parity_ == EVEN_MARKING_PARITY) { |
|
Hannes Payer (out of office)
2015/12/11 09:27:31
Move that into finish.
ulan
2015/12/11 09:35:32
Done.
| |
| 388 marking_parity_ = ODD_MARKING_PARITY; | 382 marking_parity_ = ODD_MARKING_PARITY; |
| 389 } else { | 383 } else { |
| 390 DCHECK(marking_parity_ == ODD_MARKING_PARITY); | 384 DCHECK(marking_parity_ == ODD_MARKING_PARITY); |
| 391 marking_parity_ = EVEN_MARKING_PARITY; | 385 marking_parity_ = EVEN_MARKING_PARITY; |
| 392 } | 386 } |
| 393 } | 387 } |
| 394 | 388 |
| 395 | 389 |
| 396 #ifdef VERIFY_HEAP | 390 #ifdef VERIFY_HEAP |
| 397 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { | 391 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 | 854 |
| 861 #ifdef VERIFY_HEAP | 855 #ifdef VERIFY_HEAP |
| 862 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 856 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
| 863 VerifyMarkbitsAreClean(); | 857 VerifyMarkbitsAreClean(); |
| 864 } | 858 } |
| 865 #endif | 859 #endif |
| 866 } | 860 } |
| 867 | 861 |
| 868 | 862 |
| 869 void MarkCompactCollector::Finish() { | 863 void MarkCompactCollector::Finish() { |
| 864 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_FINISH); | |
| 865 | |
| 866 // The hashing of weak_object_to_code_table is no longer valid. | |
| 867 heap()->weak_object_to_code_table()->Rehash( | |
| 868 heap()->isolate()->factory()->undefined_value()); | |
| 869 | |
| 870 // Clear the marking state of live large objects. | |
| 871 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); | |
| 872 | |
| 870 #ifdef DEBUG | 873 #ifdef DEBUG |
| 871 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 874 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
| 872 state_ = IDLE; | 875 state_ = IDLE; |
| 873 #endif | 876 #endif |
| 877 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); | |
| 878 | |
| 874 // The stub cache is not traversed during GC; clear the cache to | 879 // 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 | 880 // 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 | 881 // GC, because it relies on the new address of certain old space |
| 877 // objects (empty string, illegal builtin). | 882 // objects (empty string, illegal builtin). |
| 878 isolate()->stub_cache()->Clear(); | 883 isolate()->stub_cache()->Clear(); |
| 879 | 884 |
| 880 if (have_code_to_deoptimize_) { | 885 if (have_code_to_deoptimize_) { |
| 881 // Some code objects were marked for deoptimization during the GC. | 886 // Some code objects were marked for deoptimization during the GC. |
| 882 Deoptimizer::DeoptimizeMarkedCode(isolate()); | 887 Deoptimizer::DeoptimizeMarkedCode(isolate()); |
| 883 have_code_to_deoptimize_ = false; | 888 have_code_to_deoptimize_ = false; |
| (...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1962 | 1967 |
| 1963 { | 1968 { |
| 1964 GCTracer::Scope gc_scope(heap()->tracer(), | 1969 GCTracer::Scope gc_scope(heap()->tracer(), |
| 1965 GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); | 1970 GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); |
| 1966 PrepareForCodeFlushing(); | 1971 PrepareForCodeFlushing(); |
| 1967 } | 1972 } |
| 1968 | 1973 |
| 1969 RootMarkingVisitor root_visitor(heap()); | 1974 RootMarkingVisitor root_visitor(heap()); |
| 1970 | 1975 |
| 1971 { | 1976 { |
| 1972 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOT); | 1977 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS); |
| 1973 MarkRoots(&root_visitor); | 1978 MarkRoots(&root_visitor); |
| 1974 } | |
| 1975 | |
| 1976 { | |
| 1977 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_TOPOPT); | |
| 1978 ProcessTopOptimizedFrame(&root_visitor); | 1979 ProcessTopOptimizedFrame(&root_visitor); |
| 1979 } | 1980 } |
| 1980 | 1981 |
| 1981 { | 1982 { |
| 1982 GCTracer::Scope gc_scope(heap()->tracer(), | 1983 GCTracer::Scope gc_scope(heap()->tracer(), |
| 1983 GCTracer::Scope::MC_MARK_WEAK_CLOSURE); | 1984 GCTracer::Scope::MC_MARK_WEAK_CLOSURE); |
| 1984 | 1985 |
| 1985 // The objects reachable from the roots are marked, yet unreachable | 1986 // The objects reachable from the roots are marked, yet unreachable |
| 1986 // objects are unmarked. Mark objects reachable due to host | 1987 // objects are unmarked. Mark objects reachable due to host |
| 1987 // application specific logic or through Harmony weak maps. | 1988 // application specific logic or through Harmony weak maps. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2001 ProcessMarkingDeque(); | 2002 ProcessMarkingDeque(); |
| 2002 | 2003 |
| 2003 // Repeat Harmony weak maps marking to mark unmarked objects reachable from | 2004 // Repeat Harmony weak maps marking to mark unmarked objects reachable from |
| 2004 // the weak roots we just marked as pending destruction. | 2005 // the weak roots we just marked as pending destruction. |
| 2005 // | 2006 // |
| 2006 // We only process harmony collections, as all object groups have been fully | 2007 // We only process harmony collections, as all object groups have been fully |
| 2007 // processed and no weakly reachable node can discover new objects groups. | 2008 // processed and no weakly reachable node can discover new objects groups. |
| 2008 ProcessEphemeralMarking(&root_visitor, true); | 2009 ProcessEphemeralMarking(&root_visitor, true); |
| 2009 } | 2010 } |
| 2010 | 2011 |
| 2011 AfterMarking(); | |
| 2012 | |
| 2013 if (FLAG_print_cumulative_gc_stat) { | 2012 if (FLAG_print_cumulative_gc_stat) { |
| 2014 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 2013 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
| 2015 start_time); | 2014 start_time); |
| 2016 } | 2015 } |
| 2016 if (FLAG_track_gc_object_stats) { | |
| 2017 if (FLAG_trace_gc_object_stats) { | |
| 2018 heap()->object_stats_->TraceObjectStats(); | |
| 2019 } | |
| 2020 heap()->object_stats_->CheckpointObjectStats(); | |
| 2021 } | |
| 2017 } | 2022 } |
| 2018 | 2023 |
| 2019 | 2024 |
| 2020 void MarkCompactCollector::AfterMarking() { | 2025 void MarkCompactCollector::ClearNonLiveReferences() { |
| 2026 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | |
| 2027 | |
| 2021 { | 2028 { |
| 2022 GCTracer::Scope gc_scope(heap()->tracer(), | 2029 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2023 GCTracer::Scope::MC_MARK_STRING_TABLE); | 2030 GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
| 2024 | 2031 |
| 2025 // Prune the string table removing all strings only pointed to by the | 2032 // Prune the string table removing all strings only pointed to by the |
| 2026 // string table. Cannot use string_table() here because the string | 2033 // string table. Cannot use string_table() here because the string |
| 2027 // table is marked. | 2034 // table is marked. |
| 2028 StringTable* string_table = heap()->string_table(); | 2035 StringTable* string_table = heap()->string_table(); |
| 2029 InternalizedStringTableCleaner internalized_visitor(heap()); | 2036 InternalizedStringTableCleaner internalized_visitor(heap()); |
| 2030 string_table->IterateElements(&internalized_visitor); | 2037 string_table->IterateElements(&internalized_visitor); |
| 2031 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); | 2038 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); |
| 2032 | 2039 |
| 2033 ExternalStringTableCleaner external_visitor(heap()); | 2040 ExternalStringTableCleaner external_visitor(heap()); |
| 2034 heap()->external_string_table_.Iterate(&external_visitor); | 2041 heap()->external_string_table_.Iterate(&external_visitor); |
| 2035 heap()->external_string_table_.CleanUp(); | 2042 heap()->external_string_table_.CleanUp(); |
| 2036 } | 2043 } |
| 2037 | 2044 |
| 2038 { | 2045 { |
| 2039 GCTracer::Scope gc_scope(heap()->tracer(), | 2046 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2040 GCTracer::Scope::MC_MARK_WEAK_REFERENCES); | 2047 GCTracer::Scope::MC_CLEAR_WEAK_LISTS); |
| 2041 | |
| 2042 // Process the weak references. | 2048 // Process the weak references. |
| 2043 MarkCompactWeakObjectRetainer mark_compact_object_retainer; | 2049 MarkCompactWeakObjectRetainer mark_compact_object_retainer; |
| 2044 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); | 2050 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); |
| 2045 } | 2051 } |
| 2046 | 2052 |
| 2047 { | 2053 { |
| 2048 GCTracer::Scope gc_scope(heap()->tracer(), | 2054 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2049 GCTracer::Scope::MC_MARK_GLOBAL_HANDLES); | 2055 GCTracer::Scope::MC_CLEAR_GLOBAL_HANDLES); |
| 2050 | 2056 |
| 2051 // Remove object groups after marking phase. | 2057 // Remove object groups after marking phase. |
| 2052 heap()->isolate()->global_handles()->RemoveObjectGroups(); | 2058 heap()->isolate()->global_handles()->RemoveObjectGroups(); |
| 2053 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); | 2059 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); |
| 2054 } | 2060 } |
| 2055 | 2061 |
| 2056 // Flush code from collected candidates. | 2062 // Flush code from collected candidates. |
| 2057 if (is_code_flushing_enabled()) { | 2063 if (is_code_flushing_enabled()) { |
| 2058 GCTracer::Scope gc_scope(heap()->tracer(), | 2064 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2059 GCTracer::Scope::MC_MARK_CODE_FLUSH); | 2065 GCTracer::Scope::MC_CLEAR_CODE_FLUSH); |
| 2060 code_flusher_->ProcessCandidates(); | 2066 code_flusher_->ProcessCandidates(); |
| 2061 } | 2067 } |
| 2062 | 2068 |
| 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 | 2069 |
| 2075 DependentCode* dependent_code_list; | 2070 DependentCode* dependent_code_list; |
| 2076 Object* non_live_map_list; | 2071 Object* non_live_map_list; |
| 2077 ClearWeakCells(&non_live_map_list, &dependent_code_list); | 2072 ClearWeakCells(&non_live_map_list, &dependent_code_list); |
| 2078 | 2073 |
| 2079 { | 2074 { |
| 2080 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAP); | 2075 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAPS); |
| 2081 ClearSimpleMapTransitions(non_live_map_list); | 2076 ClearSimpleMapTransitions(non_live_map_list); |
| 2082 ClearFullMapTransitions(); | 2077 ClearFullMapTransitions(); |
| 2083 } | 2078 } |
| 2084 | 2079 |
| 2085 MarkDependentCodeForDeoptimization(dependent_code_list); | 2080 MarkDependentCodeForDeoptimization(dependent_code_list); |
| 2081 | |
| 2082 ClearWeakCollections(); | |
| 2083 | |
| 2084 ClearInvalidStoreAndSlotsBufferEntries(); | |
| 2085 #ifdef VERIFY_HEAP | |
|
Hannes Payer (out of office)
2015/12/11 09:27:31
We could move the debugging code into ClearInvalid
ulan
2015/12/11 09:35:32
Done.
| |
| 2086 if (FLAG_verify_heap) { | |
| 2087 VerifyValidStoreAndSlotsBufferEntries(); | |
| 2088 } | |
| 2089 #endif | |
| 2086 } | 2090 } |
| 2087 | 2091 |
| 2088 | 2092 |
| 2089 void MarkCompactCollector::MarkDependentCodeForDeoptimization( | 2093 void MarkCompactCollector::MarkDependentCodeForDeoptimization( |
| 2090 DependentCode* list_head) { | 2094 DependentCode* list_head) { |
| 2091 GCTracer::Scope gc_scope(heap()->tracer(), | 2095 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2092 GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | 2096 GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); |
| 2093 | |
| 2094 Isolate* isolate = this->isolate(); | 2097 Isolate* isolate = this->isolate(); |
| 2095 DependentCode* current = list_head; | 2098 DependentCode* current = list_head; |
| 2096 while (current->length() > 0) { | 2099 while (current->length() > 0) { |
| 2097 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 2100 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( |
| 2098 isolate, DependentCode::kWeakCodeGroup); | 2101 isolate, DependentCode::kWeakCodeGroup); |
| 2099 current = current->next_link(); | 2102 current = current->next_link(); |
| 2100 } | 2103 } |
| 2101 | 2104 |
| 2102 WeakHashTable* table = heap_->weak_object_to_code_table(); | 2105 WeakHashTable* table = heap_->weak_object_to_code_table(); |
| 2103 uint32_t capacity = table->Capacity(); | 2106 uint32_t capacity = table->Capacity(); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2279 descriptors->GetEnumCache(), to_trim); | 2282 descriptors->GetEnumCache(), to_trim); |
| 2280 | 2283 |
| 2281 if (!descriptors->HasEnumIndicesCache()) return; | 2284 if (!descriptors->HasEnumIndicesCache()) return; |
| 2282 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); | 2285 FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache(); |
| 2283 heap_->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(enum_indices_cache, | 2286 heap_->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(enum_indices_cache, |
| 2284 to_trim); | 2287 to_trim); |
| 2285 } | 2288 } |
| 2286 | 2289 |
| 2287 | 2290 |
| 2288 void MarkCompactCollector::ProcessWeakCollections() { | 2291 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(); | 2292 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2292 while (weak_collection_obj != Smi::FromInt(0)) { | 2293 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2293 JSWeakCollection* weak_collection = | 2294 JSWeakCollection* weak_collection = |
| 2294 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2295 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2295 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); | 2296 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
| 2296 if (weak_collection->table()->IsHashTable()) { | 2297 if (weak_collection->table()->IsHashTable()) { |
| 2297 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2298 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
| 2298 for (int i = 0; i < table->Capacity(); i++) { | 2299 for (int i = 0; i < table->Capacity(); i++) { |
| 2299 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2300 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
| 2300 Object** key_slot = | 2301 Object** key_slot = |
| 2301 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); | 2302 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); |
| 2302 RecordSlot(table, key_slot, *key_slot); | 2303 RecordSlot(table, key_slot, *key_slot); |
| 2303 Object** value_slot = | 2304 Object** value_slot = |
| 2304 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); | 2305 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); |
| 2305 MarkCompactMarkingVisitor::MarkObjectByPointer(this, table, | 2306 MarkCompactMarkingVisitor::MarkObjectByPointer(this, table, |
| 2306 value_slot); | 2307 value_slot); |
| 2307 } | 2308 } |
| 2308 } | 2309 } |
| 2309 } | 2310 } |
| 2310 weak_collection_obj = weak_collection->next(); | 2311 weak_collection_obj = weak_collection->next(); |
| 2311 } | 2312 } |
| 2312 } | 2313 } |
| 2313 | 2314 |
| 2314 | 2315 |
| 2315 void MarkCompactCollector::ClearWeakCollections() { | 2316 void MarkCompactCollector::ClearWeakCollections() { |
| 2316 GCTracer::Scope gc_scope(heap()->tracer(), | 2317 GCTracer::Scope gc_scope(heap()->tracer(), |
| 2317 GCTracer::Scope::MC_WEAKCOLLECTION_CLEAR); | 2318 GCTracer::Scope::MC_CLEAR_WEAK_COLLECTIONS); |
| 2318 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2319 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2319 while (weak_collection_obj != Smi::FromInt(0)) { | 2320 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2320 JSWeakCollection* weak_collection = | 2321 JSWeakCollection* weak_collection = |
| 2321 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2322 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2322 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); | 2323 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
| 2323 if (weak_collection->table()->IsHashTable()) { | 2324 if (weak_collection->table()->IsHashTable()) { |
| 2324 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2325 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
| 2325 for (int i = 0; i < table->Capacity(); i++) { | 2326 for (int i = 0; i < table->Capacity(); i++) { |
| 2326 HeapObject* key = HeapObject::cast(table->KeyAt(i)); | 2327 HeapObject* key = HeapObject::cast(table->KeyAt(i)); |
| 2327 if (!MarkCompactCollector::IsMarked(key)) { | 2328 if (!MarkCompactCollector::IsMarked(key)) { |
| 2328 table->RemoveEntry(i); | 2329 table->RemoveEntry(i); |
| 2329 } | 2330 } |
| 2330 } | 2331 } |
| 2331 } | 2332 } |
| 2332 weak_collection_obj = weak_collection->next(); | 2333 weak_collection_obj = weak_collection->next(); |
| 2333 weak_collection->set_next(heap()->undefined_value()); | 2334 weak_collection->set_next(heap()->undefined_value()); |
| 2334 } | 2335 } |
| 2335 heap()->set_encountered_weak_collections(Smi::FromInt(0)); | 2336 heap()->set_encountered_weak_collections(Smi::FromInt(0)); |
| 2336 } | 2337 } |
| 2337 | 2338 |
| 2338 | 2339 |
| 2339 void MarkCompactCollector::AbortWeakCollections() { | 2340 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(); | 2341 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2343 while (weak_collection_obj != Smi::FromInt(0)) { | 2342 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2344 JSWeakCollection* weak_collection = | 2343 JSWeakCollection* weak_collection = |
| 2345 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2344 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2346 weak_collection_obj = weak_collection->next(); | 2345 weak_collection_obj = weak_collection->next(); |
| 2347 weak_collection->set_next(heap()->undefined_value()); | 2346 weak_collection->set_next(heap()->undefined_value()); |
| 2348 } | 2347 } |
| 2349 heap()->set_encountered_weak_collections(Smi::FromInt(0)); | 2348 heap()->set_encountered_weak_collections(Smi::FromInt(0)); |
| 2350 } | 2349 } |
| 2351 | 2350 |
| 2352 | 2351 |
| 2353 void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list, | 2352 void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list, |
| 2354 DependentCode** dependent_code_list) { | 2353 DependentCode** dependent_code_list) { |
| 2355 Heap* heap = this->heap(); | 2354 Heap* heap = this->heap(); |
| 2356 GCTracer::Scope gc_scope(heap->tracer(), GCTracer::Scope::MC_CLEAR_WEAKCELL); | 2355 GCTracer::Scope gc_scope(heap->tracer(), |
| 2356 GCTracer::Scope::MC_CLEAR_WEAK_CELLS); | |
| 2357 Object* weak_cell_obj = heap->encountered_weak_cells(); | 2357 Object* weak_cell_obj = heap->encountered_weak_cells(); |
| 2358 Object* the_hole_value = heap->the_hole_value(); | 2358 Object* the_hole_value = heap->the_hole_value(); |
| 2359 DependentCode* dependent_code_head = | 2359 DependentCode* dependent_code_head = |
| 2360 DependentCode::cast(heap->empty_fixed_array()); | 2360 DependentCode::cast(heap->empty_fixed_array()); |
| 2361 Object* non_live_map_head = Smi::FromInt(0); | 2361 Object* non_live_map_head = Smi::FromInt(0); |
| 2362 while (weak_cell_obj != Smi::FromInt(0)) { | 2362 while (weak_cell_obj != Smi::FromInt(0)) { |
| 2363 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); | 2363 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); |
| 2364 Object* next_weak_cell = weak_cell->next(); | 2364 Object* next_weak_cell = weak_cell->next(); |
| 2365 bool clear_value = true; | 2365 bool clear_value = true; |
| 2366 bool clear_next = true; | 2366 bool clear_next = true; |
| (...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3442 default: | 3442 default: |
| 3443 UNREACHABLE(); | 3443 UNREACHABLE(); |
| 3444 break; | 3444 break; |
| 3445 } | 3445 } |
| 3446 } | 3446 } |
| 3447 } | 3447 } |
| 3448 } | 3448 } |
| 3449 | 3449 |
| 3450 | 3450 |
| 3451 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 3451 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 3452 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); | |
| 3452 Heap::RelocationLock relocation_lock(heap()); | 3453 Heap::RelocationLock relocation_lock(heap()); |
| 3453 | 3454 |
| 3454 { | 3455 { |
| 3455 GCTracer::Scope gc_scope(heap()->tracer(), | 3456 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3456 GCTracer::Scope::MC_SWEEP_NEWSPACE); | 3457 GCTracer::Scope::MC_EVACUATE_NEW_SPACE); |
| 3457 EvacuationScope evacuation_scope(this); | 3458 EvacuationScope evacuation_scope(this); |
| 3458 EvacuateNewSpace(); | 3459 EvacuateNewSpace(); |
| 3459 } | 3460 } |
| 3460 | 3461 |
| 3461 { | 3462 { |
| 3462 GCTracer::Scope gc_scope(heap()->tracer(), | 3463 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3463 GCTracer::Scope::MC_EVACUATE_PAGES); | 3464 GCTracer::Scope::MC_EVACUATE_CANDIDATES); |
| 3464 EvacuationScope evacuation_scope(this); | 3465 EvacuationScope evacuation_scope(this); |
| 3465 EvacuatePagesInParallel(); | 3466 EvacuatePagesInParallel(); |
| 3466 } | 3467 } |
| 3467 | 3468 |
| 3469 UpdatePointersAfterEvacuation(); | |
| 3470 | |
| 3468 { | 3471 { |
| 3469 GCTracer::Scope gc_scope(heap()->tracer(), | 3472 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3470 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); | 3473 GCTracer::Scope::MC_EVACUATE_CLEAN_UP); |
| 3474 // After updating all pointers, we can finally sweep the aborted pages, | |
| 3475 // effectively overriding any forward pointers. | |
| 3476 SweepAbortedPages(); | |
| 3477 | |
| 3478 // EvacuateNewSpaceAndCandidates iterates over new space objects and for | |
| 3479 // ArrayBuffers either re-registers them as live or promotes them. This is | |
| 3480 // needed to properly free them. | |
| 3481 heap()->array_buffer_tracker()->FreeDead(false); | |
| 3482 | |
| 3483 // Deallocate evacuated candidate pages. | |
| 3484 ReleaseEvacuationCandidates(); | |
| 3485 } | |
| 3486 | |
| 3487 #ifdef VERIFY_HEAP | |
| 3488 if (FLAG_verify_heap && !sweeping_in_progress_) { | |
| 3489 VerifyEvacuation(heap()); | |
| 3490 } | |
| 3491 #endif | |
| 3492 } | |
| 3493 | |
| 3494 | |
| 3495 void MarkCompactCollector::UpdatePointersAfterEvacuation() { | |
| 3496 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3497 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); | |
| 3498 { | |
| 3499 GCTracer::Scope gc_scope( | |
| 3500 heap()->tracer(), | |
| 3501 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); | |
| 3471 UpdateSlotsRecordedIn(migration_slots_buffer_); | 3502 UpdateSlotsRecordedIn(migration_slots_buffer_); |
| 3472 if (FLAG_trace_fragmentation_verbose) { | 3503 if (FLAG_trace_fragmentation_verbose) { |
| 3473 PrintF(" migration slots buffer: %d\n", | 3504 PrintF(" migration slots buffer: %d\n", |
| 3474 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | 3505 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); |
| 3475 } | 3506 } |
| 3476 slots_buffer_allocator_->DeallocateChain(&migration_slots_buffer_); | 3507 slots_buffer_allocator_->DeallocateChain(&migration_slots_buffer_); |
| 3477 DCHECK(migration_slots_buffer_ == NULL); | 3508 DCHECK(migration_slots_buffer_ == NULL); |
| 3478 | 3509 |
| 3479 // TODO(hpayer): Process the slots buffers in parallel. This has to be done | 3510 // TODO(hpayer): Process the slots buffers in parallel. This has to be done |
| 3480 // after evacuation of all pages finishes. | 3511 // after evacuation of all pages finishes. |
| 3481 int buffers = evacuation_slots_buffers_.length(); | 3512 int buffers = evacuation_slots_buffers_.length(); |
| 3482 for (int i = 0; i < buffers; i++) { | 3513 for (int i = 0; i < buffers; i++) { |
| 3483 SlotsBuffer* buffer = evacuation_slots_buffers_[i]; | 3514 SlotsBuffer* buffer = evacuation_slots_buffers_[i]; |
| 3484 UpdateSlotsRecordedIn(buffer); | 3515 UpdateSlotsRecordedIn(buffer); |
| 3485 slots_buffer_allocator_->DeallocateChain(&buffer); | 3516 slots_buffer_allocator_->DeallocateChain(&buffer); |
| 3486 } | 3517 } |
| 3487 evacuation_slots_buffers_.Rewind(0); | 3518 evacuation_slots_buffers_.Rewind(0); |
| 3488 } | 3519 } |
| 3489 | 3520 |
| 3490 // Second pass: find pointers to new space and update them. | 3521 // Second pass: find pointers to new space and update them. |
| 3491 PointersUpdatingVisitor updating_visitor(heap()); | 3522 PointersUpdatingVisitor updating_visitor(heap()); |
| 3492 | 3523 |
| 3493 { | 3524 { |
| 3494 GCTracer::Scope gc_scope(heap()->tracer(), | 3525 GCTracer::Scope gc_scope( |
| 3495 GCTracer::Scope::MC_UPDATE_NEW_TO_NEW_POINTERS); | 3526 heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
| 3496 // Update pointers in to space. | 3527 // Update pointers in to space. |
| 3497 SemiSpaceIterator to_it(heap()->new_space()); | 3528 SemiSpaceIterator to_it(heap()->new_space()); |
| 3498 for (HeapObject* object = to_it.Next(); object != NULL; | 3529 for (HeapObject* object = to_it.Next(); object != NULL; |
| 3499 object = to_it.Next()) { | 3530 object = to_it.Next()) { |
| 3500 Map* map = object->map(); | 3531 Map* map = object->map(); |
| 3501 object->IterateBody(map->instance_type(), object->SizeFromMap(map), | 3532 object->IterateBody(map->instance_type(), object->SizeFromMap(map), |
| 3502 &updating_visitor); | 3533 &updating_visitor); |
| 3503 } | 3534 } |
| 3504 } | |
| 3505 | |
| 3506 { | |
| 3507 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3508 GCTracer::Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS); | |
| 3509 // Update roots. | 3535 // Update roots. |
| 3510 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3536 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 3511 } | |
| 3512 | 3537 |
| 3513 { | |
| 3514 GCTracer::Scope gc_scope(heap()->tracer(), | |
| 3515 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); | |
| 3516 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), | 3538 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), |
| 3517 &Heap::ScavengeStoreBufferCallback); | 3539 &Heap::ScavengeStoreBufferCallback); |
| 3518 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 3540 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
| 3519 } | 3541 } |
| 3520 | 3542 |
| 3521 int npages = evacuation_candidates_.length(); | 3543 int npages = evacuation_candidates_.length(); |
| 3522 { | 3544 { |
| 3523 GCTracer::Scope gc_scope( | 3545 GCTracer::Scope gc_scope( |
| 3524 heap()->tracer(), | 3546 heap()->tracer(), |
| 3525 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); | 3547 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED); |
| 3526 for (int i = 0; i < npages; i++) { | 3548 for (int i = 0; i < npages; i++) { |
| 3527 Page* p = evacuation_candidates_[i]; | 3549 Page* p = evacuation_candidates_[i]; |
| 3528 DCHECK(p->IsEvacuationCandidate() || | 3550 DCHECK(p->IsEvacuationCandidate() || |
| 3529 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3551 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
| 3530 | 3552 |
| 3531 if (p->IsEvacuationCandidate()) { | 3553 if (p->IsEvacuationCandidate()) { |
| 3532 UpdateSlotsRecordedIn(p->slots_buffer()); | 3554 UpdateSlotsRecordedIn(p->slots_buffer()); |
| 3533 if (FLAG_trace_fragmentation_verbose) { | 3555 if (FLAG_trace_fragmentation_verbose) { |
| 3534 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), | 3556 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), |
| 3535 SlotsBuffer::SizeOfChain(p->slots_buffer())); | 3557 SlotsBuffer::SizeOfChain(p->slots_buffer())); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3577 default: | 3599 default: |
| 3578 UNREACHABLE(); | 3600 UNREACHABLE(); |
| 3579 break; | 3601 break; |
| 3580 } | 3602 } |
| 3581 } | 3603 } |
| 3582 } | 3604 } |
| 3583 } | 3605 } |
| 3584 | 3606 |
| 3585 { | 3607 { |
| 3586 GCTracer::Scope gc_scope(heap()->tracer(), | 3608 GCTracer::Scope gc_scope(heap()->tracer(), |
| 3587 GCTracer::Scope::MC_UPDATE_MISC_POINTERS); | 3609 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); |
| 3588 heap_->string_table()->Iterate(&updating_visitor); | 3610 heap_->string_table()->Iterate(&updating_visitor); |
| 3589 | 3611 |
| 3590 // Update pointers from external string table. | 3612 // Update pointers from external string table. |
| 3591 heap_->UpdateReferencesInExternalStringTable( | 3613 heap_->UpdateReferencesInExternalStringTable( |
| 3592 &UpdateReferenceInExternalStringTableEntry); | 3614 &UpdateReferenceInExternalStringTableEntry); |
| 3593 | 3615 |
| 3594 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3616 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 3595 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); | 3617 heap()->ProcessAllWeakReferences(&evacuation_object_retainer); |
| 3596 } | 3618 } |
| 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 } | 3619 } |
| 3612 | 3620 |
| 3613 | 3621 |
| 3614 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { | 3622 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { |
| 3615 int npages = evacuation_candidates_.length(); | 3623 int npages = evacuation_candidates_.length(); |
| 3616 for (int i = 0; i < npages; i++) { | 3624 for (int i = 0; i < npages; i++) { |
| 3617 Page* p = evacuation_candidates_[i]; | 3625 Page* p = evacuation_candidates_[i]; |
| 3618 if (!p->IsEvacuationCandidate()) continue; | 3626 if (!p->IsEvacuationCandidate()) continue; |
| 3619 p->Unlink(); | 3627 p->Unlink(); |
| 3620 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3628 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3822 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_SWEEP); | 3830 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_SWEEP); |
| 3823 double start_time = 0.0; | 3831 double start_time = 0.0; |
| 3824 if (FLAG_print_cumulative_gc_stat) { | 3832 if (FLAG_print_cumulative_gc_stat) { |
| 3825 start_time = heap_->MonotonicallyIncreasingTimeInMs(); | 3833 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
| 3826 } | 3834 } |
| 3827 | 3835 |
| 3828 #ifdef DEBUG | 3836 #ifdef DEBUG |
| 3829 state_ = SWEEP_SPACES; | 3837 state_ = SWEEP_SPACES; |
| 3830 #endif | 3838 #endif |
| 3831 | 3839 |
| 3832 MoveEvacuationCandidatesToEndOfPagesList(); | |
|
Hannes Payer (out of office)
2015/12/11 09:27:31
I would leave this call in here, move them there t
ulan
2015/12/11 09:35:32
Done.
| |
| 3833 | |
| 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 |