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/incremental-marking.h" | 5 #include "src/heap/incremental-marking.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/compilation-cache.h" | 8 #include "src/compilation-cache.h" |
9 #include "src/conversions.h" | 9 #include "src/conversions.h" |
10 #include "src/heap/concurrent-marking.h" | 10 #include "src/heap/concurrent-marking.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 was_activated_(false), | 45 was_activated_(false), |
46 black_allocation_(false), | 46 black_allocation_(false), |
47 finalize_marking_completed_(false), | 47 finalize_marking_completed_(false), |
48 trace_wrappers_toggle_(false), | 48 trace_wrappers_toggle_(false), |
49 request_type_(NONE), | 49 request_type_(NONE), |
50 new_generation_observer_(*this, kAllocatedThreshold), | 50 new_generation_observer_(*this, kAllocatedThreshold), |
51 old_generation_observer_(*this, kAllocatedThreshold) {} | 51 old_generation_observer_(*this, kAllocatedThreshold) {} |
52 | 52 |
53 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { | 53 bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) { |
54 HeapObject* value_heap_obj = HeapObject::cast(value); | 54 HeapObject* value_heap_obj = HeapObject::cast(value); |
55 DCHECK(!ObjectMarking::IsImpossible(value_heap_obj, | 55 DCHECK(!ObjectMarking::IsImpossible<kAtomicity>( |
56 marking_state(value_heap_obj))); | 56 value_heap_obj, marking_state(value_heap_obj))); |
57 DCHECK(!ObjectMarking::IsImpossible(obj, marking_state(obj))); | 57 DCHECK(!ObjectMarking::IsImpossible<kAtomicity>(obj, marking_state(obj))); |
58 const bool is_black = ObjectMarking::IsBlack(obj, marking_state(obj)); | 58 const bool is_black = |
| 59 ObjectMarking::IsBlack<kAtomicity>(obj, marking_state(obj)); |
59 | 60 |
60 if (is_black && WhiteToGreyAndPush(value_heap_obj)) { | 61 if (is_black && WhiteToGreyAndPush(value_heap_obj)) { |
61 RestartIfNotMarking(); | 62 RestartIfNotMarking(); |
62 } | 63 } |
63 return is_compacting_ && is_black; | 64 return is_compacting_ && is_black; |
64 } | 65 } |
65 | 66 |
66 | 67 |
67 void IncrementalMarking::RecordWriteSlow(HeapObject* obj, Object** slot, | 68 void IncrementalMarking::RecordWriteSlow(HeapObject* obj, Object** slot, |
68 Object* value) { | 69 Object* value) { |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 | 123 |
123 void IncrementalMarking::RecordWriteIntoCodeSlow(Code* host, RelocInfo* rinfo, | 124 void IncrementalMarking::RecordWriteIntoCodeSlow(Code* host, RelocInfo* rinfo, |
124 Object* value) { | 125 Object* value) { |
125 if (BaseRecordWrite(host, value)) { | 126 if (BaseRecordWrite(host, value)) { |
126 // Object is not going to be rescanned. We need to record the slot. | 127 // Object is not going to be rescanned. We need to record the slot. |
127 heap_->mark_compact_collector()->RecordRelocSlot(host, rinfo, value); | 128 heap_->mark_compact_collector()->RecordRelocSlot(host, rinfo, value); |
128 } | 129 } |
129 } | 130 } |
130 | 131 |
131 bool IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj) { | 132 bool IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj) { |
132 if (ObjectMarking::WhiteToGrey(obj, marking_state(obj))) { | 133 if (ObjectMarking::WhiteToGrey<kAtomicity>(obj, marking_state(obj))) { |
133 marking_deque()->Push(obj); | 134 marking_deque()->Push(obj); |
134 return true; | 135 return true; |
135 } | 136 } |
136 return false; | 137 return false; |
137 } | 138 } |
138 | 139 |
139 void IncrementalMarking::TransferMark(Heap* heap, HeapObject* from, | 140 void IncrementalMarking::TransferMark(Heap* heap, HeapObject* from, |
140 HeapObject* to) { | 141 HeapObject* to) { |
141 DCHECK(MemoryChunk::FromAddress(from->address())->SweepingDone()); | 142 DCHECK(MemoryChunk::FromAddress(from->address())->SweepingDone()); |
142 // This is only used when resizing an object. | 143 // This is only used when resizing an object. |
143 DCHECK(MemoryChunk::FromAddress(from->address()) == | 144 DCHECK(MemoryChunk::FromAddress(from->address()) == |
144 MemoryChunk::FromAddress(to->address())); | 145 MemoryChunk::FromAddress(to->address())); |
145 | 146 |
146 if (!IsMarking()) return; | 147 if (!IsMarking()) return; |
147 | 148 |
148 // If the mark doesn't move, we don't check the color of the object. | 149 // If the mark doesn't move, we don't check the color of the object. |
149 // It doesn't matter whether the object is black, since it hasn't changed | 150 // It doesn't matter whether the object is black, since it hasn't changed |
150 // size, so the adjustment to the live data count will be zero anyway. | 151 // size, so the adjustment to the live data count will be zero anyway. |
151 if (from == to) return; | 152 if (from == to) return; |
152 | 153 |
153 MarkBit new_mark_bit = ObjectMarking::MarkBitFrom(to, marking_state(to)); | 154 MarkBit new_mark_bit = ObjectMarking::MarkBitFrom(to, marking_state(to)); |
154 MarkBit old_mark_bit = ObjectMarking::MarkBitFrom(from, marking_state(from)); | 155 MarkBit old_mark_bit = ObjectMarking::MarkBitFrom(from, marking_state(from)); |
155 | 156 |
156 if (Marking::IsBlack(old_mark_bit)) { | 157 if (Marking::IsBlack<kAtomicity>(old_mark_bit)) { |
157 if (from->address() + kPointerSize == to->address()) { | 158 if (from->address() + kPointerSize == to->address()) { |
158 // The old and the new markbits overlap. The |to| object has the | 159 // The old and the new markbits overlap. The |to| object has the |
159 // grey color. To make it black, we need to set the second bit. | 160 // grey color. To make it black, we need to set the second bit. |
160 DCHECK(new_mark_bit.Get()); | 161 DCHECK(new_mark_bit.Get<kAtomicity>()); |
161 new_mark_bit.Next().Set(); | 162 new_mark_bit.Next().Set<kAtomicity>(); |
162 } else { | 163 } else { |
163 bool success = Marking::WhiteToBlack(new_mark_bit); | 164 bool success = Marking::WhiteToBlack<kAtomicity>(new_mark_bit); |
164 DCHECK(success); | 165 DCHECK(success); |
165 USE(success); | 166 USE(success); |
166 } | 167 } |
167 } else if (Marking::IsGrey(old_mark_bit)) { | 168 } else if (Marking::IsGrey<kAtomicity>(old_mark_bit)) { |
168 if (from->address() + kPointerSize == to->address()) { | 169 if (from->address() + kPointerSize == to->address()) { |
169 // The old and the new markbits overlap. The |to| object has the | 170 // The old and the new markbits overlap. The |to| object has the |
170 // white color. To make it grey, we need to set the first bit. | 171 // white color. To make it grey, we need to set the first bit. |
171 // Note that Marking::WhiteToGrey does not work here because | 172 // Note that Marking::WhiteToGrey does not work here because |
172 // old_mark_bit.Next() can be set by the concurrent marker at any time. | 173 // old_mark_bit.Next() can be set by the concurrent marker at any time. |
173 new_mark_bit.Set(); | 174 new_mark_bit.Set(); |
174 DCHECK(!new_mark_bit.Next().Get()); | 175 DCHECK(!new_mark_bit.Next().Get()); |
175 } else { | 176 } else { |
176 bool success = Marking::WhiteToGrey(new_mark_bit); | 177 bool success = Marking::WhiteToGrey<kAtomicity>(new_mark_bit); |
177 DCHECK(success); | 178 DCHECK(success); |
178 USE(success); | 179 USE(success); |
179 } | 180 } |
180 marking_deque()->Push(to); | 181 marking_deque()->Push(to); |
181 RestartIfNotMarking(); | 182 RestartIfNotMarking(); |
182 } | 183 } |
183 } | 184 } |
184 | 185 |
185 class IncrementalMarkingMarkingVisitor | 186 class IncrementalMarkingMarkingVisitor |
186 : public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> { | 187 : public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> { |
(...skipping 25 matching lines...) Expand all Loading... |
212 bool scan_until_end = false; | 213 bool scan_until_end = false; |
213 do { | 214 do { |
214 VisitPointers(heap, object, HeapObject::RawField(object, start_offset), | 215 VisitPointers(heap, object, HeapObject::RawField(object, start_offset), |
215 HeapObject::RawField(object, end_offset)); | 216 HeapObject::RawField(object, end_offset)); |
216 start_offset = end_offset; | 217 start_offset = end_offset; |
217 end_offset = Min(object_size, end_offset + kProgressBarScanningChunk); | 218 end_offset = Min(object_size, end_offset + kProgressBarScanningChunk); |
218 scan_until_end = heap->incremental_marking()->marking_deque()->IsFull(); | 219 scan_until_end = heap->incremental_marking()->marking_deque()->IsFull(); |
219 } while (scan_until_end && start_offset < object_size); | 220 } while (scan_until_end && start_offset < object_size); |
220 chunk->set_progress_bar(start_offset); | 221 chunk->set_progress_bar(start_offset); |
221 if (start_offset < object_size) { | 222 if (start_offset < object_size) { |
222 if (ObjectMarking::IsGrey( | 223 if (ObjectMarking::IsGrey<IncrementalMarking::kAtomicity>( |
223 object, heap->incremental_marking()->marking_state(object))) { | 224 object, heap->incremental_marking()->marking_state(object))) { |
224 heap->incremental_marking()->marking_deque()->Unshift(object); | 225 heap->incremental_marking()->marking_deque()->Unshift(object); |
225 } else { | 226 } else { |
226 DCHECK(ObjectMarking::IsBlack( | 227 DCHECK(ObjectMarking::IsBlack<IncrementalMarking::kAtomicity>( |
227 object, heap->incremental_marking()->marking_state(object))); | 228 object, heap->incremental_marking()->marking_state(object))); |
228 heap->mark_compact_collector()->UnshiftBlack(object); | 229 heap->mark_compact_collector()->UnshiftBlack(object); |
229 } | 230 } |
230 heap->incremental_marking()->NotifyIncompleteScanOfObject( | 231 heap->incremental_marking()->NotifyIncompleteScanOfObject( |
231 object_size - (start_offset - already_scanned_offset)); | 232 object_size - (start_offset - already_scanned_offset)); |
232 } | 233 } |
233 } else { | 234 } else { |
234 FixedArrayVisitor::Visit(map, object); | 235 FixedArrayVisitor::Visit(map, object); |
235 } | 236 } |
236 } | 237 } |
237 | 238 |
238 static void VisitNativeContextIncremental(Map* map, HeapObject* object) { | 239 static void VisitNativeContextIncremental(Map* map, HeapObject* object) { |
239 Context* context = Context::cast(object); | 240 Context* context = Context::cast(object); |
240 | 241 |
241 // We will mark cache black with a separate pass when we finish marking. | 242 // We will mark cache black with a separate pass when we finish marking. |
242 // Note that GC can happen when the context is not fully initialized, | 243 // Note that GC can happen when the context is not fully initialized, |
243 // so the cache can be undefined. | 244 // so the cache can be undefined. |
244 Object* cache = context->get(Context::NORMALIZED_MAP_CACHE_INDEX); | 245 Object* cache = context->get(Context::NORMALIZED_MAP_CACHE_INDEX); |
245 if (!cache->IsUndefined(map->GetIsolate())) { | 246 if (!cache->IsUndefined(map->GetIsolate())) { |
246 if (cache->IsHeapObject()) { | 247 if (cache->IsHeapObject()) { |
247 HeapObject* heap_obj = HeapObject::cast(cache); | 248 HeapObject* heap_obj = HeapObject::cast(cache); |
248 // Mark the object grey if it is white, do not enque it into the marking | 249 // Mark the object grey if it is white, do not enque it into the marking |
249 // deque. | 250 // deque. |
250 Heap* heap = map->GetHeap(); | 251 Heap* heap = map->GetHeap(); |
251 bool ignored = ObjectMarking::WhiteToGrey( | 252 bool ignored = |
252 heap_obj, heap->incremental_marking()->marking_state(heap_obj)); | 253 ObjectMarking::WhiteToGrey<IncrementalMarking::kAtomicity>( |
| 254 heap_obj, heap->incremental_marking()->marking_state(heap_obj)); |
253 USE(ignored); | 255 USE(ignored); |
254 } | 256 } |
255 } | 257 } |
256 VisitNativeContext(map, context); | 258 VisitNativeContext(map, context); |
257 } | 259 } |
258 | 260 |
259 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { | 261 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { |
260 Object* target = *p; | 262 Object* target = *p; |
261 if (target->IsHeapObject()) { | 263 if (target->IsHeapObject()) { |
262 heap->mark_compact_collector()->RecordSlot(object, p, target); | 264 heap->mark_compact_collector()->RecordSlot(object, p, target); |
(...skipping 14 matching lines...) Expand all Loading... |
277 | 279 |
278 // Marks the object grey and pushes it on the marking stack. | 280 // Marks the object grey and pushes it on the marking stack. |
279 INLINE(static void MarkObject(Heap* heap, Object* obj)) { | 281 INLINE(static void MarkObject(Heap* heap, Object* obj)) { |
280 heap->incremental_marking()->WhiteToGreyAndPush(HeapObject::cast(obj)); | 282 heap->incremental_marking()->WhiteToGreyAndPush(HeapObject::cast(obj)); |
281 } | 283 } |
282 | 284 |
283 // Marks the object black without pushing it on the marking stack. | 285 // Marks the object black without pushing it on the marking stack. |
284 // Returns true if object needed marking and false otherwise. | 286 // Returns true if object needed marking and false otherwise. |
285 INLINE(static bool MarkObjectWithoutPush(Heap* heap, Object* obj)) { | 287 INLINE(static bool MarkObjectWithoutPush(Heap* heap, Object* obj)) { |
286 HeapObject* heap_object = HeapObject::cast(obj); | 288 HeapObject* heap_object = HeapObject::cast(obj); |
287 return ObjectMarking::WhiteToBlack( | 289 return ObjectMarking::WhiteToBlack<IncrementalMarking::kAtomicity>( |
288 heap_object, heap->incremental_marking()->marking_state(heap_object)); | 290 heap_object, heap->incremental_marking()->marking_state(heap_object)); |
289 } | 291 } |
290 }; | 292 }; |
291 | 293 |
292 void IncrementalMarking::IterateBlackObject(HeapObject* object) { | 294 void IncrementalMarking::IterateBlackObject(HeapObject* object) { |
293 if (IsMarking() && ObjectMarking::IsBlack(object, marking_state(object))) { | 295 if (IsMarking() && |
| 296 ObjectMarking::IsBlack<kAtomicity>(object, marking_state(object))) { |
294 Page* page = Page::FromAddress(object->address()); | 297 Page* page = Page::FromAddress(object->address()); |
295 if ((page->owner() != nullptr) && (page->owner()->identity() == LO_SPACE)) { | 298 if ((page->owner() != nullptr) && (page->owner()->identity() == LO_SPACE)) { |
296 // IterateBlackObject requires us to visit the whole object. | 299 // IterateBlackObject requires us to visit the whole object. |
297 page->ResetProgressBar(); | 300 page->ResetProgressBar(); |
298 } | 301 } |
299 Map* map = object->map(); | 302 Map* map = object->map(); |
300 WhiteToGreyAndPush(map); | 303 WhiteToGreyAndPush(map); |
301 IncrementalMarkingMarkingVisitor::IterateBody(map, object); | 304 IncrementalMarkingMarkingVisitor::IterateBody(map, object); |
302 } | 305 } |
303 } | 306 } |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 Object* weak_cell_obj = heap()->encountered_weak_cells(); | 643 Object* weak_cell_obj = heap()->encountered_weak_cells(); |
641 Object* weak_cell_head = Smi::kZero; | 644 Object* weak_cell_head = Smi::kZero; |
642 WeakCell* prev_weak_cell_obj = NULL; | 645 WeakCell* prev_weak_cell_obj = NULL; |
643 while (weak_cell_obj != Smi::kZero) { | 646 while (weak_cell_obj != Smi::kZero) { |
644 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); | 647 WeakCell* weak_cell = reinterpret_cast<WeakCell*>(weak_cell_obj); |
645 // We do not insert cleared weak cells into the list, so the value | 648 // We do not insert cleared weak cells into the list, so the value |
646 // cannot be a Smi here. | 649 // cannot be a Smi here. |
647 HeapObject* value = HeapObject::cast(weak_cell->value()); | 650 HeapObject* value = HeapObject::cast(weak_cell->value()); |
648 // Remove weak cells with live objects from the list, they do not need | 651 // Remove weak cells with live objects from the list, they do not need |
649 // clearing. | 652 // clearing. |
650 if (ObjectMarking::IsBlackOrGrey(value, marking_state(value))) { | 653 if (ObjectMarking::IsBlackOrGrey<kAtomicity>(value, marking_state(value))) { |
651 // Record slot, if value is pointing to an evacuation candidate. | 654 // Record slot, if value is pointing to an evacuation candidate. |
652 Object** slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); | 655 Object** slot = HeapObject::RawField(weak_cell, WeakCell::kValueOffset); |
653 heap_->mark_compact_collector()->RecordSlot(weak_cell, slot, *slot); | 656 heap_->mark_compact_collector()->RecordSlot(weak_cell, slot, *slot); |
654 // Remove entry somewhere after top. | 657 // Remove entry somewhere after top. |
655 if (prev_weak_cell_obj != NULL) { | 658 if (prev_weak_cell_obj != NULL) { |
656 prev_weak_cell_obj->set_next(weak_cell->next()); | 659 prev_weak_cell_obj->set_next(weak_cell->next()); |
657 } | 660 } |
658 weak_cell_obj = weak_cell->next(); | 661 weak_cell_obj = weak_cell->next(); |
659 weak_cell->clear_next(the_hole_value); | 662 weak_cell->clear_next(the_hole_value); |
660 } else { | 663 } else { |
(...skipping 10 matching lines...) Expand all Loading... |
671 | 674 |
672 | 675 |
673 bool ShouldRetainMap(Map* map, int age) { | 676 bool ShouldRetainMap(Map* map, int age) { |
674 if (age == 0) { | 677 if (age == 0) { |
675 // The map has aged. Do not retain this map. | 678 // The map has aged. Do not retain this map. |
676 return false; | 679 return false; |
677 } | 680 } |
678 Object* constructor = map->GetConstructor(); | 681 Object* constructor = map->GetConstructor(); |
679 Heap* heap = map->GetHeap(); | 682 Heap* heap = map->GetHeap(); |
680 if (!constructor->IsHeapObject() || | 683 if (!constructor->IsHeapObject() || |
681 ObjectMarking::IsWhite(HeapObject::cast(constructor), | 684 ObjectMarking::IsWhite<IncrementalMarking::kAtomicity>( |
682 heap->incremental_marking()->marking_state( | 685 HeapObject::cast(constructor), |
683 HeapObject::cast(constructor)))) { | 686 heap->incremental_marking()->marking_state( |
| 687 HeapObject::cast(constructor)))) { |
684 // The constructor is dead, no new objects with this map can | 688 // The constructor is dead, no new objects with this map can |
685 // be created. Do not retain this map. | 689 // be created. Do not retain this map. |
686 return false; | 690 return false; |
687 } | 691 } |
688 return true; | 692 return true; |
689 } | 693 } |
690 | 694 |
691 | 695 |
692 void IncrementalMarking::RetainMaps() { | 696 void IncrementalMarking::RetainMaps() { |
693 // Do not retain dead maps if flag disables it or there is | 697 // Do not retain dead maps if flag disables it or there is |
694 // - memory pressure (reduce_memory_footprint_), | 698 // - memory pressure (reduce_memory_footprint_), |
695 // - GC is requested by tests or dev-tools (abort_incremental_marking_). | 699 // - GC is requested by tests or dev-tools (abort_incremental_marking_). |
696 bool map_retaining_is_disabled = heap()->ShouldReduceMemory() || | 700 bool map_retaining_is_disabled = heap()->ShouldReduceMemory() || |
697 heap()->ShouldAbortIncrementalMarking() || | 701 heap()->ShouldAbortIncrementalMarking() || |
698 FLAG_retain_maps_for_n_gc == 0; | 702 FLAG_retain_maps_for_n_gc == 0; |
699 ArrayList* retained_maps = heap()->retained_maps(); | 703 ArrayList* retained_maps = heap()->retained_maps(); |
700 int length = retained_maps->Length(); | 704 int length = retained_maps->Length(); |
701 // The number_of_disposed_maps separates maps in the retained_maps | 705 // The number_of_disposed_maps separates maps in the retained_maps |
702 // array that were created before and after context disposal. | 706 // array that were created before and after context disposal. |
703 // We do not age and retain disposed maps to avoid memory leaks. | 707 // We do not age and retain disposed maps to avoid memory leaks. |
704 int number_of_disposed_maps = heap()->number_of_disposed_maps_; | 708 int number_of_disposed_maps = heap()->number_of_disposed_maps_; |
705 for (int i = 0; i < length; i += 2) { | 709 for (int i = 0; i < length; i += 2) { |
706 DCHECK(retained_maps->Get(i)->IsWeakCell()); | 710 DCHECK(retained_maps->Get(i)->IsWeakCell()); |
707 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); | 711 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); |
708 if (cell->cleared()) continue; | 712 if (cell->cleared()) continue; |
709 int age = Smi::cast(retained_maps->Get(i + 1))->value(); | 713 int age = Smi::cast(retained_maps->Get(i + 1))->value(); |
710 int new_age; | 714 int new_age; |
711 Map* map = Map::cast(cell->value()); | 715 Map* map = Map::cast(cell->value()); |
712 if (i >= number_of_disposed_maps && !map_retaining_is_disabled && | 716 if (i >= number_of_disposed_maps && !map_retaining_is_disabled && |
713 ObjectMarking::IsWhite(map, marking_state(map))) { | 717 ObjectMarking::IsWhite<kAtomicity>(map, marking_state(map))) { |
714 if (ShouldRetainMap(map, age)) { | 718 if (ShouldRetainMap(map, age)) { |
715 WhiteToGreyAndPush(map); | 719 WhiteToGreyAndPush(map); |
716 } | 720 } |
717 Object* prototype = map->prototype(); | 721 Object* prototype = map->prototype(); |
718 if (age > 0 && prototype->IsHeapObject() && | 722 if (age > 0 && prototype->IsHeapObject() && |
719 ObjectMarking::IsWhite(HeapObject::cast(prototype), | 723 ObjectMarking::IsWhite<kAtomicity>( |
720 marking_state(HeapObject::cast(prototype)))) { | 724 HeapObject::cast(prototype), |
| 725 marking_state(HeapObject::cast(prototype)))) { |
721 // The prototype is not marked, age the map. | 726 // The prototype is not marked, age the map. |
722 new_age = age - 1; | 727 new_age = age - 1; |
723 } else { | 728 } else { |
724 // The prototype and the constructor are marked, this map keeps only | 729 // The prototype and the constructor are marked, this map keeps only |
725 // transition tree alive, not JSObjects. Do not age the map. | 730 // transition tree alive, not JSObjects. Do not age the map. |
726 new_age = age; | 731 new_age = age; |
727 } | 732 } |
728 } else { | 733 } else { |
729 new_age = FLAG_retain_maps_for_n_gc; | 734 new_age = FLAG_retain_maps_for_n_gc; |
730 } | 735 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
801 MapWord map_word = obj->map_word(); | 806 MapWord map_word = obj->map_word(); |
802 if (!map_word.IsForwardingAddress()) { | 807 if (!map_word.IsForwardingAddress()) { |
803 // There may be objects on the marking deque that do not exist anymore, | 808 // There may be objects on the marking deque that do not exist anymore, |
804 // e.g. left trimmed objects or objects from the root set (frames). | 809 // e.g. left trimmed objects or objects from the root set (frames). |
805 // If these object are dead at scavenging time, their marking deque | 810 // If these object are dead at scavenging time, their marking deque |
806 // entries will not point to forwarding addresses. Hence, we can discard | 811 // entries will not point to forwarding addresses. Hence, we can discard |
807 // them. | 812 // them. |
808 return nullptr; | 813 return nullptr; |
809 } | 814 } |
810 HeapObject* dest = map_word.ToForwardingAddress(); | 815 HeapObject* dest = map_word.ToForwardingAddress(); |
811 if (ObjectMarking::IsBlack(dest, marking_state(dest))) { | 816 if (ObjectMarking::IsBlack<kAtomicity>(dest, marking_state(dest))) { |
812 // The object is already processed by the marker. | 817 // The object is already processed by the marker. |
813 return nullptr; | 818 return nullptr; |
814 } | 819 } |
815 DCHECK( | 820 DCHECK(ObjectMarking::IsGrey<kAtomicity>(obj, marking_state(obj)) || |
816 ObjectMarking::IsGrey(obj, marking_state(obj)) || | 821 (obj->IsFiller() && |
817 (obj->IsFiller() && ObjectMarking::IsWhite(obj, marking_state(obj)))); | 822 ObjectMarking::IsWhite<kAtomicity>(obj, marking_state(obj)))); |
818 return dest; | 823 return dest; |
819 } else { | 824 } else { |
820 DCHECK(ObjectMarking::IsGrey(obj, marking_state(obj)) || | 825 DCHECK(ObjectMarking::IsGrey<kAtomicity>(obj, marking_state(obj)) || |
821 (obj->IsFiller() && | 826 (obj->IsFiller() && |
822 ObjectMarking::IsWhite(obj, marking_state(obj))) || | 827 ObjectMarking::IsWhite<kAtomicity>(obj, marking_state(obj))) || |
823 (MemoryChunk::FromAddress(obj->address()) | 828 (MemoryChunk::FromAddress(obj->address()) |
824 ->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | 829 ->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && |
825 ObjectMarking::IsBlack(obj, marking_state(obj)))); | 830 ObjectMarking::IsBlack<kAtomicity>(obj, marking_state(obj)))); |
826 // Skip one word filler objects that appear on the | 831 // Skip one word filler objects that appear on the |
827 // stack when we perform in place array shift. | 832 // stack when we perform in place array shift. |
828 return (obj->map() == filler_map) ? nullptr : obj; | 833 return (obj->map() == filler_map) ? nullptr : obj; |
829 } | 834 } |
830 }); | 835 }); |
831 } | 836 } |
832 | 837 |
833 | 838 |
834 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { | 839 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { |
835 WhiteToGreyAndPush(map); | 840 WhiteToGreyAndPush(map); |
836 | 841 |
837 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); | 842 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); |
838 | 843 |
839 #if ENABLE_SLOW_DCHECKS | 844 #if ENABLE_SLOW_DCHECKS |
840 MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj, marking_state(obj)); | 845 MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj, marking_state(obj)); |
841 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | 846 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
842 SLOW_DCHECK(Marking::IsGrey(mark_bit) || | 847 SLOW_DCHECK(Marking::IsGrey<kAtomicity>(mark_bit) || |
843 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | 848 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && |
844 Marking::IsBlack(mark_bit))); | 849 Marking::IsBlack<kAtomicity>(mark_bit))); |
845 #endif | 850 #endif |
846 ObjectMarking::GreyToBlack(obj, marking_state(obj)); | 851 ObjectMarking::GreyToBlack<kAtomicity>(obj, marking_state(obj)); |
847 } | 852 } |
848 | 853 |
849 intptr_t IncrementalMarking::ProcessMarkingDeque( | 854 intptr_t IncrementalMarking::ProcessMarkingDeque( |
850 intptr_t bytes_to_process, ForceCompletionAction completion) { | 855 intptr_t bytes_to_process, ForceCompletionAction completion) { |
851 intptr_t bytes_processed = 0; | 856 intptr_t bytes_processed = 0; |
852 while (!marking_deque()->IsEmpty() && (bytes_processed < bytes_to_process || | 857 while (!marking_deque()->IsEmpty() && (bytes_processed < bytes_to_process || |
853 completion == FORCE_COMPLETION)) { | 858 completion == FORCE_COMPLETION)) { |
854 HeapObject* obj = marking_deque()->Pop(); | 859 HeapObject* obj = marking_deque()->Pop(); |
855 | 860 |
856 // Left trimming may result in white, grey, or black filler objects on the | 861 // Left trimming may result in white, grey, or black filler objects on the |
857 // marking deque. Ignore these objects. | 862 // marking deque. Ignore these objects. |
858 if (obj->IsFiller()) { | 863 if (obj->IsFiller()) { |
859 DCHECK(!ObjectMarking::IsImpossible(obj, marking_state(obj))); | 864 DCHECK(!ObjectMarking::IsImpossible<kAtomicity>(obj, marking_state(obj))); |
860 continue; | 865 continue; |
861 } | 866 } |
862 | 867 |
863 Map* map = obj->map(); | 868 Map* map = obj->map(); |
864 int size = obj->SizeFromMap(map); | 869 int size = obj->SizeFromMap(map); |
865 unscanned_bytes_of_large_object_ = 0; | 870 unscanned_bytes_of_large_object_ = 0; |
866 VisitObject(map, obj, size); | 871 VisitObject(map, obj, size); |
867 bytes_processed += size - unscanned_bytes_of_large_object_; | 872 bytes_processed += size - unscanned_bytes_of_large_object_; |
868 } | 873 } |
869 // Report all found wrappers to the embedder. This is necessary as the | 874 // Report all found wrappers to the embedder. This is necessary as the |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
905 } | 910 } |
906 | 911 |
907 Object* context = heap_->native_contexts_list(); | 912 Object* context = heap_->native_contexts_list(); |
908 while (!context->IsUndefined(heap_->isolate())) { | 913 while (!context->IsUndefined(heap_->isolate())) { |
909 // GC can happen when the context is not fully initialized, | 914 // GC can happen when the context is not fully initialized, |
910 // so the cache can be undefined. | 915 // so the cache can be undefined. |
911 HeapObject* cache = HeapObject::cast( | 916 HeapObject* cache = HeapObject::cast( |
912 Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX)); | 917 Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX)); |
913 if (!cache->IsUndefined(heap_->isolate())) { | 918 if (!cache->IsUndefined(heap_->isolate())) { |
914 // Mark the cache black if it is grey. | 919 // Mark the cache black if it is grey. |
915 bool ignored = ObjectMarking::GreyToBlack(cache, marking_state(cache)); | 920 bool ignored = |
| 921 ObjectMarking::GreyToBlack<kAtomicity>(cache, marking_state(cache)); |
916 USE(ignored); | 922 USE(ignored); |
917 } | 923 } |
918 context = Context::cast(context)->next_context_link(); | 924 context = Context::cast(context)->next_context_link(); |
919 } | 925 } |
920 } | 926 } |
921 | 927 |
922 | 928 |
923 void IncrementalMarking::Stop() { | 929 void IncrementalMarking::Stop() { |
924 if (IsStopped()) return; | 930 if (IsStopped()) return; |
925 if (FLAG_trace_incremental_marking) { | 931 if (FLAG_trace_incremental_marking) { |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 idle_marking_delay_counter_++; | 1192 idle_marking_delay_counter_++; |
1187 } | 1193 } |
1188 | 1194 |
1189 | 1195 |
1190 void IncrementalMarking::ClearIdleMarkingDelayCounter() { | 1196 void IncrementalMarking::ClearIdleMarkingDelayCounter() { |
1191 idle_marking_delay_counter_ = 0; | 1197 idle_marking_delay_counter_ = 0; |
1192 } | 1198 } |
1193 | 1199 |
1194 } // namespace internal | 1200 } // namespace internal |
1195 } // namespace v8 | 1201 } // namespace v8 |
OLD | NEW |