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