Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
| 6 | 6 |
| 7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
| 8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
| 9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 2854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2865 Object** p) { | 2865 Object** p) { |
| 2866 MapWord map_word = HeapObject::cast(*p)->map_word(); | 2866 MapWord map_word = HeapObject::cast(*p)->map_word(); |
| 2867 | 2867 |
| 2868 if (map_word.IsForwardingAddress()) { | 2868 if (map_word.IsForwardingAddress()) { |
| 2869 return String::cast(map_word.ToForwardingAddress()); | 2869 return String::cast(map_word.ToForwardingAddress()); |
| 2870 } | 2870 } |
| 2871 | 2871 |
| 2872 return String::cast(*p); | 2872 return String::cast(*p); |
| 2873 } | 2873 } |
| 2874 | 2874 |
| 2875 bool MarkCompactCollector::IsSlotInBlackObject(MemoryChunk* p, Address slot) { | |
|
Michael Lippautz
2016/10/20 16:28:24
I would like to express my deepest gratitude for d
Hannes Payer (out of office)
2016/10/21 07:13:29
Drinks are on you :D
| |
| 2876 Space* owner = p->owner(); | |
| 2877 DCHECK(owner != heap_->lo_space() && owner != nullptr); | |
| 2878 USE(owner); | |
| 2879 | |
| 2880 // We may be part of a black area. | |
| 2881 if (Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(slot))) { | |
| 2882 return true; | |
| 2883 } | |
| 2884 | |
| 2885 uint32_t mark_bit_index = p->AddressToMarkbitIndex(slot); | |
| 2886 unsigned int cell_index = mark_bit_index >> Bitmap::kBitsPerCellLog2; | |
| 2887 MarkBit::CellType index_mask = 1u << Bitmap::IndexInCell(mark_bit_index); | |
| 2888 MarkBit::CellType* cells = p->markbits()->cells(); | |
| 2889 Address base_address = p->area_start(); | |
| 2890 unsigned int base_address_cell_index = Bitmap::IndexToCell( | |
| 2891 Bitmap::CellAlignIndex(p->AddressToMarkbitIndex(base_address))); | |
| 2892 | |
| 2893 // Check if the slot points to the start of an object. This can happen e.g. | |
| 2894 // when we left trim a fixed array. Such slots are invalid and we can remove | |
| 2895 // them. | |
| 2896 if (index_mask > 1) { | |
| 2897 if ((cells[cell_index] & index_mask) != 0 && | |
| 2898 (cells[cell_index] & (index_mask >> 1)) == 0) { | |
| 2899 return false; | |
| 2900 } | |
| 2901 } else { | |
| 2902 // Left trimming moves the mark bits so we cannot be in the very first cell. | |
| 2903 DCHECK(cell_index != base_address_cell_index); | |
| 2904 if ((cells[cell_index] & index_mask) != 0 && | |
| 2905 (cells[cell_index - 1] & (1u << Bitmap::kBitIndexMask)) == 0) { | |
| 2906 return false; | |
| 2907 } | |
| 2908 } | |
| 2909 | |
| 2910 // Check if the object is in the current cell. | |
| 2911 MarkBit::CellType slot_mask; | |
| 2912 if ((cells[cell_index] == 0) || | |
| 2913 (base::bits::CountTrailingZeros32(cells[cell_index]) > | |
| 2914 base::bits::CountTrailingZeros32(cells[cell_index] | index_mask))) { | |
| 2915 // If we are already in the first cell, there is no live object. | |
| 2916 if (cell_index == base_address_cell_index) return false; | |
| 2917 | |
| 2918 // If not, find a cell in a preceding cell slot that has a mark bit set. | |
| 2919 do { | |
| 2920 cell_index--; | |
| 2921 } while (cell_index > base_address_cell_index && cells[cell_index] == 0); | |
| 2922 | |
| 2923 // The slot must be in a dead object if there are no preceding cells that | |
| 2924 // have mark bits set. | |
| 2925 if (cells[cell_index] == 0) { | |
| 2926 return false; | |
| 2927 } | |
| 2928 | |
| 2929 // The object is in a preceding cell. Set the mask to find any object. | |
| 2930 slot_mask = ~0u; | |
| 2931 } else { | |
| 2932 // We are interested in object mark bits right before the slot. | |
| 2933 slot_mask = index_mask + (index_mask - 1); | |
| 2934 } | |
| 2935 | |
| 2936 MarkBit::CellType current_cell = cells[cell_index]; | |
| 2937 CHECK(current_cell != 0); | |
| 2938 | |
| 2939 // Find the last live object in the cell. | |
| 2940 unsigned int leading_zeros = | |
| 2941 base::bits::CountLeadingZeros32(current_cell & slot_mask); | |
| 2942 CHECK(leading_zeros != Bitmap::kBitsPerCell); | |
| 2943 int offset = static_cast<int>(Bitmap::kBitIndexMask - leading_zeros) - 1; | |
| 2944 | |
| 2945 base_address += (cell_index - base_address_cell_index) * | |
| 2946 Bitmap::kBitsPerCell * kPointerSize; | |
| 2947 Address address = base_address + offset * kPointerSize; | |
| 2948 | |
| 2949 // If the found mark bit is part of a black area, the slot cannot be part | |
| 2950 // of a live object since it is not marked. | |
| 2951 if (p->IsBlackAreaEndMarker(address + kPointerSize)) return false; | |
| 2952 | |
| 2953 HeapObject* object = HeapObject::FromAddress(address); | |
| 2954 CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object))); | |
| 2955 CHECK(object->address() < reinterpret_cast<Address>(slot)); | |
| 2956 if ((object->address() + kPointerSize) <= slot && | |
| 2957 (object->address() + object->Size()) > slot) { | |
| 2958 // If the slot is within the last found object in the cell, the slot is | |
| 2959 // in a live object. | |
| 2960 // Slots pointing to the first word of an object are invalid and removed. | |
| 2961 // This can happen when we move the object header while left trimming. | |
| 2962 return true; | |
| 2963 } | |
| 2964 return false; | |
| 2965 } | |
| 2966 | |
| 2967 HeapObject* MarkCompactCollector::FindBlackObjectBySlotSlow(Address slot) { | |
| 2968 Page* p = Page::FromAddress(slot); | |
| 2969 Space* owner = p->owner(); | |
| 2970 if (owner == heap_->lo_space() || owner == nullptr) { | |
| 2971 Object* large_object = heap_->lo_space()->FindObject(slot); | |
| 2972 // This object has to exist, otherwise we would not have recorded a slot | |
| 2973 // for it. | |
| 2974 CHECK(large_object->IsHeapObject()); | |
| 2975 HeapObject* large_heap_object = HeapObject::cast(large_object); | |
| 2976 | |
| 2977 if (IsMarked(large_heap_object)) { | |
| 2978 return large_heap_object; | |
| 2979 } | |
| 2980 return nullptr; | |
| 2981 } | |
| 2982 | |
| 2983 LiveObjectIterator<kBlackObjects> it(p); | |
| 2984 HeapObject* object = nullptr; | |
| 2985 while ((object = it.Next()) != nullptr) { | |
| 2986 int size = object->Size(); | |
| 2987 if (object->address() > slot) return nullptr; | |
| 2988 if (object->address() <= slot && slot < (object->address() + size)) { | |
| 2989 return object; | |
| 2990 } | |
| 2991 } | |
| 2992 | |
| 2993 return nullptr; | |
| 2994 } | |
| 2995 | |
| 2996 | |
| 2997 void MarkCompactCollector::EvacuateNewSpacePrologue() { | 2875 void MarkCompactCollector::EvacuateNewSpacePrologue() { |
| 2998 NewSpace* new_space = heap()->new_space(); | 2876 NewSpace* new_space = heap()->new_space(); |
| 2999 // Append the list of new space pages to be processed. | 2877 // Append the list of new space pages to be processed. |
| 3000 for (Page* p : NewSpacePageRange(new_space->bottom(), new_space->top())) { | 2878 for (Page* p : NewSpacePageRange(new_space->bottom(), new_space->top())) { |
| 3001 newspace_evacuation_candidates_.Add(p); | 2879 newspace_evacuation_candidates_.Add(p); |
| 3002 } | 2880 } |
| 3003 new_space->Flip(); | 2881 new_space->Flip(); |
| 3004 new_space->ResetAllocationInfo(); | 2882 new_space->ResetAllocationInfo(); |
| 3005 } | 2883 } |
| 3006 | 2884 |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3309 HeapObject* heap_object = HeapObject::cast(object); | 3187 HeapObject* heap_object = HeapObject::cast(object); |
| 3310 MapWord map_word = heap_object->map_word(); | 3188 MapWord map_word = heap_object->map_word(); |
| 3311 if (map_word.IsForwardingAddress()) { | 3189 if (map_word.IsForwardingAddress()) { |
| 3312 return map_word.ToForwardingAddress(); | 3190 return map_word.ToForwardingAddress(); |
| 3313 } | 3191 } |
| 3314 } | 3192 } |
| 3315 return object; | 3193 return object; |
| 3316 } | 3194 } |
| 3317 }; | 3195 }; |
| 3318 | 3196 |
| 3197 MarkCompactCollector::Sweeper::ClearOldToNewSlotsMode | |
| 3198 MarkCompactCollector::Sweeper::GetClearOldToNewSlotsMode(Page* p) { | |
| 3199 AllocationSpace identity = p->owner()->identity(); | |
| 3200 if (p->old_to_new_slots() && | |
| 3201 (identity == OLD_SPACE || identity == MAP_SPACE)) { | |
| 3202 return MarkCompactCollector::Sweeper::CLEAR_REGULAR_SLOTS; | |
| 3203 } else if (p->typed_old_to_new_slots() && identity == CODE_SPACE) { | |
| 3204 return MarkCompactCollector::Sweeper::CLEAR_TYPED_SLOTS; | |
| 3205 } | |
| 3206 return MarkCompactCollector::Sweeper::DO_NOT_CLEAR; | |
| 3207 } | |
| 3208 | |
| 3319 int MarkCompactCollector::Sweeper::RawSweep( | 3209 int MarkCompactCollector::Sweeper::RawSweep( |
| 3320 Page* p, FreeListRebuildingMode free_list_mode, | 3210 Page* p, FreeListRebuildingMode free_list_mode, |
| 3321 FreeSpaceTreatmentMode free_space_mode) { | 3211 FreeSpaceTreatmentMode free_space_mode) { |
| 3322 Space* space = p->owner(); | 3212 Space* space = p->owner(); |
| 3323 AllocationSpace identity = space->identity(); | |
| 3324 DCHECK_NOT_NULL(space); | 3213 DCHECK_NOT_NULL(space); |
| 3325 DCHECK(free_list_mode == IGNORE_FREE_LIST || identity == OLD_SPACE || | 3214 DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE || |
| 3326 identity == CODE_SPACE || identity == MAP_SPACE); | 3215 space->identity() == CODE_SPACE || space->identity() == MAP_SPACE); |
| 3327 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3216 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
| 3328 | 3217 |
| 3218 // If there are old-to-new slots in that page, we have to filter out slots | |
| 3219 // that are in dead memory which is freed by the sweeper. | |
| 3220 ClearOldToNewSlotsMode slots_clearing_mode = GetClearOldToNewSlotsMode(p); | |
| 3221 | |
| 3222 // The free ranges map is used for filtering typed slots. | |
| 3223 std::map<uint32_t, uint32_t> free_ranges; | |
|
ulan
2016/10/20 15:48:19
Alternative solution was to have host_objects of t
Hannes Payer (out of office)
2016/10/21 07:13:29
Are you referring to the solution where you
1) tra
| |
| 3224 | |
| 3329 // Before we sweep objects on the page, we free dead array buffers which | 3225 // Before we sweep objects on the page, we free dead array buffers which |
| 3330 // requires valid mark bits. | 3226 // requires valid mark bits. |
| 3331 ArrayBufferTracker::FreeDead(p); | 3227 ArrayBufferTracker::FreeDead(p); |
| 3332 | 3228 |
| 3333 // We also release the black area markers here. | |
| 3334 p->ReleaseBlackAreaEndMarkerMap(); | |
| 3335 | |
| 3336 Address free_start = p->area_start(); | 3229 Address free_start = p->area_start(); |
| 3337 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3230 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 3338 | 3231 |
| 3339 // If we use the skip list for code space pages, we have to lock the skip | 3232 // If we use the skip list for code space pages, we have to lock the skip |
| 3340 // list because it could be accessed concurrently by the runtime or the | 3233 // list because it could be accessed concurrently by the runtime or the |
| 3341 // deoptimizer. | 3234 // deoptimizer. |
| 3342 const bool rebuild_skip_list = | 3235 const bool rebuild_skip_list = |
| 3343 space->identity() == CODE_SPACE && p->skip_list() != nullptr; | 3236 space->identity() == CODE_SPACE && p->skip_list() != nullptr; |
| 3344 SkipList* skip_list = p->skip_list(); | 3237 SkipList* skip_list = p->skip_list(); |
| 3345 if (rebuild_skip_list) { | 3238 if (rebuild_skip_list) { |
| 3346 skip_list->Clear(); | 3239 skip_list->Clear(); |
| 3347 } | 3240 } |
| 3348 | 3241 |
| 3349 intptr_t freed_bytes = 0; | 3242 intptr_t freed_bytes = 0; |
| 3350 intptr_t max_freed_bytes = 0; | 3243 intptr_t max_freed_bytes = 0; |
| 3351 int curr_region = -1; | 3244 int curr_region = -1; |
| 3352 | 3245 |
| 3353 LiveObjectIterator<kBlackObjects> it(p); | 3246 LiveObjectIterator<kBlackObjects> it(p); |
| 3354 HeapObject* object = NULL; | 3247 HeapObject* object = NULL; |
| 3355 bool clear_slots = | 3248 |
| 3356 p->old_to_new_slots() && (identity == OLD_SPACE || identity == MAP_SPACE); | |
| 3357 while ((object = it.Next()) != NULL) { | 3249 while ((object = it.Next()) != NULL) { |
| 3358 DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object))); | 3250 DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object))); |
| 3359 Address free_end = object->address(); | 3251 Address free_end = object->address(); |
| 3360 if (free_end != free_start) { | 3252 if (free_end != free_start) { |
| 3361 CHECK_GT(free_end, free_start); | 3253 CHECK_GT(free_end, free_start); |
| 3362 size_t size = static_cast<size_t>(free_end - free_start); | 3254 size_t size = static_cast<size_t>(free_end - free_start); |
| 3363 if (free_space_mode == ZAP_FREE_SPACE) { | 3255 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3364 memset(free_start, 0xcc, size); | 3256 memset(free_start, 0xcc, size); |
| 3365 } | 3257 } |
| 3366 if (free_list_mode == REBUILD_FREE_LIST) { | 3258 if (free_list_mode == REBUILD_FREE_LIST) { |
| 3367 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( | 3259 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( |
| 3368 free_start, size); | 3260 free_start, size); |
| 3369 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3261 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3370 } else { | 3262 } else { |
| 3371 p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size), | 3263 p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size), |
| 3372 ClearRecordedSlots::kNo); | 3264 ClearRecordedSlots::kNo); |
| 3373 } | 3265 } |
| 3374 | 3266 |
| 3375 if (clear_slots) { | 3267 if (slots_clearing_mode == CLEAR_REGULAR_SLOTS) { |
| 3376 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, free_end, | 3268 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, free_end, |
| 3377 SlotSet::KEEP_EMPTY_BUCKETS); | 3269 SlotSet::KEEP_EMPTY_BUCKETS); |
| 3270 } else if (slots_clearing_mode == CLEAR_TYPED_SLOTS) { | |
| 3271 free_ranges.insert(std::pair<uint32_t, uint32_t>( | |
| 3272 static_cast<uint32_t>(free_start - p->address()), | |
| 3273 static_cast<uint32_t>(free_end - p->address()))); | |
| 3378 } | 3274 } |
| 3379 } | 3275 } |
| 3380 Map* map = object->synchronized_map(); | 3276 Map* map = object->synchronized_map(); |
| 3381 int size = object->SizeFromMap(map); | 3277 int size = object->SizeFromMap(map); |
| 3382 if (rebuild_skip_list) { | 3278 if (rebuild_skip_list) { |
| 3383 int new_region_start = SkipList::RegionNumber(free_end); | 3279 int new_region_start = SkipList::RegionNumber(free_end); |
| 3384 int new_region_end = | 3280 int new_region_end = |
| 3385 SkipList::RegionNumber(free_end + size - kPointerSize); | 3281 SkipList::RegionNumber(free_end + size - kPointerSize); |
| 3386 if (new_region_start != curr_region || new_region_end != curr_region) { | 3282 if (new_region_start != curr_region || new_region_end != curr_region) { |
| 3387 skip_list->AddObject(free_end, size); | 3283 skip_list->AddObject(free_end, size); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 3399 } | 3295 } |
| 3400 if (free_list_mode == REBUILD_FREE_LIST) { | 3296 if (free_list_mode == REBUILD_FREE_LIST) { |
| 3401 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( | 3297 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( |
| 3402 free_start, size); | 3298 free_start, size); |
| 3403 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3299 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3404 } else { | 3300 } else { |
| 3405 p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size), | 3301 p->heap()->CreateFillerObjectAt(free_start, static_cast<int>(size), |
| 3406 ClearRecordedSlots::kNo); | 3302 ClearRecordedSlots::kNo); |
| 3407 } | 3303 } |
| 3408 | 3304 |
| 3409 if (clear_slots) { | 3305 if (slots_clearing_mode == CLEAR_REGULAR_SLOTS) { |
| 3410 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(), | 3306 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(), |
| 3411 SlotSet::KEEP_EMPTY_BUCKETS); | 3307 SlotSet::KEEP_EMPTY_BUCKETS); |
| 3308 } else if (slots_clearing_mode == CLEAR_TYPED_SLOTS) { | |
| 3309 free_ranges.insert(std::pair<uint32_t, uint32_t>( | |
| 3310 static_cast<uint32_t>(free_start - p->address()), | |
| 3311 static_cast<uint32_t>(p->area_end() - p->address()))); | |
| 3312 p->typed_old_to_new_slots()->RemoveInvaldSlots(free_ranges); | |
|
Michael Lippautz
2016/10/20 16:28:24
This call should go outside of the last if block a
Hannes Payer (out of office)
2016/10/21 07:13:29
Uh, good catch. Too many branches. Done
| |
| 3412 } | 3313 } |
| 3413 } | 3314 } |
| 3414 | 3315 |
| 3415 // Clear the mark bits of that page and reset live bytes count. | 3316 // Clear the mark bits of that page and reset live bytes count. |
| 3416 p->ClearLiveness(); | 3317 p->ClearLiveness(); |
| 3417 | 3318 |
| 3418 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3319 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3419 if (free_list_mode == IGNORE_FREE_LIST) return 0; | 3320 if (free_list_mode == IGNORE_FREE_LIST) return 0; |
| 3420 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3321 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
| 3421 } | 3322 } |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3830 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { | 3731 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { |
| 3831 page->mutex()->Unlock(); | 3732 page->mutex()->Unlock(); |
| 3832 return 0; | 3733 return 0; |
| 3833 } | 3734 } |
| 3834 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3735 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3835 const Sweeper::FreeSpaceTreatmentMode free_space_mode = | 3736 const Sweeper::FreeSpaceTreatmentMode free_space_mode = |
| 3836 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; | 3737 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; |
| 3837 if (identity == NEW_SPACE) { | 3738 if (identity == NEW_SPACE) { |
| 3838 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); | 3739 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); |
| 3839 } else { | 3740 } else { |
| 3840 if (identity == CODE_SPACE) { | |
| 3841 RememberedSet<OLD_TO_NEW>::ClearInvalidTypedSlots(heap_, page); | |
| 3842 } | |
| 3843 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); | 3741 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); |
| 3844 } | 3742 } |
| 3845 | 3743 |
| 3846 // After finishing sweeping of a page we clean up its remembered set. | 3744 // After finishing sweeping of a page we clean up its remembered set. |
| 3847 if (page->typed_old_to_new_slots()) { | 3745 if (page->typed_old_to_new_slots()) { |
| 3848 page->typed_old_to_new_slots()->FreeToBeFreedChunks(); | 3746 page->typed_old_to_new_slots()->FreeToBeFreedChunks(); |
| 3849 } | 3747 } |
| 3850 if (page->old_to_new_slots()) { | 3748 if (page->old_to_new_slots()) { |
| 3851 page->old_to_new_slots()->FreeToBeFreedBuckets(); | 3749 page->old_to_new_slots()->FreeToBeFreedBuckets(); |
| 3852 } | 3750 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3900 bool unused_page_present = false; | 3798 bool unused_page_present = false; |
| 3901 | 3799 |
| 3902 // Loop needs to support deletion if live bytes == 0 for a page. | 3800 // Loop needs to support deletion if live bytes == 0 for a page. |
| 3903 for (auto it = space->begin(); it != space->end();) { | 3801 for (auto it = space->begin(); it != space->end();) { |
| 3904 Page* p = *(it++); | 3802 Page* p = *(it++); |
| 3905 DCHECK(p->SweepingDone()); | 3803 DCHECK(p->SweepingDone()); |
| 3906 | 3804 |
| 3907 if (p->IsEvacuationCandidate()) { | 3805 if (p->IsEvacuationCandidate()) { |
| 3908 // Will be processed in EvacuateNewSpaceAndCandidates. | 3806 // Will be processed in EvacuateNewSpaceAndCandidates. |
| 3909 DCHECK(evacuation_candidates_.length() > 0); | 3807 DCHECK(evacuation_candidates_.length() > 0); |
| 3910 DCHECK(!p->HasBlackAreas()); | |
| 3911 continue; | 3808 continue; |
| 3912 } | 3809 } |
| 3913 | 3810 |
| 3914 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 3811 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
| 3915 // We need to sweep the page to get it into an iterable state again. Note | 3812 // We need to sweep the page to get it into an iterable state again. Note |
| 3916 // that this adds unusable memory into the free list that is later on | 3813 // that this adds unusable memory into the free list that is later on |
| 3917 // (in the free list) dropped again. Since we only use the flag for | 3814 // (in the free list) dropped again. Since we only use the flag for |
| 3918 // testing this is fine. | 3815 // testing this is fine. |
| 3919 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3816 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3920 Sweeper::RawSweep(p, Sweeper::IGNORE_FREE_LIST, | 3817 Sweeper::RawSweep(p, Sweeper::IGNORE_FREE_LIST, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4010 // The target is always in old space, we don't have to record the slot in | 3907 // The target is always in old space, we don't have to record the slot in |
| 4011 // the old-to-new remembered set. | 3908 // the old-to-new remembered set. |
| 4012 DCHECK(!heap()->InNewSpace(target)); | 3909 DCHECK(!heap()->InNewSpace(target)); |
| 4013 RecordRelocSlot(host, &rinfo, target); | 3910 RecordRelocSlot(host, &rinfo, target); |
| 4014 } | 3911 } |
| 4015 } | 3912 } |
| 4016 } | 3913 } |
| 4017 | 3914 |
| 4018 } // namespace internal | 3915 } // namespace internal |
| 4019 } // namespace v8 | 3916 } // namespace v8 |
| OLD | NEW |