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/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compilation-cache.h" | 9 #include "src/compilation-cache.h" |
10 #include "src/cpu-profiler.h" | 10 #include "src/cpu-profiler.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 void VisitPointers(Object** start, Object** end) { | 61 void VisitPointers(Object** start, Object** end) { |
62 for (Object** current = start; current < end; current++) { | 62 for (Object** current = start; current < end; current++) { |
63 if ((*current)->IsHeapObject()) { | 63 if ((*current)->IsHeapObject()) { |
64 HeapObject* object = HeapObject::cast(*current); | 64 HeapObject* object = HeapObject::cast(*current); |
65 CHECK(heap_->mark_compact_collector()->IsMarked(object)); | 65 CHECK(heap_->mark_compact_collector()->IsMarked(object)); |
66 } | 66 } |
67 } | 67 } |
68 } | 68 } |
69 | 69 |
70 void VisitEmbeddedPointer(RelocInfo* rinfo) { | 70 void VisitEmbeddedPointer(RelocInfo* rinfo) { |
71 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 71 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
72 if (!rinfo->host()->IsWeakObject(rinfo->target_object())) { | 72 if (!rinfo->host()->IsWeakObject(rinfo->target_object())) { |
73 Object* p = rinfo->target_object(); | 73 Object* p = rinfo->target_object(); |
74 VisitPointer(&p); | 74 VisitPointer(&p); |
75 } | 75 } |
76 } | 76 } |
77 | 77 |
78 void VisitCell(RelocInfo* rinfo) { | 78 void VisitCell(RelocInfo* rinfo) { |
79 Code* code = rinfo->host(); | 79 Code* code = rinfo->host(); |
80 ASSERT(rinfo->rmode() == RelocInfo::CELL); | 80 DCHECK(rinfo->rmode() == RelocInfo::CELL); |
81 if (!code->IsWeakObject(rinfo->target_cell())) { | 81 if (!code->IsWeakObject(rinfo->target_cell())) { |
82 ObjectVisitor::VisitCell(rinfo); | 82 ObjectVisitor::VisitCell(rinfo); |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 private: | 86 private: |
87 Heap* heap_; | 87 Heap* heap_; |
88 }; | 88 }; |
89 | 89 |
90 | 90 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 PrintF("[%s]: %d pages, %d (%.1f%%) free\n", | 350 PrintF("[%s]: %d pages, %d (%.1f%%) free\n", |
351 AllocationSpaceName(space->identity()), | 351 AllocationSpaceName(space->identity()), |
352 number_of_pages, | 352 number_of_pages, |
353 static_cast<int>(free), | 353 static_cast<int>(free), |
354 static_cast<double>(free) * 100 / reserved); | 354 static_cast<double>(free) * 100 / reserved); |
355 } | 355 } |
356 | 356 |
357 | 357 |
358 bool MarkCompactCollector::StartCompaction(CompactionMode mode) { | 358 bool MarkCompactCollector::StartCompaction(CompactionMode mode) { |
359 if (!compacting_) { | 359 if (!compacting_) { |
360 ASSERT(evacuation_candidates_.length() == 0); | 360 DCHECK(evacuation_candidates_.length() == 0); |
361 | 361 |
362 #ifdef ENABLE_GDB_JIT_INTERFACE | 362 #ifdef ENABLE_GDB_JIT_INTERFACE |
363 // If GDBJIT interface is active disable compaction. | 363 // If GDBJIT interface is active disable compaction. |
364 if (FLAG_gdbjit) return false; | 364 if (FLAG_gdbjit) return false; |
365 #endif | 365 #endif |
366 | 366 |
367 CollectEvacuationCandidates(heap()->old_pointer_space()); | 367 CollectEvacuationCandidates(heap()->old_pointer_space()); |
368 CollectEvacuationCandidates(heap()->old_data_space()); | 368 CollectEvacuationCandidates(heap()->old_data_space()); |
369 | 369 |
370 if (FLAG_compact_code_space && | 370 if (FLAG_compact_code_space && |
(...skipping 17 matching lines...) Expand all Loading... |
388 compacting_ = evacuation_candidates_.length() > 0; | 388 compacting_ = evacuation_candidates_.length() > 0; |
389 } | 389 } |
390 | 390 |
391 return compacting_; | 391 return compacting_; |
392 } | 392 } |
393 | 393 |
394 | 394 |
395 void MarkCompactCollector::CollectGarbage() { | 395 void MarkCompactCollector::CollectGarbage() { |
396 // Make sure that Prepare() has been called. The individual steps below will | 396 // Make sure that Prepare() has been called. The individual steps below will |
397 // update the state as they proceed. | 397 // update the state as they proceed. |
398 ASSERT(state_ == PREPARE_GC); | 398 DCHECK(state_ == PREPARE_GC); |
399 | 399 |
400 MarkLiveObjects(); | 400 MarkLiveObjects(); |
401 ASSERT(heap_->incremental_marking()->IsStopped()); | 401 DCHECK(heap_->incremental_marking()->IsStopped()); |
402 | 402 |
403 if (FLAG_collect_maps) ClearNonLiveReferences(); | 403 if (FLAG_collect_maps) ClearNonLiveReferences(); |
404 | 404 |
405 ClearWeakCollections(); | 405 ClearWeakCollections(); |
406 | 406 |
407 #ifdef VERIFY_HEAP | 407 #ifdef VERIFY_HEAP |
408 if (FLAG_verify_heap) { | 408 if (FLAG_verify_heap) { |
409 VerifyMarking(heap_); | 409 VerifyMarking(heap_); |
410 } | 410 } |
411 #endif | 411 #endif |
(...skipping 13 matching lines...) Expand all Loading... |
425 if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { | 425 if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) { |
426 VerifyOmittedMapChecks(); | 426 VerifyOmittedMapChecks(); |
427 } | 427 } |
428 #endif | 428 #endif |
429 | 429 |
430 Finish(); | 430 Finish(); |
431 | 431 |
432 if (marking_parity_ == EVEN_MARKING_PARITY) { | 432 if (marking_parity_ == EVEN_MARKING_PARITY) { |
433 marking_parity_ = ODD_MARKING_PARITY; | 433 marking_parity_ = ODD_MARKING_PARITY; |
434 } else { | 434 } else { |
435 ASSERT(marking_parity_ == ODD_MARKING_PARITY); | 435 DCHECK(marking_parity_ == ODD_MARKING_PARITY); |
436 marking_parity_ = EVEN_MARKING_PARITY; | 436 marking_parity_ = EVEN_MARKING_PARITY; |
437 } | 437 } |
438 } | 438 } |
439 | 439 |
440 | 440 |
441 #ifdef VERIFY_HEAP | 441 #ifdef VERIFY_HEAP |
442 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { | 442 void MarkCompactCollector::VerifyMarkbitsAreClean(PagedSpace* space) { |
443 PageIterator it(space); | 443 PageIterator it(space); |
444 | 444 |
445 while (it.has_next()) { | 445 while (it.has_next()) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
557 } | 557 } |
558 | 558 |
559 Heap* heap_; | 559 Heap* heap_; |
560 PagedSpace* space_; | 560 PagedSpace* space_; |
561 | 561 |
562 DISALLOW_COPY_AND_ASSIGN(SweeperTask); | 562 DISALLOW_COPY_AND_ASSIGN(SweeperTask); |
563 }; | 563 }; |
564 | 564 |
565 | 565 |
566 void MarkCompactCollector::StartSweeperThreads() { | 566 void MarkCompactCollector::StartSweeperThreads() { |
567 ASSERT(free_list_old_pointer_space_.get()->IsEmpty()); | 567 DCHECK(free_list_old_pointer_space_.get()->IsEmpty()); |
568 ASSERT(free_list_old_data_space_.get()->IsEmpty()); | 568 DCHECK(free_list_old_data_space_.get()->IsEmpty()); |
569 sweeping_in_progress_ = true; | 569 sweeping_in_progress_ = true; |
570 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 570 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { |
571 isolate()->sweeper_threads()[i]->StartSweeping(); | 571 isolate()->sweeper_threads()[i]->StartSweeping(); |
572 } | 572 } |
573 if (FLAG_job_based_sweeping) { | 573 if (FLAG_job_based_sweeping) { |
574 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 574 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
575 new SweeperTask(heap(), heap()->old_data_space()), | 575 new SweeperTask(heap(), heap()->old_data_space()), |
576 v8::Platform::kShortRunningTask); | 576 v8::Platform::kShortRunningTask); |
577 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 577 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
578 new SweeperTask(heap(), heap()->old_pointer_space()), | 578 new SweeperTask(heap(), heap()->old_pointer_space()), |
579 v8::Platform::kShortRunningTask); | 579 v8::Platform::kShortRunningTask); |
580 } | 580 } |
581 } | 581 } |
582 | 582 |
583 | 583 |
584 void MarkCompactCollector::EnsureSweepingCompleted() { | 584 void MarkCompactCollector::EnsureSweepingCompleted() { |
585 ASSERT(sweeping_in_progress_ == true); | 585 DCHECK(sweeping_in_progress_ == true); |
586 | 586 |
587 // If sweeping is not completed, we try to complete it here. If we do not | 587 // If sweeping is not completed, we try to complete it here. If we do not |
588 // have sweeper threads we have to complete since we do not have a good | 588 // have sweeper threads we have to complete since we do not have a good |
589 // indicator for a swept space in that case. | 589 // indicator for a swept space in that case. |
590 if (!AreSweeperThreadsActivated() || !IsSweepingCompleted()) { | 590 if (!AreSweeperThreadsActivated() || !IsSweepingCompleted()) { |
591 SweepInParallel(heap()->paged_space(OLD_DATA_SPACE), 0); | 591 SweepInParallel(heap()->paged_space(OLD_DATA_SPACE), 0); |
592 SweepInParallel(heap()->paged_space(OLD_POINTER_SPACE), 0); | 592 SweepInParallel(heap()->paged_space(OLD_POINTER_SPACE), 0); |
593 } | 593 } |
594 | 594 |
595 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 595 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 } | 653 } |
654 | 654 |
655 | 655 |
656 bool MarkCompactCollector::AreSweeperThreadsActivated() { | 656 bool MarkCompactCollector::AreSweeperThreadsActivated() { |
657 return isolate()->sweeper_threads() != NULL || FLAG_job_based_sweeping; | 657 return isolate()->sweeper_threads() != NULL || FLAG_job_based_sweeping; |
658 } | 658 } |
659 | 659 |
660 | 660 |
661 void Marking::TransferMark(Address old_start, Address new_start) { | 661 void Marking::TransferMark(Address old_start, Address new_start) { |
662 // This is only used when resizing an object. | 662 // This is only used when resizing an object. |
663 ASSERT(MemoryChunk::FromAddress(old_start) == | 663 DCHECK(MemoryChunk::FromAddress(old_start) == |
664 MemoryChunk::FromAddress(new_start)); | 664 MemoryChunk::FromAddress(new_start)); |
665 | 665 |
666 if (!heap_->incremental_marking()->IsMarking()) return; | 666 if (!heap_->incremental_marking()->IsMarking()) return; |
667 | 667 |
668 // If the mark doesn't move, we don't check the color of the object. | 668 // If the mark doesn't move, we don't check the color of the object. |
669 // It doesn't matter whether the object is black, since it hasn't changed | 669 // It doesn't matter whether the object is black, since it hasn't changed |
670 // size, so the adjustment to the live data count will be zero anyway. | 670 // size, so the adjustment to the live data count will be zero anyway. |
671 if (old_start == new_start) return; | 671 if (old_start == new_start) return; |
672 | 672 |
673 MarkBit new_mark_bit = MarkBitFrom(new_start); | 673 MarkBit new_mark_bit = MarkBitFrom(new_start); |
674 MarkBit old_mark_bit = MarkBitFrom(old_start); | 674 MarkBit old_mark_bit = MarkBitFrom(old_start); |
675 | 675 |
676 #ifdef DEBUG | 676 #ifdef DEBUG |
677 ObjectColor old_color = Color(old_mark_bit); | 677 ObjectColor old_color = Color(old_mark_bit); |
678 #endif | 678 #endif |
679 | 679 |
680 if (Marking::IsBlack(old_mark_bit)) { | 680 if (Marking::IsBlack(old_mark_bit)) { |
681 old_mark_bit.Clear(); | 681 old_mark_bit.Clear(); |
682 ASSERT(IsWhite(old_mark_bit)); | 682 DCHECK(IsWhite(old_mark_bit)); |
683 Marking::MarkBlack(new_mark_bit); | 683 Marking::MarkBlack(new_mark_bit); |
684 return; | 684 return; |
685 } else if (Marking::IsGrey(old_mark_bit)) { | 685 } else if (Marking::IsGrey(old_mark_bit)) { |
686 old_mark_bit.Clear(); | 686 old_mark_bit.Clear(); |
687 old_mark_bit.Next().Clear(); | 687 old_mark_bit.Next().Clear(); |
688 ASSERT(IsWhite(old_mark_bit)); | 688 DCHECK(IsWhite(old_mark_bit)); |
689 heap_->incremental_marking()->WhiteToGreyAndPush( | 689 heap_->incremental_marking()->WhiteToGreyAndPush( |
690 HeapObject::FromAddress(new_start), new_mark_bit); | 690 HeapObject::FromAddress(new_start), new_mark_bit); |
691 heap_->incremental_marking()->RestartIfNotMarking(); | 691 heap_->incremental_marking()->RestartIfNotMarking(); |
692 } | 692 } |
693 | 693 |
694 #ifdef DEBUG | 694 #ifdef DEBUG |
695 ObjectColor new_color = Color(new_mark_bit); | 695 ObjectColor new_color = Color(new_mark_bit); |
696 ASSERT(new_color == old_color); | 696 DCHECK(new_color == old_color); |
697 #endif | 697 #endif |
698 } | 698 } |
699 | 699 |
700 | 700 |
701 const char* AllocationSpaceName(AllocationSpace space) { | 701 const char* AllocationSpaceName(AllocationSpace space) { |
702 switch (space) { | 702 switch (space) { |
703 case NEW_SPACE: return "NEW_SPACE"; | 703 case NEW_SPACE: return "NEW_SPACE"; |
704 case OLD_POINTER_SPACE: return "OLD_POINTER_SPACE"; | 704 case OLD_POINTER_SPACE: return "OLD_POINTER_SPACE"; |
705 case OLD_DATA_SPACE: return "OLD_DATA_SPACE"; | 705 case OLD_DATA_SPACE: return "OLD_DATA_SPACE"; |
706 case CODE_SPACE: return "CODE_SPACE"; | 706 case CODE_SPACE: return "CODE_SPACE"; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 return 1; | 771 return 1; |
772 } | 772 } |
773 | 773 |
774 if (ratio <= ratio_threshold) return 0; // Not fragmented. | 774 if (ratio <= ratio_threshold) return 0; // Not fragmented. |
775 | 775 |
776 return static_cast<int>(ratio - ratio_threshold); | 776 return static_cast<int>(ratio - ratio_threshold); |
777 } | 777 } |
778 | 778 |
779 | 779 |
780 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { | 780 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
781 ASSERT(space->identity() == OLD_POINTER_SPACE || | 781 DCHECK(space->identity() == OLD_POINTER_SPACE || |
782 space->identity() == OLD_DATA_SPACE || | 782 space->identity() == OLD_DATA_SPACE || |
783 space->identity() == CODE_SPACE); | 783 space->identity() == CODE_SPACE); |
784 | 784 |
785 static const int kMaxMaxEvacuationCandidates = 1000; | 785 static const int kMaxMaxEvacuationCandidates = 1000; |
786 int number_of_pages = space->CountTotalPages(); | 786 int number_of_pages = space->CountTotalPages(); |
787 int max_evacuation_candidates = | 787 int max_evacuation_candidates = |
788 static_cast<int>(std::sqrt(number_of_pages / 2.0) + 1); | 788 static_cast<int>(std::sqrt(number_of_pages / 2.0) + 1); |
789 | 789 |
790 if (FLAG_stress_compaction || FLAG_always_compact) { | 790 if (FLAG_stress_compaction || FLAG_always_compact) { |
791 max_evacuation_candidates = kMaxMaxEvacuationCandidates; | 791 max_evacuation_candidates = kMaxMaxEvacuationCandidates; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 for (int i = 0; i < npages; i++) { | 938 for (int i = 0; i < npages; i++) { |
939 Page* p = evacuation_candidates_[i]; | 939 Page* p = evacuation_candidates_[i]; |
940 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); | 940 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); |
941 p->ClearEvacuationCandidate(); | 941 p->ClearEvacuationCandidate(); |
942 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); | 942 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); |
943 } | 943 } |
944 compacting_ = false; | 944 compacting_ = false; |
945 evacuation_candidates_.Rewind(0); | 945 evacuation_candidates_.Rewind(0); |
946 invalidated_code_.Rewind(0); | 946 invalidated_code_.Rewind(0); |
947 } | 947 } |
948 ASSERT_EQ(0, evacuation_candidates_.length()); | 948 DCHECK_EQ(0, evacuation_candidates_.length()); |
949 } | 949 } |
950 | 950 |
951 | 951 |
952 void MarkCompactCollector::Prepare() { | 952 void MarkCompactCollector::Prepare() { |
953 was_marked_incrementally_ = heap()->incremental_marking()->IsMarking(); | 953 was_marked_incrementally_ = heap()->incremental_marking()->IsMarking(); |
954 | 954 |
955 #ifdef DEBUG | 955 #ifdef DEBUG |
956 ASSERT(state_ == IDLE); | 956 DCHECK(state_ == IDLE); |
957 state_ = PREPARE_GC; | 957 state_ = PREPARE_GC; |
958 #endif | 958 #endif |
959 | 959 |
960 ASSERT(!FLAG_never_compact || !FLAG_always_compact); | 960 DCHECK(!FLAG_never_compact || !FLAG_always_compact); |
961 | 961 |
962 if (sweeping_in_progress()) { | 962 if (sweeping_in_progress()) { |
963 // Instead of waiting we could also abort the sweeper threads here. | 963 // Instead of waiting we could also abort the sweeper threads here. |
964 EnsureSweepingCompleted(); | 964 EnsureSweepingCompleted(); |
965 } | 965 } |
966 | 966 |
967 // Clear marking bits if incremental marking is aborted. | 967 // Clear marking bits if incremental marking is aborted. |
968 if (was_marked_incrementally_ && abort_incremental_marking_) { | 968 if (was_marked_incrementally_ && abort_incremental_marking_) { |
969 heap()->incremental_marking()->Abort(); | 969 heap()->incremental_marking()->Abort(); |
970 ClearMarkbits(); | 970 ClearMarkbits(); |
(...skipping 17 matching lines...) Expand all Loading... |
988 #ifdef VERIFY_HEAP | 988 #ifdef VERIFY_HEAP |
989 if (!was_marked_incrementally_ && FLAG_verify_heap) { | 989 if (!was_marked_incrementally_ && FLAG_verify_heap) { |
990 VerifyMarkbitsAreClean(); | 990 VerifyMarkbitsAreClean(); |
991 } | 991 } |
992 #endif | 992 #endif |
993 } | 993 } |
994 | 994 |
995 | 995 |
996 void MarkCompactCollector::Finish() { | 996 void MarkCompactCollector::Finish() { |
997 #ifdef DEBUG | 997 #ifdef DEBUG |
998 ASSERT(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); | 998 DCHECK(state_ == SWEEP_SPACES || state_ == RELOCATE_OBJECTS); |
999 state_ = IDLE; | 999 state_ = IDLE; |
1000 #endif | 1000 #endif |
1001 // The stub cache is not traversed during GC; clear the cache to | 1001 // The stub cache is not traversed during GC; clear the cache to |
1002 // force lazy re-initialization of it. This must be done after the | 1002 // force lazy re-initialization of it. This must be done after the |
1003 // GC, because it relies on the new address of certain old space | 1003 // GC, because it relies on the new address of certain old space |
1004 // objects (empty string, illegal builtin). | 1004 // objects (empty string, illegal builtin). |
1005 isolate()->stub_cache()->Clear(); | 1005 isolate()->stub_cache()->Clear(); |
1006 | 1006 |
1007 if (have_code_to_deoptimize_) { | 1007 if (have_code_to_deoptimize_) { |
1008 // Some code objects were marked for deoptimization during the GC. | 1008 // Some code objects were marked for deoptimization during the GC. |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset)); | 1139 Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset)); |
1140 if (!Marking::MarkBitFrom(code).Get()) continue; | 1140 if (!Marking::MarkBitFrom(code).Get()) continue; |
1141 | 1141 |
1142 // Move every slot in the entry. | 1142 // Move every slot in the entry. |
1143 for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) { | 1143 for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) { |
1144 int dst_index = new_length++; | 1144 int dst_index = new_length++; |
1145 Object** slot = code_map->RawFieldOfElementAt(dst_index); | 1145 Object** slot = code_map->RawFieldOfElementAt(dst_index); |
1146 Object* object = code_map->get(i + j); | 1146 Object* object = code_map->get(i + j); |
1147 code_map->set(dst_index, object); | 1147 code_map->set(dst_index, object); |
1148 if (j == SharedFunctionInfo::kOsrAstIdOffset) { | 1148 if (j == SharedFunctionInfo::kOsrAstIdOffset) { |
1149 ASSERT(object->IsSmi()); | 1149 DCHECK(object->IsSmi()); |
1150 } else { | 1150 } else { |
1151 ASSERT(Marking::IsBlack( | 1151 DCHECK(Marking::IsBlack( |
1152 Marking::MarkBitFrom(HeapObject::cast(*slot)))); | 1152 Marking::MarkBitFrom(HeapObject::cast(*slot)))); |
1153 isolate_->heap()->mark_compact_collector()-> | 1153 isolate_->heap()->mark_compact_collector()-> |
1154 RecordSlot(slot, slot, *slot); | 1154 RecordSlot(slot, slot, *slot); |
1155 } | 1155 } |
1156 } | 1156 } |
1157 } | 1157 } |
1158 | 1158 |
1159 // Trim the optimized code map if entries have been removed. | 1159 // Trim the optimized code map if entries have been removed. |
1160 if (new_length < old_length) { | 1160 if (new_length < old_length) { |
1161 holder->TrimOptimizedCodeMap(old_length - new_length); | 1161 holder->TrimOptimizedCodeMap(old_length - new_length); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1195 break; | 1195 break; |
1196 } | 1196 } |
1197 | 1197 |
1198 candidate = next_candidate; | 1198 candidate = next_candidate; |
1199 } | 1199 } |
1200 } | 1200 } |
1201 } | 1201 } |
1202 | 1202 |
1203 | 1203 |
1204 void CodeFlusher::EvictCandidate(JSFunction* function) { | 1204 void CodeFlusher::EvictCandidate(JSFunction* function) { |
1205 ASSERT(!function->next_function_link()->IsUndefined()); | 1205 DCHECK(!function->next_function_link()->IsUndefined()); |
1206 Object* undefined = isolate_->heap()->undefined_value(); | 1206 Object* undefined = isolate_->heap()->undefined_value(); |
1207 | 1207 |
1208 // Make sure previous flushing decisions are revisited. | 1208 // Make sure previous flushing decisions are revisited. |
1209 isolate_->heap()->incremental_marking()->RecordWrites(function); | 1209 isolate_->heap()->incremental_marking()->RecordWrites(function); |
1210 isolate_->heap()->incremental_marking()->RecordWrites(function->shared()); | 1210 isolate_->heap()->incremental_marking()->RecordWrites(function->shared()); |
1211 | 1211 |
1212 if (FLAG_trace_code_flushing) { | 1212 if (FLAG_trace_code_flushing) { |
1213 PrintF("[code-flushing abandons closure: "); | 1213 PrintF("[code-flushing abandons closure: "); |
1214 function->shared()->ShortPrint(); | 1214 function->shared()->ShortPrint(); |
1215 PrintF("]\n"); | 1215 PrintF("]\n"); |
(...skipping 16 matching lines...) Expand all Loading... |
1232 break; | 1232 break; |
1233 } | 1233 } |
1234 | 1234 |
1235 candidate = next_candidate; | 1235 candidate = next_candidate; |
1236 } | 1236 } |
1237 } | 1237 } |
1238 } | 1238 } |
1239 | 1239 |
1240 | 1240 |
1241 void CodeFlusher::EvictOptimizedCodeMap(SharedFunctionInfo* code_map_holder) { | 1241 void CodeFlusher::EvictOptimizedCodeMap(SharedFunctionInfo* code_map_holder) { |
1242 ASSERT(!FixedArray::cast(code_map_holder->optimized_code_map())-> | 1242 DCHECK(!FixedArray::cast(code_map_holder->optimized_code_map())-> |
1243 get(SharedFunctionInfo::kNextMapIndex)->IsUndefined()); | 1243 get(SharedFunctionInfo::kNextMapIndex)->IsUndefined()); |
1244 | 1244 |
1245 // Make sure previous flushing decisions are revisited. | 1245 // Make sure previous flushing decisions are revisited. |
1246 isolate_->heap()->incremental_marking()->RecordWrites(code_map_holder); | 1246 isolate_->heap()->incremental_marking()->RecordWrites(code_map_holder); |
1247 | 1247 |
1248 if (FLAG_trace_code_flushing) { | 1248 if (FLAG_trace_code_flushing) { |
1249 PrintF("[code-flushing abandons code-map: "); | 1249 PrintF("[code-flushing abandons code-map: "); |
1250 code_map_holder->ShortPrint(); | 1250 code_map_holder->ShortPrint(); |
1251 PrintF("]\n"); | 1251 PrintF("]\n"); |
1252 } | 1252 } |
(...skipping 22 matching lines...) Expand all Loading... |
1275 | 1275 |
1276 | 1276 |
1277 void CodeFlusher::EvictJSFunctionCandidates() { | 1277 void CodeFlusher::EvictJSFunctionCandidates() { |
1278 JSFunction* candidate = jsfunction_candidates_head_; | 1278 JSFunction* candidate = jsfunction_candidates_head_; |
1279 JSFunction* next_candidate; | 1279 JSFunction* next_candidate; |
1280 while (candidate != NULL) { | 1280 while (candidate != NULL) { |
1281 next_candidate = GetNextCandidate(candidate); | 1281 next_candidate = GetNextCandidate(candidate); |
1282 EvictCandidate(candidate); | 1282 EvictCandidate(candidate); |
1283 candidate = next_candidate; | 1283 candidate = next_candidate; |
1284 } | 1284 } |
1285 ASSERT(jsfunction_candidates_head_ == NULL); | 1285 DCHECK(jsfunction_candidates_head_ == NULL); |
1286 } | 1286 } |
1287 | 1287 |
1288 | 1288 |
1289 void CodeFlusher::EvictSharedFunctionInfoCandidates() { | 1289 void CodeFlusher::EvictSharedFunctionInfoCandidates() { |
1290 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; | 1290 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; |
1291 SharedFunctionInfo* next_candidate; | 1291 SharedFunctionInfo* next_candidate; |
1292 while (candidate != NULL) { | 1292 while (candidate != NULL) { |
1293 next_candidate = GetNextCandidate(candidate); | 1293 next_candidate = GetNextCandidate(candidate); |
1294 EvictCandidate(candidate); | 1294 EvictCandidate(candidate); |
1295 candidate = next_candidate; | 1295 candidate = next_candidate; |
1296 } | 1296 } |
1297 ASSERT(shared_function_info_candidates_head_ == NULL); | 1297 DCHECK(shared_function_info_candidates_head_ == NULL); |
1298 } | 1298 } |
1299 | 1299 |
1300 | 1300 |
1301 void CodeFlusher::EvictOptimizedCodeMaps() { | 1301 void CodeFlusher::EvictOptimizedCodeMaps() { |
1302 SharedFunctionInfo* holder = optimized_code_map_holder_head_; | 1302 SharedFunctionInfo* holder = optimized_code_map_holder_head_; |
1303 SharedFunctionInfo* next_holder; | 1303 SharedFunctionInfo* next_holder; |
1304 while (holder != NULL) { | 1304 while (holder != NULL) { |
1305 next_holder = GetNextCodeMap(holder); | 1305 next_holder = GetNextCodeMap(holder); |
1306 EvictOptimizedCodeMap(holder); | 1306 EvictOptimizedCodeMap(holder); |
1307 holder = next_holder; | 1307 holder = next_holder; |
1308 } | 1308 } |
1309 ASSERT(optimized_code_map_holder_head_ == NULL); | 1309 DCHECK(optimized_code_map_holder_head_ == NULL); |
1310 } | 1310 } |
1311 | 1311 |
1312 | 1312 |
1313 void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) { | 1313 void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) { |
1314 Heap* heap = isolate_->heap(); | 1314 Heap* heap = isolate_->heap(); |
1315 | 1315 |
1316 JSFunction** slot = &jsfunction_candidates_head_; | 1316 JSFunction** slot = &jsfunction_candidates_head_; |
1317 JSFunction* candidate = jsfunction_candidates_head_; | 1317 JSFunction* candidate = jsfunction_candidates_head_; |
1318 while (candidate != NULL) { | 1318 while (candidate != NULL) { |
1319 if (heap->InFromSpace(candidate)) { | 1319 if (heap->InFromSpace(candidate)) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 collector->RecordSlot(anchor_slot, p, object); | 1431 collector->RecordSlot(anchor_slot, p, object); |
1432 MarkBit mark = Marking::MarkBitFrom(object); | 1432 MarkBit mark = Marking::MarkBitFrom(object); |
1433 collector->MarkObject(object, mark); | 1433 collector->MarkObject(object, mark); |
1434 } | 1434 } |
1435 | 1435 |
1436 | 1436 |
1437 // Visit an unmarked object. | 1437 // Visit an unmarked object. |
1438 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, | 1438 INLINE(static void VisitUnmarkedObject(MarkCompactCollector* collector, |
1439 HeapObject* obj)) { | 1439 HeapObject* obj)) { |
1440 #ifdef DEBUG | 1440 #ifdef DEBUG |
1441 ASSERT(collector->heap()->Contains(obj)); | 1441 DCHECK(collector->heap()->Contains(obj)); |
1442 ASSERT(!collector->heap()->mark_compact_collector()->IsMarked(obj)); | 1442 DCHECK(!collector->heap()->mark_compact_collector()->IsMarked(obj)); |
1443 #endif | 1443 #endif |
1444 Map* map = obj->map(); | 1444 Map* map = obj->map(); |
1445 Heap* heap = obj->GetHeap(); | 1445 Heap* heap = obj->GetHeap(); |
1446 MarkBit mark = Marking::MarkBitFrom(obj); | 1446 MarkBit mark = Marking::MarkBitFrom(obj); |
1447 heap->mark_compact_collector()->SetMark(obj, mark); | 1447 heap->mark_compact_collector()->SetMark(obj, mark); |
1448 // Mark the map pointer and the body. | 1448 // Mark the map pointer and the body. |
1449 MarkBit map_mark = Marking::MarkBitFrom(map); | 1449 MarkBit map_mark = Marking::MarkBitFrom(map); |
1450 heap->mark_compact_collector()->MarkObject(map, map_mark); | 1450 heap->mark_compact_collector()->MarkObject(map, map_mark); |
1451 IterateBody(map, obj); | 1451 IterateBody(map, obj); |
1452 } | 1452 } |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 } | 1598 } |
1599 | 1599 |
1600 | 1600 |
1601 template<> | 1601 template<> |
1602 class MarkCompactMarkingVisitor::ObjectStatsTracker< | 1602 class MarkCompactMarkingVisitor::ObjectStatsTracker< |
1603 MarkCompactMarkingVisitor::kVisitMap> { | 1603 MarkCompactMarkingVisitor::kVisitMap> { |
1604 public: | 1604 public: |
1605 static inline void Visit(Map* map, HeapObject* obj) { | 1605 static inline void Visit(Map* map, HeapObject* obj) { |
1606 Heap* heap = map->GetHeap(); | 1606 Heap* heap = map->GetHeap(); |
1607 Map* map_obj = Map::cast(obj); | 1607 Map* map_obj = Map::cast(obj); |
1608 ASSERT(map->instance_type() == MAP_TYPE); | 1608 DCHECK(map->instance_type() == MAP_TYPE); |
1609 DescriptorArray* array = map_obj->instance_descriptors(); | 1609 DescriptorArray* array = map_obj->instance_descriptors(); |
1610 if (map_obj->owns_descriptors() && | 1610 if (map_obj->owns_descriptors() && |
1611 array != heap->empty_descriptor_array()) { | 1611 array != heap->empty_descriptor_array()) { |
1612 int fixed_array_size = array->Size(); | 1612 int fixed_array_size = array->Size(); |
1613 heap->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, | 1613 heap->RecordFixedArraySubTypeStats(DESCRIPTOR_ARRAY_SUB_TYPE, |
1614 fixed_array_size); | 1614 fixed_array_size); |
1615 } | 1615 } |
1616 if (map_obj->HasTransitionArray()) { | 1616 if (map_obj->HasTransitionArray()) { |
1617 int fixed_array_size = map_obj->transitions()->Size(); | 1617 int fixed_array_size = map_obj->transitions()->Size(); |
1618 heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, | 1618 heap->RecordFixedArraySubTypeStats(TRANSITION_ARRAY_SUB_TYPE, |
(...skipping 14 matching lines...) Expand all Loading... |
1633 }; | 1633 }; |
1634 | 1634 |
1635 | 1635 |
1636 template<> | 1636 template<> |
1637 class MarkCompactMarkingVisitor::ObjectStatsTracker< | 1637 class MarkCompactMarkingVisitor::ObjectStatsTracker< |
1638 MarkCompactMarkingVisitor::kVisitCode> { | 1638 MarkCompactMarkingVisitor::kVisitCode> { |
1639 public: | 1639 public: |
1640 static inline void Visit(Map* map, HeapObject* obj) { | 1640 static inline void Visit(Map* map, HeapObject* obj) { |
1641 Heap* heap = map->GetHeap(); | 1641 Heap* heap = map->GetHeap(); |
1642 int object_size = obj->Size(); | 1642 int object_size = obj->Size(); |
1643 ASSERT(map->instance_type() == CODE_TYPE); | 1643 DCHECK(map->instance_type() == CODE_TYPE); |
1644 Code* code_obj = Code::cast(obj); | 1644 Code* code_obj = Code::cast(obj); |
1645 heap->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetRawAge(), | 1645 heap->RecordCodeSubTypeStats(code_obj->kind(), code_obj->GetRawAge(), |
1646 object_size); | 1646 object_size); |
1647 ObjectStatsVisitBase(kVisitCode, map, obj); | 1647 ObjectStatsVisitBase(kVisitCode, map, obj); |
1648 } | 1648 } |
1649 }; | 1649 }; |
1650 | 1650 |
1651 | 1651 |
1652 template<> | 1652 template<> |
1653 class MarkCompactMarkingVisitor::ObjectStatsTracker< | 1653 class MarkCompactMarkingVisitor::ObjectStatsTracker< |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1771 // If code flushing is disabled, there is no need to prepare for it. | 1771 // If code flushing is disabled, there is no need to prepare for it. |
1772 if (!is_code_flushing_enabled()) return; | 1772 if (!is_code_flushing_enabled()) return; |
1773 | 1773 |
1774 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray | 1774 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray |
1775 // relies on it being marked before any other descriptor array. | 1775 // relies on it being marked before any other descriptor array. |
1776 HeapObject* descriptor_array = heap()->empty_descriptor_array(); | 1776 HeapObject* descriptor_array = heap()->empty_descriptor_array(); |
1777 MarkBit descriptor_array_mark = Marking::MarkBitFrom(descriptor_array); | 1777 MarkBit descriptor_array_mark = Marking::MarkBitFrom(descriptor_array); |
1778 MarkObject(descriptor_array, descriptor_array_mark); | 1778 MarkObject(descriptor_array, descriptor_array_mark); |
1779 | 1779 |
1780 // Make sure we are not referencing the code from the stack. | 1780 // Make sure we are not referencing the code from the stack. |
1781 ASSERT(this == heap()->mark_compact_collector()); | 1781 DCHECK(this == heap()->mark_compact_collector()); |
1782 PrepareThreadForCodeFlushing(heap()->isolate(), | 1782 PrepareThreadForCodeFlushing(heap()->isolate(), |
1783 heap()->isolate()->thread_local_top()); | 1783 heap()->isolate()->thread_local_top()); |
1784 | 1784 |
1785 // Iterate the archived stacks in all threads to check if | 1785 // Iterate the archived stacks in all threads to check if |
1786 // the code is referenced. | 1786 // the code is referenced. |
1787 CodeMarkingVisitor code_marking_visitor(this); | 1787 CodeMarkingVisitor code_marking_visitor(this); |
1788 heap()->isolate()->thread_manager()->IterateArchivedThreads( | 1788 heap()->isolate()->thread_manager()->IterateArchivedThreads( |
1789 &code_marking_visitor); | 1789 &code_marking_visitor); |
1790 | 1790 |
1791 SharedFunctionInfoMarkingVisitor visitor(this); | 1791 SharedFunctionInfoMarkingVisitor visitor(this); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 explicit StringTableCleaner(Heap* heap) | 1848 explicit StringTableCleaner(Heap* heap) |
1849 : heap_(heap), pointers_removed_(0) { } | 1849 : heap_(heap), pointers_removed_(0) { } |
1850 | 1850 |
1851 virtual void VisitPointers(Object** start, Object** end) { | 1851 virtual void VisitPointers(Object** start, Object** end) { |
1852 // Visit all HeapObject pointers in [start, end). | 1852 // Visit all HeapObject pointers in [start, end). |
1853 for (Object** p = start; p < end; p++) { | 1853 for (Object** p = start; p < end; p++) { |
1854 Object* o = *p; | 1854 Object* o = *p; |
1855 if (o->IsHeapObject() && | 1855 if (o->IsHeapObject() && |
1856 !Marking::MarkBitFrom(HeapObject::cast(o)).Get()) { | 1856 !Marking::MarkBitFrom(HeapObject::cast(o)).Get()) { |
1857 if (finalize_external_strings) { | 1857 if (finalize_external_strings) { |
1858 ASSERT(o->IsExternalString()); | 1858 DCHECK(o->IsExternalString()); |
1859 heap_->FinalizeExternalString(String::cast(*p)); | 1859 heap_->FinalizeExternalString(String::cast(*p)); |
1860 } else { | 1860 } else { |
1861 pointers_removed_++; | 1861 pointers_removed_++; |
1862 } | 1862 } |
1863 // Set the entry to the_hole_value (as deleted). | 1863 // Set the entry to the_hole_value (as deleted). |
1864 *p = heap_->the_hole_value(); | 1864 *p = heap_->the_hole_value(); |
1865 } | 1865 } |
1866 } | 1866 } |
1867 } | 1867 } |
1868 | 1868 |
1869 int PointersRemoved() { | 1869 int PointersRemoved() { |
1870 ASSERT(!finalize_external_strings); | 1870 DCHECK(!finalize_external_strings); |
1871 return pointers_removed_; | 1871 return pointers_removed_; |
1872 } | 1872 } |
1873 | 1873 |
1874 private: | 1874 private: |
1875 Heap* heap_; | 1875 Heap* heap_; |
1876 int pointers_removed_; | 1876 int pointers_removed_; |
1877 }; | 1877 }; |
1878 | 1878 |
1879 | 1879 |
1880 typedef StringTableCleaner<false> InternalizedStringTableCleaner; | 1880 typedef StringTableCleaner<false> InternalizedStringTableCleaner; |
(...skipping 24 matching lines...) Expand all Loading... |
1905 | 1905 |
1906 // Fill the marking stack with overflowed objects returned by the given | 1906 // Fill the marking stack with overflowed objects returned by the given |
1907 // iterator. Stop when the marking stack is filled or the end of the space | 1907 // iterator. Stop when the marking stack is filled or the end of the space |
1908 // is reached, whichever comes first. | 1908 // is reached, whichever comes first. |
1909 template<class T> | 1909 template<class T> |
1910 static void DiscoverGreyObjectsWithIterator(Heap* heap, | 1910 static void DiscoverGreyObjectsWithIterator(Heap* heap, |
1911 MarkingDeque* marking_deque, | 1911 MarkingDeque* marking_deque, |
1912 T* it) { | 1912 T* it) { |
1913 // The caller should ensure that the marking stack is initially not full, | 1913 // The caller should ensure that the marking stack is initially not full, |
1914 // so that we don't waste effort pointlessly scanning for objects. | 1914 // so that we don't waste effort pointlessly scanning for objects. |
1915 ASSERT(!marking_deque->IsFull()); | 1915 DCHECK(!marking_deque->IsFull()); |
1916 | 1916 |
1917 Map* filler_map = heap->one_pointer_filler_map(); | 1917 Map* filler_map = heap->one_pointer_filler_map(); |
1918 for (HeapObject* object = it->Next(); | 1918 for (HeapObject* object = it->Next(); |
1919 object != NULL; | 1919 object != NULL; |
1920 object = it->Next()) { | 1920 object = it->Next()) { |
1921 MarkBit markbit = Marking::MarkBitFrom(object); | 1921 MarkBit markbit = Marking::MarkBitFrom(object); |
1922 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { | 1922 if ((object->map() != filler_map) && Marking::IsGrey(markbit)) { |
1923 Marking::GreyToBlack(markbit); | 1923 Marking::GreyToBlack(markbit); |
1924 MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size()); | 1924 MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size()); |
1925 marking_deque->PushBlack(object); | 1925 marking_deque->PushBlack(object); |
1926 if (marking_deque->IsFull()) return; | 1926 if (marking_deque->IsFull()) return; |
1927 } | 1927 } |
1928 } | 1928 } |
1929 } | 1929 } |
1930 | 1930 |
1931 | 1931 |
1932 static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts); | 1932 static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts); |
1933 | 1933 |
1934 | 1934 |
1935 static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, | 1935 static void DiscoverGreyObjectsOnPage(MarkingDeque* marking_deque, |
1936 MemoryChunk* p) { | 1936 MemoryChunk* p) { |
1937 ASSERT(!marking_deque->IsFull()); | 1937 DCHECK(!marking_deque->IsFull()); |
1938 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 1938 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
1939 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 1939 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
1940 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 1940 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
1941 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 1941 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
1942 | 1942 |
1943 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { | 1943 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
1944 Address cell_base = it.CurrentCellBase(); | 1944 Address cell_base = it.CurrentCellBase(); |
1945 MarkBit::CellType* cell = it.CurrentCell(); | 1945 MarkBit::CellType* cell = it.CurrentCell(); |
1946 | 1946 |
1947 const MarkBit::CellType current_cell = *cell; | 1947 const MarkBit::CellType current_cell = *cell; |
1948 if (current_cell == 0) continue; | 1948 if (current_cell == 0) continue; |
1949 | 1949 |
1950 MarkBit::CellType grey_objects; | 1950 MarkBit::CellType grey_objects; |
1951 if (it.HasNext()) { | 1951 if (it.HasNext()) { |
1952 const MarkBit::CellType next_cell = *(cell+1); | 1952 const MarkBit::CellType next_cell = *(cell+1); |
1953 grey_objects = current_cell & | 1953 grey_objects = current_cell & |
1954 ((current_cell >> 1) | (next_cell << (Bitmap::kBitsPerCell - 1))); | 1954 ((current_cell >> 1) | (next_cell << (Bitmap::kBitsPerCell - 1))); |
1955 } else { | 1955 } else { |
1956 grey_objects = current_cell & (current_cell >> 1); | 1956 grey_objects = current_cell & (current_cell >> 1); |
1957 } | 1957 } |
1958 | 1958 |
1959 int offset = 0; | 1959 int offset = 0; |
1960 while (grey_objects != 0) { | 1960 while (grey_objects != 0) { |
1961 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(grey_objects); | 1961 int trailing_zeros = CompilerIntrinsics::CountTrailingZeros(grey_objects); |
1962 grey_objects >>= trailing_zeros; | 1962 grey_objects >>= trailing_zeros; |
1963 offset += trailing_zeros; | 1963 offset += trailing_zeros; |
1964 MarkBit markbit(cell, 1 << offset, false); | 1964 MarkBit markbit(cell, 1 << offset, false); |
1965 ASSERT(Marking::IsGrey(markbit)); | 1965 DCHECK(Marking::IsGrey(markbit)); |
1966 Marking::GreyToBlack(markbit); | 1966 Marking::GreyToBlack(markbit); |
1967 Address addr = cell_base + offset * kPointerSize; | 1967 Address addr = cell_base + offset * kPointerSize; |
1968 HeapObject* object = HeapObject::FromAddress(addr); | 1968 HeapObject* object = HeapObject::FromAddress(addr); |
1969 MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size()); | 1969 MemoryChunk::IncrementLiveBytesFromGC(object->address(), object->Size()); |
1970 marking_deque->PushBlack(object); | 1970 marking_deque->PushBlack(object); |
1971 if (marking_deque->IsFull()) return; | 1971 if (marking_deque->IsFull()) return; |
1972 offset += 2; | 1972 offset += 2; |
1973 grey_objects >>= 2; | 1973 grey_objects >>= 2; |
1974 } | 1974 } |
1975 | 1975 |
1976 grey_objects >>= (Bitmap::kBitsPerCell - 1); | 1976 grey_objects >>= (Bitmap::kBitsPerCell - 1); |
1977 } | 1977 } |
1978 } | 1978 } |
1979 | 1979 |
1980 | 1980 |
1981 int MarkCompactCollector::DiscoverAndEvacuateBlackObjectsOnPage( | 1981 int MarkCompactCollector::DiscoverAndEvacuateBlackObjectsOnPage( |
1982 NewSpace* new_space, | 1982 NewSpace* new_space, |
1983 NewSpacePage* p) { | 1983 NewSpacePage* p) { |
1984 ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 1984 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
1985 ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); | 1985 DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); |
1986 ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); | 1986 DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); |
1987 ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 1987 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
1988 | 1988 |
1989 MarkBit::CellType* cells = p->markbits()->cells(); | 1989 MarkBit::CellType* cells = p->markbits()->cells(); |
1990 int survivors_size = 0; | 1990 int survivors_size = 0; |
1991 | 1991 |
1992 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { | 1992 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
1993 Address cell_base = it.CurrentCellBase(); | 1993 Address cell_base = it.CurrentCellBase(); |
1994 MarkBit::CellType* cell = it.CurrentCell(); | 1994 MarkBit::CellType* cell = it.CurrentCell(); |
1995 | 1995 |
1996 MarkBit::CellType current_cell = *cell; | 1996 MarkBit::CellType current_cell = *cell; |
1997 if (current_cell == 0) continue; | 1997 if (current_cell == 0) continue; |
(...skipping 22 matching lines...) Expand all Loading... |
2020 | 2020 |
2021 AllocationResult allocation = new_space->AllocateRaw(size); | 2021 AllocationResult allocation = new_space->AllocateRaw(size); |
2022 if (allocation.IsRetry()) { | 2022 if (allocation.IsRetry()) { |
2023 if (!new_space->AddFreshPage()) { | 2023 if (!new_space->AddFreshPage()) { |
2024 // Shouldn't happen. We are sweeping linearly, and to-space | 2024 // Shouldn't happen. We are sweeping linearly, and to-space |
2025 // has the same number of pages as from-space, so there is | 2025 // has the same number of pages as from-space, so there is |
2026 // always room. | 2026 // always room. |
2027 UNREACHABLE(); | 2027 UNREACHABLE(); |
2028 } | 2028 } |
2029 allocation = new_space->AllocateRaw(size); | 2029 allocation = new_space->AllocateRaw(size); |
2030 ASSERT(!allocation.IsRetry()); | 2030 DCHECK(!allocation.IsRetry()); |
2031 } | 2031 } |
2032 Object* target = allocation.ToObjectChecked(); | 2032 Object* target = allocation.ToObjectChecked(); |
2033 | 2033 |
2034 MigrateObject(HeapObject::cast(target), | 2034 MigrateObject(HeapObject::cast(target), |
2035 object, | 2035 object, |
2036 size, | 2036 size, |
2037 NEW_SPACE); | 2037 NEW_SPACE); |
2038 heap()->IncrementSemiSpaceCopiedObjectSize(size); | 2038 heap()->IncrementSemiSpaceCopiedObjectSize(size); |
2039 } | 2039 } |
2040 *cells = 0; | 2040 *cells = 0; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2077 if (!o->IsHeapObject()) return false; | 2077 if (!o->IsHeapObject()) return false; |
2078 HeapObject* heap_object = HeapObject::cast(o); | 2078 HeapObject* heap_object = HeapObject::cast(o); |
2079 MarkBit mark = Marking::MarkBitFrom(heap_object); | 2079 MarkBit mark = Marking::MarkBitFrom(heap_object); |
2080 return !mark.Get(); | 2080 return !mark.Get(); |
2081 } | 2081 } |
2082 | 2082 |
2083 | 2083 |
2084 bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, | 2084 bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap, |
2085 Object** p) { | 2085 Object** p) { |
2086 Object* o = *p; | 2086 Object* o = *p; |
2087 ASSERT(o->IsHeapObject()); | 2087 DCHECK(o->IsHeapObject()); |
2088 HeapObject* heap_object = HeapObject::cast(o); | 2088 HeapObject* heap_object = HeapObject::cast(o); |
2089 MarkBit mark = Marking::MarkBitFrom(heap_object); | 2089 MarkBit mark = Marking::MarkBitFrom(heap_object); |
2090 return !mark.Get(); | 2090 return !mark.Get(); |
2091 } | 2091 } |
2092 | 2092 |
2093 | 2093 |
2094 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { | 2094 void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) { |
2095 StringTable* string_table = heap()->string_table(); | 2095 StringTable* string_table = heap()->string_table(); |
2096 // Mark the string table itself. | 2096 // Mark the string table itself. |
2097 MarkBit string_table_mark = Marking::MarkBitFrom(string_table); | 2097 MarkBit string_table_mark = Marking::MarkBitFrom(string_table); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2129 } | 2129 } |
2130 | 2130 |
2131 | 2131 |
2132 void MarkCompactCollector::MarkImplicitRefGroups() { | 2132 void MarkCompactCollector::MarkImplicitRefGroups() { |
2133 List<ImplicitRefGroup*>* ref_groups = | 2133 List<ImplicitRefGroup*>* ref_groups = |
2134 isolate()->global_handles()->implicit_ref_groups(); | 2134 isolate()->global_handles()->implicit_ref_groups(); |
2135 | 2135 |
2136 int last = 0; | 2136 int last = 0; |
2137 for (int i = 0; i < ref_groups->length(); i++) { | 2137 for (int i = 0; i < ref_groups->length(); i++) { |
2138 ImplicitRefGroup* entry = ref_groups->at(i); | 2138 ImplicitRefGroup* entry = ref_groups->at(i); |
2139 ASSERT(entry != NULL); | 2139 DCHECK(entry != NULL); |
2140 | 2140 |
2141 if (!IsMarked(*entry->parent)) { | 2141 if (!IsMarked(*entry->parent)) { |
2142 (*ref_groups)[last++] = entry; | 2142 (*ref_groups)[last++] = entry; |
2143 continue; | 2143 continue; |
2144 } | 2144 } |
2145 | 2145 |
2146 Object*** children = entry->children; | 2146 Object*** children = entry->children; |
2147 // A parent object is marked, so mark all child heap objects. | 2147 // A parent object is marked, so mark all child heap objects. |
2148 for (size_t j = 0; j < entry->length; ++j) { | 2148 for (size_t j = 0; j < entry->length; ++j) { |
2149 if ((*children[j])->IsHeapObject()) { | 2149 if ((*children[j])->IsHeapObject()) { |
(...skipping 21 matching lines...) Expand all Loading... |
2171 } | 2171 } |
2172 | 2172 |
2173 | 2173 |
2174 // Mark all objects reachable from the objects on the marking stack. | 2174 // Mark all objects reachable from the objects on the marking stack. |
2175 // Before: the marking stack contains zero or more heap object pointers. | 2175 // Before: the marking stack contains zero or more heap object pointers. |
2176 // After: the marking stack is empty, and all objects reachable from the | 2176 // After: the marking stack is empty, and all objects reachable from the |
2177 // marking stack have been marked, or are overflowed in the heap. | 2177 // marking stack have been marked, or are overflowed in the heap. |
2178 void MarkCompactCollector::EmptyMarkingDeque() { | 2178 void MarkCompactCollector::EmptyMarkingDeque() { |
2179 while (!marking_deque_.IsEmpty()) { | 2179 while (!marking_deque_.IsEmpty()) { |
2180 HeapObject* object = marking_deque_.Pop(); | 2180 HeapObject* object = marking_deque_.Pop(); |
2181 ASSERT(object->IsHeapObject()); | 2181 DCHECK(object->IsHeapObject()); |
2182 ASSERT(heap()->Contains(object)); | 2182 DCHECK(heap()->Contains(object)); |
2183 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); | 2183 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
2184 | 2184 |
2185 Map* map = object->map(); | 2185 Map* map = object->map(); |
2186 MarkBit map_mark = Marking::MarkBitFrom(map); | 2186 MarkBit map_mark = Marking::MarkBitFrom(map); |
2187 MarkObject(map, map_mark); | 2187 MarkObject(map, map_mark); |
2188 | 2188 |
2189 MarkCompactMarkingVisitor::IterateBody(map, object); | 2189 MarkCompactMarkingVisitor::IterateBody(map, object); |
2190 } | 2190 } |
2191 } | 2191 } |
2192 | 2192 |
2193 | 2193 |
2194 // Sweep the heap for overflowed objects, clear their overflow bits, and | 2194 // Sweep the heap for overflowed objects, clear their overflow bits, and |
2195 // push them on the marking stack. Stop early if the marking stack fills | 2195 // push them on the marking stack. Stop early if the marking stack fills |
2196 // before sweeping completes. If sweeping completes, there are no remaining | 2196 // before sweeping completes. If sweeping completes, there are no remaining |
2197 // overflowed objects in the heap so the overflow flag on the markings stack | 2197 // overflowed objects in the heap so the overflow flag on the markings stack |
2198 // is cleared. | 2198 // is cleared. |
2199 void MarkCompactCollector::RefillMarkingDeque() { | 2199 void MarkCompactCollector::RefillMarkingDeque() { |
2200 ASSERT(marking_deque_.overflowed()); | 2200 DCHECK(marking_deque_.overflowed()); |
2201 | 2201 |
2202 DiscoverGreyObjectsInNewSpace(heap(), &marking_deque_); | 2202 DiscoverGreyObjectsInNewSpace(heap(), &marking_deque_); |
2203 if (marking_deque_.IsFull()) return; | 2203 if (marking_deque_.IsFull()) return; |
2204 | 2204 |
2205 DiscoverGreyObjectsInSpace(heap(), | 2205 DiscoverGreyObjectsInSpace(heap(), |
2206 &marking_deque_, | 2206 &marking_deque_, |
2207 heap()->old_pointer_space()); | 2207 heap()->old_pointer_space()); |
2208 if (marking_deque_.IsFull()) return; | 2208 if (marking_deque_.IsFull()) return; |
2209 | 2209 |
2210 DiscoverGreyObjectsInSpace(heap(), | 2210 DiscoverGreyObjectsInSpace(heap(), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2252 RefillMarkingDeque(); | 2252 RefillMarkingDeque(); |
2253 EmptyMarkingDeque(); | 2253 EmptyMarkingDeque(); |
2254 } | 2254 } |
2255 } | 2255 } |
2256 | 2256 |
2257 | 2257 |
2258 // Mark all objects reachable (transitively) from objects on the marking | 2258 // Mark all objects reachable (transitively) from objects on the marking |
2259 // stack including references only considered in the atomic marking pause. | 2259 // stack including references only considered in the atomic marking pause. |
2260 void MarkCompactCollector::ProcessEphemeralMarking(ObjectVisitor* visitor) { | 2260 void MarkCompactCollector::ProcessEphemeralMarking(ObjectVisitor* visitor) { |
2261 bool work_to_do = true; | 2261 bool work_to_do = true; |
2262 ASSERT(marking_deque_.IsEmpty()); | 2262 DCHECK(marking_deque_.IsEmpty()); |
2263 while (work_to_do) { | 2263 while (work_to_do) { |
2264 isolate()->global_handles()->IterateObjectGroups( | 2264 isolate()->global_handles()->IterateObjectGroups( |
2265 visitor, &IsUnmarkedHeapObjectWithHeap); | 2265 visitor, &IsUnmarkedHeapObjectWithHeap); |
2266 MarkImplicitRefGroups(); | 2266 MarkImplicitRefGroups(); |
2267 ProcessWeakCollections(); | 2267 ProcessWeakCollections(); |
2268 work_to_do = !marking_deque_.IsEmpty(); | 2268 work_to_do = !marking_deque_.IsEmpty(); |
2269 ProcessMarkingDeque(); | 2269 ProcessMarkingDeque(); |
2270 } | 2270 } |
2271 } | 2271 } |
2272 | 2272 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2312 incremental_marking->Finalize(); | 2312 incremental_marking->Finalize(); |
2313 incremental_marking_overflowed = | 2313 incremental_marking_overflowed = |
2314 incremental_marking->marking_deque()->overflowed(); | 2314 incremental_marking->marking_deque()->overflowed(); |
2315 incremental_marking->marking_deque()->ClearOverflowed(); | 2315 incremental_marking->marking_deque()->ClearOverflowed(); |
2316 } else { | 2316 } else { |
2317 // Abort any pending incremental activities e.g. incremental sweeping. | 2317 // Abort any pending incremental activities e.g. incremental sweeping. |
2318 incremental_marking->Abort(); | 2318 incremental_marking->Abort(); |
2319 } | 2319 } |
2320 | 2320 |
2321 #ifdef DEBUG | 2321 #ifdef DEBUG |
2322 ASSERT(state_ == PREPARE_GC); | 2322 DCHECK(state_ == PREPARE_GC); |
2323 state_ = MARK_LIVE_OBJECTS; | 2323 state_ = MARK_LIVE_OBJECTS; |
2324 #endif | 2324 #endif |
2325 // The to space contains live objects, a page in from space is used as a | 2325 // The to space contains live objects, a page in from space is used as a |
2326 // marking stack. | 2326 // marking stack. |
2327 Address marking_deque_start = heap()->new_space()->FromSpacePageLow(); | 2327 Address marking_deque_start = heap()->new_space()->FromSpacePageLow(); |
2328 Address marking_deque_end = heap()->new_space()->FromSpacePageHigh(); | 2328 Address marking_deque_end = heap()->new_space()->FromSpacePageHigh(); |
2329 if (FLAG_force_marking_deque_overflows) { | 2329 if (FLAG_force_marking_deque_overflows) { |
2330 marking_deque_end = marking_deque_start + 64 * kPointerSize; | 2330 marking_deque_end = marking_deque_start + 64 * kPointerSize; |
2331 } | 2331 } |
2332 marking_deque_.Initialize(marking_deque_start, | 2332 marking_deque_.Initialize(marking_deque_start, |
2333 marking_deque_end); | 2333 marking_deque_end); |
2334 ASSERT(!marking_deque_.overflowed()); | 2334 DCHECK(!marking_deque_.overflowed()); |
2335 | 2335 |
2336 if (incremental_marking_overflowed) { | 2336 if (incremental_marking_overflowed) { |
2337 // There are overflowed objects left in the heap after incremental marking. | 2337 // There are overflowed objects left in the heap after incremental marking. |
2338 marking_deque_.SetOverflowed(); | 2338 marking_deque_.SetOverflowed(); |
2339 } | 2339 } |
2340 | 2340 |
2341 PrepareForCodeFlushing(); | 2341 PrepareForCodeFlushing(); |
2342 | 2342 |
2343 if (was_marked_incrementally_) { | 2343 if (was_marked_incrementally_) { |
2344 // There is no write barrier on cells so we have to scan them now at the end | 2344 // There is no write barrier on cells so we have to scan them now at the end |
2345 // of the incremental marking. | 2345 // of the incremental marking. |
2346 { | 2346 { |
2347 HeapObjectIterator cell_iterator(heap()->cell_space()); | 2347 HeapObjectIterator cell_iterator(heap()->cell_space()); |
2348 HeapObject* cell; | 2348 HeapObject* cell; |
2349 while ((cell = cell_iterator.Next()) != NULL) { | 2349 while ((cell = cell_iterator.Next()) != NULL) { |
2350 ASSERT(cell->IsCell()); | 2350 DCHECK(cell->IsCell()); |
2351 if (IsMarked(cell)) { | 2351 if (IsMarked(cell)) { |
2352 int offset = Cell::kValueOffset; | 2352 int offset = Cell::kValueOffset; |
2353 MarkCompactMarkingVisitor::VisitPointer( | 2353 MarkCompactMarkingVisitor::VisitPointer( |
2354 heap(), | 2354 heap(), |
2355 reinterpret_cast<Object**>(cell->address() + offset)); | 2355 reinterpret_cast<Object**>(cell->address() + offset)); |
2356 } | 2356 } |
2357 } | 2357 } |
2358 } | 2358 } |
2359 { | 2359 { |
2360 HeapObjectIterator js_global_property_cell_iterator( | 2360 HeapObjectIterator js_global_property_cell_iterator( |
2361 heap()->property_cell_space()); | 2361 heap()->property_cell_space()); |
2362 HeapObject* cell; | 2362 HeapObject* cell; |
2363 while ((cell = js_global_property_cell_iterator.Next()) != NULL) { | 2363 while ((cell = js_global_property_cell_iterator.Next()) != NULL) { |
2364 ASSERT(cell->IsPropertyCell()); | 2364 DCHECK(cell->IsPropertyCell()); |
2365 if (IsMarked(cell)) { | 2365 if (IsMarked(cell)) { |
2366 MarkCompactMarkingVisitor::VisitPropertyCell(cell->map(), cell); | 2366 MarkCompactMarkingVisitor::VisitPropertyCell(cell->map(), cell); |
2367 } | 2367 } |
2368 } | 2368 } |
2369 } | 2369 } |
2370 } | 2370 } |
2371 | 2371 |
2372 RootMarkingVisitor root_visitor(heap()); | 2372 RootMarkingVisitor root_visitor(heap()); |
2373 MarkRoots(&root_visitor); | 2373 MarkRoots(&root_visitor); |
2374 | 2374 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2469 i += MapCache::kEntrySize) { | 2469 i += MapCache::kEntrySize) { |
2470 Object* raw_key = map_cache->get(i); | 2470 Object* raw_key = map_cache->get(i); |
2471 if (raw_key == heap()->undefined_value() || | 2471 if (raw_key == heap()->undefined_value() || |
2472 raw_key == heap()->the_hole_value()) continue; | 2472 raw_key == heap()->the_hole_value()) continue; |
2473 STATIC_ASSERT(MapCache::kEntrySize == 2); | 2473 STATIC_ASSERT(MapCache::kEntrySize == 2); |
2474 Object* raw_map = map_cache->get(i + 1); | 2474 Object* raw_map = map_cache->get(i + 1); |
2475 if (raw_map->IsHeapObject() && IsMarked(raw_map)) { | 2475 if (raw_map->IsHeapObject() && IsMarked(raw_map)) { |
2476 ++used_elements; | 2476 ++used_elements; |
2477 } else { | 2477 } else { |
2478 // Delete useless entries with unmarked maps. | 2478 // Delete useless entries with unmarked maps. |
2479 ASSERT(raw_map->IsMap()); | 2479 DCHECK(raw_map->IsMap()); |
2480 map_cache->set_the_hole(i); | 2480 map_cache->set_the_hole(i); |
2481 map_cache->set_the_hole(i + 1); | 2481 map_cache->set_the_hole(i + 1); |
2482 } | 2482 } |
2483 } | 2483 } |
2484 if (used_elements == 0) { | 2484 if (used_elements == 0) { |
2485 context->set(Context::MAP_CACHE_INDEX, heap()->undefined_value()); | 2485 context->set(Context::MAP_CACHE_INDEX, heap()->undefined_value()); |
2486 } else { | 2486 } else { |
2487 // Note: we don't actually shrink the cache here to avoid | 2487 // Note: we don't actually shrink the cache here to avoid |
2488 // extra complexity during GC. We rely on subsequent cache | 2488 // extra complexity during GC. We rely on subsequent cache |
2489 // usages (EnsureCapacity) to do this. | 2489 // usages (EnsureCapacity) to do this. |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2590 | 2590 |
2591 int new_number_of_transitions = 0; | 2591 int new_number_of_transitions = 0; |
2592 const int header = Map::kProtoTransitionHeaderSize; | 2592 const int header = Map::kProtoTransitionHeaderSize; |
2593 const int proto_offset = header + Map::kProtoTransitionPrototypeOffset; | 2593 const int proto_offset = header + Map::kProtoTransitionPrototypeOffset; |
2594 const int map_offset = header + Map::kProtoTransitionMapOffset; | 2594 const int map_offset = header + Map::kProtoTransitionMapOffset; |
2595 const int step = Map::kProtoTransitionElementsPerEntry; | 2595 const int step = Map::kProtoTransitionElementsPerEntry; |
2596 for (int i = 0; i < number_of_transitions; i++) { | 2596 for (int i = 0; i < number_of_transitions; i++) { |
2597 Object* prototype = prototype_transitions->get(proto_offset + i * step); | 2597 Object* prototype = prototype_transitions->get(proto_offset + i * step); |
2598 Object* cached_map = prototype_transitions->get(map_offset + i * step); | 2598 Object* cached_map = prototype_transitions->get(map_offset + i * step); |
2599 if (IsMarked(prototype) && IsMarked(cached_map)) { | 2599 if (IsMarked(prototype) && IsMarked(cached_map)) { |
2600 ASSERT(!prototype->IsUndefined()); | 2600 DCHECK(!prototype->IsUndefined()); |
2601 int proto_index = proto_offset + new_number_of_transitions * step; | 2601 int proto_index = proto_offset + new_number_of_transitions * step; |
2602 int map_index = map_offset + new_number_of_transitions * step; | 2602 int map_index = map_offset + new_number_of_transitions * step; |
2603 if (new_number_of_transitions != i) { | 2603 if (new_number_of_transitions != i) { |
2604 prototype_transitions->set( | 2604 prototype_transitions->set( |
2605 proto_index, | 2605 proto_index, |
2606 prototype, | 2606 prototype, |
2607 UPDATE_WRITE_BARRIER); | 2607 UPDATE_WRITE_BARRIER); |
2608 prototype_transitions->set( | 2608 prototype_transitions->set( |
2609 map_index, | 2609 map_index, |
2610 cached_map, | 2610 cached_map, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2644 } | 2644 } |
2645 } | 2645 } |
2646 | 2646 |
2647 | 2647 |
2648 void MarkCompactCollector::ClearDependentICList(Object* head) { | 2648 void MarkCompactCollector::ClearDependentICList(Object* head) { |
2649 Object* current = head; | 2649 Object* current = head; |
2650 Object* undefined = heap()->undefined_value(); | 2650 Object* undefined = heap()->undefined_value(); |
2651 while (current != undefined) { | 2651 while (current != undefined) { |
2652 Code* code = Code::cast(current); | 2652 Code* code = Code::cast(current); |
2653 if (IsMarked(code)) { | 2653 if (IsMarked(code)) { |
2654 ASSERT(code->is_weak_stub()); | 2654 DCHECK(code->is_weak_stub()); |
2655 IC::InvalidateMaps(code); | 2655 IC::InvalidateMaps(code); |
2656 } | 2656 } |
2657 current = code->next_code_link(); | 2657 current = code->next_code_link(); |
2658 code->set_next_code_link(undefined); | 2658 code->set_next_code_link(undefined); |
2659 } | 2659 } |
2660 } | 2660 } |
2661 | 2661 |
2662 | 2662 |
2663 void MarkCompactCollector::ClearDependentCode( | 2663 void MarkCompactCollector::ClearDependentCode( |
2664 DependentCode* entries) { | 2664 DependentCode* entries) { |
2665 DisallowHeapAllocation no_allocation; | 2665 DisallowHeapAllocation no_allocation; |
2666 DependentCode::GroupStartIndexes starts(entries); | 2666 DependentCode::GroupStartIndexes starts(entries); |
2667 int number_of_entries = starts.number_of_entries(); | 2667 int number_of_entries = starts.number_of_entries(); |
2668 if (number_of_entries == 0) return; | 2668 if (number_of_entries == 0) return; |
2669 int g = DependentCode::kWeakICGroup; | 2669 int g = DependentCode::kWeakICGroup; |
2670 if (starts.at(g) != starts.at(g + 1)) { | 2670 if (starts.at(g) != starts.at(g + 1)) { |
2671 int i = starts.at(g); | 2671 int i = starts.at(g); |
2672 ASSERT(i + 1 == starts.at(g + 1)); | 2672 DCHECK(i + 1 == starts.at(g + 1)); |
2673 Object* head = entries->object_at(i); | 2673 Object* head = entries->object_at(i); |
2674 ClearDependentICList(head); | 2674 ClearDependentICList(head); |
2675 } | 2675 } |
2676 g = DependentCode::kWeakCodeGroup; | 2676 g = DependentCode::kWeakCodeGroup; |
2677 for (int i = starts.at(g); i < starts.at(g + 1); i++) { | 2677 for (int i = starts.at(g); i < starts.at(g + 1); i++) { |
2678 // If the entry is compilation info then the map must be alive, | 2678 // If the entry is compilation info then the map must be alive, |
2679 // and ClearDependentCode shouldn't be called. | 2679 // and ClearDependentCode shouldn't be called. |
2680 ASSERT(entries->is_code_at(i)); | 2680 DCHECK(entries->is_code_at(i)); |
2681 Code* code = entries->code_at(i); | 2681 Code* code = entries->code_at(i); |
2682 if (IsMarked(code) && !code->marked_for_deoptimization()) { | 2682 if (IsMarked(code) && !code->marked_for_deoptimization()) { |
2683 code->set_marked_for_deoptimization(true); | 2683 code->set_marked_for_deoptimization(true); |
2684 code->InvalidateEmbeddedObjects(); | 2684 code->InvalidateEmbeddedObjects(); |
2685 have_code_to_deoptimize_ = true; | 2685 have_code_to_deoptimize_ = true; |
2686 } | 2686 } |
2687 } | 2687 } |
2688 for (int i = 0; i < number_of_entries; i++) { | 2688 for (int i = 0; i < number_of_entries; i++) { |
2689 entries->clear_at(i); | 2689 entries->clear_at(i); |
2690 } | 2690 } |
2691 } | 2691 } |
2692 | 2692 |
2693 | 2693 |
2694 int MarkCompactCollector::ClearNonLiveDependentCodeInGroup( | 2694 int MarkCompactCollector::ClearNonLiveDependentCodeInGroup( |
2695 DependentCode* entries, int group, int start, int end, int new_start) { | 2695 DependentCode* entries, int group, int start, int end, int new_start) { |
2696 int survived = 0; | 2696 int survived = 0; |
2697 if (group == DependentCode::kWeakICGroup) { | 2697 if (group == DependentCode::kWeakICGroup) { |
2698 // Dependent weak IC stubs form a linked list and only the head is stored | 2698 // Dependent weak IC stubs form a linked list and only the head is stored |
2699 // in the dependent code array. | 2699 // in the dependent code array. |
2700 if (start != end) { | 2700 if (start != end) { |
2701 ASSERT(start + 1 == end); | 2701 DCHECK(start + 1 == end); |
2702 Object* old_head = entries->object_at(start); | 2702 Object* old_head = entries->object_at(start); |
2703 MarkCompactWeakObjectRetainer retainer; | 2703 MarkCompactWeakObjectRetainer retainer; |
2704 Object* head = VisitWeakList<Code>(heap(), old_head, &retainer); | 2704 Object* head = VisitWeakList<Code>(heap(), old_head, &retainer); |
2705 entries->set_object_at(new_start, head); | 2705 entries->set_object_at(new_start, head); |
2706 Object** slot = entries->slot_at(new_start); | 2706 Object** slot = entries->slot_at(new_start); |
2707 RecordSlot(slot, slot, head); | 2707 RecordSlot(slot, slot, head); |
2708 // We do not compact this group even if the head is undefined, | 2708 // We do not compact this group even if the head is undefined, |
2709 // more dependent ICs are likely to be added later. | 2709 // more dependent ICs are likely to be added later. |
2710 survived = 1; | 2710 survived = 1; |
2711 } | 2711 } |
2712 } else { | 2712 } else { |
2713 for (int i = start; i < end; i++) { | 2713 for (int i = start; i < end; i++) { |
2714 Object* obj = entries->object_at(i); | 2714 Object* obj = entries->object_at(i); |
2715 ASSERT(obj->IsCode() || IsMarked(obj)); | 2715 DCHECK(obj->IsCode() || IsMarked(obj)); |
2716 if (IsMarked(obj) && | 2716 if (IsMarked(obj) && |
2717 (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { | 2717 (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) { |
2718 if (new_start + survived != i) { | 2718 if (new_start + survived != i) { |
2719 entries->set_object_at(new_start + survived, obj); | 2719 entries->set_object_at(new_start + survived, obj); |
2720 } | 2720 } |
2721 Object** slot = entries->slot_at(new_start + survived); | 2721 Object** slot = entries->slot_at(new_start + survived); |
2722 RecordSlot(slot, slot, obj); | 2722 RecordSlot(slot, slot, obj); |
2723 survived++; | 2723 survived++; |
2724 } | 2724 } |
2725 } | 2725 } |
(...skipping 22 matching lines...) Expand all Loading... |
2748 } | 2748 } |
2749 | 2749 |
2750 | 2750 |
2751 void MarkCompactCollector::ProcessWeakCollections() { | 2751 void MarkCompactCollector::ProcessWeakCollections() { |
2752 GCTracer::Scope gc_scope(heap()->tracer(), | 2752 GCTracer::Scope gc_scope(heap()->tracer(), |
2753 GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); | 2753 GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS); |
2754 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2754 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
2755 while (weak_collection_obj != Smi::FromInt(0)) { | 2755 while (weak_collection_obj != Smi::FromInt(0)) { |
2756 JSWeakCollection* weak_collection = | 2756 JSWeakCollection* weak_collection = |
2757 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2757 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
2758 ASSERT(MarkCompactCollector::IsMarked(weak_collection)); | 2758 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
2759 if (weak_collection->table()->IsHashTable()) { | 2759 if (weak_collection->table()->IsHashTable()) { |
2760 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2760 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
2761 Object** anchor = reinterpret_cast<Object**>(table->address()); | 2761 Object** anchor = reinterpret_cast<Object**>(table->address()); |
2762 for (int i = 0; i < table->Capacity(); i++) { | 2762 for (int i = 0; i < table->Capacity(); i++) { |
2763 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2763 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
2764 Object** key_slot = | 2764 Object** key_slot = |
2765 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); | 2765 table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i)); |
2766 RecordSlot(anchor, key_slot, *key_slot); | 2766 RecordSlot(anchor, key_slot, *key_slot); |
2767 Object** value_slot = | 2767 Object** value_slot = |
2768 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); | 2768 table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i)); |
2769 MarkCompactMarkingVisitor::MarkObjectByPointer( | 2769 MarkCompactMarkingVisitor::MarkObjectByPointer( |
2770 this, anchor, value_slot); | 2770 this, anchor, value_slot); |
2771 } | 2771 } |
2772 } | 2772 } |
2773 } | 2773 } |
2774 weak_collection_obj = weak_collection->next(); | 2774 weak_collection_obj = weak_collection->next(); |
2775 } | 2775 } |
2776 } | 2776 } |
2777 | 2777 |
2778 | 2778 |
2779 void MarkCompactCollector::ClearWeakCollections() { | 2779 void MarkCompactCollector::ClearWeakCollections() { |
2780 GCTracer::Scope gc_scope(heap()->tracer(), | 2780 GCTracer::Scope gc_scope(heap()->tracer(), |
2781 GCTracer::Scope::MC_WEAKCOLLECTION_CLEAR); | 2781 GCTracer::Scope::MC_WEAKCOLLECTION_CLEAR); |
2782 Object* weak_collection_obj = heap()->encountered_weak_collections(); | 2782 Object* weak_collection_obj = heap()->encountered_weak_collections(); |
2783 while (weak_collection_obj != Smi::FromInt(0)) { | 2783 while (weak_collection_obj != Smi::FromInt(0)) { |
2784 JSWeakCollection* weak_collection = | 2784 JSWeakCollection* weak_collection = |
2785 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); | 2785 reinterpret_cast<JSWeakCollection*>(weak_collection_obj); |
2786 ASSERT(MarkCompactCollector::IsMarked(weak_collection)); | 2786 DCHECK(MarkCompactCollector::IsMarked(weak_collection)); |
2787 if (weak_collection->table()->IsHashTable()) { | 2787 if (weak_collection->table()->IsHashTable()) { |
2788 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); | 2788 ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table()); |
2789 for (int i = 0; i < table->Capacity(); i++) { | 2789 for (int i = 0; i < table->Capacity(); i++) { |
2790 HeapObject* key = HeapObject::cast(table->KeyAt(i)); | 2790 HeapObject* key = HeapObject::cast(table->KeyAt(i)); |
2791 if (!MarkCompactCollector::IsMarked(key)) { | 2791 if (!MarkCompactCollector::IsMarked(key)) { |
2792 table->RemoveEntry(i); | 2792 table->RemoveEntry(i); |
2793 } | 2793 } |
2794 } | 2794 } |
2795 } | 2795 } |
2796 weak_collection_obj = weak_collection->next(); | 2796 weak_collection_obj = weak_collection->next(); |
(...skipping 29 matching lines...) Expand all Loading... |
2826 // to new space. We should clear them to avoid encountering them during next | 2826 // to new space. We should clear them to avoid encountering them during next |
2827 // pointer iteration. This is an issue if the store buffer overflows and we | 2827 // pointer iteration. This is an issue if the store buffer overflows and we |
2828 // have to scan the entire old space, including dead objects, looking for | 2828 // have to scan the entire old space, including dead objects, looking for |
2829 // pointers to new space. | 2829 // pointers to new space. |
2830 void MarkCompactCollector::MigrateObject(HeapObject* dst, | 2830 void MarkCompactCollector::MigrateObject(HeapObject* dst, |
2831 HeapObject* src, | 2831 HeapObject* src, |
2832 int size, | 2832 int size, |
2833 AllocationSpace dest) { | 2833 AllocationSpace dest) { |
2834 Address dst_addr = dst->address(); | 2834 Address dst_addr = dst->address(); |
2835 Address src_addr = src->address(); | 2835 Address src_addr = src->address(); |
2836 ASSERT(heap()->AllowedToBeMigrated(src, dest)); | 2836 DCHECK(heap()->AllowedToBeMigrated(src, dest)); |
2837 ASSERT(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize); | 2837 DCHECK(dest != LO_SPACE && size <= Page::kMaxRegularHeapObjectSize); |
2838 if (dest == OLD_POINTER_SPACE) { | 2838 if (dest == OLD_POINTER_SPACE) { |
2839 Address src_slot = src_addr; | 2839 Address src_slot = src_addr; |
2840 Address dst_slot = dst_addr; | 2840 Address dst_slot = dst_addr; |
2841 ASSERT(IsAligned(size, kPointerSize)); | 2841 DCHECK(IsAligned(size, kPointerSize)); |
2842 | 2842 |
2843 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { | 2843 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { |
2844 Object* value = Memory::Object_at(src_slot); | 2844 Object* value = Memory::Object_at(src_slot); |
2845 | 2845 |
2846 Memory::Object_at(dst_slot) = value; | 2846 Memory::Object_at(dst_slot) = value; |
2847 | 2847 |
2848 // We special case ConstantPoolArrays below since they could contain | 2848 // We special case ConstantPoolArrays below since they could contain |
2849 // integers value entries which look like tagged pointers. | 2849 // integers value entries which look like tagged pointers. |
2850 // TODO(mstarzinger): restructure this code to avoid this special-casing. | 2850 // TODO(mstarzinger): restructure this code to avoid this special-casing. |
2851 if (!src->IsConstantPoolArray()) { | 2851 if (!src->IsConstantPoolArray()) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2894 } else if (dest == CODE_SPACE) { | 2894 } else if (dest == CODE_SPACE) { |
2895 PROFILE(isolate(), CodeMoveEvent(src_addr, dst_addr)); | 2895 PROFILE(isolate(), CodeMoveEvent(src_addr, dst_addr)); |
2896 heap()->MoveBlock(dst_addr, src_addr, size); | 2896 heap()->MoveBlock(dst_addr, src_addr, size); |
2897 SlotsBuffer::AddTo(&slots_buffer_allocator_, | 2897 SlotsBuffer::AddTo(&slots_buffer_allocator_, |
2898 &migration_slots_buffer_, | 2898 &migration_slots_buffer_, |
2899 SlotsBuffer::RELOCATED_CODE_OBJECT, | 2899 SlotsBuffer::RELOCATED_CODE_OBJECT, |
2900 dst_addr, | 2900 dst_addr, |
2901 SlotsBuffer::IGNORE_OVERFLOW); | 2901 SlotsBuffer::IGNORE_OVERFLOW); |
2902 Code::cast(dst)->Relocate(dst_addr - src_addr); | 2902 Code::cast(dst)->Relocate(dst_addr - src_addr); |
2903 } else { | 2903 } else { |
2904 ASSERT(dest == OLD_DATA_SPACE || dest == NEW_SPACE); | 2904 DCHECK(dest == OLD_DATA_SPACE || dest == NEW_SPACE); |
2905 heap()->MoveBlock(dst_addr, src_addr, size); | 2905 heap()->MoveBlock(dst_addr, src_addr, size); |
2906 } | 2906 } |
2907 heap()->OnMoveEvent(dst, src, size); | 2907 heap()->OnMoveEvent(dst, src, size); |
2908 Memory::Address_at(src_addr) = dst_addr; | 2908 Memory::Address_at(src_addr) = dst_addr; |
2909 } | 2909 } |
2910 | 2910 |
2911 | 2911 |
2912 // Visitor for updating pointers from live objects in old spaces to new space. | 2912 // Visitor for updating pointers from live objects in old spaces to new space. |
2913 // It does not expect to encounter pointers to dead objects. | 2913 // It does not expect to encounter pointers to dead objects. |
2914 class PointersUpdatingVisitor: public ObjectVisitor { | 2914 class PointersUpdatingVisitor: public ObjectVisitor { |
2915 public: | 2915 public: |
2916 explicit PointersUpdatingVisitor(Heap* heap) : heap_(heap) { } | 2916 explicit PointersUpdatingVisitor(Heap* heap) : heap_(heap) { } |
2917 | 2917 |
2918 void VisitPointer(Object** p) { | 2918 void VisitPointer(Object** p) { |
2919 UpdatePointer(p); | 2919 UpdatePointer(p); |
2920 } | 2920 } |
2921 | 2921 |
2922 void VisitPointers(Object** start, Object** end) { | 2922 void VisitPointers(Object** start, Object** end) { |
2923 for (Object** p = start; p < end; p++) UpdatePointer(p); | 2923 for (Object** p = start; p < end; p++) UpdatePointer(p); |
2924 } | 2924 } |
2925 | 2925 |
2926 void VisitEmbeddedPointer(RelocInfo* rinfo) { | 2926 void VisitEmbeddedPointer(RelocInfo* rinfo) { |
2927 ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); | 2927 DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT); |
2928 Object* target = rinfo->target_object(); | 2928 Object* target = rinfo->target_object(); |
2929 Object* old_target = target; | 2929 Object* old_target = target; |
2930 VisitPointer(&target); | 2930 VisitPointer(&target); |
2931 // Avoid unnecessary changes that might unnecessary flush the instruction | 2931 // Avoid unnecessary changes that might unnecessary flush the instruction |
2932 // cache. | 2932 // cache. |
2933 if (target != old_target) { | 2933 if (target != old_target) { |
2934 rinfo->set_target_object(target); | 2934 rinfo->set_target_object(target); |
2935 } | 2935 } |
2936 } | 2936 } |
2937 | 2937 |
2938 void VisitCodeTarget(RelocInfo* rinfo) { | 2938 void VisitCodeTarget(RelocInfo* rinfo) { |
2939 ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode())); | 2939 DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode())); |
2940 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | 2940 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); |
2941 Object* old_target = target; | 2941 Object* old_target = target; |
2942 VisitPointer(&target); | 2942 VisitPointer(&target); |
2943 if (target != old_target) { | 2943 if (target != old_target) { |
2944 rinfo->set_target_address(Code::cast(target)->instruction_start()); | 2944 rinfo->set_target_address(Code::cast(target)->instruction_start()); |
2945 } | 2945 } |
2946 } | 2946 } |
2947 | 2947 |
2948 void VisitCodeAgeSequence(RelocInfo* rinfo) { | 2948 void VisitCodeAgeSequence(RelocInfo* rinfo) { |
2949 ASSERT(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); | 2949 DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode())); |
2950 Object* stub = rinfo->code_age_stub(); | 2950 Object* stub = rinfo->code_age_stub(); |
2951 ASSERT(stub != NULL); | 2951 DCHECK(stub != NULL); |
2952 VisitPointer(&stub); | 2952 VisitPointer(&stub); |
2953 if (stub != rinfo->code_age_stub()) { | 2953 if (stub != rinfo->code_age_stub()) { |
2954 rinfo->set_code_age_stub(Code::cast(stub)); | 2954 rinfo->set_code_age_stub(Code::cast(stub)); |
2955 } | 2955 } |
2956 } | 2956 } |
2957 | 2957 |
2958 void VisitDebugTarget(RelocInfo* rinfo) { | 2958 void VisitDebugTarget(RelocInfo* rinfo) { |
2959 ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) && | 2959 DCHECK((RelocInfo::IsJSReturn(rinfo->rmode()) && |
2960 rinfo->IsPatchedReturnSequence()) || | 2960 rinfo->IsPatchedReturnSequence()) || |
2961 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && | 2961 (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) && |
2962 rinfo->IsPatchedDebugBreakSlotSequence())); | 2962 rinfo->IsPatchedDebugBreakSlotSequence())); |
2963 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); | 2963 Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address()); |
2964 VisitPointer(&target); | 2964 VisitPointer(&target); |
2965 rinfo->set_call_address(Code::cast(target)->instruction_start()); | 2965 rinfo->set_call_address(Code::cast(target)->instruction_start()); |
2966 } | 2966 } |
2967 | 2967 |
2968 static inline void UpdateSlot(Heap* heap, Object** slot) { | 2968 static inline void UpdateSlot(Heap* heap, Object** slot) { |
2969 Object* obj = *slot; | 2969 Object* obj = *slot; |
2970 | 2970 |
2971 if (!obj->IsHeapObject()) return; | 2971 if (!obj->IsHeapObject()) return; |
2972 | 2972 |
2973 HeapObject* heap_obj = HeapObject::cast(obj); | 2973 HeapObject* heap_obj = HeapObject::cast(obj); |
2974 | 2974 |
2975 MapWord map_word = heap_obj->map_word(); | 2975 MapWord map_word = heap_obj->map_word(); |
2976 if (map_word.IsForwardingAddress()) { | 2976 if (map_word.IsForwardingAddress()) { |
2977 ASSERT(heap->InFromSpace(heap_obj) || | 2977 DCHECK(heap->InFromSpace(heap_obj) || |
2978 MarkCompactCollector::IsOnEvacuationCandidate(heap_obj)); | 2978 MarkCompactCollector::IsOnEvacuationCandidate(heap_obj)); |
2979 HeapObject* target = map_word.ToForwardingAddress(); | 2979 HeapObject* target = map_word.ToForwardingAddress(); |
2980 *slot = target; | 2980 *slot = target; |
2981 ASSERT(!heap->InFromSpace(target) && | 2981 DCHECK(!heap->InFromSpace(target) && |
2982 !MarkCompactCollector::IsOnEvacuationCandidate(target)); | 2982 !MarkCompactCollector::IsOnEvacuationCandidate(target)); |
2983 } | 2983 } |
2984 } | 2984 } |
2985 | 2985 |
2986 private: | 2986 private: |
2987 inline void UpdatePointer(Object** p) { | 2987 inline void UpdatePointer(Object** p) { |
2988 UpdateSlot(heap_, p); | 2988 UpdateSlot(heap_, p); |
2989 } | 2989 } |
2990 | 2990 |
2991 Heap* heap_; | 2991 Heap* heap_; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3027 if (map_word.IsForwardingAddress()) { | 3027 if (map_word.IsForwardingAddress()) { |
3028 return String::cast(map_word.ToForwardingAddress()); | 3028 return String::cast(map_word.ToForwardingAddress()); |
3029 } | 3029 } |
3030 | 3030 |
3031 return String::cast(*p); | 3031 return String::cast(*p); |
3032 } | 3032 } |
3033 | 3033 |
3034 | 3034 |
3035 bool MarkCompactCollector::TryPromoteObject(HeapObject* object, | 3035 bool MarkCompactCollector::TryPromoteObject(HeapObject* object, |
3036 int object_size) { | 3036 int object_size) { |
3037 ASSERT(object_size <= Page::kMaxRegularHeapObjectSize); | 3037 DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); |
3038 | 3038 |
3039 OldSpace* target_space = heap()->TargetSpace(object); | 3039 OldSpace* target_space = heap()->TargetSpace(object); |
3040 | 3040 |
3041 ASSERT(target_space == heap()->old_pointer_space() || | 3041 DCHECK(target_space == heap()->old_pointer_space() || |
3042 target_space == heap()->old_data_space()); | 3042 target_space == heap()->old_data_space()); |
3043 HeapObject* target; | 3043 HeapObject* target; |
3044 AllocationResult allocation = target_space->AllocateRaw(object_size); | 3044 AllocationResult allocation = target_space->AllocateRaw(object_size); |
3045 if (allocation.To(&target)) { | 3045 if (allocation.To(&target)) { |
3046 MigrateObject(target, | 3046 MigrateObject(target, |
3047 object, | 3047 object, |
3048 object_size, | 3048 object_size, |
3049 target_space->identity()); | 3049 target_space->identity()); |
3050 heap()->IncrementPromotedObjectsSize(object_size); | 3050 heap()->IncrementPromotedObjectsSize(object_size); |
3051 return true; | 3051 return true; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3085 } | 3085 } |
3086 | 3086 |
3087 heap_->IncrementYoungSurvivorsCounter(survivors_size); | 3087 heap_->IncrementYoungSurvivorsCounter(survivors_size); |
3088 new_space->set_age_mark(new_space->top()); | 3088 new_space->set_age_mark(new_space->top()); |
3089 } | 3089 } |
3090 | 3090 |
3091 | 3091 |
3092 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { | 3092 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { |
3093 AlwaysAllocateScope always_allocate(isolate()); | 3093 AlwaysAllocateScope always_allocate(isolate()); |
3094 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3094 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3095 ASSERT(p->IsEvacuationCandidate() && !p->WasSwept()); | 3095 DCHECK(p->IsEvacuationCandidate() && !p->WasSwept()); |
3096 p->MarkSweptPrecisely(); | 3096 p->MarkSweptPrecisely(); |
3097 | 3097 |
3098 int offsets[16]; | 3098 int offsets[16]; |
3099 | 3099 |
3100 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { | 3100 for (MarkBitCellIterator it(p); !it.Done(); it.Advance()) { |
3101 Address cell_base = it.CurrentCellBase(); | 3101 Address cell_base = it.CurrentCellBase(); |
3102 MarkBit::CellType* cell = it.CurrentCell(); | 3102 MarkBit::CellType* cell = it.CurrentCell(); |
3103 | 3103 |
3104 if (*cell == 0) continue; | 3104 if (*cell == 0) continue; |
3105 | 3105 |
3106 int live_objects = MarkWordToObjectStarts(*cell, offsets); | 3106 int live_objects = MarkWordToObjectStarts(*cell, offsets); |
3107 for (int i = 0; i < live_objects; i++) { | 3107 for (int i = 0; i < live_objects; i++) { |
3108 Address object_addr = cell_base + offsets[i] * kPointerSize; | 3108 Address object_addr = cell_base + offsets[i] * kPointerSize; |
3109 HeapObject* object = HeapObject::FromAddress(object_addr); | 3109 HeapObject* object = HeapObject::FromAddress(object_addr); |
3110 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); | 3110 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
3111 | 3111 |
3112 int size = object->Size(); | 3112 int size = object->Size(); |
3113 | 3113 |
3114 HeapObject* target_object; | 3114 HeapObject* target_object; |
3115 AllocationResult allocation = space->AllocateRaw(size); | 3115 AllocationResult allocation = space->AllocateRaw(size); |
3116 if (!allocation.To(&target_object)) { | 3116 if (!allocation.To(&target_object)) { |
3117 // If allocation failed, use emergency memory and re-try allocation. | 3117 // If allocation failed, use emergency memory and re-try allocation. |
3118 CHECK(space->HasEmergencyMemory()); | 3118 CHECK(space->HasEmergencyMemory()); |
3119 space->UseEmergencyMemory(); | 3119 space->UseEmergencyMemory(); |
3120 allocation = space->AllocateRaw(size); | 3120 allocation = space->AllocateRaw(size); |
3121 } | 3121 } |
3122 if (!allocation.To(&target_object)) { | 3122 if (!allocation.To(&target_object)) { |
3123 // OS refused to give us memory. | 3123 // OS refused to give us memory. |
3124 V8::FatalProcessOutOfMemory("Evacuation"); | 3124 V8::FatalProcessOutOfMemory("Evacuation"); |
3125 return; | 3125 return; |
3126 } | 3126 } |
3127 | 3127 |
3128 MigrateObject(target_object, object, size, space->identity()); | 3128 MigrateObject(target_object, object, size, space->identity()); |
3129 ASSERT(object->map_word().IsForwardingAddress()); | 3129 DCHECK(object->map_word().IsForwardingAddress()); |
3130 } | 3130 } |
3131 | 3131 |
3132 // Clear marking bits for current cell. | 3132 // Clear marking bits for current cell. |
3133 *cell = 0; | 3133 *cell = 0; |
3134 } | 3134 } |
3135 p->ResetLiveBytes(); | 3135 p->ResetLiveBytes(); |
3136 } | 3136 } |
3137 | 3137 |
3138 | 3138 |
3139 void MarkCompactCollector::EvacuatePages() { | 3139 void MarkCompactCollector::EvacuatePages() { |
3140 int npages = evacuation_candidates_.length(); | 3140 int npages = evacuation_candidates_.length(); |
3141 for (int i = 0; i < npages; i++) { | 3141 for (int i = 0; i < npages; i++) { |
3142 Page* p = evacuation_candidates_[i]; | 3142 Page* p = evacuation_candidates_[i]; |
3143 ASSERT(p->IsEvacuationCandidate() || | 3143 DCHECK(p->IsEvacuationCandidate() || |
3144 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3144 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
3145 ASSERT(static_cast<int>(p->parallel_sweeping()) == | 3145 DCHECK(static_cast<int>(p->parallel_sweeping()) == |
3146 MemoryChunk::SWEEPING_DONE); | 3146 MemoryChunk::SWEEPING_DONE); |
3147 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3147 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
3148 // Allocate emergency memory for the case when compaction fails due to out | 3148 // Allocate emergency memory for the case when compaction fails due to out |
3149 // of memory. | 3149 // of memory. |
3150 if (!space->HasEmergencyMemory()) { | 3150 if (!space->HasEmergencyMemory()) { |
3151 space->CreateEmergencyMemory(); | 3151 space->CreateEmergencyMemory(); |
3152 } | 3152 } |
3153 if (p->IsEvacuationCandidate()) { | 3153 if (p->IsEvacuationCandidate()) { |
3154 // During compaction we might have to request a new page. Check that we | 3154 // During compaction we might have to request a new page. Check that we |
3155 // have an emergency page and the space still has room for that. | 3155 // have an emergency page and the space still has room for that. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3254 ZAP_FREE_SPACE | 3254 ZAP_FREE_SPACE |
3255 }; | 3255 }; |
3256 | 3256 |
3257 | 3257 |
3258 template<MarkCompactCollector::SweepingParallelism mode> | 3258 template<MarkCompactCollector::SweepingParallelism mode> |
3259 static intptr_t Free(PagedSpace* space, | 3259 static intptr_t Free(PagedSpace* space, |
3260 FreeList* free_list, | 3260 FreeList* free_list, |
3261 Address start, | 3261 Address start, |
3262 int size) { | 3262 int size) { |
3263 if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) { | 3263 if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) { |
3264 ASSERT(free_list == NULL); | 3264 DCHECK(free_list == NULL); |
3265 return space->Free(start, size); | 3265 return space->Free(start, size); |
3266 } else { | 3266 } else { |
3267 // TODO(hpayer): account for wasted bytes in concurrent sweeping too. | 3267 // TODO(hpayer): account for wasted bytes in concurrent sweeping too. |
3268 return size - free_list->Free(start, size); | 3268 return size - free_list->Free(start, size); |
3269 } | 3269 } |
3270 } | 3270 } |
3271 | 3271 |
3272 | 3272 |
3273 // Sweep a space precisely. After this has been done the space can | 3273 // Sweep a space precisely. After this has been done the space can |
3274 // be iterated precisely, hitting only the live objects. Code space | 3274 // be iterated precisely, hitting only the live objects. Code space |
3275 // is always swept precisely because we want to be able to iterate | 3275 // is always swept precisely because we want to be able to iterate |
3276 // over it. Map space is swept precisely, because it is not compacted. | 3276 // over it. Map space is swept precisely, because it is not compacted. |
3277 // Slots in live objects pointing into evacuation candidates are updated | 3277 // Slots in live objects pointing into evacuation candidates are updated |
3278 // if requested. | 3278 // if requested. |
3279 // Returns the size of the biggest continuous freed memory chunk in bytes. | 3279 // Returns the size of the biggest continuous freed memory chunk in bytes. |
3280 template<SweepingMode sweeping_mode, | 3280 template<SweepingMode sweeping_mode, |
3281 MarkCompactCollector::SweepingParallelism parallelism, | 3281 MarkCompactCollector::SweepingParallelism parallelism, |
3282 SkipListRebuildingMode skip_list_mode, | 3282 SkipListRebuildingMode skip_list_mode, |
3283 FreeSpaceTreatmentMode free_space_mode> | 3283 FreeSpaceTreatmentMode free_space_mode> |
3284 static int SweepPrecisely(PagedSpace* space, | 3284 static int SweepPrecisely(PagedSpace* space, |
3285 FreeList* free_list, | 3285 FreeList* free_list, |
3286 Page* p, | 3286 Page* p, |
3287 ObjectVisitor* v) { | 3287 ObjectVisitor* v) { |
3288 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 3288 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept()); |
3289 ASSERT_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3289 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
3290 space->identity() == CODE_SPACE); | 3290 space->identity() == CODE_SPACE); |
3291 ASSERT((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3291 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
3292 ASSERT(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || | 3292 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || |
3293 sweeping_mode == SWEEP_ONLY); | 3293 sweeping_mode == SWEEP_ONLY); |
3294 | 3294 |
3295 Address free_start = p->area_start(); | 3295 Address free_start = p->area_start(); |
3296 ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3296 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
3297 int offsets[16]; | 3297 int offsets[16]; |
3298 | 3298 |
3299 SkipList* skip_list = p->skip_list(); | 3299 SkipList* skip_list = p->skip_list(); |
3300 int curr_region = -1; | 3300 int curr_region = -1; |
3301 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { | 3301 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list) { |
3302 skip_list->Clear(); | 3302 skip_list->Clear(); |
3303 } | 3303 } |
3304 | 3304 |
3305 intptr_t freed_bytes = 0; | 3305 intptr_t freed_bytes = 0; |
3306 intptr_t max_freed_bytes = 0; | 3306 intptr_t max_freed_bytes = 0; |
(...skipping 12 matching lines...) Expand all Loading... |
3319 } | 3319 } |
3320 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3320 freed_bytes = Free<parallelism>(space, free_list, free_start, size); |
3321 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3321 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
3322 #ifdef ENABLE_GDB_JIT_INTERFACE | 3322 #ifdef ENABLE_GDB_JIT_INTERFACE |
3323 if (FLAG_gdbjit && space->identity() == CODE_SPACE) { | 3323 if (FLAG_gdbjit && space->identity() == CODE_SPACE) { |
3324 GDBJITInterface::RemoveCodeRange(free_start, free_end); | 3324 GDBJITInterface::RemoveCodeRange(free_start, free_end); |
3325 } | 3325 } |
3326 #endif | 3326 #endif |
3327 } | 3327 } |
3328 HeapObject* live_object = HeapObject::FromAddress(free_end); | 3328 HeapObject* live_object = HeapObject::FromAddress(free_end); |
3329 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); | 3329 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(live_object))); |
3330 Map* map = live_object->map(); | 3330 Map* map = live_object->map(); |
3331 int size = live_object->SizeFromMap(map); | 3331 int size = live_object->SizeFromMap(map); |
3332 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { | 3332 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { |
3333 live_object->IterateBody(map->instance_type(), size, v); | 3333 live_object->IterateBody(map->instance_type(), size, v); |
3334 } | 3334 } |
3335 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { | 3335 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { |
3336 int new_region_start = | 3336 int new_region_start = |
3337 SkipList::RegionNumber(free_end); | 3337 SkipList::RegionNumber(free_end); |
3338 int new_region_end = | 3338 int new_region_end = |
3339 SkipList::RegionNumber(free_end + size - kPointerSize); | 3339 SkipList::RegionNumber(free_end + size - kPointerSize); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3435 MarkBit mark_bit = | 3435 MarkBit mark_bit = |
3436 p->markbits()->MarkBitFromIndex(Page::FastAddressToMarkbitIndex(addr)); | 3436 p->markbits()->MarkBitFromIndex(Page::FastAddressToMarkbitIndex(addr)); |
3437 | 3437 |
3438 return mark_bit.Get(); | 3438 return mark_bit.Get(); |
3439 } | 3439 } |
3440 | 3440 |
3441 | 3441 |
3442 void MarkCompactCollector::InvalidateCode(Code* code) { | 3442 void MarkCompactCollector::InvalidateCode(Code* code) { |
3443 if (heap_->incremental_marking()->IsCompacting() && | 3443 if (heap_->incremental_marking()->IsCompacting() && |
3444 !ShouldSkipEvacuationSlotRecording(code)) { | 3444 !ShouldSkipEvacuationSlotRecording(code)) { |
3445 ASSERT(compacting_); | 3445 DCHECK(compacting_); |
3446 | 3446 |
3447 // If the object is white than no slots were recorded on it yet. | 3447 // If the object is white than no slots were recorded on it yet. |
3448 MarkBit mark_bit = Marking::MarkBitFrom(code); | 3448 MarkBit mark_bit = Marking::MarkBitFrom(code); |
3449 if (Marking::IsWhite(mark_bit)) return; | 3449 if (Marking::IsWhite(mark_bit)) return; |
3450 | 3450 |
3451 invalidated_code_.Add(code); | 3451 invalidated_code_.Add(code); |
3452 } | 3452 } |
3453 } | 3453 } |
3454 | 3454 |
3455 | 3455 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3569 } | 3569 } |
3570 } | 3570 } |
3571 } | 3571 } |
3572 } | 3572 } |
3573 | 3573 |
3574 int npages = evacuation_candidates_.length(); | 3574 int npages = evacuation_candidates_.length(); |
3575 { GCTracer::Scope gc_scope( | 3575 { GCTracer::Scope gc_scope( |
3576 heap()->tracer(), GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); | 3576 heap()->tracer(), GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); |
3577 for (int i = 0; i < npages; i++) { | 3577 for (int i = 0; i < npages; i++) { |
3578 Page* p = evacuation_candidates_[i]; | 3578 Page* p = evacuation_candidates_[i]; |
3579 ASSERT(p->IsEvacuationCandidate() || | 3579 DCHECK(p->IsEvacuationCandidate() || |
3580 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | 3580 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); |
3581 | 3581 |
3582 if (p->IsEvacuationCandidate()) { | 3582 if (p->IsEvacuationCandidate()) { |
3583 SlotsBuffer::UpdateSlotsRecordedIn(heap_, | 3583 SlotsBuffer::UpdateSlotsRecordedIn(heap_, |
3584 p->slots_buffer(), | 3584 p->slots_buffer(), |
3585 code_slots_filtering_required); | 3585 code_slots_filtering_required); |
3586 if (FLAG_trace_fragmentation) { | 3586 if (FLAG_trace_fragmentation) { |
3587 PrintF(" page %p slots buffer: %d\n", | 3587 PrintF(" page %p slots buffer: %d\n", |
3588 reinterpret_cast<void*>(p), | 3588 reinterpret_cast<void*>(p), |
3589 SlotsBuffer::SizeOfChain(p->slots_buffer())); | 3589 SlotsBuffer::SizeOfChain(p->slots_buffer())); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3675 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3675 EvacuationWeakObjectRetainer evacuation_object_retainer; |
3676 heap()->ProcessWeakReferences(&evacuation_object_retainer); | 3676 heap()->ProcessWeakReferences(&evacuation_object_retainer); |
3677 | 3677 |
3678 // Visit invalidated code (we ignored all slots on it) and clear mark-bits | 3678 // Visit invalidated code (we ignored all slots on it) and clear mark-bits |
3679 // under it. | 3679 // under it. |
3680 ProcessInvalidatedCode(&updating_visitor); | 3680 ProcessInvalidatedCode(&updating_visitor); |
3681 | 3681 |
3682 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); | 3682 heap_->isolate()->inner_pointer_to_code_cache()->Flush(); |
3683 | 3683 |
3684 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); | 3684 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); |
3685 ASSERT(migration_slots_buffer_ == NULL); | 3685 DCHECK(migration_slots_buffer_ == NULL); |
3686 } | 3686 } |
3687 | 3687 |
3688 | 3688 |
3689 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { | 3689 void MarkCompactCollector::MoveEvacuationCandidatesToEndOfPagesList() { |
3690 int npages = evacuation_candidates_.length(); | 3690 int npages = evacuation_candidates_.length(); |
3691 for (int i = 0; i < npages; i++) { | 3691 for (int i = 0; i < npages; i++) { |
3692 Page* p = evacuation_candidates_[i]; | 3692 Page* p = evacuation_candidates_[i]; |
3693 if (!p->IsEvacuationCandidate()) continue; | 3693 if (!p->IsEvacuationCandidate()) continue; |
3694 p->Unlink(); | 3694 p->Unlink(); |
3695 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3695 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3909 #undef X | 3909 #undef X |
3910 | 3910 |
3911 | 3911 |
3912 // Takes a word of mark bits. Returns the number of objects that start in the | 3912 // Takes a word of mark bits. Returns the number of objects that start in the |
3913 // range. Puts the offsets of the words in the supplied array. | 3913 // range. Puts the offsets of the words in the supplied array. |
3914 static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts) { | 3914 static inline int MarkWordToObjectStarts(uint32_t mark_bits, int* starts) { |
3915 int objects = 0; | 3915 int objects = 0; |
3916 int offset = 0; | 3916 int offset = 0; |
3917 | 3917 |
3918 // No consecutive 1 bits. | 3918 // No consecutive 1 bits. |
3919 ASSERT((mark_bits & 0x180) != 0x180); | 3919 DCHECK((mark_bits & 0x180) != 0x180); |
3920 ASSERT((mark_bits & 0x18000) != 0x18000); | 3920 DCHECK((mark_bits & 0x18000) != 0x18000); |
3921 ASSERT((mark_bits & 0x1800000) != 0x1800000); | 3921 DCHECK((mark_bits & 0x1800000) != 0x1800000); |
3922 | 3922 |
3923 while (mark_bits != 0) { | 3923 while (mark_bits != 0) { |
3924 int byte = (mark_bits & 0xff); | 3924 int byte = (mark_bits & 0xff); |
3925 mark_bits >>= 8; | 3925 mark_bits >>= 8; |
3926 if (byte != 0) { | 3926 if (byte != 0) { |
3927 ASSERT(byte < kStartTableLines); // No consecutive 1 bits. | 3927 DCHECK(byte < kStartTableLines); // No consecutive 1 bits. |
3928 char* table = kStartTable + byte * kStartTableEntriesPerLine; | 3928 char* table = kStartTable + byte * kStartTableEntriesPerLine; |
3929 int objects_in_these_8_words = table[0]; | 3929 int objects_in_these_8_words = table[0]; |
3930 ASSERT(objects_in_these_8_words != kStartTableInvalidLine); | 3930 DCHECK(objects_in_these_8_words != kStartTableInvalidLine); |
3931 ASSERT(objects_in_these_8_words < kStartTableEntriesPerLine); | 3931 DCHECK(objects_in_these_8_words < kStartTableEntriesPerLine); |
3932 for (int i = 0; i < objects_in_these_8_words; i++) { | 3932 for (int i = 0; i < objects_in_these_8_words; i++) { |
3933 starts[objects++] = offset + table[1 + i]; | 3933 starts[objects++] = offset + table[1 + i]; |
3934 } | 3934 } |
3935 } | 3935 } |
3936 offset += 8; | 3936 offset += 8; |
3937 } | 3937 } |
3938 return objects; | 3938 return objects; |
3939 } | 3939 } |
3940 | 3940 |
3941 | 3941 |
3942 static inline Address DigestFreeStart(Address approximate_free_start, | 3942 static inline Address DigestFreeStart(Address approximate_free_start, |
3943 uint32_t free_start_cell) { | 3943 uint32_t free_start_cell) { |
3944 ASSERT(free_start_cell != 0); | 3944 DCHECK(free_start_cell != 0); |
3945 | 3945 |
3946 // No consecutive 1 bits. | 3946 // No consecutive 1 bits. |
3947 ASSERT((free_start_cell & (free_start_cell << 1)) == 0); | 3947 DCHECK((free_start_cell & (free_start_cell << 1)) == 0); |
3948 | 3948 |
3949 int offsets[16]; | 3949 int offsets[16]; |
3950 uint32_t cell = free_start_cell; | 3950 uint32_t cell = free_start_cell; |
3951 int offset_of_last_live; | 3951 int offset_of_last_live; |
3952 if ((cell & 0x80000000u) != 0) { | 3952 if ((cell & 0x80000000u) != 0) { |
3953 // This case would overflow below. | 3953 // This case would overflow below. |
3954 offset_of_last_live = 31; | 3954 offset_of_last_live = 31; |
3955 } else { | 3955 } else { |
3956 // Remove all but one bit, the most significant. This is an optimization | 3956 // Remove all but one bit, the most significant. This is an optimization |
3957 // that may or may not be worthwhile. | 3957 // that may or may not be worthwhile. |
3958 cell |= cell >> 16; | 3958 cell |= cell >> 16; |
3959 cell |= cell >> 8; | 3959 cell |= cell >> 8; |
3960 cell |= cell >> 4; | 3960 cell |= cell >> 4; |
3961 cell |= cell >> 2; | 3961 cell |= cell >> 2; |
3962 cell |= cell >> 1; | 3962 cell |= cell >> 1; |
3963 cell = (cell + 1) >> 1; | 3963 cell = (cell + 1) >> 1; |
3964 int live_objects = MarkWordToObjectStarts(cell, offsets); | 3964 int live_objects = MarkWordToObjectStarts(cell, offsets); |
3965 ASSERT(live_objects == 1); | 3965 DCHECK(live_objects == 1); |
3966 offset_of_last_live = offsets[live_objects - 1]; | 3966 offset_of_last_live = offsets[live_objects - 1]; |
3967 } | 3967 } |
3968 Address last_live_start = | 3968 Address last_live_start = |
3969 approximate_free_start + offset_of_last_live * kPointerSize; | 3969 approximate_free_start + offset_of_last_live * kPointerSize; |
3970 HeapObject* last_live = HeapObject::FromAddress(last_live_start); | 3970 HeapObject* last_live = HeapObject::FromAddress(last_live_start); |
3971 Address free_start = last_live_start + last_live->Size(); | 3971 Address free_start = last_live_start + last_live->Size(); |
3972 return free_start; | 3972 return free_start; |
3973 } | 3973 } |
3974 | 3974 |
3975 | 3975 |
3976 static inline Address StartOfLiveObject(Address block_address, uint32_t cell) { | 3976 static inline Address StartOfLiveObject(Address block_address, uint32_t cell) { |
3977 ASSERT(cell != 0); | 3977 DCHECK(cell != 0); |
3978 | 3978 |
3979 // No consecutive 1 bits. | 3979 // No consecutive 1 bits. |
3980 ASSERT((cell & (cell << 1)) == 0); | 3980 DCHECK((cell & (cell << 1)) == 0); |
3981 | 3981 |
3982 int offsets[16]; | 3982 int offsets[16]; |
3983 if (cell == 0x80000000u) { // Avoid overflow below. | 3983 if (cell == 0x80000000u) { // Avoid overflow below. |
3984 return block_address + 31 * kPointerSize; | 3984 return block_address + 31 * kPointerSize; |
3985 } | 3985 } |
3986 uint32_t first_set_bit = ((cell ^ (cell - 1)) + 1) >> 1; | 3986 uint32_t first_set_bit = ((cell ^ (cell - 1)) + 1) >> 1; |
3987 ASSERT((first_set_bit & cell) == first_set_bit); | 3987 DCHECK((first_set_bit & cell) == first_set_bit); |
3988 int live_objects = MarkWordToObjectStarts(first_set_bit, offsets); | 3988 int live_objects = MarkWordToObjectStarts(first_set_bit, offsets); |
3989 ASSERT(live_objects == 1); | 3989 DCHECK(live_objects == 1); |
3990 USE(live_objects); | 3990 USE(live_objects); |
3991 return block_address + offsets[0] * kPointerSize; | 3991 return block_address + offsets[0] * kPointerSize; |
3992 } | 3992 } |
3993 | 3993 |
3994 | 3994 |
3995 // Force instantiation of templatized SweepConservatively method for | 3995 // Force instantiation of templatized SweepConservatively method for |
3996 // SWEEP_ON_MAIN_THREAD mode. | 3996 // SWEEP_ON_MAIN_THREAD mode. |
3997 template int MarkCompactCollector:: | 3997 template int MarkCompactCollector:: |
3998 SweepConservatively<MarkCompactCollector::SWEEP_ON_MAIN_THREAD>( | 3998 SweepConservatively<MarkCompactCollector::SWEEP_ON_MAIN_THREAD>( |
3999 PagedSpace*, FreeList*, Page*); | 3999 PagedSpace*, FreeList*, Page*); |
(...skipping 10 matching lines...) Expand all Loading... |
4010 // spaces have been put on the free list and the smaller ones have been | 4010 // spaces have been put on the free list and the smaller ones have been |
4011 // ignored and left untouched. A free space is always either ignored or put | 4011 // ignored and left untouched. A free space is always either ignored or put |
4012 // on the free list, never split up into two parts. This is important | 4012 // on the free list, never split up into two parts. This is important |
4013 // because it means that any FreeSpace maps left actually describe a region of | 4013 // because it means that any FreeSpace maps left actually describe a region of |
4014 // memory that can be ignored when scanning. Dead objects other than free | 4014 // memory that can be ignored when scanning. Dead objects other than free |
4015 // spaces will not contain the free space map. | 4015 // spaces will not contain the free space map. |
4016 template<MarkCompactCollector::SweepingParallelism mode> | 4016 template<MarkCompactCollector::SweepingParallelism mode> |
4017 int MarkCompactCollector::SweepConservatively(PagedSpace* space, | 4017 int MarkCompactCollector::SweepConservatively(PagedSpace* space, |
4018 FreeList* free_list, | 4018 FreeList* free_list, |
4019 Page* p) { | 4019 Page* p) { |
4020 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); | 4020 DCHECK(!p->IsEvacuationCandidate() && !p->WasSwept()); |
4021 ASSERT((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && | 4021 DCHECK((mode == MarkCompactCollector::SWEEP_IN_PARALLEL && |
4022 free_list != NULL) || | 4022 free_list != NULL) || |
4023 (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD && | 4023 (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD && |
4024 free_list == NULL)); | 4024 free_list == NULL)); |
4025 | 4025 |
4026 intptr_t freed_bytes = 0; | 4026 intptr_t freed_bytes = 0; |
4027 intptr_t max_freed_bytes = 0; | 4027 intptr_t max_freed_bytes = 0; |
4028 size_t size = 0; | 4028 size_t size = 0; |
4029 | 4029 |
4030 // Skip over all the dead objects at the start of the page and mark them free. | 4030 // Skip over all the dead objects at the start of the page and mark them free. |
4031 Address cell_base = 0; | 4031 Address cell_base = 0; |
4032 MarkBit::CellType* cell = NULL; | 4032 MarkBit::CellType* cell = NULL; |
4033 MarkBitCellIterator it(p); | 4033 MarkBitCellIterator it(p); |
4034 for (; !it.Done(); it.Advance()) { | 4034 for (; !it.Done(); it.Advance()) { |
4035 cell_base = it.CurrentCellBase(); | 4035 cell_base = it.CurrentCellBase(); |
4036 cell = it.CurrentCell(); | 4036 cell = it.CurrentCell(); |
4037 if (*cell != 0) break; | 4037 if (*cell != 0) break; |
4038 } | 4038 } |
4039 | 4039 |
4040 if (it.Done()) { | 4040 if (it.Done()) { |
4041 size = p->area_end() - p->area_start(); | 4041 size = p->area_end() - p->area_start(); |
4042 freed_bytes = Free<mode>(space, free_list, p->area_start(), | 4042 freed_bytes = Free<mode>(space, free_list, p->area_start(), |
4043 static_cast<int>(size)); | 4043 static_cast<int>(size)); |
4044 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 4044 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
4045 ASSERT_EQ(0, p->LiveBytes()); | 4045 DCHECK_EQ(0, p->LiveBytes()); |
4046 if (mode == MarkCompactCollector::SWEEP_IN_PARALLEL) { | 4046 if (mode == MarkCompactCollector::SWEEP_IN_PARALLEL) { |
4047 // When concurrent sweeping is active, the page will be marked after | 4047 // When concurrent sweeping is active, the page will be marked after |
4048 // sweeping by the main thread. | 4048 // sweeping by the main thread. |
4049 p->set_parallel_sweeping(MemoryChunk::SWEEPING_FINALIZE); | 4049 p->set_parallel_sweeping(MemoryChunk::SWEEPING_FINALIZE); |
4050 } else { | 4050 } else { |
4051 p->MarkSweptConservatively(); | 4051 p->MarkSweptConservatively(); |
4052 } | 4052 } |
4053 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 4053 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
4054 } | 4054 } |
4055 | 4055 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4119 | 4119 |
4120 | 4120 |
4121 int MarkCompactCollector::SweepInParallel(PagedSpace* space, | 4121 int MarkCompactCollector::SweepInParallel(PagedSpace* space, |
4122 int required_freed_bytes) { | 4122 int required_freed_bytes) { |
4123 int max_freed = 0; | 4123 int max_freed = 0; |
4124 int max_freed_overall = 0; | 4124 int max_freed_overall = 0; |
4125 PageIterator it(space); | 4125 PageIterator it(space); |
4126 while (it.has_next()) { | 4126 while (it.has_next()) { |
4127 Page* p = it.next(); | 4127 Page* p = it.next(); |
4128 max_freed = SweepInParallel(p, space); | 4128 max_freed = SweepInParallel(p, space); |
4129 ASSERT(max_freed >= 0); | 4129 DCHECK(max_freed >= 0); |
4130 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { | 4130 if (required_freed_bytes > 0 && max_freed >= required_freed_bytes) { |
4131 return max_freed; | 4131 return max_freed; |
4132 } | 4132 } |
4133 max_freed_overall = Max(max_freed, max_freed_overall); | 4133 max_freed_overall = Max(max_freed, max_freed_overall); |
4134 if (p == space->end_of_unswept_pages()) break; | 4134 if (p == space->end_of_unswept_pages()) break; |
4135 } | 4135 } |
4136 return max_freed_overall; | 4136 return max_freed_overall; |
4137 } | 4137 } |
4138 | 4138 |
4139 | 4139 |
(...skipping 29 matching lines...) Expand all Loading... |
4169 space->set_end_of_unswept_pages(space->FirstPage()); | 4169 space->set_end_of_unswept_pages(space->FirstPage()); |
4170 | 4170 |
4171 PageIterator it(space); | 4171 PageIterator it(space); |
4172 | 4172 |
4173 int pages_swept = 0; | 4173 int pages_swept = 0; |
4174 bool unused_page_present = false; | 4174 bool unused_page_present = false; |
4175 bool parallel_sweeping_active = false; | 4175 bool parallel_sweeping_active = false; |
4176 | 4176 |
4177 while (it.has_next()) { | 4177 while (it.has_next()) { |
4178 Page* p = it.next(); | 4178 Page* p = it.next(); |
4179 ASSERT(p->parallel_sweeping() == MemoryChunk::SWEEPING_DONE); | 4179 DCHECK(p->parallel_sweeping() == MemoryChunk::SWEEPING_DONE); |
4180 | 4180 |
4181 // Clear sweeping flags indicating that marking bits are still intact. | 4181 // Clear sweeping flags indicating that marking bits are still intact. |
4182 p->ClearSweptPrecisely(); | 4182 p->ClearSweptPrecisely(); |
4183 p->ClearSweptConservatively(); | 4183 p->ClearSweptConservatively(); |
4184 | 4184 |
4185 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || | 4185 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION) || |
4186 p->IsEvacuationCandidate()) { | 4186 p->IsEvacuationCandidate()) { |
4187 // Will be processed in EvacuateNewSpaceAndCandidates. | 4187 // Will be processed in EvacuateNewSpaceAndCandidates. |
4188 ASSERT(evacuation_candidates_.length() > 0); | 4188 DCHECK(evacuation_candidates_.length() > 0); |
4189 continue; | 4189 continue; |
4190 } | 4190 } |
4191 | 4191 |
4192 // One unused page is kept, all further are released before sweeping them. | 4192 // One unused page is kept, all further are released before sweeping them. |
4193 if (p->LiveBytes() == 0) { | 4193 if (p->LiveBytes() == 0) { |
4194 if (unused_page_present) { | 4194 if (unused_page_present) { |
4195 if (FLAG_gc_verbose) { | 4195 if (FLAG_gc_verbose) { |
4196 PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", | 4196 PrintF("Sweeping 0x%" V8PRIxPTR " released page.\n", |
4197 reinterpret_cast<intptr_t>(p)); | 4197 reinterpret_cast<intptr_t>(p)); |
4198 } | 4198 } |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4390 while (it.has_next()) { | 4390 while (it.has_next()) { |
4391 Page* p = it.next(); | 4391 Page* p = it.next(); |
4392 if (p->parallel_sweeping() == MemoryChunk::SWEEPING_FINALIZE) { | 4392 if (p->parallel_sweeping() == MemoryChunk::SWEEPING_FINALIZE) { |
4393 p->set_parallel_sweeping(MemoryChunk::SWEEPING_DONE); | 4393 p->set_parallel_sweeping(MemoryChunk::SWEEPING_DONE); |
4394 if (space->swept_precisely()) { | 4394 if (space->swept_precisely()) { |
4395 p->MarkSweptPrecisely(); | 4395 p->MarkSweptPrecisely(); |
4396 } else { | 4396 } else { |
4397 p->MarkSweptConservatively(); | 4397 p->MarkSweptConservatively(); |
4398 } | 4398 } |
4399 } | 4399 } |
4400 ASSERT(p->parallel_sweeping() == MemoryChunk::SWEEPING_DONE); | 4400 DCHECK(p->parallel_sweeping() == MemoryChunk::SWEEPING_DONE); |
4401 } | 4401 } |
4402 } | 4402 } |
4403 | 4403 |
4404 | 4404 |
4405 void MarkCompactCollector::ParallelSweepSpacesComplete() { | 4405 void MarkCompactCollector::ParallelSweepSpacesComplete() { |
4406 ParallelSweepSpaceComplete(heap()->old_pointer_space()); | 4406 ParallelSweepSpaceComplete(heap()->old_pointer_space()); |
4407 ParallelSweepSpaceComplete(heap()->old_data_space()); | 4407 ParallelSweepSpaceComplete(heap()->old_data_space()); |
4408 } | 4408 } |
4409 | 4409 |
4410 | 4410 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4464 AdditionMode mode) { | 4464 AdditionMode mode) { |
4465 SlotsBuffer* buffer = *buffer_address; | 4465 SlotsBuffer* buffer = *buffer_address; |
4466 if (buffer == NULL || !buffer->HasSpaceForTypedSlot()) { | 4466 if (buffer == NULL || !buffer->HasSpaceForTypedSlot()) { |
4467 if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) { | 4467 if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) { |
4468 allocator->DeallocateChain(buffer_address); | 4468 allocator->DeallocateChain(buffer_address); |
4469 return false; | 4469 return false; |
4470 } | 4470 } |
4471 buffer = allocator->AllocateBuffer(buffer); | 4471 buffer = allocator->AllocateBuffer(buffer); |
4472 *buffer_address = buffer; | 4472 *buffer_address = buffer; |
4473 } | 4473 } |
4474 ASSERT(buffer->HasSpaceForTypedSlot()); | 4474 DCHECK(buffer->HasSpaceForTypedSlot()); |
4475 buffer->Add(reinterpret_cast<ObjectSlot>(type)); | 4475 buffer->Add(reinterpret_cast<ObjectSlot>(type)); |
4476 buffer->Add(reinterpret_cast<ObjectSlot>(addr)); | 4476 buffer->Add(reinterpret_cast<ObjectSlot>(addr)); |
4477 return true; | 4477 return true; |
4478 } | 4478 } |
4479 | 4479 |
4480 | 4480 |
4481 static inline SlotsBuffer::SlotType SlotTypeForRMode(RelocInfo::Mode rmode) { | 4481 static inline SlotsBuffer::SlotType SlotTypeForRMode(RelocInfo::Mode rmode) { |
4482 if (RelocInfo::IsCodeTarget(rmode)) { | 4482 if (RelocInfo::IsCodeTarget(rmode)) { |
4483 return SlotsBuffer::CODE_TARGET_SLOT; | 4483 return SlotsBuffer::CODE_TARGET_SLOT; |
4484 } else if (RelocInfo::IsEmbeddedObject(rmode)) { | 4484 } else if (RelocInfo::IsEmbeddedObject(rmode)) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4537 SlotsBuffer::CODE_ENTRY_SLOT, | 4537 SlotsBuffer::CODE_ENTRY_SLOT, |
4538 slot, | 4538 slot, |
4539 SlotsBuffer::FAIL_ON_OVERFLOW)) { | 4539 SlotsBuffer::FAIL_ON_OVERFLOW)) { |
4540 EvictEvacuationCandidate(target_page); | 4540 EvictEvacuationCandidate(target_page); |
4541 } | 4541 } |
4542 } | 4542 } |
4543 } | 4543 } |
4544 | 4544 |
4545 | 4545 |
4546 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { | 4546 void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) { |
4547 ASSERT(heap()->gc_state() == Heap::MARK_COMPACT); | 4547 DCHECK(heap()->gc_state() == Heap::MARK_COMPACT); |
4548 if (is_compacting()) { | 4548 if (is_compacting()) { |
4549 Code* host = isolate()->inner_pointer_to_code_cache()-> | 4549 Code* host = isolate()->inner_pointer_to_code_cache()-> |
4550 GcSafeFindCodeForInnerPointer(pc); | 4550 GcSafeFindCodeForInnerPointer(pc); |
4551 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4551 MarkBit mark_bit = Marking::MarkBitFrom(host); |
4552 if (Marking::IsBlack(mark_bit)) { | 4552 if (Marking::IsBlack(mark_bit)) { |
4553 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); | 4553 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); |
4554 RecordRelocSlot(&rinfo, target); | 4554 RecordRelocSlot(&rinfo, target); |
4555 } | 4555 } |
4556 } | 4556 } |
4557 } | 4557 } |
4558 | 4558 |
4559 | 4559 |
4560 static inline SlotsBuffer::SlotType DecodeSlotType( | 4560 static inline SlotsBuffer::SlotType DecodeSlotType( |
4561 SlotsBuffer::ObjectSlot slot) { | 4561 SlotsBuffer::ObjectSlot slot) { |
4562 return static_cast<SlotsBuffer::SlotType>(reinterpret_cast<intptr_t>(slot)); | 4562 return static_cast<SlotsBuffer::SlotType>(reinterpret_cast<intptr_t>(slot)); |
4563 } | 4563 } |
4564 | 4564 |
4565 | 4565 |
4566 void SlotsBuffer::UpdateSlots(Heap* heap) { | 4566 void SlotsBuffer::UpdateSlots(Heap* heap) { |
4567 PointersUpdatingVisitor v(heap); | 4567 PointersUpdatingVisitor v(heap); |
4568 | 4568 |
4569 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { | 4569 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { |
4570 ObjectSlot slot = slots_[slot_idx]; | 4570 ObjectSlot slot = slots_[slot_idx]; |
4571 if (!IsTypedSlot(slot)) { | 4571 if (!IsTypedSlot(slot)) { |
4572 PointersUpdatingVisitor::UpdateSlot(heap, slot); | 4572 PointersUpdatingVisitor::UpdateSlot(heap, slot); |
4573 } else { | 4573 } else { |
4574 ++slot_idx; | 4574 ++slot_idx; |
4575 ASSERT(slot_idx < idx_); | 4575 DCHECK(slot_idx < idx_); |
4576 UpdateSlot(heap->isolate(), | 4576 UpdateSlot(heap->isolate(), |
4577 &v, | 4577 &v, |
4578 DecodeSlotType(slot), | 4578 DecodeSlotType(slot), |
4579 reinterpret_cast<Address>(slots_[slot_idx])); | 4579 reinterpret_cast<Address>(slots_[slot_idx])); |
4580 } | 4580 } |
4581 } | 4581 } |
4582 } | 4582 } |
4583 | 4583 |
4584 | 4584 |
4585 void SlotsBuffer::UpdateSlotsWithFilter(Heap* heap) { | 4585 void SlotsBuffer::UpdateSlotsWithFilter(Heap* heap) { |
4586 PointersUpdatingVisitor v(heap); | 4586 PointersUpdatingVisitor v(heap); |
4587 | 4587 |
4588 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { | 4588 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { |
4589 ObjectSlot slot = slots_[slot_idx]; | 4589 ObjectSlot slot = slots_[slot_idx]; |
4590 if (!IsTypedSlot(slot)) { | 4590 if (!IsTypedSlot(slot)) { |
4591 if (!IsOnInvalidatedCodeObject(reinterpret_cast<Address>(slot))) { | 4591 if (!IsOnInvalidatedCodeObject(reinterpret_cast<Address>(slot))) { |
4592 PointersUpdatingVisitor::UpdateSlot(heap, slot); | 4592 PointersUpdatingVisitor::UpdateSlot(heap, slot); |
4593 } | 4593 } |
4594 } else { | 4594 } else { |
4595 ++slot_idx; | 4595 ++slot_idx; |
4596 ASSERT(slot_idx < idx_); | 4596 DCHECK(slot_idx < idx_); |
4597 Address pc = reinterpret_cast<Address>(slots_[slot_idx]); | 4597 Address pc = reinterpret_cast<Address>(slots_[slot_idx]); |
4598 if (!IsOnInvalidatedCodeObject(pc)) { | 4598 if (!IsOnInvalidatedCodeObject(pc)) { |
4599 UpdateSlot(heap->isolate(), | 4599 UpdateSlot(heap->isolate(), |
4600 &v, | 4600 &v, |
4601 DecodeSlotType(slot), | 4601 DecodeSlotType(slot), |
4602 reinterpret_cast<Address>(slots_[slot_idx])); | 4602 reinterpret_cast<Address>(slots_[slot_idx])); |
4603 } | 4603 } |
4604 } | 4604 } |
4605 } | 4605 } |
4606 } | 4606 } |
(...skipping 14 matching lines...) Expand all Loading... |
4621 while (buffer != NULL) { | 4621 while (buffer != NULL) { |
4622 SlotsBuffer* next_buffer = buffer->next(); | 4622 SlotsBuffer* next_buffer = buffer->next(); |
4623 DeallocateBuffer(buffer); | 4623 DeallocateBuffer(buffer); |
4624 buffer = next_buffer; | 4624 buffer = next_buffer; |
4625 } | 4625 } |
4626 *buffer_address = NULL; | 4626 *buffer_address = NULL; |
4627 } | 4627 } |
4628 | 4628 |
4629 | 4629 |
4630 } } // namespace v8::internal | 4630 } } // namespace v8::internal |
OLD | NEW |