| 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 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 heap()->code_space()->EvictEvacuationCandidatesFromLinearAllocationArea(); | 310 heap()->code_space()->EvictEvacuationCandidatesFromLinearAllocationArea(); |
| 311 | 311 |
| 312 compacting_ = evacuation_candidates_.length() > 0; | 312 compacting_ = evacuation_candidates_.length() > 0; |
| 313 } | 313 } |
| 314 | 314 |
| 315 return compacting_; | 315 return compacting_; |
| 316 } | 316 } |
| 317 | 317 |
| 318 void MarkCompactCollector::ClearInvalidRememberedSetSlots() { | 318 void MarkCompactCollector::ClearInvalidRememberedSetSlots() { |
| 319 { | 319 { |
| 320 GCTracer::Scope gc_scope(heap()->tracer(), | 320 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STORE_BUFFER); |
| 321 GCTracer::Scope::MC_CLEAR_STORE_BUFFER); | |
| 322 RememberedSet<OLD_TO_NEW>::ClearInvalidSlots(heap()); | 321 RememberedSet<OLD_TO_NEW>::ClearInvalidSlots(heap()); |
| 323 } | 322 } |
| 324 // There is not need to filter the old to old set because | 323 // There is not need to filter the old to old set because |
| 325 // it is completely cleared after the mark-compact GC. | 324 // it is completely cleared after the mark-compact GC. |
| 326 // The slots that become invalid due to runtime transitions are | 325 // The slots that become invalid due to runtime transitions are |
| 327 // cleared eagerly immediately after the transition. | 326 // cleared eagerly immediately after the transition. |
| 328 | 327 |
| 329 #ifdef VERIFY_HEAP | 328 #ifdef VERIFY_HEAP |
| 330 if (FLAG_verify_heap) { | 329 if (FLAG_verify_heap) { |
| 331 RememberedSet<OLD_TO_NEW>::VerifyValidSlots(heap()); | 330 RememberedSet<OLD_TO_NEW>::VerifyValidSlots(heap()); |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 849 | 848 |
| 850 #ifdef VERIFY_HEAP | 849 #ifdef VERIFY_HEAP |
| 851 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 850 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
| 852 VerifyMarkbitsAreClean(); | 851 VerifyMarkbitsAreClean(); |
| 853 } | 852 } |
| 854 #endif | 853 #endif |
| 855 } | 854 } |
| 856 | 855 |
| 857 | 856 |
| 858 void MarkCompactCollector::Finish() { | 857 void MarkCompactCollector::Finish() { |
| 859 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_FINISH); | 858 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_FINISH); |
| 860 | 859 |
| 861 // The hashing of weak_object_to_code_table is no longer valid. | 860 // The hashing of weak_object_to_code_table is no longer valid. |
| 862 heap()->weak_object_to_code_table()->Rehash( | 861 heap()->weak_object_to_code_table()->Rehash( |
| 863 heap()->isolate()->factory()->undefined_value()); | 862 heap()->isolate()->factory()->undefined_value()); |
| 864 | 863 |
| 865 // Clear the marking state of live large objects. | 864 // Clear the marking state of live large objects. |
| 866 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); | 865 heap_->lo_space()->ClearMarkingStateOfLiveObjects(); |
| 867 | 866 |
| 868 #ifdef DEBUG | 867 #ifdef DEBUG |
| 869 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 868 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
| (...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2075 DCHECK(IsEmpty()); | 2074 DCHECK(IsEmpty()); |
| 2076 DCHECK(!overflowed_); | 2075 DCHECK(!overflowed_); |
| 2077 } | 2076 } |
| 2078 DCHECK(in_use_); | 2077 DCHECK(in_use_); |
| 2079 top_ = bottom_ = 0xdecbad; | 2078 top_ = bottom_ = 0xdecbad; |
| 2080 in_use_ = false; | 2079 in_use_ = false; |
| 2081 } | 2080 } |
| 2082 | 2081 |
| 2083 | 2082 |
| 2084 void MarkCompactCollector::MarkLiveObjects() { | 2083 void MarkCompactCollector::MarkLiveObjects() { |
| 2085 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK); | 2084 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK); |
| 2086 double start_time = 0.0; | 2085 double start_time = 0.0; |
| 2087 if (FLAG_print_cumulative_gc_stat) { | 2086 if (FLAG_print_cumulative_gc_stat) { |
| 2088 start_time = heap_->MonotonicallyIncreasingTimeInMs(); | 2087 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
| 2089 } | 2088 } |
| 2090 // The recursive GC marker detects when it is nearing stack overflow, | 2089 // The recursive GC marker detects when it is nearing stack overflow, |
| 2091 // and switches to a different marking system. JS interrupts interfere | 2090 // and switches to a different marking system. JS interrupts interfere |
| 2092 // with the C stack limit check. | 2091 // with the C stack limit check. |
| 2093 PostponeInterruptsScope postpone(isolate()); | 2092 PostponeInterruptsScope postpone(isolate()); |
| 2094 | 2093 |
| 2095 { | 2094 { |
| 2096 GCTracer::Scope gc_scope(heap()->tracer(), | 2095 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); |
| 2097 GCTracer::Scope::MC_MARK_FINISH_INCREMENTAL); | |
| 2098 IncrementalMarking* incremental_marking = heap_->incremental_marking(); | 2096 IncrementalMarking* incremental_marking = heap_->incremental_marking(); |
| 2099 if (was_marked_incrementally_) { | 2097 if (was_marked_incrementally_) { |
| 2100 incremental_marking->Finalize(); | 2098 incremental_marking->Finalize(); |
| 2101 } else { | 2099 } else { |
| 2102 // Abort any pending incremental activities e.g. incremental sweeping. | 2100 // Abort any pending incremental activities e.g. incremental sweeping. |
| 2103 incremental_marking->Stop(); | 2101 incremental_marking->Stop(); |
| 2104 if (marking_deque_.in_use()) { | 2102 if (marking_deque_.in_use()) { |
| 2105 marking_deque_.Uninitialize(true); | 2103 marking_deque_.Uninitialize(true); |
| 2106 } | 2104 } |
| 2107 } | 2105 } |
| 2108 } | 2106 } |
| 2109 | 2107 |
| 2110 #ifdef DEBUG | 2108 #ifdef DEBUG |
| 2111 DCHECK(state_ == PREPARE_GC); | 2109 DCHECK(state_ == PREPARE_GC); |
| 2112 state_ = MARK_LIVE_OBJECTS; | 2110 state_ = MARK_LIVE_OBJECTS; |
| 2113 #endif | 2111 #endif |
| 2114 | 2112 |
| 2115 EnsureMarkingDequeIsCommittedAndInitialize( | 2113 EnsureMarkingDequeIsCommittedAndInitialize( |
| 2116 MarkCompactCollector::kMaxMarkingDequeSize); | 2114 MarkCompactCollector::kMaxMarkingDequeSize); |
| 2117 | 2115 |
| 2118 { | 2116 { |
| 2119 GCTracer::Scope gc_scope(heap()->tracer(), | 2117 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); |
| 2120 GCTracer::Scope::MC_MARK_PREPARE_CODE_FLUSH); | |
| 2121 PrepareForCodeFlushing(); | 2118 PrepareForCodeFlushing(); |
| 2122 } | 2119 } |
| 2123 | 2120 |
| 2124 RootMarkingVisitor root_visitor(heap()); | 2121 RootMarkingVisitor root_visitor(heap()); |
| 2125 | 2122 |
| 2126 { | 2123 { |
| 2127 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS); | 2124 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS); |
| 2128 MarkRoots(&root_visitor); | 2125 MarkRoots(&root_visitor); |
| 2129 ProcessTopOptimizedFrame(&root_visitor); | 2126 ProcessTopOptimizedFrame(&root_visitor); |
| 2130 } | 2127 } |
| 2131 | 2128 |
| 2132 { | 2129 { |
| 2133 GCTracer::Scope gc_scope(heap()->tracer(), | 2130 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE); |
| 2134 GCTracer::Scope::MC_MARK_WEAK_CLOSURE); | |
| 2135 | 2131 |
| 2136 // The objects reachable from the roots are marked, yet unreachable | 2132 // The objects reachable from the roots are marked, yet unreachable |
| 2137 // objects are unmarked. Mark objects reachable due to host | 2133 // objects are unmarked. Mark objects reachable due to host |
| 2138 // application specific logic or through Harmony weak maps. | 2134 // application specific logic or through Harmony weak maps. |
| 2139 { | 2135 { |
| 2140 GCTracer::Scope gc_scope(heap()->tracer(), | 2136 TRACE_GC(heap()->tracer(), |
| 2141 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_EPHEMERAL); | 2137 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_EPHEMERAL); |
| 2142 ProcessEphemeralMarking(&root_visitor, false); | 2138 ProcessEphemeralMarking(&root_visitor, false); |
| 2143 ProcessMarkingDeque(); | 2139 ProcessMarkingDeque(); |
| 2144 } | 2140 } |
| 2145 | 2141 |
| 2146 // The objects reachable from the roots, weak maps or object groups | 2142 // The objects reachable from the roots, weak maps or object groups |
| 2147 // are marked. Objects pointed to only by weak global handles cannot be | 2143 // are marked. Objects pointed to only by weak global handles cannot be |
| 2148 // immediately reclaimed. Instead, we have to mark them as pending and mark | 2144 // immediately reclaimed. Instead, we have to mark them as pending and mark |
| 2149 // objects reachable from them. | 2145 // objects reachable from them. |
| 2150 // | 2146 // |
| 2151 // First we identify nonlive weak handles and mark them as pending | 2147 // First we identify nonlive weak handles and mark them as pending |
| 2152 // destruction. | 2148 // destruction. |
| 2153 { | 2149 { |
| 2154 GCTracer::Scope gc_scope( | 2150 TRACE_GC(heap()->tracer(), |
| 2155 heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_HANDLES); | 2151 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_HANDLES); |
| 2156 heap()->isolate()->global_handles()->IdentifyWeakHandles( | 2152 heap()->isolate()->global_handles()->IdentifyWeakHandles( |
| 2157 &IsUnmarkedHeapObject); | 2153 &IsUnmarkedHeapObject); |
| 2158 ProcessMarkingDeque(); | 2154 ProcessMarkingDeque(); |
| 2159 } | 2155 } |
| 2160 // Then we mark the objects. | 2156 // Then we mark the objects. |
| 2161 | 2157 |
| 2162 { | 2158 { |
| 2163 GCTracer::Scope gc_scope( | 2159 TRACE_GC(heap()->tracer(), |
| 2164 heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_ROOTS); | 2160 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_ROOTS); |
| 2165 heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor); | 2161 heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor); |
| 2166 ProcessMarkingDeque(); | 2162 ProcessMarkingDeque(); |
| 2167 } | 2163 } |
| 2168 | 2164 |
| 2169 // Repeat Harmony weak maps marking to mark unmarked objects reachable from | 2165 // Repeat Harmony weak maps marking to mark unmarked objects reachable from |
| 2170 // the weak roots we just marked as pending destruction. | 2166 // the weak roots we just marked as pending destruction. |
| 2171 // | 2167 // |
| 2172 // We only process harmony collections, as all object groups have been fully | 2168 // We only process harmony collections, as all object groups have been fully |
| 2173 // processed and no weakly reachable node can discover new objects groups. | 2169 // processed and no weakly reachable node can discover new objects groups. |
| 2174 { | 2170 { |
| 2175 GCTracer::Scope gc_scope(heap()->tracer(), | 2171 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); |
| 2176 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); | |
| 2177 ProcessEphemeralMarking(&root_visitor, true); | 2172 ProcessEphemeralMarking(&root_visitor, true); |
| 2178 ProcessMarkingDeque(); | 2173 ProcessMarkingDeque(); |
| 2179 } | 2174 } |
| 2180 } | 2175 } |
| 2181 | 2176 |
| 2182 if (FLAG_print_cumulative_gc_stat) { | 2177 if (FLAG_print_cumulative_gc_stat) { |
| 2183 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - | 2178 heap_->tracer()->AddMarkingTime(heap_->MonotonicallyIncreasingTimeInMs() - |
| 2184 start_time); | 2179 start_time); |
| 2185 } | 2180 } |
| 2186 if (FLAG_track_gc_object_stats) { | 2181 if (FLAG_track_gc_object_stats) { |
| 2187 if (FLAG_trace_gc_object_stats) { | 2182 if (FLAG_trace_gc_object_stats) { |
| 2188 heap()->object_stats_->TraceObjectStats(); | 2183 heap()->object_stats_->TraceObjectStats(); |
| 2189 } | 2184 } |
| 2190 heap()->object_stats_->CheckpointObjectStats(); | 2185 heap()->object_stats_->CheckpointObjectStats(); |
| 2191 } | 2186 } |
| 2192 } | 2187 } |
| 2193 | 2188 |
| 2194 | 2189 |
| 2195 void MarkCompactCollector::ClearNonLiveReferences() { | 2190 void MarkCompactCollector::ClearNonLiveReferences() { |
| 2196 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | 2191 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
| 2197 | 2192 |
| 2198 { | 2193 { |
| 2199 GCTracer::Scope gc_scope(heap()->tracer(), | 2194 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
| 2200 GCTracer::Scope::MC_CLEAR_STRING_TABLE); | |
| 2201 | 2195 |
| 2202 // Prune the string table removing all strings only pointed to by the | 2196 // Prune the string table removing all strings only pointed to by the |
| 2203 // string table. Cannot use string_table() here because the string | 2197 // string table. Cannot use string_table() here because the string |
| 2204 // table is marked. | 2198 // table is marked. |
| 2205 StringTable* string_table = heap()->string_table(); | 2199 StringTable* string_table = heap()->string_table(); |
| 2206 InternalizedStringTableCleaner internalized_visitor(heap(), string_table); | 2200 InternalizedStringTableCleaner internalized_visitor(heap(), string_table); |
| 2207 string_table->IterateElements(&internalized_visitor); | 2201 string_table->IterateElements(&internalized_visitor); |
| 2208 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); | 2202 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); |
| 2209 | 2203 |
| 2210 ExternalStringTableCleaner external_visitor(heap(), nullptr); | 2204 ExternalStringTableCleaner external_visitor(heap(), nullptr); |
| 2211 heap()->external_string_table_.Iterate(&external_visitor); | 2205 heap()->external_string_table_.Iterate(&external_visitor); |
| 2212 heap()->external_string_table_.CleanUp(); | 2206 heap()->external_string_table_.CleanUp(); |
| 2213 } | 2207 } |
| 2214 | 2208 |
| 2215 { | 2209 { |
| 2216 GCTracer::Scope gc_scope(heap()->tracer(), | 2210 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_LISTS); |
| 2217 GCTracer::Scope::MC_CLEAR_WEAK_LISTS); | |
| 2218 // Process the weak references. | 2211 // Process the weak references. |
| 2219 MarkCompactWeakObjectRetainer mark_compact_object_retainer; | 2212 MarkCompactWeakObjectRetainer mark_compact_object_retainer; |
| 2220 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); | 2213 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); |
| 2221 } | 2214 } |
| 2222 | 2215 |
| 2223 { | 2216 { |
| 2224 GCTracer::Scope gc_scope(heap()->tracer(), | 2217 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_GLOBAL_HANDLES); |
| 2225 GCTracer::Scope::MC_CLEAR_GLOBAL_HANDLES); | |
| 2226 | 2218 |
| 2227 // Remove object groups after marking phase. | 2219 // Remove object groups after marking phase. |
| 2228 heap()->isolate()->global_handles()->RemoveObjectGroups(); | 2220 heap()->isolate()->global_handles()->RemoveObjectGroups(); |
| 2229 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); | 2221 heap()->isolate()->global_handles()->RemoveImplicitRefGroups(); |
| 2230 } | 2222 } |
| 2231 | 2223 |
| 2232 // Flush code from collected candidates. | 2224 // Flush code from collected candidates. |
| 2233 if (is_code_flushing_enabled()) { | 2225 if (is_code_flushing_enabled()) { |
| 2234 GCTracer::Scope gc_scope(heap()->tracer(), | 2226 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_CODE_FLUSH); |
| 2235 GCTracer::Scope::MC_CLEAR_CODE_FLUSH); | |
| 2236 code_flusher_->ProcessCandidates(); | 2227 code_flusher_->ProcessCandidates(); |
| 2237 } | 2228 } |
| 2238 | 2229 |
| 2239 | 2230 |
| 2240 DependentCode* dependent_code_list; | 2231 DependentCode* dependent_code_list; |
| 2241 Object* non_live_map_list; | 2232 Object* non_live_map_list; |
| 2242 ClearWeakCells(&non_live_map_list, &dependent_code_list); | 2233 ClearWeakCells(&non_live_map_list, &dependent_code_list); |
| 2243 | 2234 |
| 2244 { | 2235 { |
| 2245 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAPS); | 2236 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_MAPS); |
| 2246 ClearSimpleMapTransitions(non_live_map_list); | 2237 ClearSimpleMapTransitions(non_live_map_list); |
| 2247 ClearFullMapTransitions(); | 2238 ClearFullMapTransitions(); |
| 2248 } | 2239 } |
| 2249 | 2240 |
| 2250 MarkDependentCodeForDeoptimization(dependent_code_list); | 2241 MarkDependentCodeForDeoptimization(dependent_code_list); |
| 2251 | 2242 |
| 2252 ClearWeakCollections(); | 2243 ClearWeakCollections(); |
| 2253 | 2244 |
| 2254 ClearInvalidRememberedSetSlots(); | 2245 ClearInvalidRememberedSetSlots(); |
| 2255 } | 2246 } |
| 2256 | 2247 |
| 2257 | 2248 |
| 2258 void MarkCompactCollector::MarkDependentCodeForDeoptimization( | 2249 void MarkCompactCollector::MarkDependentCodeForDeoptimization( |
| 2259 DependentCode* list_head) { | 2250 DependentCode* list_head) { |
| 2260 GCTracer::Scope gc_scope(heap()->tracer(), | 2251 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); |
| 2261 GCTracer::Scope::MC_CLEAR_DEPENDENT_CODE); | |
| 2262 Isolate* isolate = this->isolate(); | 2252 Isolate* isolate = this->isolate(); |
| 2263 DependentCode* current = list_head; | 2253 DependentCode* current = list_head; |
| 2264 while (current->length() > 0) { | 2254 while (current->length() > 0) { |
| 2265 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( | 2255 have_code_to_deoptimize_ |= current->MarkCodeForDeoptimization( |
| 2266 isolate, DependentCode::kWeakCodeGroup); | 2256 isolate, DependentCode::kWeakCodeGroup); |
| 2267 current = current->next_link(); | 2257 current = current->next_link(); |
| 2268 } | 2258 } |
| 2269 | 2259 |
| 2270 WeakHashTable* table = heap_->weak_object_to_code_table(); | 2260 WeakHashTable* table = heap_->weak_object_to_code_table(); |
| 2271 uint32_t capacity = table->Capacity(); | 2261 uint32_t capacity = table->Capacity(); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2472 value_slot); | 2462 value_slot); |
| 2473 } | 2463 } |
| 2474 } | 2464 } |
| 2475 } | 2465 } |
| 2476 weak_collection_obj = weak_collection->next(); | 2466 weak_collection_obj = weak_collection->next(); |
| 2477 } | 2467 } |
| 2478 } | 2468 } |
| 2479 | 2469 |
| 2480 | 2470 |
| 2481 void MarkCompactCollector::ClearWeakCollections() { | 2471 void MarkCompactCollector::ClearWeakCollections() { |
| 2482 GCTracer::Scope gc_scope(heap()->tracer(), | 2472 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_COLLECTIONS); |
| 2483 GCTracer::Scope::MC_CLEAR_WEAK_COLLECTIONS); | |
| 2484 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2473 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
| 2485 while (weak_collection_obj != Smi::FromInt(0)) { | 2474 while (weak_collection_obj != Smi::FromInt(0)) { |
| 2486 JSWeakCollection* weak_collection = | 2475 JSWeakCollection* weak_collection = |
| 2487 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2476 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
| 2488 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); | 2477 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
| 2489 if (weak_collection->table()->IsHashTable()) { | 2478 if (weak_collection->table()->IsHashTable()) { |
| 2490 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2479 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
| 2491 for (int i = 0; i < table->Capacity(); i++) { | 2480 for (int i = 0; i < table->Capacity(); i++) { |
| 2492 HeapObject* key = HeapObject::cast(table->KeyAt(i)); | 2481 HeapObject* key = HeapObject::cast(table->KeyAt(i)); |
| 2493 if (!MarkCompactCollector::IsMarked(key)) { | 2482 if (!MarkCompactCollector::IsMarked(key)) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2510 weak_collection_obj = weak_collection->next(); | 2499 weak_collection_obj = weak_collection->next(); |
| 2511 weak_collection->set_next(heap()->undefined_value()); | 2500 weak_collection->set_next(heap()->undefined_value()); |
| 2512 } | 2501 } |
| 2513 heap()->set_encountered_weak_collections(Smi::FromInt(0)); | 2502 heap()->set_encountered_weak_collections(Smi::FromInt(0)); |
| 2514 } | 2503 } |
| 2515 | 2504 |
| 2516 | 2505 |
| 2517 void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list, | 2506 void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list, |
| 2518 DependentCode** dependent_code_list) { | 2507 DependentCode** dependent_code_list) { |
| 2519 Heap* heap = this->heap(); | 2508 Heap* heap = this->heap(); |
| 2520 GCTracer::Scope gc_scope(heap->tracer(), | 2509 TRACE_GC(heap->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_CELLS); |
| 2521 GCTracer::Scope::MC_CLEAR_WEAK_CELLS); | |
| 2522 Object* weak_cell_obj = heap->encountered_weak_cells(); | 2510 Object* weak_cell_obj = heap->encountered_weak_cells(); |
| 2523 Object* the_hole_value = heap->the_hole_value(); | 2511 Object* the_hole_value = heap->the_hole_value(); |
| 2524 DependentCode* dependent_code_head = | 2512 DependentCode* dependent_code_head = |
| 2525 DependentCode::cast(heap->empty_fixed_array()); | 2513 DependentCode::cast(heap->empty_fixed_array()); |
| 2526 Object* non_live_map_head = Smi::FromInt(0); | 2514 Object* non_live_map_head = Smi::FromInt(0); |
| 2527 while (weak_cell_obj != Smi::FromInt(0)) { | 2515 while (weak_cell_obj != Smi::FromInt(0)) { |
| 2528 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); | 2516 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); |
| 2529 Object* next_weak_cell = weak_cell->next(); | 2517 Object* next_weak_cell = weak_cell->next(); |
| 2530 bool clear_value = true; | 2518 bool clear_value = true; |
| 2531 bool clear_next = true; | 2519 bool clear_next = true; |
| (...skipping 858 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3390 { | 3378 { |
| 3391 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); | 3379 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); |
| 3392 swept_pages(space->identity())->Add(p); | 3380 swept_pages(space->identity())->Add(p); |
| 3393 } | 3381 } |
| 3394 } | 3382 } |
| 3395 } | 3383 } |
| 3396 } | 3384 } |
| 3397 | 3385 |
| 3398 | 3386 |
| 3399 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 3387 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 3400 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); | 3388 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); |
| 3401 Heap::RelocationLock relocation_lock(heap()); | 3389 Heap::RelocationLock relocation_lock(heap()); |
| 3402 | 3390 |
| 3403 { | 3391 { |
| 3404 GCTracer::Scope gc_scope(heap()->tracer(), | 3392 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_COPY); |
| 3405 GCTracer::Scope::MC_EVACUATE_COPY); | |
| 3406 EvacuationScope evacuation_scope(this); | 3393 EvacuationScope evacuation_scope(this); |
| 3407 | 3394 |
| 3408 EvacuateNewSpacePrologue(); | 3395 EvacuateNewSpacePrologue(); |
| 3409 EvacuatePagesInParallel(); | 3396 EvacuatePagesInParallel(); |
| 3410 EvacuateNewSpaceEpilogue(); | 3397 EvacuateNewSpaceEpilogue(); |
| 3411 heap()->new_space()->set_age_mark(heap()->new_space()->top()); | 3398 heap()->new_space()->set_age_mark(heap()->new_space()->top()); |
| 3412 } | 3399 } |
| 3413 | 3400 |
| 3414 UpdatePointersAfterEvacuation(); | 3401 UpdatePointersAfterEvacuation(); |
| 3415 | 3402 |
| 3416 // Give pages that are queued to be freed back to the OS. Note that filtering | 3403 // Give pages that are queued to be freed back to the OS. Note that filtering |
| 3417 // slots only handles old space (for unboxed doubles), and thus map space can | 3404 // slots only handles old space (for unboxed doubles), and thus map space can |
| 3418 // still contain stale pointers. We only free the chunks after pointer updates | 3405 // still contain stale pointers. We only free the chunks after pointer updates |
| 3419 // to still have access to page headers. | 3406 // to still have access to page headers. |
| 3420 heap()->FreeQueuedChunks(); | 3407 heap()->FreeQueuedChunks(); |
| 3421 | 3408 |
| 3422 { | 3409 { |
| 3423 GCTracer::Scope gc_scope(heap()->tracer(), | 3410 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_CLEAN_UP); |
| 3424 GCTracer::Scope::MC_EVACUATE_CLEAN_UP); | |
| 3425 // After updating all pointers, we can finally sweep the aborted pages, | 3411 // After updating all pointers, we can finally sweep the aborted pages, |
| 3426 // effectively overriding any forward pointers. | 3412 // effectively overriding any forward pointers. |
| 3427 SweepAbortedPages(); | 3413 SweepAbortedPages(); |
| 3428 | 3414 |
| 3429 // EvacuateNewSpaceAndCandidates iterates over new space objects and for | 3415 // EvacuateNewSpaceAndCandidates iterates over new space objects and for |
| 3430 // ArrayBuffers either re-registers them as live or promotes them. This is | 3416 // ArrayBuffers either re-registers them as live or promotes them. This is |
| 3431 // needed to properly free them. | 3417 // needed to properly free them. |
| 3432 heap()->array_buffer_tracker()->FreeDead(false); | 3418 heap()->array_buffer_tracker()->FreeDead(false); |
| 3433 | 3419 |
| 3434 // Deallocate evacuated candidate pages. | 3420 // Deallocate evacuated candidate pages. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3551 page->Contains(space_start) ? space_start : page->area_start(); | 3537 page->Contains(space_start) ? space_start : page->area_start(); |
| 3552 Address end = page->Contains(space_end) ? space_end : page->area_end(); | 3538 Address end = page->Contains(space_end) ? space_end : page->area_end(); |
| 3553 job.AddPage(page, std::make_pair(start, end)); | 3539 job.AddPage(page, std::make_pair(start, end)); |
| 3554 } | 3540 } |
| 3555 PointersUpdatingVisitor visitor(heap); | 3541 PointersUpdatingVisitor visitor(heap); |
| 3556 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; | 3542 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; |
| 3557 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3543 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); |
| 3558 } | 3544 } |
| 3559 | 3545 |
| 3560 void MarkCompactCollector::UpdatePointersAfterEvacuation() { | 3546 void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
| 3561 GCTracer::Scope gc_scope(heap()->tracer(), | 3547 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
| 3562 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); | |
| 3563 | 3548 |
| 3564 PointersUpdatingVisitor updating_visitor(heap()); | 3549 PointersUpdatingVisitor updating_visitor(heap()); |
| 3565 | 3550 |
| 3566 { | 3551 { |
| 3567 GCTracer::Scope gc_scope( | 3552 TRACE_GC(heap()->tracer(), |
| 3568 heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); | 3553 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
| 3569 UpdateToSpacePointersInParallel(heap_); | 3554 UpdateToSpacePointersInParallel(heap_); |
| 3570 // Update roots. | 3555 // Update roots. |
| 3571 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3556 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 3572 UpdatePointersInParallel<OLD_TO_NEW>(heap_); | 3557 UpdatePointersInParallel<OLD_TO_NEW>(heap_); |
| 3573 } | 3558 } |
| 3574 | 3559 |
| 3575 { | 3560 { |
| 3576 Heap* heap = this->heap(); | 3561 Heap* heap = this->heap(); |
| 3577 GCTracer::Scope gc_scope( | 3562 TRACE_GC(heap->tracer(), |
| 3578 heap->tracer(), | 3563 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); |
| 3579 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); | |
| 3580 UpdatePointersInParallel<OLD_TO_OLD>(heap_); | 3564 UpdatePointersInParallel<OLD_TO_OLD>(heap_); |
| 3581 } | 3565 } |
| 3582 | 3566 |
| 3583 { | 3567 { |
| 3584 GCTracer::Scope gc_scope( | 3568 TRACE_GC(heap()->tracer(), |
| 3585 heap()->tracer(), | 3569 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED); |
| 3586 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_BETWEEN_EVACUATED); | |
| 3587 for (Page* p : evacuation_candidates_) { | 3570 for (Page* p : evacuation_candidates_) { |
| 3588 DCHECK(p->IsEvacuationCandidate()); | 3571 DCHECK(p->IsEvacuationCandidate()); |
| 3589 // Important: skip list should be cleared only after roots were updated | 3572 // Important: skip list should be cleared only after roots were updated |
| 3590 // because root iteration traverses the stack and might have to find | 3573 // because root iteration traverses the stack and might have to find |
| 3591 // code objects from non-updated pc pointing into evacuation candidate. | 3574 // code objects from non-updated pc pointing into evacuation candidate. |
| 3592 SkipList* list = p->skip_list(); | 3575 SkipList* list = p->skip_list(); |
| 3593 if (list != NULL) list->Clear(); | 3576 if (list != NULL) list->Clear(); |
| 3594 | 3577 |
| 3595 // First pass on aborted pages, fixing up all live objects. | 3578 // First pass on aborted pages, fixing up all live objects. |
| 3596 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { | 3579 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
| 3597 p->ClearEvacuationCandidate(); | 3580 p->ClearEvacuationCandidate(); |
| 3598 VisitLiveObjectsBody(p, &updating_visitor); | 3581 VisitLiveObjectsBody(p, &updating_visitor); |
| 3599 } | 3582 } |
| 3600 } | 3583 } |
| 3601 } | 3584 } |
| 3602 | 3585 |
| 3603 { | 3586 { |
| 3604 GCTracer::Scope gc_scope(heap()->tracer(), | 3587 TRACE_GC(heap()->tracer(), |
| 3605 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); | 3588 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK); |
| 3606 // Update pointers from external string table. | 3589 // Update pointers from external string table. |
| 3607 heap_->UpdateReferencesInExternalStringTable( | 3590 heap_->UpdateReferencesInExternalStringTable( |
| 3608 &UpdateReferenceInExternalStringTableEntry); | 3591 &UpdateReferenceInExternalStringTableEntry); |
| 3609 | 3592 |
| 3610 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3593 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 3611 heap()->ProcessWeakListRoots(&evacuation_object_retainer); | 3594 heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
| 3612 } | 3595 } |
| 3613 } | 3596 } |
| 3614 | 3597 |
| 3615 | 3598 |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3740 if (FLAG_gc_verbose) { | 3723 if (FLAG_gc_verbose) { |
| 3741 PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d", | 3724 PrintIsolate(isolate(), "sweeping: space=%s initialized_for_sweeping=%d", |
| 3742 AllocationSpaceName(space->identity()), will_be_swept); | 3725 AllocationSpaceName(space->identity()), will_be_swept); |
| 3743 } | 3726 } |
| 3744 std::sort(sweeping_list(space).begin(), sweeping_list(space).end(), | 3727 std::sort(sweeping_list(space).begin(), sweeping_list(space).end(), |
| 3745 [](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); }); | 3728 [](Page* a, Page* b) { return a->LiveBytes() < b->LiveBytes(); }); |
| 3746 } | 3729 } |
| 3747 | 3730 |
| 3748 | 3731 |
| 3749 void MarkCompactCollector::SweepSpaces() { | 3732 void MarkCompactCollector::SweepSpaces() { |
| 3750 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_SWEEP); | 3733 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_SWEEP); |
| 3751 double start_time = 0.0; | 3734 double start_time = 0.0; |
| 3752 if (FLAG_print_cumulative_gc_stat) { | 3735 if (FLAG_print_cumulative_gc_stat) { |
| 3753 start_time = heap_->MonotonicallyIncreasingTimeInMs(); | 3736 start_time = heap_->MonotonicallyIncreasingTimeInMs(); |
| 3754 } | 3737 } |
| 3755 | 3738 |
| 3756 #ifdef DEBUG | 3739 #ifdef DEBUG |
| 3757 state_ = SWEEP_SPACES; | 3740 state_ = SWEEP_SPACES; |
| 3758 #endif | 3741 #endif |
| 3759 | 3742 |
| 3760 { | 3743 { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3823 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3806 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3824 if (Marking::IsBlack(mark_bit)) { | 3807 if (Marking::IsBlack(mark_bit)) { |
| 3825 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3808 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3826 RecordRelocSlot(host, &rinfo, target); | 3809 RecordRelocSlot(host, &rinfo, target); |
| 3827 } | 3810 } |
| 3828 } | 3811 } |
| 3829 } | 3812 } |
| 3830 | 3813 |
| 3831 } // namespace internal | 3814 } // namespace internal |
| 3832 } // namespace v8 | 3815 } // namespace v8 |
| OLD | NEW |