| 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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 } | 247 } |
| 248 #endif // VERIFY_HEAP | 248 #endif // VERIFY_HEAP |
| 249 | 249 |
| 250 | 250 |
| 251 void MarkCompactCollector::SetUp() { | 251 void MarkCompactCollector::SetUp() { |
| 252 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 252 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 253 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); | 253 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); |
| 254 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); | 254 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); |
| 255 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 255 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 256 | 256 |
| 257 free_list_old_space_.Reset(new FreeList(heap_->old_space())); | |
| 258 free_list_code_space_.Reset(new FreeList(heap_->code_space())); | |
| 259 free_list_map_space_.Reset(new FreeList(heap_->map_space())); | |
| 260 EnsureMarkingDequeIsReserved(); | 257 EnsureMarkingDequeIsReserved(); |
| 261 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize); | 258 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize); |
| 262 | 259 |
| 263 if (FLAG_flush_code) { | 260 if (FLAG_flush_code) { |
| 264 code_flusher_ = new CodeFlusher(isolate()); | 261 code_flusher_ = new CodeFlusher(isolate()); |
| 265 if (FLAG_trace_code_flushing) { | 262 if (FLAG_trace_code_flushing) { |
| 266 PrintF("[code-flushing is now on]\n"); | 263 PrintF("[code-flushing is now on]\n"); |
| 267 } | 264 } |
| 268 } | 265 } |
| 269 } | 266 } |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 } | 486 } |
| 490 | 487 |
| 491 Heap* heap_; | 488 Heap* heap_; |
| 492 AllocationSpace space_to_start_; | 489 AllocationSpace space_to_start_; |
| 493 | 490 |
| 494 DISALLOW_COPY_AND_ASSIGN(SweeperTask); | 491 DISALLOW_COPY_AND_ASSIGN(SweeperTask); |
| 495 }; | 492 }; |
| 496 | 493 |
| 497 | 494 |
| 498 void MarkCompactCollector::StartSweeperThreads() { | 495 void MarkCompactCollector::StartSweeperThreads() { |
| 499 DCHECK(free_list_old_space_.get()->IsEmpty()); | |
| 500 DCHECK(free_list_code_space_.get()->IsEmpty()); | |
| 501 DCHECK(free_list_map_space_.get()->IsEmpty()); | |
| 502 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 496 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 503 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask); | 497 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask); |
| 504 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 498 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 505 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask); | 499 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask); |
| 506 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 500 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 507 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask); | 501 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask); |
| 508 } | 502 } |
| 509 | 503 |
| 510 | 504 |
| 511 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { | 505 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { |
| (...skipping 2726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3238 HeapObject* heap_object = HeapObject::cast(object); | 3232 HeapObject* heap_object = HeapObject::cast(object); |
| 3239 MapWord map_word = heap_object->map_word(); | 3233 MapWord map_word = heap_object->map_word(); |
| 3240 if (map_word.IsForwardingAddress()) { | 3234 if (map_word.IsForwardingAddress()) { |
| 3241 return map_word.ToForwardingAddress(); | 3235 return map_word.ToForwardingAddress(); |
| 3242 } | 3236 } |
| 3243 } | 3237 } |
| 3244 return object; | 3238 return object; |
| 3245 } | 3239 } |
| 3246 }; | 3240 }; |
| 3247 | 3241 |
| 3248 | |
| 3249 enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS }; | 3242 enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS }; |
| 3250 | 3243 |
| 3251 | |
| 3252 enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST }; | 3244 enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST }; |
| 3253 | 3245 |
| 3254 | |
| 3255 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; | 3246 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; |
| 3256 | 3247 |
| 3257 | |
| 3258 template <MarkCompactCollector::SweepingParallelism mode> | |
| 3259 static intptr_t Free(PagedSpace* space, FreeList* free_list, Address start, | |
| 3260 int size) { | |
| 3261 if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) { | |
| 3262 DCHECK(free_list == NULL); | |
| 3263 return space->Free(start, size); | |
| 3264 } else { | |
| 3265 return size - free_list->Free(start, size); | |
| 3266 } | |
| 3267 } | |
| 3268 | |
| 3269 | |
| 3270 // Sweeps a page. After sweeping the page can be iterated. | 3248 // Sweeps a page. After sweeping the page can be iterated. |
| 3271 // Slots in live objects pointing into evacuation candidates are updated | 3249 // Slots in live objects pointing into evacuation candidates are updated |
| 3272 // if requested. | 3250 // if requested. |
| 3273 // Returns the size of the biggest continuous freed memory chunk in bytes. | 3251 // Returns the size of the biggest continuous freed memory chunk in bytes. |
| 3274 template <SweepingMode sweeping_mode, | 3252 template <SweepingMode sweeping_mode, |
| 3275 MarkCompactCollector::SweepingParallelism parallelism, | 3253 MarkCompactCollector::SweepingParallelism parallelism, |
| 3276 SkipListRebuildingMode skip_list_mode, | 3254 SkipListRebuildingMode skip_list_mode, |
| 3277 FreeSpaceTreatmentMode free_space_mode> | 3255 FreeSpaceTreatmentMode free_space_mode> |
| 3278 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, | 3256 static int Sweep(PagedSpace* space, Page* p, ObjectVisitor* v) { |
| 3279 ObjectVisitor* v) { | |
| 3280 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3257 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
| 3281 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE)); | 3258 DCHECK(!p->IsFlagSet(Page::BLACK_PAGE)); |
| 3282 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3259 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
| 3283 space->identity() == CODE_SPACE); | 3260 space->identity() == CODE_SPACE); |
| 3284 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3261 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
| 3285 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || | 3262 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || |
| 3286 sweeping_mode == SWEEP_ONLY); | 3263 sweeping_mode == SWEEP_ONLY); |
| 3287 | 3264 |
| 3288 Address free_start = p->area_start(); | 3265 Address free_start = p->area_start(); |
| 3289 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3266 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3303 LiveObjectIterator<kBlackObjects> it(p); | 3280 LiveObjectIterator<kBlackObjects> it(p); |
| 3304 HeapObject* object = NULL; | 3281 HeapObject* object = NULL; |
| 3305 while ((object = it.Next()) != NULL) { | 3282 while ((object = it.Next()) != NULL) { |
| 3306 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); | 3283 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 3307 Address free_end = object->address(); | 3284 Address free_end = object->address(); |
| 3308 if (free_end != free_start) { | 3285 if (free_end != free_start) { |
| 3309 int size = static_cast<int>(free_end - free_start); | 3286 int size = static_cast<int>(free_end - free_start); |
| 3310 if (free_space_mode == ZAP_FREE_SPACE) { | 3287 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3311 memset(free_start, 0xcc, size); | 3288 memset(free_start, 0xcc, size); |
| 3312 } | 3289 } |
| 3313 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3290 freed_bytes = space->UnaccountedFree(free_start, size); |
| 3314 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3291 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3315 } | 3292 } |
| 3316 Map* map = object->synchronized_map(); | 3293 Map* map = object->synchronized_map(); |
| 3317 int size = object->SizeFromMap(map); | 3294 int size = object->SizeFromMap(map); |
| 3318 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { | 3295 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { |
| 3319 object->IterateBody(map->instance_type(), size, v); | 3296 object->IterateBody(map->instance_type(), size, v); |
| 3320 } | 3297 } |
| 3321 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { | 3298 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { |
| 3322 int new_region_start = SkipList::RegionNumber(free_end); | 3299 int new_region_start = SkipList::RegionNumber(free_end); |
| 3323 int new_region_end = | 3300 int new_region_end = |
| 3324 SkipList::RegionNumber(free_end + size - kPointerSize); | 3301 SkipList::RegionNumber(free_end + size - kPointerSize); |
| 3325 if (new_region_start != curr_region || new_region_end != curr_region) { | 3302 if (new_region_start != curr_region || new_region_end != curr_region) { |
| 3326 skip_list->AddObject(free_end, size); | 3303 skip_list->AddObject(free_end, size); |
| 3327 curr_region = new_region_end; | 3304 curr_region = new_region_end; |
| 3328 } | 3305 } |
| 3329 } | 3306 } |
| 3330 free_start = free_end + size; | 3307 free_start = free_end + size; |
| 3331 } | 3308 } |
| 3332 | 3309 |
| 3333 // Clear the mark bits of that page and reset live bytes count. | 3310 // Clear the mark bits of that page and reset live bytes count. |
| 3334 Bitmap::Clear(p); | 3311 Bitmap::Clear(p); |
| 3335 | 3312 |
| 3336 if (free_start != p->area_end()) { | 3313 if (free_start != p->area_end()) { |
| 3337 int size = static_cast<int>(p->area_end() - free_start); | 3314 int size = static_cast<int>(p->area_end() - free_start); |
| 3338 if (free_space_mode == ZAP_FREE_SPACE) { | 3315 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3339 memset(free_start, 0xcc, size); | 3316 memset(free_start, 0xcc, size); |
| 3340 } | 3317 } |
| 3341 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3318 freed_bytes = space->UnaccountedFree(free_start, size); |
| 3342 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3319 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3343 } | 3320 } |
| 3344 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3321 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3345 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3322 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
| 3346 } | 3323 } |
| 3347 | 3324 |
| 3348 | 3325 |
| 3349 void MarkCompactCollector::InvalidateCode(Code* code) { | 3326 void MarkCompactCollector::InvalidateCode(Code* code) { |
| 3350 if (heap_->incremental_marking()->IsCompacting() && | 3327 if (heap_->incremental_marking()->IsCompacting() && |
| 3351 !ShouldSkipEvacuationSlotRecording(code)) { | 3328 !ShouldSkipEvacuationSlotRecording(code)) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3446 void MarkCompactCollector::SweepAbortedPages() { | 3423 void MarkCompactCollector::SweepAbortedPages() { |
| 3447 // Second pass on aborted pages. | 3424 // Second pass on aborted pages. |
| 3448 for (Page* p : evacuation_candidates_) { | 3425 for (Page* p : evacuation_candidates_) { |
| 3449 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { | 3426 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
| 3450 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); | 3427 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); |
| 3451 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3428 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3452 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3429 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3453 switch (space->identity()) { | 3430 switch (space->identity()) { |
| 3454 case OLD_SPACE: | 3431 case OLD_SPACE: |
| 3455 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3432 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
| 3456 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3433 IGNORE_FREE_SPACE>(space, p, nullptr); |
| 3457 break; | 3434 break; |
| 3458 case CODE_SPACE: | 3435 case CODE_SPACE: |
| 3459 if (FLAG_zap_code_space) { | 3436 if (FLAG_zap_code_space) { |
| 3460 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, | 3437 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, |
| 3461 ZAP_FREE_SPACE>(space, NULL, p, nullptr); | 3438 ZAP_FREE_SPACE>(space, p, nullptr); |
| 3462 } else { | 3439 } else { |
| 3463 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, | 3440 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, |
| 3464 IGNORE_FREE_SPACE>(space, NULL, p, nullptr); | 3441 IGNORE_FREE_SPACE>(space, p, nullptr); |
| 3465 } | 3442 } |
| 3466 break; | 3443 break; |
| 3467 default: | 3444 default: |
| 3468 UNREACHABLE(); | 3445 UNREACHABLE(); |
| 3469 break; | 3446 break; |
| 3470 } | 3447 } |
| 3448 { |
| 3449 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); |
| 3450 swept_pages(space->identity())->Add(p); |
| 3451 } |
| 3471 } | 3452 } |
| 3472 } | 3453 } |
| 3473 } | 3454 } |
| 3474 | 3455 |
| 3475 | 3456 |
| 3476 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 3457 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 3477 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); | 3458 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); |
| 3478 Heap::RelocationLock relocation_lock(heap()); | 3459 Heap::RelocationLock relocation_lock(heap()); |
| 3479 | 3460 |
| 3480 { | 3461 { |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3658 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3639 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 3659 heap()->ProcessWeakListRoots(&evacuation_object_retainer); | 3640 heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
| 3660 } | 3641 } |
| 3661 } | 3642 } |
| 3662 | 3643 |
| 3663 | 3644 |
| 3664 void MarkCompactCollector::ReleaseEvacuationCandidates() { | 3645 void MarkCompactCollector::ReleaseEvacuationCandidates() { |
| 3665 for (Page* p : evacuation_candidates_) { | 3646 for (Page* p : evacuation_candidates_) { |
| 3666 if (!p->IsEvacuationCandidate()) continue; | 3647 if (!p->IsEvacuationCandidate()) continue; |
| 3667 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3648 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3668 space->Free(p->area_start(), p->area_size()); | |
| 3669 p->ResetLiveBytes(); | 3649 p->ResetLiveBytes(); |
| 3670 CHECK(p->SweepingDone()); | 3650 CHECK(p->SweepingDone()); |
| 3671 space->ReleasePage(p, true); | 3651 space->ReleasePage(p); |
| 3672 } | 3652 } |
| 3673 evacuation_candidates_.Rewind(0); | 3653 evacuation_candidates_.Rewind(0); |
| 3674 compacting_ = false; | 3654 compacting_ = false; |
| 3675 heap()->FreeQueuedChunks(); | 3655 heap()->FreeQueuedChunks(); |
| 3676 } | 3656 } |
| 3677 | 3657 |
| 3678 | 3658 |
| 3679 int MarkCompactCollector::SweepInParallel(PagedSpace* space, | 3659 int MarkCompactCollector::SweepInParallel(PagedSpace* space, |
| 3680 int required_freed_bytes, | 3660 int required_freed_bytes, |
| 3681 int max_pages) { | 3661 int max_pages) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3700 | 3680 |
| 3701 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { | 3681 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { |
| 3702 int max_freed = 0; | 3682 int max_freed = 0; |
| 3703 if (page->mutex()->TryLock()) { | 3683 if (page->mutex()->TryLock()) { |
| 3704 // If this page was already swept in the meantime, we can return here. | 3684 // If this page was already swept in the meantime, we can return here. |
| 3705 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { | 3685 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { |
| 3706 page->mutex()->Unlock(); | 3686 page->mutex()->Unlock(); |
| 3707 return 0; | 3687 return 0; |
| 3708 } | 3688 } |
| 3709 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3689 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3710 FreeList* free_list; | |
| 3711 FreeList private_free_list(space); | |
| 3712 if (space->identity() == OLD_SPACE) { | 3690 if (space->identity() == OLD_SPACE) { |
| 3713 free_list = free_list_old_space_.get(); | 3691 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, |
| 3714 max_freed = | 3692 IGNORE_FREE_SPACE>(space, page, NULL); |
| 3715 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, | |
| 3716 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | |
| 3717 } else if (space->identity() == CODE_SPACE) { | 3693 } else if (space->identity() == CODE_SPACE) { |
| 3718 free_list = free_list_code_space_.get(); | 3694 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, |
| 3719 max_freed = | 3695 IGNORE_FREE_SPACE>(space, page, NULL); |
| 3720 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, | |
| 3721 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | |
| 3722 } else { | 3696 } else { |
| 3723 free_list = free_list_map_space_.get(); | 3697 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, |
| 3724 max_freed = | 3698 IGNORE_FREE_SPACE>(space, page, NULL); |
| 3725 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, | |
| 3726 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | |
| 3727 } | 3699 } |
| 3728 free_list->Concatenate(&private_free_list); | 3700 { |
| 3701 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); |
| 3702 swept_pages(space->identity())->Add(page); |
| 3703 } |
| 3729 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3704 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3730 page->mutex()->Unlock(); | 3705 page->mutex()->Unlock(); |
| 3731 } | 3706 } |
| 3732 return max_freed; | 3707 return max_freed; |
| 3733 } | 3708 } |
| 3734 | 3709 |
| 3735 | 3710 |
| 3736 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { | 3711 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { |
| 3737 space->ClearStats(); | 3712 space->ClearStats(); |
| 3738 | 3713 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3761 continue; | 3736 continue; |
| 3762 } | 3737 } |
| 3763 | 3738 |
| 3764 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 3739 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
| 3765 // We need to sweep the page to get it into an iterable state again. Note | 3740 // We need to sweep the page to get it into an iterable state again. Note |
| 3766 // that this adds unusable memory into the free list that is later on | 3741 // that this adds unusable memory into the free list that is later on |
| 3767 // (in the free list) dropped again. Since we only use the flag for | 3742 // (in the free list) dropped again. Since we only use the flag for |
| 3768 // testing this is fine. | 3743 // testing this is fine. |
| 3769 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3744 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3770 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3745 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
| 3771 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3746 IGNORE_FREE_SPACE>(space, p, nullptr); |
| 3772 continue; | 3747 continue; |
| 3773 } | 3748 } |
| 3774 | 3749 |
| 3775 // One unused page is kept, all further are released before sweeping them. | 3750 // One unused page is kept, all further are released before sweeping them. |
| 3776 if (p->LiveBytes() == 0) { | 3751 if (p->LiveBytes() == 0) { |
| 3777 if (unused_page_present) { | 3752 if (unused_page_present) { |
| 3778 if (FLAG_gc_verbose) { | 3753 if (FLAG_gc_verbose) { |
| 3779 PrintIsolate(isolate(), "sweeping: released page: %p", p); | 3754 PrintIsolate(isolate(), "sweeping: released page: %p", p); |
| 3780 } | 3755 } |
| 3781 space->ReleasePage(p, false); | 3756 space->ReleasePage(p); |
| 3782 continue; | 3757 continue; |
| 3783 } | 3758 } |
| 3784 unused_page_present = true; | 3759 unused_page_present = true; |
| 3785 } | 3760 } |
| 3786 | 3761 |
| 3787 p->concurrent_sweeping_state().SetValue(Page::kSweepingPending); | 3762 p->concurrent_sweeping_state().SetValue(Page::kSweepingPending); |
| 3788 sweeping_list(space).push_back(p); | 3763 sweeping_list(space).push_back(p); |
| 3789 int to_sweep = p->area_size() - p->LiveBytes(); | 3764 int to_sweep = p->area_size() - p->LiveBytes(); |
| 3790 space->accounting_stats_.ShrinkSpace(to_sweep); | 3765 space->accounting_stats_.ShrinkSpace(to_sweep); |
| 3791 will_be_swept++; | 3766 will_be_swept++; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3877 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3852 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3878 if (Marking::IsBlack(mark_bit)) { | 3853 if (Marking::IsBlack(mark_bit)) { |
| 3879 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3854 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3880 RecordRelocSlot(host, &rinfo, target); | 3855 RecordRelocSlot(host, &rinfo, target); |
| 3881 } | 3856 } |
| 3882 } | 3857 } |
| 3883 } | 3858 } |
| 3884 | 3859 |
| 3885 } // namespace internal | 3860 } // namespace internal |
| 3886 } // namespace v8 | 3861 } // namespace v8 |
| OLD | NEW |