| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 // produce invalid {kImpossibleBitPattern} in the marking bitmap by overlapping. | 44 // produce invalid {kImpossibleBitPattern} in the marking bitmap by overlapping. |
| 45 STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2); | 45 STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2); |
| 46 | 46 |
| 47 // ============================================================================= | 47 // ============================================================================= |
| 48 // Verifiers | 48 // Verifiers |
| 49 // ============================================================================= | 49 // ============================================================================= |
| 50 | 50 |
| 51 #ifdef VERIFY_HEAP | 51 #ifdef VERIFY_HEAP |
| 52 namespace { | 52 namespace { |
| 53 | 53 |
| 54 class MarkingVerifier : public ObjectVisitor { | 54 class MarkingVerifier : public ObjectVisitor, public RootVisitor { |
| 55 public: | 55 public: |
| 56 virtual void Run() = 0; | 56 virtual void Run() = 0; |
| 57 | 57 |
| 58 protected: | 58 protected: |
| 59 explicit MarkingVerifier(Heap* heap) : heap_(heap) {} | 59 explicit MarkingVerifier(Heap* heap) : heap_(heap) {} |
| 60 | 60 |
| 61 virtual MarkingState marking_state(MemoryChunk* chunk) = 0; | 61 virtual MarkingState marking_state(MemoryChunk* chunk) = 0; |
| 62 | 62 |
| 63 virtual void VerifyPointers(Object** start, Object** end) = 0; |
| 64 |
| 65 void VisitPointers(Object** start, Object** end) override { |
| 66 VerifyPointers(start, end); |
| 67 } |
| 68 |
| 69 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 70 VerifyPointers(start, end); |
| 71 } |
| 72 |
| 63 void VerifyRoots(VisitMode mode); | 73 void VerifyRoots(VisitMode mode); |
| 64 void VerifyMarkingOnPage(const Page& page, const MarkingState& state, | 74 void VerifyMarkingOnPage(const Page& page, const MarkingState& state, |
| 65 Address start, Address end); | 75 Address start, Address end); |
| 66 void VerifyMarking(NewSpace* new_space); | 76 void VerifyMarking(NewSpace* new_space); |
| 67 void VerifyMarking(PagedSpace* paged_space); | 77 void VerifyMarking(PagedSpace* paged_space); |
| 68 | 78 |
| 69 Heap* heap_; | 79 Heap* heap_; |
| 70 }; | 80 }; |
| 71 | 81 |
| 72 void MarkingVerifier::VerifyRoots(VisitMode mode) { | 82 void MarkingVerifier::VerifyRoots(VisitMode mode) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 | 155 |
| 146 protected: | 156 protected: |
| 147 MarkingState marking_state(MemoryChunk* chunk) override { | 157 MarkingState marking_state(MemoryChunk* chunk) override { |
| 148 return MarkingState::Internal(chunk); | 158 return MarkingState::Internal(chunk); |
| 149 } | 159 } |
| 150 | 160 |
| 151 MarkingState marking_state(HeapObject* object) { | 161 MarkingState marking_state(HeapObject* object) { |
| 152 return MarkingState::Internal(object); | 162 return MarkingState::Internal(object); |
| 153 } | 163 } |
| 154 | 164 |
| 155 void VisitPointers(Object** start, Object** end) override { | 165 void VerifyPointers(Object** start, Object** end) override { |
| 156 for (Object** current = start; current < end; current++) { | 166 for (Object** current = start; current < end; current++) { |
| 157 if ((*current)->IsHeapObject()) { | 167 if ((*current)->IsHeapObject()) { |
| 158 HeapObject* object = HeapObject::cast(*current); | 168 HeapObject* object = HeapObject::cast(*current); |
| 159 CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object))); | 169 CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object))); |
| 160 } | 170 } |
| 161 } | 171 } |
| 162 } | 172 } |
| 163 | 173 |
| 164 void VisitEmbeddedPointer(RelocInfo* rinfo) override { | 174 void VisitEmbeddedPointer(RelocInfo* rinfo) override { |
| 165 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 175 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 188 | 198 |
| 189 MarkingState marking_state(HeapObject* object) { | 199 MarkingState marking_state(HeapObject* object) { |
| 190 return MarkingState::External(object); | 200 return MarkingState::External(object); |
| 191 } | 201 } |
| 192 | 202 |
| 193 void Run() override { | 203 void Run() override { |
| 194 VerifyRoots(VISIT_ALL_IN_SCAVENGE); | 204 VerifyRoots(VISIT_ALL_IN_SCAVENGE); |
| 195 VerifyMarking(heap_->new_space()); | 205 VerifyMarking(heap_->new_space()); |
| 196 } | 206 } |
| 197 | 207 |
| 198 void VisitPointers(Object** start, Object** end) override { | 208 void VerifyPointers(Object** start, Object** end) override { |
| 199 for (Object** current = start; current < end; current++) { | 209 for (Object** current = start; current < end; current++) { |
| 200 if ((*current)->IsHeapObject()) { | 210 if ((*current)->IsHeapObject()) { |
| 201 HeapObject* object = HeapObject::cast(*current); | 211 HeapObject* object = HeapObject::cast(*current); |
| 202 if (!heap_->InNewSpace(object)) return; | 212 if (!heap_->InNewSpace(object)) return; |
| 203 CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object))); | 213 CHECK(ObjectMarking::IsBlackOrGrey(object, marking_state(object))); |
| 204 } | 214 } |
| 205 } | 215 } |
| 206 } | 216 } |
| 207 }; | 217 }; |
| 208 | 218 |
| 209 class EvacuationVerifier : public ObjectVisitor { | 219 class EvacuationVerifier : public ObjectVisitor, public RootVisitor { |
| 210 public: | 220 public: |
| 211 virtual void Run() = 0; | 221 virtual void Run() = 0; |
| 212 | 222 |
| 213 void VisitPointers(Object** start, Object** end) override { | 223 void VisitPointers(Object** start, Object** end) override { |
| 224 VerifyPointers(start, end); |
| 225 } |
| 226 |
| 227 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 228 VerifyPointers(start, end); |
| 229 } |
| 230 |
| 231 protected: |
| 232 explicit EvacuationVerifier(Heap* heap) : heap_(heap) {} |
| 233 |
| 234 void VerifyPointers(Object** start, Object** end) { |
| 214 for (Object** current = start; current < end; current++) { | 235 for (Object** current = start; current < end; current++) { |
| 215 if ((*current)->IsHeapObject()) { | 236 if ((*current)->IsHeapObject()) { |
| 216 HeapObject* object = HeapObject::cast(*current); | 237 HeapObject* object = HeapObject::cast(*current); |
| 217 CHECK(!MarkCompactCollector::IsOnEvacuationCandidate(object)); | 238 CHECK(!MarkCompactCollector::IsOnEvacuationCandidate(object)); |
| 218 } | 239 } |
| 219 } | 240 } |
| 220 } | 241 } |
| 221 | 242 |
| 222 protected: | |
| 223 explicit EvacuationVerifier(Heap* heap) : heap_(heap) {} | |
| 224 | |
| 225 void VerifyRoots(VisitMode mode); | 243 void VerifyRoots(VisitMode mode); |
| 226 void VerifyEvacuationOnPage(Address start, Address end); | 244 void VerifyEvacuationOnPage(Address start, Address end); |
| 227 void VerifyEvacuation(NewSpace* new_space); | 245 void VerifyEvacuation(NewSpace* new_space); |
| 228 void VerifyEvacuation(PagedSpace* paged_space); | 246 void VerifyEvacuation(PagedSpace* paged_space); |
| 229 | 247 |
| 230 Heap* heap_; | 248 Heap* heap_; |
| 231 }; | 249 }; |
| 232 | 250 |
| 233 void EvacuationVerifier::VerifyRoots(VisitMode mode) { | 251 void EvacuationVerifier::VerifyRoots(VisitMode mode) { |
| 234 heap_->IterateStrongRoots(this, mode); | 252 heap_->IterateStrongRoots(this, mode); |
| (...skipping 1115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 : collector_(collector) {} | 1368 : collector_(collector) {} |
| 1351 | 1369 |
| 1352 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1370 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
| 1353 collector_->PrepareThreadForCodeFlushing(isolate, top); | 1371 collector_->PrepareThreadForCodeFlushing(isolate, top); |
| 1354 } | 1372 } |
| 1355 | 1373 |
| 1356 private: | 1374 private: |
| 1357 MarkCompactCollector* collector_; | 1375 MarkCompactCollector* collector_; |
| 1358 }; | 1376 }; |
| 1359 | 1377 |
| 1360 | 1378 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor, |
| 1361 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { | 1379 public RootVisitor { |
| 1362 public: | 1380 public: |
| 1363 explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector) | 1381 explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector) |
| 1364 : collector_(collector) {} | 1382 : collector_(collector) {} |
| 1365 | 1383 |
| 1366 void VisitPointers(Object** start, Object** end) override { | 1384 void VisitPointers(Object** start, Object** end) override { |
| 1367 for (Object** p = start; p < end; p++) VisitPointer(p); | 1385 for (Object** p = start; p < end; p++) MarkObject(p); |
| 1368 } | 1386 } |
| 1369 | 1387 |
| 1370 void VisitPointer(Object** slot) override { | 1388 void VisitPointer(Object** slot) override { MarkObject(slot); } |
| 1389 |
| 1390 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 1391 for (Object** p = start; p < end; p++) MarkObject(p); |
| 1392 } |
| 1393 |
| 1394 void VisitRootPointer(Root root, Object** slot) override { MarkObject(slot); } |
| 1395 |
| 1396 private: |
| 1397 void MarkObject(Object** slot) { |
| 1371 Object* obj = *slot; | 1398 Object* obj = *slot; |
| 1372 if (obj->IsSharedFunctionInfo()) { | 1399 if (obj->IsSharedFunctionInfo()) { |
| 1373 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj); | 1400 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj); |
| 1374 collector_->MarkObject(shared->code()); | 1401 collector_->MarkObject(shared->code()); |
| 1375 collector_->MarkObject(shared); | 1402 collector_->MarkObject(shared); |
| 1376 } | 1403 } |
| 1377 } | 1404 } |
| 1378 | |
| 1379 private: | |
| 1380 MarkCompactCollector* collector_; | 1405 MarkCompactCollector* collector_; |
| 1381 }; | 1406 }; |
| 1382 | 1407 |
| 1383 | 1408 |
| 1384 void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate, | 1409 void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate, |
| 1385 ThreadLocalTop* top) { | 1410 ThreadLocalTop* top) { |
| 1386 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 1411 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
| 1387 // Note: for the frame that has a pending lazy deoptimization | 1412 // Note: for the frame that has a pending lazy deoptimization |
| 1388 // StackFrame::unchecked_code will return a non-optimized code object for | 1413 // StackFrame::unchecked_code will return a non-optimized code object for |
| 1389 // the outermost function and StackFrame::LookupCode will return | 1414 // the outermost function and StackFrame::LookupCode will return |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1414 heap()->isolate()->thread_manager()->IterateArchivedThreads( | 1439 heap()->isolate()->thread_manager()->IterateArchivedThreads( |
| 1415 &code_marking_visitor); | 1440 &code_marking_visitor); |
| 1416 | 1441 |
| 1417 SharedFunctionInfoMarkingVisitor visitor(this); | 1442 SharedFunctionInfoMarkingVisitor visitor(this); |
| 1418 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); | 1443 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); |
| 1419 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); | 1444 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); |
| 1420 | 1445 |
| 1421 ProcessMarkingDeque(); | 1446 ProcessMarkingDeque(); |
| 1422 } | 1447 } |
| 1423 | 1448 |
| 1424 class MinorMarkCompactCollector::RootMarkingVisitor : public ObjectVisitor { | 1449 class MinorMarkCompactCollector::RootMarkingVisitor : public RootVisitor { |
| 1425 public: | 1450 public: |
| 1426 explicit RootMarkingVisitor(MinorMarkCompactCollector* collector) | 1451 explicit RootMarkingVisitor(MinorMarkCompactCollector* collector) |
| 1427 : collector_(collector) {} | 1452 : collector_(collector) {} |
| 1428 | 1453 |
| 1429 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } | 1454 void VisitRootPointer(Root root, Object** p) override { |
| 1455 MarkObjectByPointer(p); |
| 1456 } |
| 1430 | 1457 |
| 1431 void VisitPointers(Object** start, Object** end) override { | 1458 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 1432 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); | 1459 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); |
| 1433 } | 1460 } |
| 1434 | 1461 |
| 1435 // Skip the weak next code link in a code object, which is visited in | |
| 1436 // ProcessTopOptimizedFrame. | |
| 1437 void VisitNextCodeLink(Object** p) override {} | |
| 1438 | |
| 1439 private: | 1462 private: |
| 1440 void MarkObjectByPointer(Object** p) { | 1463 void MarkObjectByPointer(Object** p) { |
| 1441 if (!(*p)->IsHeapObject()) return; | 1464 if (!(*p)->IsHeapObject()) return; |
| 1442 | 1465 |
| 1443 HeapObject* object = HeapObject::cast(*p); | 1466 HeapObject* object = HeapObject::cast(*p); |
| 1444 | 1467 |
| 1445 if (!collector_->heap()->InNewSpace(object)) return; | 1468 if (!collector_->heap()->InNewSpace(object)) return; |
| 1446 | 1469 |
| 1447 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( | 1470 if (ObjectMarking::IsBlackOrGrey<MarkBit::NON_ATOMIC>( |
| 1448 object, MarkingState::External(object))) | 1471 object, MarkingState::External(object))) |
| 1449 return; | 1472 return; |
| 1450 | 1473 |
| 1451 Map* map = object->map(); | 1474 Map* map = object->map(); |
| 1452 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( | 1475 ObjectMarking::WhiteToBlack<MarkBit::NON_ATOMIC>( |
| 1453 object, MarkingState::External(object)); | 1476 object, MarkingState::External(object)); |
| 1454 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); | 1477 StaticYoungGenerationMarkingVisitor::IterateBody(map, object); |
| 1455 | 1478 |
| 1456 collector_->EmptyMarkingDeque(); | 1479 collector_->EmptyMarkingDeque(); |
| 1457 } | 1480 } |
| 1458 | 1481 |
| 1459 MinorMarkCompactCollector* collector_; | 1482 MinorMarkCompactCollector* collector_; |
| 1460 }; | 1483 }; |
| 1461 | 1484 |
| 1462 // Visitor class for marking heap roots. | 1485 // Visitor class for marking heap roots. |
| 1463 class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor { | 1486 // TODO(ulan): Remove ObjectVisitor base class after fixing marking of |
| 1487 // the string table and the top optimized code. |
| 1488 class MarkCompactCollector::RootMarkingVisitor : public ObjectVisitor, |
| 1489 public RootVisitor { |
| 1464 public: | 1490 public: |
| 1465 explicit RootMarkingVisitor(Heap* heap) | 1491 explicit RootMarkingVisitor(Heap* heap) |
| 1466 : collector_(heap->mark_compact_collector()) {} | 1492 : collector_(heap->mark_compact_collector()) {} |
| 1467 | 1493 |
| 1468 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } | 1494 void VisitPointer(Object** p) override { MarkObjectByPointer(p); } |
| 1469 | 1495 |
| 1470 void VisitPointers(Object** start, Object** end) override { | 1496 void VisitPointers(Object** start, Object** end) override { |
| 1471 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); | 1497 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); |
| 1472 } | 1498 } |
| 1473 | 1499 |
| 1500 void VisitRootPointer(Root root, Object** p) override { |
| 1501 MarkObjectByPointer(p); |
| 1502 } |
| 1503 |
| 1504 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 1505 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); |
| 1506 } |
| 1507 |
| 1474 // Skip the weak next code link in a code object, which is visited in | 1508 // Skip the weak next code link in a code object, which is visited in |
| 1475 // ProcessTopOptimizedFrame. | 1509 // ProcessTopOptimizedFrame. |
| 1476 void VisitNextCodeLink(Object** p) override {} | 1510 void VisitNextCodeLink(Object** p) override {} |
| 1477 | 1511 |
| 1478 private: | 1512 private: |
| 1479 void MarkObjectByPointer(Object** p) { | 1513 void MarkObjectByPointer(Object** p) { |
| 1480 if (!(*p)->IsHeapObject()) return; | 1514 if (!(*p)->IsHeapObject()) return; |
| 1481 | 1515 |
| 1482 HeapObject* object = HeapObject::cast(*p); | 1516 HeapObject* object = HeapObject::cast(*p); |
| 1483 | 1517 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1495 MarkCompactMarkingVisitor::IterateBody(map, object); | 1529 MarkCompactMarkingVisitor::IterateBody(map, object); |
| 1496 | 1530 |
| 1497 // Mark all the objects reachable from the map and body. May leave | 1531 // Mark all the objects reachable from the map and body. May leave |
| 1498 // overflowed objects in the heap. | 1532 // overflowed objects in the heap. |
| 1499 collector_->EmptyMarkingDeque(); | 1533 collector_->EmptyMarkingDeque(); |
| 1500 } | 1534 } |
| 1501 | 1535 |
| 1502 MarkCompactCollector* collector_; | 1536 MarkCompactCollector* collector_; |
| 1503 }; | 1537 }; |
| 1504 | 1538 |
| 1505 | 1539 class InternalizedStringTableCleaner : public ObjectVisitor { |
| 1506 // Helper class for pruning the string table. | |
| 1507 template <bool finalize_external_strings, bool record_slots> | |
| 1508 class StringTableCleaner : public ObjectVisitor { | |
| 1509 public: | 1540 public: |
| 1510 StringTableCleaner(Heap* heap, HeapObject* table) | 1541 InternalizedStringTableCleaner(Heap* heap, HeapObject* table) |
| 1511 : heap_(heap), pointers_removed_(0), table_(table) { | 1542 : heap_(heap), pointers_removed_(0), table_(table) {} |
| 1512 DCHECK(!record_slots || table != nullptr); | |
| 1513 } | |
| 1514 | 1543 |
| 1515 void VisitPointers(Object** start, Object** end) override { | 1544 void VisitPointers(Object** start, Object** end) override { |
| 1516 // Visit all HeapObject pointers in [start, end). | 1545 // Visit all HeapObject pointers in [start, end). |
| 1517 MarkCompactCollector* collector = heap_->mark_compact_collector(); | 1546 MarkCompactCollector* collector = heap_->mark_compact_collector(); |
| 1547 Object* the_hole = heap_->the_hole_value(); |
| 1518 for (Object** p = start; p < end; p++) { | 1548 for (Object** p = start; p < end; p++) { |
| 1519 Object* o = *p; | 1549 Object* o = *p; |
| 1520 if (o->IsHeapObject()) { | 1550 if (o->IsHeapObject()) { |
| 1521 HeapObject* heap_object = HeapObject::cast(o); | 1551 HeapObject* heap_object = HeapObject::cast(o); |
| 1522 if (ObjectMarking::IsWhite(heap_object, | 1552 if (ObjectMarking::IsWhite(heap_object, |
| 1523 MarkingState::Internal(heap_object))) { | 1553 MarkingState::Internal(heap_object))) { |
| 1524 if (finalize_external_strings) { | 1554 pointers_removed_++; |
| 1525 if (o->IsExternalString()) { | |
| 1526 heap_->FinalizeExternalString(String::cast(*p)); | |
| 1527 } else { | |
| 1528 // The original external string may have been internalized. | |
| 1529 DCHECK(o->IsThinString()); | |
| 1530 } | |
| 1531 } else { | |
| 1532 pointers_removed_++; | |
| 1533 } | |
| 1534 // Set the entry to the_hole_value (as deleted). | 1555 // Set the entry to the_hole_value (as deleted). |
| 1535 *p = heap_->the_hole_value(); | 1556 *p = the_hole; |
| 1536 } else if (record_slots) { | 1557 } else { |
| 1537 // StringTable contains only old space strings. | 1558 // StringTable contains only old space strings. |
| 1538 DCHECK(!heap_->InNewSpace(o)); | 1559 DCHECK(!heap_->InNewSpace(o)); |
| 1539 collector->RecordSlot(table_, p, o); | 1560 collector->RecordSlot(table_, p, o); |
| 1540 } | 1561 } |
| 1541 } | 1562 } |
| 1542 } | 1563 } |
| 1543 } | 1564 } |
| 1544 | 1565 |
| 1545 int PointersRemoved() { | 1566 int PointersRemoved() { |
| 1546 DCHECK(!finalize_external_strings); | |
| 1547 return pointers_removed_; | 1567 return pointers_removed_; |
| 1548 } | 1568 } |
| 1549 | 1569 |
| 1550 private: | 1570 private: |
| 1551 Heap* heap_; | 1571 Heap* heap_; |
| 1552 int pointers_removed_; | 1572 int pointers_removed_; |
| 1553 HeapObject* table_; | 1573 HeapObject* table_; |
| 1554 }; | 1574 }; |
| 1555 | 1575 |
| 1556 typedef StringTableCleaner<false, true> InternalizedStringTableCleaner; | 1576 class ExternalStringTableCleaner : public RootVisitor { |
| 1557 typedef StringTableCleaner<true, false> ExternalStringTableCleaner; | 1577 public: |
| 1578 explicit ExternalStringTableCleaner(Heap* heap) : heap_(heap) {} |
| 1579 |
| 1580 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 1581 // Visit all HeapObject pointers in [start, end). |
| 1582 Object* the_hole = heap_->the_hole_value(); |
| 1583 for (Object** p = start; p < end; p++) { |
| 1584 Object* o = *p; |
| 1585 if (o->IsHeapObject()) { |
| 1586 HeapObject* heap_object = HeapObject::cast(o); |
| 1587 if (ObjectMarking::IsWhite(heap_object, |
| 1588 MarkingState::Internal(heap_object))) { |
| 1589 if (o->IsExternalString()) { |
| 1590 heap_->FinalizeExternalString(String::cast(*p)); |
| 1591 } else { |
| 1592 // The original external string may have been internalized. |
| 1593 DCHECK(o->IsThinString()); |
| 1594 } |
| 1595 // Set the entry to the_hole_value (as deleted). |
| 1596 *p = the_hole; |
| 1597 } |
| 1598 } |
| 1599 } |
| 1600 } |
| 1601 |
| 1602 private: |
| 1603 Heap* heap_; |
| 1604 }; |
| 1558 | 1605 |
| 1559 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects | 1606 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects |
| 1560 // are retained. | 1607 // are retained. |
| 1561 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { | 1608 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { |
| 1562 public: | 1609 public: |
| 1563 virtual Object* RetainAs(Object* object) { | 1610 virtual Object* RetainAs(Object* object) { |
| 1564 HeapObject* heap_object = HeapObject::cast(object); | 1611 HeapObject* heap_object = HeapObject::cast(object); |
| 1565 DCHECK(!ObjectMarking::IsGrey(heap_object, | 1612 DCHECK(!ObjectMarking::IsGrey(heap_object, |
| 1566 MarkingState::Internal(heap_object))); | 1613 MarkingState::Internal(heap_object))); |
| 1567 if (ObjectMarking::IsBlack(heap_object, | 1614 if (ObjectMarking::IsBlack(heap_object, |
| (...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2144 while (marking_deque()->overflowed()) { | 2191 while (marking_deque()->overflowed()) { |
| 2145 RefillMarkingDeque(); | 2192 RefillMarkingDeque(); |
| 2146 EmptyMarkingDeque(); | 2193 EmptyMarkingDeque(); |
| 2147 } | 2194 } |
| 2148 DCHECK(marking_deque()->IsEmpty()); | 2195 DCHECK(marking_deque()->IsEmpty()); |
| 2149 } | 2196 } |
| 2150 | 2197 |
| 2151 // Mark all objects reachable (transitively) from objects on the marking | 2198 // Mark all objects reachable (transitively) from objects on the marking |
| 2152 // stack including references only considered in the atomic marking pause. | 2199 // stack including references only considered in the atomic marking pause. |
| 2153 void MarkCompactCollector::ProcessEphemeralMarking( | 2200 void MarkCompactCollector::ProcessEphemeralMarking( |
| 2154 ObjectVisitor* visitor, bool only_process_harmony_weak_collections) { | 2201 bool only_process_harmony_weak_collections) { |
| 2155 DCHECK(marking_deque()->IsEmpty() && !marking_deque()->overflowed()); | 2202 DCHECK(marking_deque()->IsEmpty() && !marking_deque()->overflowed()); |
| 2156 bool work_to_do = true; | 2203 bool work_to_do = true; |
| 2157 while (work_to_do) { | 2204 while (work_to_do) { |
| 2158 if (!only_process_harmony_weak_collections) { | 2205 if (!only_process_harmony_weak_collections) { |
| 2159 if (heap_->local_embedder_heap_tracer()->InUse()) { | 2206 if (heap_->local_embedder_heap_tracer()->InUse()) { |
| 2160 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_TRACING); | 2207 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_TRACING); |
| 2161 heap_->local_embedder_heap_tracer()->RegisterWrappersWithRemoteTracer(); | 2208 heap_->local_embedder_heap_tracer()->RegisterWrappersWithRemoteTracer(); |
| 2162 heap_->local_embedder_heap_tracer()->Trace( | 2209 heap_->local_embedder_heap_tracer()->Trace( |
| 2163 0, | 2210 0, |
| 2164 EmbedderHeapTracer::AdvanceTracingActions( | 2211 EmbedderHeapTracer::AdvanceTracingActions( |
| 2165 EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)); | 2212 EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION)); |
| 2166 } | 2213 } |
| 2167 } else { | 2214 } else { |
| 2168 // TODO(mlippautz): We currently do not trace through blink when | 2215 // TODO(mlippautz): We currently do not trace through blink when |
| 2169 // discovering new objects reachable from weak roots (that have been made | 2216 // discovering new objects reachable from weak roots (that have been made |
| 2170 // strong). This is a limitation of not having a separate handle type | 2217 // strong). This is a limitation of not having a separate handle type |
| 2171 // that doesn't require zapping before this phase. See crbug.com/668060. | 2218 // that doesn't require zapping before this phase. See crbug.com/668060. |
| 2172 heap_->local_embedder_heap_tracer()->ClearCachedWrappersToTrace(); | 2219 heap_->local_embedder_heap_tracer()->ClearCachedWrappersToTrace(); |
| 2173 } | 2220 } |
| 2174 ProcessWeakCollections(); | 2221 ProcessWeakCollections(); |
| 2175 work_to_do = !marking_deque()->IsEmpty(); | 2222 work_to_do = !marking_deque()->IsEmpty(); |
| 2176 ProcessMarkingDeque(); | 2223 ProcessMarkingDeque(); |
| 2177 } | 2224 } |
| 2178 CHECK(marking_deque()->IsEmpty()); | 2225 CHECK(marking_deque()->IsEmpty()); |
| 2179 CHECK_EQ(0, heap()->local_embedder_heap_tracer()->NumberOfWrappersToTrace()); | 2226 CHECK_EQ(0, heap()->local_embedder_heap_tracer()->NumberOfWrappersToTrace()); |
| 2180 } | 2227 } |
| 2181 | 2228 |
| 2182 void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) { | 2229 void MarkCompactCollector::ProcessTopOptimizedFrame( |
| 2230 RootMarkingVisitor* visitor) { |
| 2183 for (StackFrameIterator it(isolate(), isolate()->thread_local_top()); | 2231 for (StackFrameIterator it(isolate(), isolate()->thread_local_top()); |
| 2184 !it.done(); it.Advance()) { | 2232 !it.done(); it.Advance()) { |
| 2185 if (it.frame()->type() == StackFrame::JAVA_SCRIPT) { | 2233 if (it.frame()->type() == StackFrame::JAVA_SCRIPT) { |
| 2186 return; | 2234 return; |
| 2187 } | 2235 } |
| 2188 if (it.frame()->type() == StackFrame::OPTIMIZED) { | 2236 if (it.frame()->type() == StackFrame::OPTIMIZED) { |
| 2189 Code* code = it.frame()->LookupCode(); | 2237 Code* code = it.frame()->LookupCode(); |
| 2190 if (!code->CanDeoptAt(it.frame()->pc())) { | 2238 if (!code->CanDeoptAt(it.frame()->pc())) { |
| 2191 Code::BodyDescriptor::IterateBody(code, visitor); | 2239 Code::BodyDescriptor::IterateBody(code, visitor); |
| 2192 } | 2240 } |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2402 isolate(), type, addr, [this](Object** addr) { | 2450 isolate(), type, addr, [this](Object** addr) { |
| 2403 return CheckAndMarkObject(heap(), | 2451 return CheckAndMarkObject(heap(), |
| 2404 reinterpret_cast<Address>(addr)); | 2452 reinterpret_cast<Address>(addr)); |
| 2405 }); | 2453 }); |
| 2406 }); | 2454 }); |
| 2407 ProcessMarkingDeque(); | 2455 ProcessMarkingDeque(); |
| 2408 } | 2456 } |
| 2409 | 2457 |
| 2410 { | 2458 { |
| 2411 TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK); | 2459 TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK); |
| 2412 heap()->VisitEncounteredWeakCollections(&root_visitor); | 2460 heap()->IterateEncounteredWeakCollections(&root_visitor); |
| 2413 ProcessMarkingDeque(); | 2461 ProcessMarkingDeque(); |
| 2414 } | 2462 } |
| 2415 | 2463 |
| 2416 { | 2464 { |
| 2417 TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_GLOBAL_HANDLES); | 2465 TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_GLOBAL_HANDLES); |
| 2418 isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending( | 2466 isolate()->global_handles()->MarkNewSpaceWeakUnmodifiedObjectsPending( |
| 2419 &IsUnmarkedObject); | 2467 &IsUnmarkedObject); |
| 2420 isolate() | 2468 isolate() |
| 2421 ->global_handles() | 2469 ->global_handles() |
| 2422 ->IterateNewSpaceWeakUnmodifiedRoots<GlobalHandles::VISIT_OTHERS>( | 2470 ->IterateNewSpaceWeakUnmodifiedRoots<GlobalHandles::VISIT_OTHERS>( |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2503 | 2551 |
| 2504 { | 2552 { |
| 2505 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE); | 2553 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE); |
| 2506 | 2554 |
| 2507 // The objects reachable from the roots are marked, yet unreachable | 2555 // The objects reachable from the roots are marked, yet unreachable |
| 2508 // objects are unmarked. Mark objects reachable due to host | 2556 // objects are unmarked. Mark objects reachable due to host |
| 2509 // application specific logic or through Harmony weak maps. | 2557 // application specific logic or through Harmony weak maps. |
| 2510 { | 2558 { |
| 2511 TRACE_GC(heap()->tracer(), | 2559 TRACE_GC(heap()->tracer(), |
| 2512 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_EPHEMERAL); | 2560 GCTracer::Scope::MC_MARK_WEAK_CLOSURE_EPHEMERAL); |
| 2513 ProcessEphemeralMarking(&root_visitor, false); | 2561 ProcessEphemeralMarking(false); |
| 2514 } | 2562 } |
| 2515 | 2563 |
| 2516 // The objects reachable from the roots, weak maps or object groups | 2564 // The objects reachable from the roots, weak maps or object groups |
| 2517 // are marked. Objects pointed to only by weak global handles cannot be | 2565 // are marked. Objects pointed to only by weak global handles cannot be |
| 2518 // immediately reclaimed. Instead, we have to mark them as pending and mark | 2566 // immediately reclaimed. Instead, we have to mark them as pending and mark |
| 2519 // objects reachable from them. | 2567 // objects reachable from them. |
| 2520 // | 2568 // |
| 2521 // First we identify nonlive weak handles and mark them as pending | 2569 // First we identify nonlive weak handles and mark them as pending |
| 2522 // destruction. | 2570 // destruction. |
| 2523 { | 2571 { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2536 ProcessMarkingDeque(); | 2584 ProcessMarkingDeque(); |
| 2537 } | 2585 } |
| 2538 | 2586 |
| 2539 // Repeat Harmony weak maps marking to mark unmarked objects reachable from | 2587 // Repeat Harmony weak maps marking to mark unmarked objects reachable from |
| 2540 // the weak roots we just marked as pending destruction. | 2588 // the weak roots we just marked as pending destruction. |
| 2541 // | 2589 // |
| 2542 // We only process harmony collections, as all object groups have been fully | 2590 // We only process harmony collections, as all object groups have been fully |
| 2543 // processed and no weakly reachable node can discover new objects groups. | 2591 // processed and no weakly reachable node can discover new objects groups. |
| 2544 { | 2592 { |
| 2545 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); | 2593 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY); |
| 2546 ProcessEphemeralMarking(&root_visitor, true); | 2594 ProcessEphemeralMarking(true); |
| 2547 { | 2595 { |
| 2548 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE); | 2596 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE); |
| 2549 heap()->local_embedder_heap_tracer()->TraceEpilogue(); | 2597 heap()->local_embedder_heap_tracer()->TraceEpilogue(); |
| 2550 } | 2598 } |
| 2551 } | 2599 } |
| 2552 } | 2600 } |
| 2553 } | 2601 } |
| 2554 | 2602 |
| 2555 | 2603 |
| 2556 void MarkCompactCollector::ClearNonLiveReferences() { | 2604 void MarkCompactCollector::ClearNonLiveReferences() { |
| 2557 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); | 2605 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR); |
| 2558 | 2606 |
| 2559 { | 2607 { |
| 2560 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); | 2608 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_STRING_TABLE); |
| 2561 | 2609 |
| 2562 // Prune the string table removing all strings only pointed to by the | 2610 // Prune the string table removing all strings only pointed to by the |
| 2563 // string table. Cannot use string_table() here because the string | 2611 // string table. Cannot use string_table() here because the string |
| 2564 // table is marked. | 2612 // table is marked. |
| 2565 StringTable* string_table = heap()->string_table(); | 2613 StringTable* string_table = heap()->string_table(); |
| 2566 InternalizedStringTableCleaner internalized_visitor(heap(), string_table); | 2614 InternalizedStringTableCleaner internalized_visitor(heap(), string_table); |
| 2567 string_table->IterateElements(&internalized_visitor); | 2615 string_table->IterateElements(&internalized_visitor); |
| 2568 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); | 2616 string_table->ElementsRemoved(internalized_visitor.PointersRemoved()); |
| 2569 | 2617 |
| 2570 ExternalStringTableCleaner external_visitor(heap(), nullptr); | 2618 ExternalStringTableCleaner external_visitor(heap()); |
| 2571 heap()->external_string_table_.IterateAll(&external_visitor); | 2619 heap()->external_string_table_.IterateAll(&external_visitor); |
| 2572 heap()->external_string_table_.CleanUpAll(); | 2620 heap()->external_string_table_.CleanUpAll(); |
| 2573 } | 2621 } |
| 2574 | 2622 |
| 2575 { | 2623 { |
| 2576 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_LISTS); | 2624 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_CLEAR_WEAK_LISTS); |
| 2577 // Process the weak references. | 2625 // Process the weak references. |
| 2578 MarkCompactWeakObjectRetainer mark_compact_object_retainer; | 2626 MarkCompactWeakObjectRetainer mark_compact_object_retainer; |
| 2579 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); | 2627 heap()->ProcessAllWeakReferences(&mark_compact_object_retainer); |
| 2580 } | 2628 } |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3031 reinterpret_cast<base::AtomicWord*>(slot), | 3079 reinterpret_cast<base::AtomicWord*>(slot), |
| 3032 reinterpret_cast<base::AtomicWord>(obj), | 3080 reinterpret_cast<base::AtomicWord>(obj), |
| 3033 reinterpret_cast<base::AtomicWord>(target)); | 3081 reinterpret_cast<base::AtomicWord>(target)); |
| 3034 DCHECK(!heap_obj->GetHeap()->InFromSpace(target)); | 3082 DCHECK(!heap_obj->GetHeap()->InFromSpace(target)); |
| 3035 DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(target)); | 3083 DCHECK(!MarkCompactCollector::IsOnEvacuationCandidate(target)); |
| 3036 } | 3084 } |
| 3037 } | 3085 } |
| 3038 return REMOVE_SLOT; | 3086 return REMOVE_SLOT; |
| 3039 } | 3087 } |
| 3040 | 3088 |
| 3041 // Visitor for updating pointers from live objects in old spaces to new space. | 3089 // Visitor for updating root pointers and to-space pointers. |
| 3042 // It does not expect to encounter pointers to dead objects. | 3090 // It does not expect to encounter pointers to dead objects. |
| 3043 class PointersUpdatingVisitor : public ObjectVisitor { | 3091 // TODO(ulan): Remove code object specific functions. This visitor |
| 3092 // nevers visits code objects. |
| 3093 class PointersUpdatingVisitor : public ObjectVisitor, public RootVisitor { |
| 3044 public: | 3094 public: |
| 3045 void VisitPointer(Object** p) override { UpdateSlot(p); } | 3095 void VisitPointer(Object** p) override { UpdateSlot(p); } |
| 3046 | 3096 |
| 3047 void VisitPointers(Object** start, Object** end) override { | 3097 void VisitPointers(Object** start, Object** end) override { |
| 3048 for (Object** p = start; p < end; p++) UpdateSlot(p); | 3098 for (Object** p = start; p < end; p++) UpdateSlot(p); |
| 3049 } | 3099 } |
| 3050 | 3100 |
| 3101 void VisitRootPointer(Root root, Object** p) override { UpdateSlot(p); } |
| 3102 |
| 3103 void VisitRootPointers(Root root, Object** start, Object** end) override { |
| 3104 for (Object** p = start; p < end; p++) UpdateSlot(p); |
| 3105 } |
| 3106 |
| 3051 void VisitCell(RelocInfo* rinfo) override { | 3107 void VisitCell(RelocInfo* rinfo) override { |
| 3052 UpdateTypedSlotHelper::UpdateCell(rinfo, UpdateSlot); | 3108 UpdateTypedSlotHelper::UpdateCell(rinfo, UpdateSlot); |
| 3053 } | 3109 } |
| 3054 | 3110 |
| 3055 void VisitEmbeddedPointer(RelocInfo* rinfo) override { | 3111 void VisitEmbeddedPointer(RelocInfo* rinfo) override { |
| 3056 UpdateTypedSlotHelper::UpdateEmbeddedPointer(rinfo, UpdateSlot); | 3112 UpdateTypedSlotHelper::UpdateEmbeddedPointer(rinfo, UpdateSlot); |
| 3057 } | 3113 } |
| 3058 | 3114 |
| 3059 void VisitCodeTarget(RelocInfo* rinfo) override { | 3115 void VisitCodeTarget(RelocInfo* rinfo) override { |
| 3060 UpdateTypedSlotHelper::UpdateCodeTarget(rinfo, UpdateSlot); | 3116 UpdateTypedSlotHelper::UpdateCodeTarget(rinfo, UpdateSlot); |
| (...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3902 job.AddPage(page, std::make_pair(start, end)); | 3958 job.AddPage(page, std::make_pair(start, end)); |
| 3903 } | 3959 } |
| 3904 PointersUpdatingVisitor visitor; | 3960 PointersUpdatingVisitor visitor; |
| 3905 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; | 3961 int num_tasks = FLAG_parallel_pointer_update ? job.NumberOfPages() : 1; |
| 3906 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); | 3962 job.Run(num_tasks, [&visitor](int i) { return &visitor; }); |
| 3907 } | 3963 } |
| 3908 | 3964 |
| 3909 void MarkCompactCollector::UpdatePointersAfterEvacuation() { | 3965 void MarkCompactCollector::UpdatePointersAfterEvacuation() { |
| 3910 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); | 3966 TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS); |
| 3911 | 3967 |
| 3912 PointersUpdatingVisitor updating_visitor; | |
| 3913 | 3968 |
| 3914 { | 3969 { |
| 3915 TRACE_GC(heap()->tracer(), | 3970 TRACE_GC(heap()->tracer(), |
| 3916 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); | 3971 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_NEW); |
| 3917 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_); | 3972 UpdateToSpacePointersInParallel(heap_, &page_parallel_job_semaphore_); |
| 3918 // Update roots. | 3973 // Update roots. |
| 3974 PointersUpdatingVisitor updating_visitor; |
| 3919 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 3975 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 3920 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_); | 3976 UpdatePointersInParallel<OLD_TO_NEW>(heap_, &page_parallel_job_semaphore_); |
| 3921 } | 3977 } |
| 3922 | 3978 |
| 3923 { | 3979 { |
| 3924 Heap* heap = this->heap(); | 3980 Heap* heap = this->heap(); |
| 3925 TRACE_GC(heap->tracer(), | 3981 TRACE_GC(heap->tracer(), |
| 3926 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); | 3982 GCTracer::Scope::MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED); |
| 3927 UpdatePointersInParallel<OLD_TO_OLD>(heap_, &page_parallel_job_semaphore_); | 3983 UpdatePointersInParallel<OLD_TO_OLD>(heap_, &page_parallel_job_semaphore_); |
| 3928 } | 3984 } |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4154 // The target is always in old space, we don't have to record the slot in | 4210 // The target is always in old space, we don't have to record the slot in |
| 4155 // the old-to-new remembered set. | 4211 // the old-to-new remembered set. |
| 4156 DCHECK(!heap()->InNewSpace(target)); | 4212 DCHECK(!heap()->InNewSpace(target)); |
| 4157 RecordRelocSlot(host, &rinfo, target); | 4213 RecordRelocSlot(host, &rinfo, target); |
| 4158 } | 4214 } |
| 4159 } | 4215 } |
| 4160 } | 4216 } |
| 4161 | 4217 |
| 4162 } // namespace internal | 4218 } // namespace internal |
| 4163 } // namespace v8 | 4219 } // namespace v8 |
| OLD | NEW |