| 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 3301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3312 } | 3312 } |
| 3313 } | 3313 } |
| 3314 return object; | 3314 return object; |
| 3315 } | 3315 } |
| 3316 }; | 3316 }; |
| 3317 | 3317 |
| 3318 int MarkCompactCollector::Sweeper::RawSweep( | 3318 int MarkCompactCollector::Sweeper::RawSweep( |
| 3319 Page* p, FreeListRebuildingMode free_list_mode, | 3319 Page* p, FreeListRebuildingMode free_list_mode, |
| 3320 FreeSpaceTreatmentMode free_space_mode) { | 3320 FreeSpaceTreatmentMode free_space_mode) { |
| 3321 Space* space = p->owner(); | 3321 Space* space = p->owner(); |
| 3322 AllocationSpace identity = space->identity(); | |
| 3323 DCHECK_NOT_NULL(space); | 3322 DCHECK_NOT_NULL(space); |
| 3324 DCHECK(free_list_mode == IGNORE_FREE_LIST || identity == OLD_SPACE || | 3323 DCHECK(free_list_mode == IGNORE_FREE_LIST || space->identity() == OLD_SPACE || |
| 3325 identity == CODE_SPACE || identity == MAP_SPACE); | 3324 space->identity() == CODE_SPACE || space->identity() == MAP_SPACE); |
| 3326 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3325 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
| 3327 | 3326 |
| 3328 // Before we sweep objects on the page, we free dead array buffers which | 3327 // Before we sweep objects on the page, we free dead array buffers which |
| 3329 // requires valid mark bits. | 3328 // requires valid mark bits. |
| 3330 ArrayBufferTracker::FreeDead(p); | 3329 ArrayBufferTracker::FreeDead(p); |
| 3331 | 3330 |
| 3332 // We also release the black area markers here. | 3331 // We also release the black area markers here. |
| 3333 p->ReleaseBlackAreaEndMarkerMap(); | 3332 p->ReleaseBlackAreaEndMarkerMap(); |
| 3334 | 3333 |
| 3335 Address free_start = p->area_start(); | 3334 Address free_start = p->area_start(); |
| 3336 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3335 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 3337 | 3336 |
| 3338 // If we use the skip list for code space pages, we have to lock the skip | 3337 // If we use the skip list for code space pages, we have to lock the skip |
| 3339 // list because it could be accessed concurrently by the runtime or the | 3338 // list because it could be accessed concurrently by the runtime or the |
| 3340 // deoptimizer. | 3339 // deoptimizer. |
| 3341 const bool rebuild_skip_list = | 3340 const bool rebuild_skip_list = |
| 3342 space->identity() == CODE_SPACE && p->skip_list() != nullptr; | 3341 space->identity() == CODE_SPACE && p->skip_list() != nullptr; |
| 3343 SkipList* skip_list = p->skip_list(); | 3342 SkipList* skip_list = p->skip_list(); |
| 3344 if (rebuild_skip_list) { | 3343 if (rebuild_skip_list) { |
| 3345 skip_list->Clear(); | 3344 skip_list->Clear(); |
| 3346 } | 3345 } |
| 3347 | 3346 |
| 3348 intptr_t freed_bytes = 0; | 3347 intptr_t freed_bytes = 0; |
| 3349 intptr_t max_freed_bytes = 0; | 3348 intptr_t max_freed_bytes = 0; |
| 3350 int curr_region = -1; | 3349 int curr_region = -1; |
| 3351 | 3350 |
| 3352 LiveObjectIterator<kBlackObjects> it(p); | 3351 LiveObjectIterator<kBlackObjects> it(p); |
| 3353 HeapObject* object = NULL; | 3352 HeapObject* object = NULL; |
| 3354 bool clear_slots = | |
| 3355 p->old_to_new_slots() && (identity == OLD_SPACE || identity == MAP_SPACE); | |
| 3356 while ((object = it.Next()) != NULL) { | 3353 while ((object = it.Next()) != NULL) { |
| 3357 DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object))); | 3354 DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object))); |
| 3358 Address free_end = object->address(); | 3355 Address free_end = object->address(); |
| 3359 if (free_end != free_start) { | 3356 if (free_end != free_start) { |
| 3360 int size = static_cast<int>(free_end - free_start); | 3357 int size = static_cast<int>(free_end - free_start); |
| 3361 if (free_space_mode == ZAP_FREE_SPACE) { | 3358 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3362 memset(free_start, 0xcc, size); | 3359 memset(free_start, 0xcc, size); |
| 3363 } | 3360 } |
| 3364 if (free_list_mode == REBUILD_FREE_LIST) { | 3361 if (free_list_mode == REBUILD_FREE_LIST) { |
| 3365 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( | 3362 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( |
| 3366 free_start, size); | 3363 free_start, size); |
| 3367 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3364 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3368 } else { | 3365 } else { |
| 3369 p->heap()->CreateFillerObjectAt(free_start, size, | 3366 p->heap()->CreateFillerObjectAt(free_start, size, |
| 3370 ClearRecordedSlots::kNo); | 3367 ClearRecordedSlots::kNo); |
| 3371 } | 3368 } |
| 3372 | |
| 3373 if (clear_slots) { | |
| 3374 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, free_end, | |
| 3375 SlotSet::KEEP_EMPTY_BUCKETS); | |
| 3376 } | |
| 3377 } | 3369 } |
| 3378 Map* map = object->synchronized_map(); | 3370 Map* map = object->synchronized_map(); |
| 3379 int size = object->SizeFromMap(map); | 3371 int size = object->SizeFromMap(map); |
| 3380 if (rebuild_skip_list) { | 3372 if (rebuild_skip_list) { |
| 3381 int new_region_start = SkipList::RegionNumber(free_end); | 3373 int new_region_start = SkipList::RegionNumber(free_end); |
| 3382 int new_region_end = | 3374 int new_region_end = |
| 3383 SkipList::RegionNumber(free_end + size - kPointerSize); | 3375 SkipList::RegionNumber(free_end + size - kPointerSize); |
| 3384 if (new_region_start != curr_region || new_region_end != curr_region) { | 3376 if (new_region_start != curr_region || new_region_end != curr_region) { |
| 3385 skip_list->AddObject(free_end, size); | 3377 skip_list->AddObject(free_end, size); |
| 3386 curr_region = new_region_end; | 3378 curr_region = new_region_end; |
| 3387 } | 3379 } |
| 3388 } | 3380 } |
| 3389 free_start = free_end + size; | 3381 free_start = free_end + size; |
| 3390 } | 3382 } |
| 3391 | 3383 |
| 3384 // Clear the mark bits of that page and reset live bytes count. |
| 3385 p->ClearLiveness(); |
| 3386 |
| 3392 if (free_start != p->area_end()) { | 3387 if (free_start != p->area_end()) { |
| 3393 int size = static_cast<int>(p->area_end() - free_start); | 3388 int size = static_cast<int>(p->area_end() - free_start); |
| 3394 if (free_space_mode == ZAP_FREE_SPACE) { | 3389 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3395 memset(free_start, 0xcc, size); | 3390 memset(free_start, 0xcc, size); |
| 3396 } | 3391 } |
| 3397 if (free_list_mode == REBUILD_FREE_LIST) { | 3392 if (free_list_mode == REBUILD_FREE_LIST) { |
| 3398 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( | 3393 freed_bytes = reinterpret_cast<PagedSpace*>(space)->UnaccountedFree( |
| 3399 free_start, size); | 3394 free_start, size); |
| 3400 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3395 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3401 } else { | 3396 } else { |
| 3402 p->heap()->CreateFillerObjectAt(free_start, size, | 3397 p->heap()->CreateFillerObjectAt(free_start, size, |
| 3403 ClearRecordedSlots::kNo); | 3398 ClearRecordedSlots::kNo); |
| 3404 } | 3399 } |
| 3405 | |
| 3406 if (clear_slots) { | |
| 3407 RememberedSet<OLD_TO_NEW>::RemoveRange(p, free_start, p->area_end(), | |
| 3408 SlotSet::KEEP_EMPTY_BUCKETS); | |
| 3409 } | |
| 3410 } | 3400 } |
| 3411 | |
| 3412 // Clear the mark bits of that page and reset live bytes count. | |
| 3413 p->ClearLiveness(); | |
| 3414 | |
| 3415 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3401 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3416 if (free_list_mode == IGNORE_FREE_LIST) return 0; | 3402 if (free_list_mode == IGNORE_FREE_LIST) return 0; |
| 3417 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3403 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
| 3418 } | 3404 } |
| 3419 | 3405 |
| 3420 void MarkCompactCollector::InvalidateCode(Code* code) { | 3406 void MarkCompactCollector::InvalidateCode(Code* code) { |
| 3421 Page* page = Page::FromAddress(code->address()); | 3407 Page* page = Page::FromAddress(code->address()); |
| 3422 Address start = code->instruction_start(); | 3408 Address start = code->instruction_start(); |
| 3423 Address end = code->address() + code->Size(); | 3409 Address end = code->address() + code->Size(); |
| 3424 | 3410 |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3820 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { | 3806 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { |
| 3821 page->mutex()->Unlock(); | 3807 page->mutex()->Unlock(); |
| 3822 return 0; | 3808 return 0; |
| 3823 } | 3809 } |
| 3824 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3810 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3825 const Sweeper::FreeSpaceTreatmentMode free_space_mode = | 3811 const Sweeper::FreeSpaceTreatmentMode free_space_mode = |
| 3826 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; | 3812 Heap::ShouldZapGarbage() ? ZAP_FREE_SPACE : IGNORE_FREE_SPACE; |
| 3827 if (identity == NEW_SPACE) { | 3813 if (identity == NEW_SPACE) { |
| 3828 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); | 3814 RawSweep(page, IGNORE_FREE_LIST, free_space_mode); |
| 3829 } else { | 3815 } else { |
| 3830 if (identity == CODE_SPACE) { | 3816 if (identity == OLD_SPACE || identity == MAP_SPACE) { |
| 3817 RememberedSet<OLD_TO_NEW>::ClearInvalidSlots(heap_, page); |
| 3818 } else { |
| 3831 RememberedSet<OLD_TO_NEW>::ClearInvalidTypedSlots(heap_, page); | 3819 RememberedSet<OLD_TO_NEW>::ClearInvalidTypedSlots(heap_, page); |
| 3832 } | 3820 } |
| 3833 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); | 3821 max_freed = RawSweep(page, REBUILD_FREE_LIST, free_space_mode); |
| 3834 } | 3822 } |
| 3835 | 3823 |
| 3836 // After finishing sweeping of a page we clean up its remembered set. | 3824 // After finishing sweeping of a page we clean up its remembered set. |
| 3837 if (page->typed_old_to_new_slots()) { | 3825 if (page->typed_old_to_new_slots()) { |
| 3838 page->typed_old_to_new_slots()->FreeToBeFreedChunks(); | 3826 page->typed_old_to_new_slots()->FreeToBeFreedChunks(); |
| 3839 } | 3827 } |
| 3840 if (page->old_to_new_slots()) { | 3828 if (page->old_to_new_slots()) { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4008 // The target is always in old space, we don't have to record the slot in | 3996 // The target is always in old space, we don't have to record the slot in |
| 4009 // the old-to-new remembered set. | 3997 // the old-to-new remembered set. |
| 4010 DCHECK(!heap()->InNewSpace(target)); | 3998 DCHECK(!heap()->InNewSpace(target)); |
| 4011 RecordRelocSlot(host, &rinfo, target); | 3999 RecordRelocSlot(host, &rinfo, target); |
| 4012 } | 4000 } |
| 4013 } | 4001 } |
| 4014 } | 4002 } |
| 4015 | 4003 |
| 4016 } // namespace internal | 4004 } // namespace internal |
| 4017 } // namespace v8 | 4005 } // namespace v8 |
| OLD | NEW |