Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
| 6 | 6 |
| 7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1169 if (MarkRecursively(heap, target_object)) return; | 1169 if (MarkRecursively(heap, target_object)) return; |
| 1170 heap->minor_mark_compact_collector()->MarkObject(target_object); | 1170 heap->minor_mark_compact_collector()->MarkObject(target_object); |
| 1171 } | 1171 } |
| 1172 } | 1172 } |
| 1173 | 1173 |
| 1174 protected: | 1174 protected: |
| 1175 inline static bool MarkRecursively(Heap* heap, HeapObject* object) { | 1175 inline static bool MarkRecursively(Heap* heap, HeapObject* object) { |
| 1176 StackLimitCheck check(heap->isolate()); | 1176 StackLimitCheck check(heap->isolate()); |
| 1177 if (check.HasOverflowed()) return false; | 1177 if (check.HasOverflowed()) return false; |
| 1178 | 1178 |
| 1179 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1179 if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1180 object, MarkingState::External(object))) | 1180 object, MarkingState::External(object))) { |
| 1181 return true; | 1181 IterateBody(object->map(), object); |
| 1182 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1182 } |
| 1183 object, MarkingState::External(object)); | |
| 1184 IterateBody(object->map(), object); | |
| 1185 return true; | 1183 return true; |
| 1186 } | 1184 } |
| 1187 }; | 1185 }; |
| 1188 | 1186 |
| 1189 class MarkCompactMarkingVisitor | 1187 class MarkCompactMarkingVisitor |
| 1190 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { | 1188 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { |
| 1191 public: | 1189 public: |
| 1192 static void Initialize(); | 1190 static void Initialize(); |
| 1193 | 1191 |
| 1194 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { | 1192 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1210 } | 1208 } |
| 1211 | 1209 |
| 1212 // Marks the object black and pushes it on the marking stack. | 1210 // Marks the object black and pushes it on the marking stack. |
| 1213 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { | 1211 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { |
| 1214 heap->mark_compact_collector()->MarkObject(object); | 1212 heap->mark_compact_collector()->MarkObject(object); |
| 1215 } | 1213 } |
| 1216 | 1214 |
| 1217 // Marks the object black without pushing it on the marking stack. | 1215 // Marks the object black without pushing it on the marking stack. |
| 1218 // Returns true if object needed marking and false otherwise. | 1216 // Returns true if object needed marking and false otherwise. |
| 1219 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { | 1217 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { |
| 1220 if (ObjectMarking::IsWhite(object, MarkingState::Internal(object))) { | 1218 return ObjectMarking::WhiteToBlack(object, MarkingState::Internal(object)); |
| 1221 ObjectMarking::WhiteToBlack(object, MarkingState::Internal(object)); | |
| 1222 return true; | |
| 1223 } | |
| 1224 return false; | |
| 1225 } | 1219 } |
| 1226 | 1220 |
| 1227 // Mark object pointed to by p. | 1221 // Mark object pointed to by p. |
| 1228 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, | 1222 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, |
| 1229 HeapObject* object, Object** p)) { | 1223 HeapObject* object, Object** p)) { |
| 1230 if (!(*p)->IsHeapObject()) return; | 1224 if (!(*p)->IsHeapObject()) return; |
| 1231 HeapObject* target_object = HeapObject::cast(*p); | 1225 HeapObject* target_object = HeapObject::cast(*p); |
| 1232 collector->RecordSlot(object, p, target_object); | 1226 collector->RecordSlot(object, p, target_object); |
| 1233 collector->MarkObject(target_object); | 1227 collector->MarkObject(target_object); |
| 1234 } | 1228 } |
| 1235 | 1229 |
| 1236 | 1230 |
| 1237 // Visit an unmarked object. | 1231 // Visit an unmarked object. |
| 1238 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, | 1232 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, |
| 1239 HeapObject* obj)) { | 1233 HeapObject* obj)) { |
| 1240 #ifdef DEBUG | 1234 #ifdef DEBUG |
| 1241 DCHECK(collector->heap()->Contains(obj)); | 1235 DCHECK(collector->heap()->Contains(obj)); |
| 1242 DCHECK(ObjectMarking::IsWhite(obj, MarkingState::Internal(obj))); | |
| 1243 #endif | 1236 #endif |
| 1244 Map* map = obj->map(); | 1237 if (ObjectMarking::WhiteToBlack(obj, MarkingState::Internal(obj))) { |
| 1245 Heap* heap = obj->GetHeap(); | 1238 Map* map = obj->map(); |
| 1246 ObjectMarking::WhiteToBlack(obj, MarkingState::Internal(obj)); | 1239 Heap* heap = obj->GetHeap(); |
| 1247 // Mark the map pointer and the body. | 1240 ObjectMarking::WhiteToBlack(obj, MarkingState::Internal(obj)); |
| 1248 heap->mark_compact_collector()->MarkObject(map); | 1241 // Mark the map pointer and the body. |
| 1249 IterateBody(map, obj); | 1242 heap->mark_compact_collector()->MarkObject(map); |
| 1243 IterateBody(map, obj); | |
| 1244 } | |
| 1250 } | 1245 } |
| 1251 | 1246 |
| 1252 // Visit all unmarked objects pointed to by [start, end). | 1247 // Visit all unmarked objects pointed to by [start, end). |
| 1253 // Returns false if the operation fails (lack of stack space). | 1248 // Returns false if the operation fails (lack of stack space). |
| 1254 INLINE(static bool VisitUnmarkedObjects(Heap* heap, HeapObject* object, | 1249 INLINE(static bool VisitUnmarkedObjects(Heap* heap, HeapObject* object, |
| 1255 Object** start, Object** end)) { | 1250 Object** start, Object** end)) { |
| 1256 // Return false is we are close to the stack limit. | 1251 // Return false is we are close to the stack limit. |
| 1257 StackLimitCheck check(heap->isolate()); | 1252 StackLimitCheck check(heap->isolate()); |
| 1258 if (check.HasOverflowed()) return false; | 1253 if (check.HasOverflowed()) return false; |
| 1259 | 1254 |
| 1260 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1255 MarkCompactCollector* collector = heap->mark_compact_collector(); |
| 1261 // Visit the unmarked objects. | 1256 // Visit the unmarked objects. |
| 1262 for (Object** p = start; p < end; p++) { | 1257 for (Object** p = start; p < end; p++) { |
| 1263 Object* o = *p; | 1258 Object* o = *p; |
| 1264 if (!o->IsHeapObject()) continue; | 1259 if (!o->IsHeapObject()) continue; |
| 1265 collector->RecordSlot(object, p, o); | 1260 collector->RecordSlot(object, p, o); |
| 1266 HeapObject* obj = HeapObject::cast(o); | 1261 HeapObject* obj = HeapObject::cast(o); |
| 1267 if (ObjectMarking::IsBlackOrGrey(obj, MarkingState::Internal(obj))) | |
| 1268 continue; | |
| 1269 VisitUnmarkedObject(collector, obj); | 1262 VisitUnmarkedObject(collector, obj); |
| 1270 } | 1263 } |
| 1271 return true; | 1264 return true; |
| 1272 } | 1265 } |
| 1273 | 1266 |
| 1274 private: | 1267 private: |
| 1275 // Code flushing support. | 1268 // Code flushing support. |
| 1276 | 1269 |
| 1277 static const int kRegExpCodeThreshold = 5; | 1270 static const int kRegExpCodeThreshold = 5; |
| 1278 | 1271 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1455 } | 1448 } |
| 1456 | 1449 |
| 1457 private: | 1450 private: |
| 1458 void MarkObjectByPointer(Object** p) { | 1451 void MarkObjectByPointer(Object** p) { |
| 1459 if (!(*p)->IsHeapObject()) return; | 1452 if (!(*p)->IsHeapObject()) return; |
| 1460 | 1453 |
| 1461 HeapObject* object = HeapObject::cast(*p); | 1454 HeapObject* object = HeapObject::cast(*p); |
| 1462 | 1455 |
| 1463 if (!collector_->heap()->InNewSpace(object)) return; | 1456 if (!collector_->heap()->InNewSpace(object)) return; |
| 1464 | 1457 |
| 1465 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1458 if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1466 object, MarkingState::External(object))) | 1459 object, MarkingState::External(object))) { |
| 1467 return; | 1460 Map* map = object->map(); |
| 1468 | 1461 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); |
| 1469 Map* map = object->map(); | 1462 collector_->EmptyMarkingDeque(); |
| 1470 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1463 } |
| 1471 object, MarkingState::External(object)); | |
| 1472 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); | |
| 1473 | |
| 1474 collector_->EmptyMarkingDeque(); | |
| 1475 } | 1464 } |
| 1476 | 1465 |
| 1477 MinorMarkCompactCollector* collector_; | 1466 MinorMarkCompactCollector* collector_; |
| 1478 }; | 1467 }; |
| 1479 | 1468 |
| 1480 // Visitor class for marking heap roots. | 1469 // Visitor class for marking heap roots. |
| 1481 // TODO(ulan): Remove ObjectVisitor base class after fixing marking of | 1470 // TODO(ulan): Remove ObjectVisitor base class after fixing marking of |
| 1482 // the string table and the top optimized code. | 1471 // the string table and the top optimized code. |
| 1483 class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor, | 1472 class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor, |
| 1484 public RootVisitor { | 1473 public RootVisitor { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1505 // Skip the weak next code link in a code object, which is visited in | 1494 // Skip the weak next code link in a code object, which is visited in |
| 1506 // ProcessTopOptimizedFrame. | 1495 // ProcessTopOptimizedFrame. |
| 1507 void VisitNextCodeLink(Code* host, Object** p) override {} | 1496 void VisitNextCodeLink(Code* host, Object** p) override {} |
| 1508 | 1497 |
| 1509 private: | 1498 private: |
| 1510 void MarkObjectByPointer(Object** p) { | 1499 void MarkObjectByPointer(Object** p) { |
| 1511 if (!(*p)->IsHeapObject()) return; | 1500 if (!(*p)->IsHeapObject()) return; |
| 1512 | 1501 |
| 1513 HeapObject* object = HeapObject::cast(*p); | 1502 HeapObject* object = HeapObject::cast(*p); |
| 1514 | 1503 |
| 1515 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1504 if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1516 object, MarkingState::Internal(object))) | 1505 object, MarkingState::Internal(object))) { |
| 1517 return; | 1506 Map* map = object->map(); |
| 1518 | 1507 // Mark the map pointer and body, and push them on the marking stack. |
| 1519 Map* map = object->map(); | 1508 collector_->MarkObject(map); |
| 1520 // Mark the object. | 1509 MarkCompactMarkingVisitor::IterateBody(map, object); |
| 1521 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1510 // Mark all the objects reachable from the map and body. May leave |
| 1522 object, MarkingState::Internal(object)); | 1511 // overflowed objects in the heap. |
| 1523 | 1512 collector_->EmptyMarkingDeque(); |
| 1524 // Mark the map pointer and body, and push them on the marking stack. | 1513 } |
| 1525 collector_->MarkObject(map); | |
| 1526 MarkCompactMarkingVisitor::IterateBody(map, object); | |
| 1527 | |
| 1528 // Mark all the objects reachable from the map and body. May leave | |
| 1529 // overflowed objects in the heap. | |
| 1530 collector_->EmptyMarkingDeque(); | |
| 1531 } | 1514 } |
| 1532 | 1515 |
| 1533 MarkCompactCollector* collector_; | 1516 MarkCompactCollector* collector_; |
| 1534 }; | 1517 }; |
| 1535 | 1518 |
| 1536 class InternalizedStringTableCleaner : public ObjectVisitor { | 1519 class InternalizedStringTableCleaner : public ObjectVisitor { |
| 1537 public: | 1520 public: |
| 1538 InternalizedStringTableCleaner(Heap* heap, HeapObject* table) | 1521 InternalizedStringTableCleaner(Heap* heap, HeapObject* table) |
| 1539 : heap_(heap), pointers_removed_(0), table_(table) {} | 1522 : heap_(heap), pointers_removed_(0), table_(table) {} |
| 1540 | 1523 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1631 // is reached, whichever comes first. | 1614 // is reached, whichever comes first. |
| 1632 template <class T> | 1615 template <class T> |
| 1633 void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) { | 1616 void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) { |
| 1634 // The caller should ensure that the marking stack is initially not full, | 1617 // The caller should ensure that the marking stack is initially not full, |
| 1635 // so that we don't waste effort pointlessly scanning for objects. | 1618 // so that we don't waste effort pointlessly scanning for objects. |
| 1636 DCHECK(!marking_deque()->IsFull()); | 1619 DCHECK(!marking_deque()->IsFull()); |
| 1637 | 1620 |
| 1638 Map* filler_map = heap()->one_pointer_filler_map(); | 1621 Map* filler_map = heap()->one_pointer_filler_map(); |
| 1639 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { | 1622 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { |
| 1640 if ((object->map() != filler_map) && | 1623 if ((object->map() != filler_map) && |
| 1641 ObjectMarking::IsGrey(object, MarkingState::Internal(object))) { | 1624 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object))) { |
| 1642 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object)); | |
| 1643 PushBlack(object); | 1625 PushBlack(object); |
| 1644 if (marking_deque()->IsFull()) return; | 1626 if (marking_deque()->IsFull()) return; |
| 1645 } | 1627 } |
| 1646 } | 1628 } |
| 1647 } | 1629 } |
| 1648 | 1630 |
| 1649 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { | 1631 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { |
| 1650 DCHECK(!marking_deque()->IsFull()); | 1632 DCHECK(!marking_deque()->IsFull()); |
| 1651 LiveObjectIterator<kGreyObjects> it(p, MarkingState::Internal(p)); | 1633 LiveObjectIterator<kGreyObjects> it(p, MarkingState::Internal(p)); |
| 1652 HeapObject* object = NULL; | 1634 HeapObject* object = NULL; |
| 1653 while ((object = it.Next()) != NULL) { | 1635 while ((object = it.Next()) != NULL) { |
| 1654 DCHECK(ObjectMarking::IsGrey(object, MarkingState::Internal(object))); | 1636 bool success = |
| 1655 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object)); | 1637 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object)); |
| 1638 DCHECK(success); | |
| 1639 USE(success); | |
| 1656 PushBlack(object); | 1640 PushBlack(object); |
| 1657 if (marking_deque()->IsFull()) return; | 1641 if (marking_deque()->IsFull()) return; |
| 1658 } | 1642 } |
| 1659 } | 1643 } |
| 1660 | 1644 |
| 1661 class RecordMigratedSlotVisitor : public ObjectVisitor { | 1645 class RecordMigratedSlotVisitor : public ObjectVisitor { |
| 1662 public: | 1646 public: |
| 1663 explicit RecordMigratedSlotVisitor(MarkCompactCollector* collector) | 1647 explicit RecordMigratedSlotVisitor(MarkCompactCollector* collector) |
| 1664 : collector_(collector) {} | 1648 : collector_(collector) {} |
| 1665 | 1649 |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2139 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 2123 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 2140 Object* o = *p; | 2124 Object* o = *p; |
| 2141 if (!o->IsHeapObject()) return false; | 2125 if (!o->IsHeapObject()) return false; |
| 2142 return ObjectMarking::IsWhite(HeapObject::cast(o), | 2126 return ObjectMarking::IsWhite(HeapObject::cast(o), |
| 2143 MarkingState::Internal(HeapObject::cast(o))); | 2127 MarkingState::Internal(HeapObject::cast(o))); |
| 2144 } | 2128 } |
| 2145 | 2129 |
| 2146 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { | 2130 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { |
| 2147 StringTable* string_table = heap()->string_table(); | 2131 StringTable* string_table = heap()->string_table(); |
| 2148 // Mark the string table itself. | 2132 // Mark the string table itself. |
| 2149 if (ObjectMarking::IsWhite(string_table, | 2133 if (ObjectMarking::WhiteToBlack(string_table, |
| 2150 MarkingState::Internal(string_table))) { | 2134 MarkingState::Internal(string_table))) { |
| 2151 // String table could have already been marked by visiting the handles list. | 2135 // Explicitly mark the prefix. |
| 2152 ObjectMarking::WhiteToBlack(string_table, | 2136 string_table->IteratePrefix(visitor); |
| 2153 MarkingState::Internal(string_table)); | 2137 ProcessMarkingDeque(); |
| 2154 } | 2138 } |
| 2155 // Explicitly mark the prefix. | |
| 2156 string_table->IteratePrefix(visitor); | |
|
Michael Lippautz
2017/05/03 07:48:39
:)
| |
| 2157 ProcessMarkingDeque(); | |
| 2158 } | 2139 } |
| 2159 | 2140 |
| 2160 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { | 2141 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
| 2161 // Mark the heap roots including global variables, stack variables, | 2142 // Mark the heap roots including global variables, stack variables, |
| 2162 // etc., and all objects reachable from them. | 2143 // etc., and all objects reachable from them. |
| 2163 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); | 2144 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); |
| 2164 | 2145 |
| 2165 // Handle the string table specially. | 2146 // Handle the string table specially. |
| 2166 MarkStringTable(visitor); | 2147 MarkStringTable(visitor); |
| 2167 | 2148 |
| (...skipping 2018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4186 // The target is always in old space, we don't have to record the slot in | 4167 // The target is always in old space, we don't have to record the slot in |
| 4187 // the old-to-new remembered set. | 4168 // the old-to-new remembered set. |
| 4188 DCHECK(!heap()->InNewSpace(target)); | 4169 DCHECK(!heap()->InNewSpace(target)); |
| 4189 RecordRelocSlot(host, &rinfo, target); | 4170 RecordRelocSlot(host, &rinfo, target); |
| 4190 } | 4171 } |
| 4191 } | 4172 } |
| 4192 } | 4173 } |
| 4193 | 4174 |
| 4194 } // namespace internal | 4175 } // namespace internal |
| 4195 } // namespace v8 | 4176 } // namespace v8 |
| OLD | NEW |