| 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/v8.h" | 5 #include "src/v8.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/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 | 467 |
| 468 void MarkCompactCollector::ClearMarkbits() { | 468 void MarkCompactCollector::ClearMarkbits() { |
| 469 ClearMarkbitsInPagedSpace(heap_->code_space()); | 469 ClearMarkbitsInPagedSpace(heap_->code_space()); |
| 470 ClearMarkbitsInPagedSpace(heap_->map_space()); | 470 ClearMarkbitsInPagedSpace(heap_->map_space()); |
| 471 ClearMarkbitsInPagedSpace(heap_->old_space()); | 471 ClearMarkbitsInPagedSpace(heap_->old_space()); |
| 472 ClearMarkbitsInPagedSpace(heap_->cell_space()); | 472 ClearMarkbitsInPagedSpace(heap_->cell_space()); |
| 473 ClearMarkbitsInNewSpace(heap_->new_space()); | 473 ClearMarkbitsInNewSpace(heap_->new_space()); |
| 474 | 474 |
| 475 LargeObjectIterator it(heap_->lo_space()); | 475 LargeObjectIterator it(heap_->lo_space()); |
| 476 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 476 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
| 477 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 477 Marking::MarkWhite(Marking::MarkBitFrom(obj)); |
| 478 mark_bit.Clear(); | |
| 479 mark_bit.Next().Clear(); | |
| 480 Page::FromAddress(obj->address())->ResetProgressBar(); | 478 Page::FromAddress(obj->address())->ResetProgressBar(); |
| 481 Page::FromAddress(obj->address())->ResetLiveBytes(); | 479 Page::FromAddress(obj->address())->ResetLiveBytes(); |
| 482 } | 480 } |
| 483 } | 481 } |
| 484 | 482 |
| 485 | 483 |
| 486 class MarkCompactCollector::SweeperTask : public v8::Task { | 484 class MarkCompactCollector::SweeperTask : public v8::Task { |
| 487 public: | 485 public: |
| 488 SweeperTask(Heap* heap, PagedSpace* space) : heap_(heap), space_(space) {} | 486 SweeperTask(Heap* heap, PagedSpace* space) : heap_(heap), space_(space) {} |
| 489 | 487 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 // to only refill them for the old space. | 554 // to only refill them for the old space. |
| 557 return; | 555 return; |
| 558 } | 556 } |
| 559 | 557 |
| 560 intptr_t freed_bytes = space->free_list()->Concatenate(free_list); | 558 intptr_t freed_bytes = space->free_list()->Concatenate(free_list); |
| 561 space->AddToAccountingStats(freed_bytes); | 559 space->AddToAccountingStats(freed_bytes); |
| 562 space->DecrementUnsweptFreeBytes(freed_bytes); | 560 space->DecrementUnsweptFreeBytes(freed_bytes); |
| 563 } | 561 } |
| 564 | 562 |
| 565 | 563 |
| 564 void Marking::SetAllMarkBitsInRange(MarkBit start, MarkBit end) { |
| 565 MarkBit::CellType* start_cell = start.cell(); |
| 566 MarkBit::CellType* end_cell = end.cell(); |
| 567 MarkBit::CellType start_mask = ~(start.mask() - 1); |
| 568 MarkBit::CellType end_mask = (end.mask() << 1) - 1; |
| 569 |
| 570 if (start_cell == end_cell) { |
| 571 *start_cell |= start_mask & end_mask; |
| 572 } else { |
| 573 *start_cell |= start_mask; |
| 574 for (MarkBit::CellType* cell = start_cell + 1; cell < end_cell; cell++) { |
| 575 *cell = ~0; |
| 576 } |
| 577 *end_cell |= end_mask; |
| 578 } |
| 579 } |
| 580 |
| 581 |
| 582 void Marking::ClearAllMarkBitsOfCellsContainedInRange(MarkBit start, |
| 583 MarkBit end) { |
| 584 MarkBit::CellType* start_cell = start.cell(); |
| 585 MarkBit::CellType* end_cell = end.cell(); |
| 586 for (MarkBit::CellType* cell = start_cell; cell <= end_cell; cell++) { |
| 587 *cell = 0; |
| 588 } |
| 589 } |
| 590 |
| 591 |
| 566 void Marking::TransferMark(Address old_start, Address new_start) { | 592 void Marking::TransferMark(Address old_start, Address new_start) { |
| 567 // This is only used when resizing an object. | 593 // This is only used when resizing an object. |
| 568 DCHECK(MemoryChunk::FromAddress(old_start) == | 594 DCHECK(MemoryChunk::FromAddress(old_start) == |
| 569 MemoryChunk::FromAddress(new_start)); | 595 MemoryChunk::FromAddress(new_start)); |
| 570 | 596 |
| 571 if (!heap_->incremental_marking()->IsMarking()) return; | 597 if (!heap_->incremental_marking()->IsMarking()) return; |
| 572 | 598 |
| 573 // If the mark doesn't move, we don't check the color of the object. | 599 // If the mark doesn't move, we don't check the color of the object. |
| 574 // It doesn't matter whether the object is black, since it hasn't changed | 600 // It doesn't matter whether the object is black, since it hasn't changed |
| 575 // size, so the adjustment to the live data count will be zero anyway. | 601 // size, so the adjustment to the live data count will be zero anyway. |
| 576 if (old_start == new_start) return; | 602 if (old_start == new_start) return; |
| 577 | 603 |
| 578 MarkBit new_mark_bit = MarkBitFrom(new_start); | 604 MarkBit new_mark_bit = MarkBitFrom(new_start); |
| 579 MarkBit old_mark_bit = MarkBitFrom(old_start); | 605 MarkBit old_mark_bit = MarkBitFrom(old_start); |
| 580 | 606 |
| 581 #ifdef DEBUG | 607 #ifdef DEBUG |
| 582 ObjectColor old_color = Color(old_mark_bit); | 608 ObjectColor old_color = Color(old_mark_bit); |
| 583 #endif | 609 #endif |
| 584 | 610 |
| 585 if (Marking::IsBlack(old_mark_bit)) { | 611 if (Marking::IsBlack(old_mark_bit)) { |
| 586 old_mark_bit.Clear(); | 612 Marking::BlackToWhite(old_mark_bit); |
| 587 DCHECK(IsWhite(old_mark_bit)); | |
| 588 Marking::MarkBlack(new_mark_bit); | 613 Marking::MarkBlack(new_mark_bit); |
| 589 return; | 614 return; |
| 590 } else if (Marking::IsGrey(old_mark_bit)) { | 615 } else if (Marking::IsGrey(old_mark_bit)) { |
| 591 old_mark_bit.Clear(); | 616 Marking::GreyToWhite(old_mark_bit); |
| 592 old_mark_bit.Next().Clear(); | |
| 593 DCHECK(IsWhite(old_mark_bit)); | |
| 594 heap_->incremental_marking()->WhiteToGreyAndPush( | 617 heap_->incremental_marking()->WhiteToGreyAndPush( |
| 595 HeapObject::FromAddress(new_start), new_mark_bit); | 618 HeapObject::FromAddress(new_start), new_mark_bit); |
| 596 heap_->incremental_marking()->RestartIfNotMarking(); | 619 heap_->incremental_marking()->RestartIfNotMarking(); |
| 597 } | 620 } |
| 598 | 621 |
| 599 #ifdef DEBUG | 622 #ifdef DEBUG |
| 600 ObjectColor new_color = Color(new_mark_bit); | 623 ObjectColor new_color = Color(new_mark_bit); |
| 601 DCHECK(new_color == old_color); | 624 DCHECK(new_color == old_color); |
| 602 #endif | 625 #endif |
| 603 } | 626 } |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 963 JSFunction* candidate = jsfunction_candidates_head_; | 986 JSFunction* candidate = jsfunction_candidates_head_; |
| 964 JSFunction* next_candidate; | 987 JSFunction* next_candidate; |
| 965 while (candidate != NULL) { | 988 while (candidate != NULL) { |
| 966 next_candidate = GetNextCandidate(candidate); | 989 next_candidate = GetNextCandidate(candidate); |
| 967 ClearNextCandidate(candidate, undefined); | 990 ClearNextCandidate(candidate, undefined); |
| 968 | 991 |
| 969 SharedFunctionInfo* shared = candidate->shared(); | 992 SharedFunctionInfo* shared = candidate->shared(); |
| 970 | 993 |
| 971 Code* code = shared->code(); | 994 Code* code = shared->code(); |
| 972 MarkBit code_mark = Marking::MarkBitFrom(code); | 995 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 973 if (!code_mark.Get()) { | 996 if (Marking::IsWhite(code_mark)) { |
| 974 if (FLAG_trace_code_flushing && shared->is_compiled()) { | 997 if (FLAG_trace_code_flushing && shared->is_compiled()) { |
| 975 PrintF("[code-flushing clears: "); | 998 PrintF("[code-flushing clears: "); |
| 976 shared->ShortPrint(); | 999 shared->ShortPrint(); |
| 977 PrintF(" - age: %d]\n", code->GetAge()); | 1000 PrintF(" - age: %d]\n", code->GetAge()); |
| 978 } | 1001 } |
| 979 shared->set_code(lazy_compile); | 1002 shared->set_code(lazy_compile); |
| 980 candidate->set_code(lazy_compile); | 1003 candidate->set_code(lazy_compile); |
| 981 } else { | 1004 } else { |
| 1005 DCHECK(Marking::IsBlack(code_mark)); |
| 982 candidate->set_code(code); | 1006 candidate->set_code(code); |
| 983 } | 1007 } |
| 984 | 1008 |
| 985 // We are in the middle of a GC cycle so the write barrier in the code | 1009 // We are in the middle of a GC cycle so the write barrier in the code |
| 986 // setter did not record the slot update and we have to do that manually. | 1010 // setter did not record the slot update and we have to do that manually. |
| 987 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; | 1011 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; |
| 988 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); | 1012 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); |
| 989 isolate_->heap()->mark_compact_collector()->RecordCodeEntrySlot(slot, | 1013 isolate_->heap()->mark_compact_collector()->RecordCodeEntrySlot(slot, |
| 990 target); | 1014 target); |
| 991 | 1015 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1005 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); | 1029 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kCompileLazy); |
| 1006 | 1030 |
| 1007 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; | 1031 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; |
| 1008 SharedFunctionInfo* next_candidate; | 1032 SharedFunctionInfo* next_candidate; |
| 1009 while (candidate != NULL) { | 1033 while (candidate != NULL) { |
| 1010 next_candidate = GetNextCandidate(candidate); | 1034 next_candidate = GetNextCandidate(candidate); |
| 1011 ClearNextCandidate(candidate); | 1035 ClearNextCandidate(candidate); |
| 1012 | 1036 |
| 1013 Code* code = candidate->code(); | 1037 Code* code = candidate->code(); |
| 1014 MarkBit code_mark = Marking::MarkBitFrom(code); | 1038 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 1015 if (!code_mark.Get()) { | 1039 if (Marking::IsWhite(code_mark)) { |
| 1016 if (FLAG_trace_code_flushing && candidate->is_compiled()) { | 1040 if (FLAG_trace_code_flushing && candidate->is_compiled()) { |
| 1017 PrintF("[code-flushing clears: "); | 1041 PrintF("[code-flushing clears: "); |
| 1018 candidate->ShortPrint(); | 1042 candidate->ShortPrint(); |
| 1019 PrintF(" - age: %d]\n", code->GetAge()); | 1043 PrintF(" - age: %d]\n", code->GetAge()); |
| 1020 } | 1044 } |
| 1021 candidate->set_code(lazy_compile); | 1045 candidate->set_code(lazy_compile); |
| 1022 } | 1046 } |
| 1023 | 1047 |
| 1024 Object** code_slot = | 1048 Object** code_slot = |
| 1025 HeapObject::RawField(candidate, SharedFunctionInfo::kCodeOffset); | 1049 HeapObject::RawField(candidate, SharedFunctionInfo::kCodeOffset); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1043 next_holder = GetNextCodeMap(holder); | 1067 next_holder = GetNextCodeMap(holder); |
| 1044 ClearNextCodeMap(holder); | 1068 ClearNextCodeMap(holder); |
| 1045 | 1069 |
| 1046 FixedArray* code_map = FixedArray::cast(holder->optimized_code_map()); | 1070 FixedArray* code_map = FixedArray::cast(holder->optimized_code_map()); |
| 1047 int new_length = SharedFunctionInfo::kEntriesStart; | 1071 int new_length = SharedFunctionInfo::kEntriesStart; |
| 1048 int old_length = code_map->length(); | 1072 int old_length = code_map->length(); |
| 1049 for (int i = SharedFunctionInfo::kEntriesStart; i < old_length; | 1073 for (int i = SharedFunctionInfo::kEntriesStart; i < old_length; |
| 1050 i += SharedFunctionInfo::kEntryLength) { | 1074 i += SharedFunctionInfo::kEntryLength) { |
| 1051 Code* code = | 1075 Code* code = |
| 1052 Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset)); | 1076 Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset)); |
| 1053 if (!Marking::MarkBitFrom(code).Get()) continue; | 1077 if (Marking::IsWhite(Marking::MarkBitFrom(code))) continue; |
| 1054 | 1078 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(code))); |
| 1055 // Move every slot in the entry. | 1079 // Move every slot in the entry. |
| 1056 for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) { | 1080 for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) { |
| 1057 int dst_index = new_length++; | 1081 int dst_index = new_length++; |
| 1058 Object** slot = code_map->RawFieldOfElementAt(dst_index); | 1082 Object** slot = code_map->RawFieldOfElementAt(dst_index); |
| 1059 Object* object = code_map->get(i + j); | 1083 Object* object = code_map->get(i + j); |
| 1060 code_map->set(dst_index, object); | 1084 code_map->set(dst_index, object); |
| 1061 if (j == SharedFunctionInfo::kOsrAstIdOffset) { | 1085 if (j == SharedFunctionInfo::kOsrAstIdOffset) { |
| 1062 DCHECK(object->IsSmi()); | 1086 DCHECK(object->IsSmi()); |
| 1063 } else { | 1087 } else { |
| 1064 DCHECK( | 1088 DCHECK( |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1320 // Marks the object black and pushes it on the marking stack. | 1344 // Marks the object black and pushes it on the marking stack. |
| 1321 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { | 1345 INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { |
| 1322 MarkBit mark = Marking::MarkBitFrom(object); | 1346 MarkBit mark = Marking::MarkBitFrom(object); |
| 1323 heap->mark_compact_collector()->MarkObject(object, mark); | 1347 heap->mark_compact_collector()->MarkObject(object, mark); |
| 1324 } | 1348 } |
| 1325 | 1349 |
| 1326 // Marks the object black without pushing it on the marking stack. | 1350 // Marks the object black without pushing it on the marking stack. |
| 1327 // Returns true if object needed marking and false otherwise. | 1351 // Returns true if object needed marking and false otherwise. |
| 1328 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { | 1352 INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) { |
| 1329 MarkBit mark_bit = Marking::MarkBitFrom(object); | 1353 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 1330 if (!mark_bit.Get()) { | 1354 if (Marking::IsWhite(mark_bit)) { |
| 1331 heap->mark_compact_collector()->SetMark(object, mark_bit); | 1355 heap->mark_compact_collector()->SetMark(object, mark_bit); |
| 1332 return true; | 1356 return true; |
| 1333 } | 1357 } |
| 1334 return false; | 1358 return false; |
| 1335 } | 1359 } |
| 1336 | 1360 |
| 1337 // Mark object pointed to by p. | 1361 // Mark object pointed to by p. |
| 1338 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, | 1362 INLINE(static void MarkObjectByPointer(MarkCompactCollector* collector, |
| 1339 Object** anchor_slot, Object** p)) { | 1363 Object** anchor_slot, Object** p)) { |
| 1340 if (!(*p)->IsHeapObject()) return; | 1364 if (!(*p)->IsHeapObject()) return; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1371 if (check.HasOverflowed()) return false; | 1395 if (check.HasOverflowed()) return false; |
| 1372 | 1396 |
| 1373 MarkCompactCollector* collector = heap->mark_compact_collector(); | 1397 MarkCompactCollector* collector = heap->mark_compact_collector(); |
| 1374 // Visit the unmarked objects. | 1398 // Visit the unmarked objects. |
| 1375 for (Object** p = start; p < end; p++) { | 1399 for (Object** p = start; p < end; p++) { |
| 1376 Object* o = *p; | 1400 Object* o = *p; |
| 1377 if (!o->IsHeapObject()) continue; | 1401 if (!o->IsHeapObject()) continue; |
| 1378 collector->RecordSlot(start, p, o); | 1402 collector->RecordSlot(start, p, o); |
| 1379 HeapObject* obj = HeapObject::cast(o); | 1403 HeapObject* obj = HeapObject::cast(o); |
| 1380 MarkBit mark = Marking::MarkBitFrom(obj); | 1404 MarkBit mark = Marking::MarkBitFrom(obj); |
| 1381 if (mark.Get()) continue; | 1405 if (Marking::IsBlackOrGrey(mark)) continue; |
| 1382 VisitUnmarkedObject(collector, obj); | 1406 VisitUnmarkedObject(collector, obj); |
| 1383 } | 1407 } |
| 1384 return true; | 1408 return true; |
| 1385 } | 1409 } |
| 1386 | 1410 |
| 1387 private: | 1411 private: |
| 1388 template <int id> | 1412 template <int id> |
| 1389 static inline void TrackObjectStatsAndVisit(Map* map, HeapObject* obj); | 1413 static inline void TrackObjectStatsAndVisit(Map* map, HeapObject* obj); |
| 1390 | 1414 |
| 1391 // Code flushing support. | 1415 // Code flushing support. |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1716 // ProcessTopOptimizedFrame. | 1740 // ProcessTopOptimizedFrame. |
| 1717 void VisitNextCodeLink(Object** p) {} | 1741 void VisitNextCodeLink(Object** p) {} |
| 1718 | 1742 |
| 1719 private: | 1743 private: |
| 1720 void MarkObjectByPointer(Object** p) { | 1744 void MarkObjectByPointer(Object** p) { |
| 1721 if (!(*p)->IsHeapObject()) return; | 1745 if (!(*p)->IsHeapObject()) return; |
| 1722 | 1746 |
| 1723 // Replace flat cons strings in place. | 1747 // Replace flat cons strings in place. |
| 1724 HeapObject* object = ShortCircuitConsString(p); | 1748 HeapObject* object = ShortCircuitConsString(p); |
| 1725 MarkBit mark_bit = Marking::MarkBitFrom(object); | 1749 MarkBit mark_bit = Marking::MarkBitFrom(object); |
| 1726 if (mark_bit.Get()) return; | 1750 if (Marking::IsBlackOrGrey(mark_bit)) return; |
| 1727 | 1751 |
| 1728 Map* map = object->map(); | 1752 Map* map = object->map(); |
| 1729 // Mark the object. | 1753 // Mark the object. |
| 1730 collector_->SetMark(object, mark_bit); | 1754 collector_->SetMark(object, mark_bit); |
| 1731 | 1755 |
| 1732 // Mark the map pointer and body, and push them on the marking stack. | 1756 // Mark the map pointer and body, and push them on the marking stack. |
| 1733 MarkBit map_mark = Marking::MarkBitFrom(map); | 1757 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 1734 collector_->MarkObject(map, map_mark); | 1758 collector_->MarkObject(map, map_mark); |
| 1735 MarkCompactMarkingVisitor::IterateBody(map, object); | 1759 MarkCompactMarkingVisitor::IterateBody(map, object); |
| 1736 | 1760 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1747 template <bool finalize_external_strings> | 1771 template <bool finalize_external_strings> |
| 1748 class StringTableCleaner : public ObjectVisitor { | 1772 class StringTableCleaner : public ObjectVisitor { |
| 1749 public: | 1773 public: |
| 1750 explicit StringTableCleaner(Heap* heap) : heap_(heap), pointers_removed_(0) {} | 1774 explicit StringTableCleaner(Heap* heap) : heap_(heap), pointers_removed_(0) {} |
| 1751 | 1775 |
| 1752 virtual void VisitPointers(Object** start, Object** end) { | 1776 virtual void VisitPointers(Object** start, Object** end) { |
| 1753 // Visit all HeapObject pointers in [start, end). | 1777 // Visit all HeapObject pointers in [start, end). |
| 1754 for (Object** p = start; p < end; p++) { | 1778 for (Object** p = start; p < end; p++) { |
| 1755 Object* o = *p; | 1779 Object* o = *p; |
| 1756 if (o->IsHeapObject() && | 1780 if (o->IsHeapObject() && |
| 1757 !Marking::MarkBitFrom(HeapObject::cast(o)).Get()) { | 1781 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(o)))) { |
| 1758 if (finalize_external_strings) { | 1782 if (finalize_external_strings) { |
| 1759 DCHECK(o->IsExternalString()); | 1783 DCHECK(o->IsExternalString()); |
| 1760 heap_->FinalizeExternalString(String::cast(*p)); | 1784 heap_->FinalizeExternalString(String::cast(*p)); |
| 1761 } else { | 1785 } else { |
| 1762 pointers_removed_++; | 1786 pointers_removed_++; |
| 1763 } | 1787 } |
| 1764 // Set the entry to the_hole_value (as deleted). | 1788 // Set the entry to the_hole_value (as deleted). |
| 1765 *p = heap_->the_hole_value(); | 1789 *p = heap_->the_hole_value(); |
| 1766 } | 1790 } |
| 1767 } | 1791 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1780 | 1804 |
| 1781 typedef StringTableCleaner<false> InternalizedStringTableCleaner; | 1805 typedef StringTableCleaner<false> InternalizedStringTableCleaner; |
| 1782 typedef StringTableCleaner<true> ExternalStringTableCleaner; | 1806 typedef StringTableCleaner<true> ExternalStringTableCleaner; |
| 1783 | 1807 |
| 1784 | 1808 |
| 1785 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects | 1809 // Implementation of WeakObjectRetainer for mark compact GCs. All marked objects |
| 1786 // are retained. | 1810 // are retained. |
| 1787 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { | 1811 class MarkCompactWeakObjectRetainer : public WeakObjectRetainer { |
| 1788 public: | 1812 public: |
| 1789 virtual Object* RetainAs(Object* object) { | 1813 virtual Object* RetainAs(Object* object) { |
| 1790 if (Marking::MarkBitFrom(HeapObject::cast(object)).Get()) { | 1814 if (Marking::IsBlackOrGrey( |
| 1815 Marking::MarkBitFrom(HeapObject::cast(object)))) { |
| 1791 return object; | 1816 return object; |
| 1792 } else if (object->IsAllocationSite() && | 1817 } else if (object->IsAllocationSite() && |
| 1793 !(AllocationSite::cast(object)->IsZombie())) { | 1818 !(AllocationSite::cast(object)->IsZombie())) { |
| 1794 // "dead" AllocationSites need to live long enough for a traversal of new | 1819 // "dead" AllocationSites need to live long enough for a traversal of new |
| 1795 // space. These sites get a one-time reprieve. | 1820 // space. These sites get a one-time reprieve. |
| 1796 AllocationSite* site = AllocationSite::cast(object); | 1821 AllocationSite* site = AllocationSite::cast(object); |
| 1797 site->MarkZombie(); | 1822 site->MarkZombie(); |
| 1798 site->GetHeap()->mark_compact_collector()->MarkAllocationSite(site); | 1823 site->GetHeap()->mark_compact_collector()->MarkAllocationSite(site); |
| 1799 return object; | 1824 return object; |
| 1800 } else { | 1825 } else { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1894 MarkBit::CellType current_cell = *cell; | 1919 MarkBit::CellType current_cell = *cell; |
| 1895 if (current_cell == 0) continue; | 1920 if (current_cell == 0) continue; |
| 1896 | 1921 |
| 1897 int offset = 0; | 1922 int offset = 0; |
| 1898 while (current_cell != 0) { | 1923 while (current_cell != 0) { |
| 1899 int trailing_zeros = base::bits::CountTrailingZeros32(current_cell); | 1924 int trailing_zeros = base::bits::CountTrailingZeros32(current_cell); |
| 1900 current_cell >>= trailing_zeros; | 1925 current_cell >>= trailing_zeros; |
| 1901 offset += trailing_zeros; | 1926 offset += trailing_zeros; |
| 1902 Address address = cell_base + offset * kPointerSize; | 1927 Address address = cell_base + offset * kPointerSize; |
| 1903 HeapObject* object = HeapObject::FromAddress(address); | 1928 HeapObject* object = HeapObject::FromAddress(address); |
| 1929 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 1904 | 1930 |
| 1905 int size = object->Size(); | 1931 int size = object->Size(); |
| 1906 survivors_size += size; | 1932 survivors_size += size; |
| 1907 | 1933 |
| 1908 Heap::UpdateAllocationSiteFeedback(object, Heap::RECORD_SCRATCHPAD_SLOT); | 1934 Heap::UpdateAllocationSiteFeedback(object, Heap::RECORD_SCRATCHPAD_SLOT); |
| 1909 | 1935 |
| 1910 offset++; | 1936 offset += 2; |
| 1911 current_cell >>= 1; | 1937 current_cell >>= 2; |
| 1912 | 1938 |
| 1913 // TODO(hpayer): Refactor EvacuateObject and call this function instead. | 1939 // TODO(hpayer): Refactor EvacuateObject and call this function instead. |
| 1914 if (heap()->ShouldBePromoted(object->address(), size) && | 1940 if (heap()->ShouldBePromoted(object->address(), size) && |
| 1915 TryPromoteObject(object, size)) { | 1941 TryPromoteObject(object, size)) { |
| 1916 continue; | 1942 continue; |
| 1917 } | 1943 } |
| 1918 | 1944 |
| 1919 AllocationResult allocation = new_space->AllocateRaw(size); | 1945 AllocationResult allocation = new_space->AllocateRaw(size); |
| 1920 if (allocation.IsRetry()) { | 1946 if (allocation.IsRetry()) { |
| 1921 if (!new_space->AddFreshPage()) { | 1947 if (!new_space->AddFreshPage()) { |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1959 if (marking_deque->IsFull()) return; | 1985 if (marking_deque->IsFull()) return; |
| 1960 } | 1986 } |
| 1961 } | 1987 } |
| 1962 | 1988 |
| 1963 | 1989 |
| 1964 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 1990 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
| 1965 Object* o = *p; | 1991 Object* o = *p; |
| 1966 if (!o->IsHeapObject()) return false; | 1992 if (!o->IsHeapObject()) return false; |
| 1967 HeapObject* heap_object = HeapObject::cast(o); | 1993 HeapObject* heap_object = HeapObject::cast(o); |
| 1968 MarkBit mark = Marking::MarkBitFrom(heap_object); | 1994 MarkBit mark = Marking::MarkBitFrom(heap_object); |
| 1969 return !mark.Get(); | 1995 return Marking::IsWhite(mark); |
| 1970 } | 1996 } |
| 1971 | 1997 |
| 1972 | 1998 |
| 1973 bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, | 1999 bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, |
| 1974 Object** p) { | 2000 Object** p) { |
| 1975 Object* o = *p; | 2001 Object* o = *p; |
| 1976 DCHECK(o->IsHeapObject()); | 2002 DCHECK(o->IsHeapObject()); |
| 1977 HeapObject* heap_object = HeapObject::cast(o); | 2003 HeapObject* heap_object = HeapObject::cast(o); |
| 1978 MarkBit mark = Marking::MarkBitFrom(heap_object); | 2004 MarkBit mark = Marking::MarkBitFrom(heap_object); |
| 1979 return !mark.Get(); | 2005 return Marking::IsWhite(mark); |
| 1980 } | 2006 } |
| 1981 | 2007 |
| 1982 | 2008 |
| 1983 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { | 2009 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { |
| 1984 StringTable* string_table = heap()->string_table(); | 2010 StringTable* string_table = heap()->string_table(); |
| 1985 // Mark the string table itself. | 2011 // Mark the string table itself. |
| 1986 MarkBit string_table_mark = Marking::MarkBitFrom(string_table); | 2012 MarkBit string_table_mark = Marking::MarkBitFrom(string_table); |
| 1987 if (!string_table_mark.Get()) { | 2013 if (Marking::IsWhite(string_table_mark)) { |
| 1988 // String table could have already been marked by visiting the handles list. | 2014 // String table could have already been marked by visiting the handles list. |
| 1989 SetMark(string_table, string_table_mark); | 2015 SetMark(string_table, string_table_mark); |
| 1990 } | 2016 } |
| 1991 // Explicitly mark the prefix. | 2017 // Explicitly mark the prefix. |
| 1992 string_table->IteratePrefix(visitor); | 2018 string_table->IteratePrefix(visitor); |
| 1993 ProcessMarkingDeque(); | 2019 ProcessMarkingDeque(); |
| 1994 } | 2020 } |
| 1995 | 2021 |
| 1996 | 2022 |
| 1997 void MarkCompactCollector::MarkAllocationSite(AllocationSite* site) { | 2023 void MarkCompactCollector::MarkAllocationSite(AllocationSite* site) { |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2167 int length = retained_maps->Length(); | 2193 int length = retained_maps->Length(); |
| 2168 int new_length = 0; | 2194 int new_length = 0; |
| 2169 for (int i = 0; i < length; i += 2) { | 2195 for (int i = 0; i < length; i += 2) { |
| 2170 DCHECK(retained_maps->Get(i)->IsWeakCell()); | 2196 DCHECK(retained_maps->Get(i)->IsWeakCell()); |
| 2171 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); | 2197 WeakCell* cell = WeakCell::cast(retained_maps->Get(i)); |
| 2172 if (cell->cleared()) continue; | 2198 if (cell->cleared()) continue; |
| 2173 int age = Smi::cast(retained_maps->Get(i + 1))->value(); | 2199 int age = Smi::cast(retained_maps->Get(i + 1))->value(); |
| 2174 int new_age; | 2200 int new_age; |
| 2175 Map* map = Map::cast(cell->value()); | 2201 Map* map = Map::cast(cell->value()); |
| 2176 MarkBit map_mark = Marking::MarkBitFrom(map); | 2202 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 2177 if (!map_mark.Get()) { | 2203 if (Marking::IsWhite(map_mark)) { |
| 2178 if (age == 0) { | 2204 if (age == 0) { |
| 2179 // The map has aged. Do not retain this map. | 2205 // The map has aged. Do not retain this map. |
| 2180 continue; | 2206 continue; |
| 2181 } | 2207 } |
| 2182 Object* constructor = map->GetConstructor(); | 2208 Object* constructor = map->GetConstructor(); |
| 2183 if (!constructor->IsHeapObject() || | 2209 if (!constructor->IsHeapObject() || Marking::IsWhite(Marking::MarkBitFrom( |
| 2184 !Marking::MarkBitFrom(HeapObject::cast(constructor)).Get()) { | 2210 HeapObject::cast(constructor)))) { |
| 2185 // The constructor is dead, no new objects with this map can | 2211 // The constructor is dead, no new objects with this map can |
| 2186 // be created. Do not retain this map. | 2212 // be created. Do not retain this map. |
| 2187 continue; | 2213 continue; |
| 2188 } | 2214 } |
| 2189 Object* prototype = map->prototype(); | 2215 Object* prototype = map->prototype(); |
| 2190 if (prototype->IsHeapObject() && | 2216 if (prototype->IsHeapObject() && |
| 2191 !Marking::MarkBitFrom(HeapObject::cast(prototype)).Get()) { | 2217 Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) { |
| 2192 // The prototype is not marked, age the map. | 2218 // The prototype is not marked, age the map. |
| 2193 new_age = age - 1; | 2219 new_age = age - 1; |
| 2194 } else { | 2220 } else { |
| 2195 // The prototype and the constructor are marked, this map keeps only | 2221 // The prototype and the constructor are marked, this map keeps only |
| 2196 // transition tree alive, not JSObjects. Do not age the map. | 2222 // transition tree alive, not JSObjects. Do not age the map. |
| 2197 new_age = age; | 2223 new_age = age; |
| 2198 } | 2224 } |
| 2199 MarkObject(map, map_mark); | 2225 MarkObject(map, map_mark); |
| 2200 } else { | 2226 } else { |
| 2201 new_age = FLAG_retain_maps_for_n_gc; | 2227 new_age = FLAG_retain_maps_for_n_gc; |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2395 for (HeapObject* obj = map_iterator.Next(); obj != NULL; | 2421 for (HeapObject* obj = map_iterator.Next(); obj != NULL; |
| 2396 obj = map_iterator.Next()) { | 2422 obj = map_iterator.Next()) { |
| 2397 Map* map = Map::cast(obj); | 2423 Map* map = Map::cast(obj); |
| 2398 | 2424 |
| 2399 if (!map->CanTransition()) continue; | 2425 if (!map->CanTransition()) continue; |
| 2400 | 2426 |
| 2401 MarkBit map_mark = Marking::MarkBitFrom(map); | 2427 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 2402 ClearNonLivePrototypeTransitions(map); | 2428 ClearNonLivePrototypeTransitions(map); |
| 2403 ClearNonLiveMapTransitions(map, map_mark); | 2429 ClearNonLiveMapTransitions(map, map_mark); |
| 2404 | 2430 |
| 2405 if (!map_mark.Get()) { | 2431 if (Marking::IsWhite(map_mark)) { |
| 2406 have_code_to_deoptimize_ |= | 2432 have_code_to_deoptimize_ |= |
| 2407 map->dependent_code()->MarkCodeForDeoptimization( | 2433 map->dependent_code()->MarkCodeForDeoptimization( |
| 2408 isolate(), DependentCode::kWeakCodeGroup); | 2434 isolate(), DependentCode::kWeakCodeGroup); |
| 2409 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); | 2435 map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array())); |
| 2410 } | 2436 } |
| 2411 } | 2437 } |
| 2412 | 2438 |
| 2413 WeakHashTable* table = heap_->weak_object_to_code_table(); | 2439 WeakHashTable* table = heap_->weak_object_to_code_table(); |
| 2414 uint32_t capacity = table->Capacity(); | 2440 uint32_t capacity = table->Capacity(); |
| 2415 for (uint32_t i = 0; i < capacity; i++) { | 2441 for (uint32_t i = 0; i < capacity; i++) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2463 | 2489 |
| 2464 | 2490 |
| 2465 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, | 2491 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, |
| 2466 MarkBit map_mark) { | 2492 MarkBit map_mark) { |
| 2467 Object* potential_parent = map->GetBackPointer(); | 2493 Object* potential_parent = map->GetBackPointer(); |
| 2468 if (!potential_parent->IsMap()) return; | 2494 if (!potential_parent->IsMap()) return; |
| 2469 Map* parent = Map::cast(potential_parent); | 2495 Map* parent = Map::cast(potential_parent); |
| 2470 | 2496 |
| 2471 // Follow back pointer, check whether we are dealing with a map transition | 2497 // Follow back pointer, check whether we are dealing with a map transition |
| 2472 // from a live map to a dead path and in case clear transitions of parent. | 2498 // from a live map to a dead path and in case clear transitions of parent. |
| 2473 bool current_is_alive = map_mark.Get(); | 2499 bool current_is_alive = Marking::IsBlackOrGrey(map_mark); |
| 2474 bool parent_is_alive = Marking::MarkBitFrom(parent).Get(); | 2500 bool parent_is_alive = Marking::IsBlackOrGrey(Marking::MarkBitFrom(parent)); |
| 2475 if (!current_is_alive && parent_is_alive) { | 2501 if (!current_is_alive && parent_is_alive) { |
| 2476 ClearMapTransitions(parent, map); | 2502 ClearMapTransitions(parent, map); |
| 2477 } | 2503 } |
| 2478 } | 2504 } |
| 2479 | 2505 |
| 2480 | 2506 |
| 2481 // Clear a possible back pointer in case the transition leads to a dead map. | 2507 // Clear a possible back pointer in case the transition leads to a dead map. |
| 2482 // Return true in case a back pointer has been cleared and false otherwise. | 2508 // Return true in case a back pointer has been cleared and false otherwise. |
| 2483 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { | 2509 bool MarkCompactCollector::ClearMapBackPointer(Map* target) { |
| 2484 if (Marking::MarkBitFrom(target).Get()) return false; | 2510 if (Marking::IsBlackOrGrey(Marking::MarkBitFrom(target))) return false; |
| 2485 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); | 2511 target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER); |
| 2486 return true; | 2512 return true; |
| 2487 } | 2513 } |
| 2488 | 2514 |
| 2489 | 2515 |
| 2490 void MarkCompactCollector::ClearMapTransitions(Map* map, Map* dead_transition) { | 2516 void MarkCompactCollector::ClearMapTransitions(Map* map, Map* dead_transition) { |
| 2491 Object* transitions = map->raw_transitions(); | 2517 Object* transitions = map->raw_transitions(); |
| 2492 int num_transitions = TransitionArray::NumberOfTransitions(transitions); | 2518 int num_transitions = TransitionArray::NumberOfTransitions(transitions); |
| 2493 | 2519 |
| 2494 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); | 2520 int number_of_own_descriptors = map->NumberOfOwnDescriptors(); |
| (...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3543 return false; | 3569 return false; |
| 3544 } | 3570 } |
| 3545 | 3571 |
| 3546 Address code_start = code->address(); | 3572 Address code_start = code->address(); |
| 3547 Address code_end = code_start + code->Size(); | 3573 Address code_end = code_start + code->Size(); |
| 3548 | 3574 |
| 3549 uint32_t start_index = MemoryChunk::FastAddressToMarkbitIndex(code_start); | 3575 uint32_t start_index = MemoryChunk::FastAddressToMarkbitIndex(code_start); |
| 3550 uint32_t end_index = | 3576 uint32_t end_index = |
| 3551 MemoryChunk::FastAddressToMarkbitIndex(code_end - kPointerSize); | 3577 MemoryChunk::FastAddressToMarkbitIndex(code_end - kPointerSize); |
| 3552 | 3578 |
| 3579 // TODO(hpayer): Filter out invalidated code in |
| 3580 // ClearInvalidSlotsBufferEntries. |
| 3553 Bitmap* b = p->markbits(); | 3581 Bitmap* b = p->markbits(); |
| 3554 | 3582 |
| 3555 MarkBit start_mark_bit = b->MarkBitFromIndex(start_index); | 3583 MarkBit start_mark_bit = b->MarkBitFromIndex(start_index); |
| 3556 MarkBit end_mark_bit = b->MarkBitFromIndex(end_index); | 3584 MarkBit end_mark_bit = b->MarkBitFromIndex(end_index); |
| 3557 | 3585 |
| 3558 MarkBit::CellType* start_cell = start_mark_bit.cell(); | |
| 3559 MarkBit::CellType* end_cell = end_mark_bit.cell(); | |
| 3560 | |
| 3561 if (value) { | 3586 if (value) { |
| 3562 MarkBit::CellType start_mask = ~(start_mark_bit.mask() - 1); | 3587 Marking::SetAllMarkBitsInRange(start_mark_bit, end_mark_bit); |
| 3563 MarkBit::CellType end_mask = (end_mark_bit.mask() << 1) - 1; | |
| 3564 | |
| 3565 if (start_cell == end_cell) { | |
| 3566 *start_cell |= start_mask & end_mask; | |
| 3567 } else { | |
| 3568 *start_cell |= start_mask; | |
| 3569 for (MarkBit::CellType* cell = start_cell + 1; cell < end_cell; cell++) { | |
| 3570 *cell = ~0; | |
| 3571 } | |
| 3572 *end_cell |= end_mask; | |
| 3573 } | |
| 3574 } else { | 3588 } else { |
| 3575 for (MarkBit::CellType* cell = start_cell; cell <= end_cell; cell++) { | 3589 Marking::ClearAllMarkBitsOfCellsContainedInRange(start_mark_bit, |
| 3576 *cell = 0; | 3590 end_mark_bit); |
| 3577 } | |
| 3578 } | 3591 } |
| 3579 | 3592 |
| 3580 return true; | 3593 return true; |
| 3581 } | 3594 } |
| 3582 | 3595 |
| 3583 | 3596 |
| 3584 static bool IsOnInvalidatedCodeObject(Address addr) { | 3597 static bool IsOnInvalidatedCodeObject(Address addr) { |
| 3585 // We did not record any slots in large objects thus | 3598 // We did not record any slots in large objects thus |
| 3586 // we can safely go to the page from the slot address. | 3599 // we can safely go to the page from the slot address. |
| 3587 Page* p = Page::FromAddress(addr); | 3600 Page* p = Page::FromAddress(addr); |
| 3588 | 3601 |
| 3589 // First check owner's identity because old space is swept concurrently or | 3602 // First check owner's identity because old space is swept concurrently or |
| 3590 // lazily and might still have non-zero mark-bits on some pages. | 3603 // lazily and might still have non-zero mark-bits on some pages. |
| 3591 if (p->owner()->identity() != CODE_SPACE) return false; | 3604 if (p->owner()->identity() != CODE_SPACE) return false; |
| 3592 | 3605 |
| 3593 // In code space only bits on evacuation candidates (but we don't record | 3606 // In code space only bits on evacuation candidates (but we don't record |
| 3594 // any slots on them) and under invalidated code objects are non-zero. | 3607 // any slots on them) and under invalidated code objects are non-zero. |
| 3595 MarkBit mark_bit = | 3608 MarkBit mark_bit = |
| 3596 p->markbits()->MarkBitFromIndex(Page::FastAddressToMarkbitIndex(addr)); | 3609 p->markbits()->MarkBitFromIndex(Page::FastAddressToMarkbitIndex(addr)); |
| 3597 | 3610 |
| 3598 return mark_bit.Get(); | 3611 return Marking::IsBlackOrGrey(mark_bit); |
| 3599 } | 3612 } |
| 3600 | 3613 |
| 3601 | 3614 |
| 3602 void MarkCompactCollector::InvalidateCode(Code* code) { | 3615 void MarkCompactCollector::InvalidateCode(Code* code) { |
| 3603 if (heap_->incremental_marking()->IsCompacting() && | 3616 if (heap_->incremental_marking()->IsCompacting() && |
| 3604 !ShouldSkipEvacuationSlotRecording(code)) { | 3617 !ShouldSkipEvacuationSlotRecording(code)) { |
| 3605 DCHECK(compacting_); | 3618 DCHECK(compacting_); |
| 3606 | 3619 |
| 3607 // If the object is white than no slots were recorded on it yet. | 3620 // If the object is white than no slots were recorded on it yet. |
| 3608 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3621 MarkBit mark_bit = Marking::MarkBitFrom(code); |
| (...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4751 SlotsBuffer* buffer = *buffer_address; | 4764 SlotsBuffer* buffer = *buffer_address; |
| 4752 while (buffer != NULL) { | 4765 while (buffer != NULL) { |
| 4753 SlotsBuffer* next_buffer = buffer->next(); | 4766 SlotsBuffer* next_buffer = buffer->next(); |
| 4754 DeallocateBuffer(buffer); | 4767 DeallocateBuffer(buffer); |
| 4755 buffer = next_buffer; | 4768 buffer = next_buffer; |
| 4756 } | 4769 } |
| 4757 *buffer_address = NULL; | 4770 *buffer_address = NULL; |
| 4758 } | 4771 } |
| 4759 } | 4772 } |
| 4760 } // namespace v8::internal | 4773 } // namespace v8::internal |
| OLD | NEW |