| 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 1178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 if (MarkRecursively(heap, target_object)) return; | 1189 if (MarkRecursively(heap, target_object)) return; |
| 1190 heap->minor_mark_compact_collector()->MarkObject(target_object); | 1190 heap->minor_mark_compact_collector()->MarkObject(target_object); |
| 1191 } | 1191 } |
| 1192 } | 1192 } |
| 1193 | 1193 |
| 1194 protected: | 1194 protected: |
| 1195 inline static bool MarkRecursively(Heap* heap, HeapObject* object) { | 1195 inline static bool MarkRecursively(Heap* heap, HeapObject* object) { |
| 1196 StackLimitCheck check(heap->isolate()); | 1196 StackLimitCheck check(heap->isolate()); |
| 1197 if (check.HasOverflowed()) return false; | 1197 if (check.HasOverflowed()) return false; |
| 1198 | 1198 |
| 1199 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1199 if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1200 object, MarkingState::External(object))) | 1200 object, MarkingState::External(object))) { |
| 1201 return true; | 1201 IterateBody(object->map(), object); |
| 1202 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1202 } |
| 1203 object, MarkingState::External(object)); | |
| 1204 IterateBody(object->map(), object); | |
| 1205 return true; | 1203 return true; |
| 1206 } | 1204 } |
| 1207 }; | 1205 }; |
| 1208 | 1206 |
| 1209 class MarkCompactMarkingVisitor | 1207 class MarkCompactMarkingVisitor |
| 1210 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { | 1208 : public StaticMarkingVisitor<MarkCompactMarkingVisitor> { |
| 1211 public: | 1209 public: |
| 1212 static void Initialize(); | 1210 static void Initialize(); |
| 1213 | 1211 |
| 1214 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { | 1212 INLINE(static void VisitPointer(Heap* heap, HeapObject* object, Object** p)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1230 } | 1228 } |
| 1231 | 1229 |
| 1232 // Marks the object black and pushes it on the marking stack. | 1230 // Marks the object black and pushes it on the marking stack. |
| 1233 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { | 1231 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { |
| 1234 heap->mark_compact_collector()->MarkObject(object); | 1232 heap->mark_compact_collector()->MarkObject(object); |
| 1235 } | 1233 } |
| 1236 | 1234 |
| 1237 // Marks the object black without pushing it on the marking stack. | 1235 // Marks the object black without pushing it on the marking stack. |
| 1238 // Returns true if object needed marking and false otherwise. | 1236 // Returns true if object needed marking and false otherwise. |
| 1239 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { | 1237 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { |
| 1240 if (ObjectMarking::IsWhite(object, MarkingState::Internal(object))) { | 1238 return ObjectMarking::WhiteToBlack(object, MarkingState::Internal(object)); |
| 1241 ObjectMarking::WhiteToBlack(object, MarkingState::Internal(object)); | |
| 1242 return true; | |
| 1243 } | |
| 1244 return false; | |
| 1245 } | 1239 } |
| 1246 | 1240 |
| 1247 // Mark object pointed to by p. | 1241 // Mark object pointed to by p. |
| 1248 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, | 1242 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, |
| 1249 HeapObject* object, Object** p)) { | 1243 HeapObject* object, Object** p)) { |
| 1250 if (!(*p)->IsHeapObject()) return; | 1244 if (!(*p)->IsHeapObject()) return; |
| 1251 HeapObject* target_object = HeapObject::cast(*p); | 1245 HeapObject* target_object = HeapObject::cast(*p); |
| 1252 collector->RecordSlot(object, p, target_object); | 1246 collector->RecordSlot(object, p, target_object); |
| 1253 collector->MarkObject(target_object); | 1247 collector->MarkObject(target_object); |
| 1254 } | 1248 } |
| 1255 | 1249 |
| 1256 | 1250 |
| 1257 // Visit an unmarked object. | 1251 // Visit an unmarked object. |
| 1258 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, | 1252 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, |
| 1259 HeapObject* obj)) { | 1253 HeapObject* obj)) { |
| 1260 #ifdef DEBUG | 1254 #ifdef DEBUG |
| 1261 DCHECK(collector->heap()->Contains(obj)); | 1255 DCHECK(collector->heap()->Contains(obj)); |
| 1262 DCHECK(ObjectMarking::IsWhite(obj, MarkingState::Internal(obj))); | |
| 1263 #endif | 1256 #endif |
| 1264 Map* map = obj->map(); | 1257 if (ObjectMarking::WhiteToBlack(obj, MarkingState::Internal(obj))) { |
| 1265 Heap* heap = obj->GetHeap(); | 1258 Map* map = obj->map(); |
| 1266 ObjectMarking::WhiteToBlack(obj, MarkingState::Internal(obj)); | 1259 Heap* heap = obj->GetHeap(); |
| 1267 // Mark the map pointer and the body. | 1260 ObjectMarking::WhiteToBlack(obj, MarkingState::Internal(obj)); |
| 1268 heap->mark_compact_collector()->MarkObject(map); | 1261 // Mark the map pointer and the body. |
| 1269 IterateBody(map, obj); | 1262 heap->mark_compact_collector()->MarkObject(map); |
| 1263 IterateBody(map, obj); |
| 1264 } |
| 1270 } | 1265 } |
| 1271 | 1266 |
| 1272 // Visit all unmarked objects pointed to by [start, end). | 1267 // Visit all unmarked objects pointed to by [start, end). |
| 1273 // Returns false if the operation fails (lack of stack space). | 1268 // Returns false if the operation fails (lack of stack space). |
| 1274 INLINE(static bool VisitUnmarkedObjects(Heap* heap, HeapObject* object, | 1269 INLINE(static bool VisitUnmarkedObjects(Heap* heap, HeapObject* object, |
| 1275 Object** start, Object** end)) { | 1270 Object** start, Object** end)) { |
| 1276 // Return false is we are close to the stack limit. | 1271 // Return false is we are close to the stack limit. |
| 1277 StackLimitCheck check(heap->isolate()); | 1272 StackLimitCheck check(heap->isolate()); |
| 1278 if (check.HasOverflowed()) return false; | 1273 if (check.HasOverflowed()) return false; |
| 1279 | 1274 |
| 1280 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1275 MarkCompactCollector* collector = heap->mark_compact_collector(); |
| 1281 // Visit the unmarked objects. | 1276 // Visit the unmarked objects. |
| 1282 for (Object** p = start; p < end; p++) { | 1277 for (Object** p = start; p < end; p++) { |
| 1283 Object* o = *p; | 1278 Object* o = *p; |
| 1284 if (!o->IsHeapObject()) continue; | 1279 if (!o->IsHeapObject()) continue; |
| 1285 collector->RecordSlot(object, p, o); | 1280 collector->RecordSlot(object, p, o); |
| 1286 HeapObject* obj = HeapObject::cast(o); | 1281 HeapObject* obj = HeapObject::cast(o); |
| 1287 if (ObjectMarking::IsBlackOrGrey(obj, MarkingState::Internal(obj))) | |
| 1288 continue; | |
| 1289 VisitUnmarkedObject(collector, obj); | 1282 VisitUnmarkedObject(collector, obj); |
| 1290 } | 1283 } |
| 1291 return true; | 1284 return true; |
| 1292 } | 1285 } |
| 1293 | 1286 |
| 1294 private: | 1287 private: |
| 1295 // Code flushing support. | 1288 // Code flushing support. |
| 1296 | 1289 |
| 1297 static const int kRegExpCodeThreshold = 5; | 1290 static const int kRegExpCodeThreshold = 5; |
| 1298 | 1291 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1475 } | 1468 } |
| 1476 | 1469 |
| 1477 private: | 1470 private: |
| 1478 void MarkObjectByPointer(Object** p) { | 1471 void MarkObjectByPointer(Object** p) { |
| 1479 if (!(*p)->IsHeapObject()) return; | 1472 if (!(*p)->IsHeapObject()) return; |
| 1480 | 1473 |
| 1481 HeapObject* object = HeapObject::cast(*p); | 1474 HeapObject* object = HeapObject::cast(*p); |
| 1482 | 1475 |
| 1483 if (!collector_->heap()->InNewSpace(object)) return; | 1476 if (!collector_->heap()->InNewSpace(object)) return; |
| 1484 | 1477 |
| 1485 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1478 if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1486 object, MarkingState::External(object))) | 1479 object, MarkingState::External(object))) { |
| 1487 return; | 1480 Map* map = object->map(); |
| 1488 | 1481 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); |
| 1489 Map* map = object->map(); | 1482 collector_->EmptyMarkingDeque(); |
| 1490 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1483 } |
| 1491 object, MarkingState::External(object)); | |
| 1492 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); | |
| 1493 | |
| 1494 collector_->EmptyMarkingDeque(); | |
| 1495 } | 1484 } |
| 1496 | 1485 |
| 1497 MinorMarkCompactCollector* collector_; | 1486 MinorMarkCompactCollector* collector_; |
| 1498 }; | 1487 }; |
| 1499 | 1488 |
| 1500 // Visitor class for marking heap roots. | 1489 // Visitor class for marking heap roots. |
| 1501 // TODO(ulan): Remove ObjectVisitor base class after fixing marking of | 1490 // TODO(ulan): Remove ObjectVisitor base class after fixing marking of |
| 1502 // the string table and the top optimized code. | 1491 // the string table and the top optimized code. |
| 1503 class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor, | 1492 class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor, |
| 1504 public RootVisitor { | 1493 public RootVisitor { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1525 // Skip the weak next code link in a code object, which is visited in | 1514 // Skip the weak next code link in a code object, which is visited in |
| 1526 // ProcessTopOptimizedFrame. | 1515 // ProcessTopOptimizedFrame. |
| 1527 void VisitNextCodeLink(Code* host, Object** p) override {} | 1516 void VisitNextCodeLink(Code* host, Object** p) override {} |
| 1528 | 1517 |
| 1529 private: | 1518 private: |
| 1530 void MarkObjectByPointer(Object** p) { | 1519 void MarkObjectByPointer(Object** p) { |
| 1531 if (!(*p)->IsHeapObject()) return; | 1520 if (!(*p)->IsHeapObject()) return; |
| 1532 | 1521 |
| 1533 HeapObject* object = HeapObject::cast(*p); | 1522 HeapObject* object = HeapObject::cast(*p); |
| 1534 | 1523 |
| 1535 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1524 if (ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1536 object, MarkingState::Internal(object))) | 1525 object, MarkingState::Internal(object))) { |
| 1537 return; | 1526 Map* map = object->map(); |
| 1538 | 1527 // Mark the map pointer and body, and push them on the marking stack. |
| 1539 Map* map = object->map(); | 1528 collector_->MarkObject(map); |
| 1540 // Mark the object. | 1529 MarkCompactMarkingVisitor::IterateBody(map, object); |
| 1541 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1530 // Mark all the objects reachable from the map and body. May leave |
| 1542 object, MarkingState::Internal(object)); | 1531 // overflowed objects in the heap. |
| 1543 | 1532 collector_->EmptyMarkingDeque(); |
| 1544 // Mark the map pointer and body, and push them on the marking stack. | 1533 } |
| 1545 collector_->MarkObject(map); | |
| 1546 MarkCompactMarkingVisitor::IterateBody(map, object); | |
| 1547 | |
| 1548 // Mark all the objects reachable from the map and body. May leave | |
| 1549 // overflowed objects in the heap. | |
| 1550 collector_->EmptyMarkingDeque(); | |
| 1551 } | 1534 } |
| 1552 | 1535 |
| 1553 MarkCompactCollector* collector_; | 1536 MarkCompactCollector* collector_; |
| 1554 }; | 1537 }; |
| 1555 | 1538 |
| 1556 class InternalizedStringTableCleaner : public ObjectVisitor { | 1539 class InternalizedStringTableCleaner : public ObjectVisitor { |
| 1557 public: | 1540 public: |
| 1558 InternalizedStringTableCleaner(Heap* heap, HeapObject* table) | 1541 InternalizedStringTableCleaner(Heap* heap, HeapObject* table) |
| 1559 : heap_(heap), pointers_removed_(0), table_(table) {} | 1542 : heap_(heap), pointers_removed_(0), table_(table) {} |
| 1560 | 1543 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1711 // is reached, whichever comes first. | 1694 // is reached, whichever comes first. |
| 1712 template <class T> | 1695 template <class T> |
| 1713 void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) { | 1696 void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) { |
| 1714 // The caller should ensure that the marking stack is initially not full, | 1697 // The caller should ensure that the marking stack is initially not full, |
| 1715 // so that we don't waste effort pointlessly scanning for objects. | 1698 // so that we don't waste effort pointlessly scanning for objects. |
| 1716 DCHECK(!marking_deque()->IsFull()); | 1699 DCHECK(!marking_deque()->IsFull()); |
| 1717 | 1700 |
| 1718 Map* filler_map = heap()->one_pointer_filler_map(); | 1701 Map* filler_map = heap()->one_pointer_filler_map(); |
| 1719 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { | 1702 for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) { |
| 1720 if ((object->map() != filler_map) && | 1703 if ((object->map() != filler_map) && |
| 1721 ObjectMarking::IsGrey(object, MarkingState::Internal(object))) { | 1704 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object))) { |
| 1722 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object)); | |
| 1723 PushBlack(object); | 1705 PushBlack(object); |
| 1724 if (marking_deque()->IsFull()) return; | 1706 if (marking_deque()->IsFull()) return; |
| 1725 } | 1707 } |
| 1726 } | 1708 } |
| 1727 } | 1709 } |
| 1728 | 1710 |
| 1729 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { | 1711 void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) { |
| 1730 DCHECK(!marking_deque()->IsFull()); | 1712 DCHECK(!marking_deque()->IsFull()); |
| 1731 LiveObjectIterator<kGreyObjects> it(p, MarkingState::Internal(p)); | 1713 LiveObjectIterator<kGreyObjects> it(p, MarkingState::Internal(p)); |
| 1732 HeapObject* object = NULL; | 1714 HeapObject* object = NULL; |
| 1733 while ((object = it.Next()) != NULL) { | 1715 while ((object = it.Next()) != NULL) { |
| 1734 DCHECK(ObjectMarking::IsGrey(object, MarkingState::Internal(object))); | 1716 bool success = |
| 1735 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object)); | 1717 ObjectMarking::GreyToBlack(object, MarkingState::Internal(object)); |
| 1718 DCHECK(success); |
| 1719 USE(success); |
| 1736 PushBlack(object); | 1720 PushBlack(object); |
| 1737 if (marking_deque()->IsFull()) return; | 1721 if (marking_deque()->IsFull()) return; |
| 1738 } | 1722 } |
| 1739 } | 1723 } |
| 1740 | 1724 |
| 1741 class RecordMigratedSlotVisitor : public ObjectVisitor { | 1725 class RecordMigratedSlotVisitor : public ObjectVisitor { |
| 1742 public: | 1726 public: |
| 1743 explicit RecordMigratedSlotVisitor(MarkCompactCollector* collector) | 1727 explicit RecordMigratedSlotVisitor(MarkCompactCollector* collector) |
| 1744 : collector_(collector) {} | 1728 : collector_(collector) {} |
| 1745 | 1729 |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2288 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 2272 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 2289 Object* o = *p; | 2273 Object* o = *p; |
| 2290 if (!o->IsHeapObject()) return false; | 2274 if (!o->IsHeapObject()) return false; |
| 2291 return ObjectMarking::IsWhite(HeapObject::cast(o), | 2275 return ObjectMarking::IsWhite(HeapObject::cast(o), |
| 2292 MarkingState::Internal(HeapObject::cast(o))); | 2276 MarkingState::Internal(HeapObject::cast(o))); |
| 2293 } | 2277 } |
| 2294 | 2278 |
| 2295 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { | 2279 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { |
| 2296 StringTable* string_table = heap()->string_table(); | 2280 StringTable* string_table = heap()->string_table(); |
| 2297 // Mark the string table itself. | 2281 // Mark the string table itself. |
| 2298 if (ObjectMarking::IsWhite(string_table, | 2282 if (ObjectMarking::WhiteToBlack(string_table, |
| 2299 MarkingState::Internal(string_table))) { | 2283 MarkingState::Internal(string_table))) { |
| 2300 // String table could have already been marked by visiting the handles list. | 2284 // Explicitly mark the prefix. |
| 2301 ObjectMarking::WhiteToBlack(string_table, | 2285 string_table->IteratePrefix(visitor); |
| 2302 MarkingState::Internal(string_table)); | 2286 ProcessMarkingDeque(); |
| 2303 } | 2287 } |
| 2304 // Explicitly mark the prefix. | |
| 2305 string_table->IteratePrefix(visitor); | |
| 2306 ProcessMarkingDeque(); | |
| 2307 } | 2288 } |
| 2308 | 2289 |
| 2309 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { | 2290 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
| 2310 // Mark the heap roots including global variables, stack variables, | 2291 // Mark the heap roots including global variables, stack variables, |
| 2311 // etc., and all objects reachable from them. | 2292 // etc., and all objects reachable from them. |
| 2312 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); | 2293 heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG); |
| 2313 | 2294 |
| 2314 // Handle the string table specially. | 2295 // Handle the string table specially. |
| 2315 MarkStringTable(visitor); | 2296 MarkStringTable(visitor); |
| 2316 | 2297 |
| (...skipping 2223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4540 // The target is always in old space, we don't have to record the slot in | 4521 // The target is always in old space, we don't have to record the slot in |
| 4541 // the old-to-new remembered set. | 4522 // the old-to-new remembered set. |
| 4542 DCHECK(!heap()->InNewSpace(target)); | 4523 DCHECK(!heap()->InNewSpace(target)); |
| 4543 RecordRelocSlot(host, &rinfo, target); | 4524 RecordRelocSlot(host, &rinfo, target); |
| 4544 } | 4525 } |
| 4545 } | 4526 } |
| 4546 } | 4527 } |
| 4547 | 4528 |
| 4548 } // namespace internal | 4529 } // namespace internal |
| 4549 } // namespace v8 | 4530 } // namespace v8 |
| OLD | NEW |