| 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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 } | 235 } |
| 236 #endif // VERIFY_HEAP | 236 #endif // VERIFY_HEAP |
| 237 | 237 |
| 238 | 238 |
| 239 void MarkCompactCollector::SetUp() { | 239 void MarkCompactCollector::SetUp() { |
| 240 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 240 DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); |
| 241 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); | 241 DCHECK(strcmp(Marking::kBlackBitPattern, "11") == 0); |
| 242 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); | 242 DCHECK(strcmp(Marking::kGreyBitPattern, "10") == 0); |
| 243 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 243 DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |
| 244 | 244 |
| 245 free_list_old_space_.Reset(new FreeList(heap_->old_space())); | |
| 246 free_list_code_space_.Reset(new FreeList(heap_->code_space())); | |
| 247 free_list_map_space_.Reset(new FreeList(heap_->map_space())); | |
| 248 EnsureMarkingDequeIsReserved(); | 245 EnsureMarkingDequeIsReserved(); |
| 249 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize); | 246 EnsureMarkingDequeIsCommitted(kMinMarkingDequeSize); |
| 250 | 247 |
| 251 if (FLAG_flush_code) { | 248 if (FLAG_flush_code) { |
| 252 code_flusher_ = new CodeFlusher(isolate()); | 249 code_flusher_ = new CodeFlusher(isolate()); |
| 253 if (FLAG_trace_code_flushing) { | 250 if (FLAG_trace_code_flushing) { |
| 254 PrintF("[code-flushing is now on]\n"); | 251 PrintF("[code-flushing is now on]\n"); |
| 255 } | 252 } |
| 256 } | 253 } |
| 257 } | 254 } |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 } | 466 } |
| 470 | 467 |
| 471 Heap* heap_; | 468 Heap* heap_; |
| 472 AllocationSpace space_to_start_; | 469 AllocationSpace space_to_start_; |
| 473 | 470 |
| 474 DISALLOW_COPY_AND_ASSIGN(SweeperTask); | 471 DISALLOW_COPY_AND_ASSIGN(SweeperTask); |
| 475 }; | 472 }; |
| 476 | 473 |
| 477 | 474 |
| 478 void MarkCompactCollector::StartSweeperThreads() { | 475 void MarkCompactCollector::StartSweeperThreads() { |
| 479 DCHECK(free_list_old_space_.get()->IsEmpty()); | |
| 480 DCHECK(free_list_code_space_.get()->IsEmpty()); | |
| 481 DCHECK(free_list_map_space_.get()->IsEmpty()); | |
| 482 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 476 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 483 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask); | 477 new SweeperTask(heap(), OLD_SPACE), v8::Platform::kShortRunningTask); |
| 484 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 478 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 485 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask); | 479 new SweeperTask(heap(), CODE_SPACE), v8::Platform::kShortRunningTask); |
| 486 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 480 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 487 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask); | 481 new SweeperTask(heap(), MAP_SPACE), v8::Platform::kShortRunningTask); |
| 488 } | 482 } |
| 489 | 483 |
| 490 | 484 |
| 491 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { | 485 void MarkCompactCollector::SweepOrWaitUntilSweepingCompleted(Page* page) { |
| (...skipping 2800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3292 HeapObject* heap_object = HeapObject::cast(object); | 3286 HeapObject* heap_object = HeapObject::cast(object); |
| 3293 MapWord map_word = heap_object->map_word(); | 3287 MapWord map_word = heap_object->map_word(); |
| 3294 if (map_word.IsForwardingAddress()) { | 3288 if (map_word.IsForwardingAddress()) { |
| 3295 return map_word.ToForwardingAddress(); | 3289 return map_word.ToForwardingAddress(); |
| 3296 } | 3290 } |
| 3297 } | 3291 } |
| 3298 return object; | 3292 return object; |
| 3299 } | 3293 } |
| 3300 }; | 3294 }; |
| 3301 | 3295 |
| 3302 | |
| 3303 enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS }; | 3296 enum SweepingMode { SWEEP_ONLY, SWEEP_AND_VISIT_LIVE_OBJECTS }; |
| 3304 | 3297 |
| 3305 | |
| 3306 enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST }; | 3298 enum SkipListRebuildingMode { REBUILD_SKIP_LIST, IGNORE_SKIP_LIST }; |
| 3307 | 3299 |
| 3308 | |
| 3309 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; | 3300 enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE }; |
| 3310 | 3301 |
| 3311 | |
| 3312 template <MarkCompactCollector::SweepingParallelism mode> | |
| 3313 static intptr_t Free(PagedSpace* space, FreeList* free_list, Address start, | |
| 3314 int size) { | |
| 3315 if (mode == MarkCompactCollector::SWEEP_ON_MAIN_THREAD) { | |
| 3316 DCHECK(free_list == NULL); | |
| 3317 return space->Free(start, size); | |
| 3318 } else { | |
| 3319 return size - free_list->Free(start, size); | |
| 3320 } | |
| 3321 } | |
| 3322 | |
| 3323 | |
| 3324 // Sweeps a page. After sweeping the page can be iterated. | 3302 // Sweeps a page. After sweeping the page can be iterated. |
| 3325 // Slots in live objects pointing into evacuation candidates are updated | 3303 // Slots in live objects pointing into evacuation candidates are updated |
| 3326 // if requested. | 3304 // if requested. |
| 3327 // Returns the size of the biggest continuous freed memory chunk in bytes. | 3305 // Returns the size of the biggest continuous freed memory chunk in bytes. |
| 3328 template <SweepingMode sweeping_mode, | 3306 template <SweepingMode sweeping_mode, |
| 3329 MarkCompactCollector::SweepingParallelism parallelism, | 3307 MarkCompactCollector::SweepingParallelism parallelism, |
| 3330 SkipListRebuildingMode skip_list_mode, | 3308 SkipListRebuildingMode skip_list_mode, |
| 3331 FreeSpaceTreatmentMode free_space_mode> | 3309 FreeSpaceTreatmentMode free_space_mode> |
| 3332 static int Sweep(PagedSpace* space, FreeList* free_list, Page* p, | 3310 static int Sweep(PagedSpace* space, Page* p, ObjectVisitor* v) { |
| 3333 ObjectVisitor* v) { | |
| 3334 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); | 3311 DCHECK(!p->IsEvacuationCandidate() && !p->SweepingDone()); |
| 3335 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, | 3312 DCHECK_EQ(skip_list_mode == REBUILD_SKIP_LIST, |
| 3336 space->identity() == CODE_SPACE); | 3313 space->identity() == CODE_SPACE); |
| 3337 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); | 3314 DCHECK((p->skip_list() == NULL) || (skip_list_mode == REBUILD_SKIP_LIST)); |
| 3338 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || | 3315 DCHECK(parallelism == MarkCompactCollector::SWEEP_ON_MAIN_THREAD || |
| 3339 sweeping_mode == SWEEP_ONLY); | 3316 sweeping_mode == SWEEP_ONLY); |
| 3340 | 3317 |
| 3341 Address free_start = p->area_start(); | 3318 Address free_start = p->area_start(); |
| 3342 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | 3319 DCHECK(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); |
| 3343 | 3320 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3356 LiveObjectIterator<kBlackObjects> it(p); | 3333 LiveObjectIterator<kBlackObjects> it(p); |
| 3357 HeapObject* object = NULL; | 3334 HeapObject* object = NULL; |
| 3358 while ((object = it.Next()) != NULL) { | 3335 while ((object = it.Next()) != NULL) { |
| 3359 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); | 3336 DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 3360 Address free_end = object->address(); | 3337 Address free_end = object->address(); |
| 3361 if (free_end != free_start) { | 3338 if (free_end != free_start) { |
| 3362 int size = static_cast<int>(free_end - free_start); | 3339 int size = static_cast<int>(free_end - free_start); |
| 3363 if (free_space_mode == ZAP_FREE_SPACE) { | 3340 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3364 memset(free_start, 0xcc, size); | 3341 memset(free_start, 0xcc, size); |
| 3365 } | 3342 } |
| 3366 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3343 freed_bytes = space->UnaccountedFree(free_start, size); |
| 3367 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3344 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3368 } | 3345 } |
| 3369 Map* map = object->synchronized_map(); | 3346 Map* map = object->synchronized_map(); |
| 3370 int size = object->SizeFromMap(map); | 3347 int size = object->SizeFromMap(map); |
| 3371 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { | 3348 if (sweeping_mode == SWEEP_AND_VISIT_LIVE_OBJECTS) { |
| 3372 object->IterateBody(map->instance_type(), size, v); | 3349 object->IterateBody(map->instance_type(), size, v); |
| 3373 } | 3350 } |
| 3374 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { | 3351 if ((skip_list_mode == REBUILD_SKIP_LIST) && skip_list != NULL) { |
| 3375 int new_region_start = SkipList::RegionNumber(free_end); | 3352 int new_region_start = SkipList::RegionNumber(free_end); |
| 3376 int new_region_end = | 3353 int new_region_end = |
| 3377 SkipList::RegionNumber(free_end + size - kPointerSize); | 3354 SkipList::RegionNumber(free_end + size - kPointerSize); |
| 3378 if (new_region_start != curr_region || new_region_end != curr_region) { | 3355 if (new_region_start != curr_region || new_region_end != curr_region) { |
| 3379 skip_list->AddObject(free_end, size); | 3356 skip_list->AddObject(free_end, size); |
| 3380 curr_region = new_region_end; | 3357 curr_region = new_region_end; |
| 3381 } | 3358 } |
| 3382 } | 3359 } |
| 3383 free_start = free_end + size; | 3360 free_start = free_end + size; |
| 3384 } | 3361 } |
| 3385 | 3362 |
| 3386 // Clear the mark bits of that page and reset live bytes count. | 3363 // Clear the mark bits of that page and reset live bytes count. |
| 3387 Bitmap::Clear(p); | 3364 Bitmap::Clear(p); |
| 3388 | 3365 |
| 3389 if (free_start != p->area_end()) { | 3366 if (free_start != p->area_end()) { |
| 3390 int size = static_cast<int>(p->area_end() - free_start); | 3367 int size = static_cast<int>(p->area_end() - free_start); |
| 3391 if (free_space_mode == ZAP_FREE_SPACE) { | 3368 if (free_space_mode == ZAP_FREE_SPACE) { |
| 3392 memset(free_start, 0xcc, size); | 3369 memset(free_start, 0xcc, size); |
| 3393 } | 3370 } |
| 3394 freed_bytes = Free<parallelism>(space, free_list, free_start, size); | 3371 freed_bytes = space->UnaccountedFree(free_start, size); |
| 3395 max_freed_bytes = Max(freed_bytes, max_freed_bytes); | 3372 max_freed_bytes = Max(freed_bytes, max_freed_bytes); |
| 3396 } | 3373 } |
| 3397 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3374 p->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3398 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); | 3375 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); |
| 3399 } | 3376 } |
| 3400 | 3377 |
| 3401 | 3378 |
| 3402 void MarkCompactCollector::InvalidateCode(Code* code) { | 3379 void MarkCompactCollector::InvalidateCode(Code* code) { |
| 3403 if (heap_->incremental_marking()->IsCompacting() && | 3380 if (heap_->incremental_marking()->IsCompacting() && |
| 3404 !ShouldSkipEvacuationSlotRecording(code)) { | 3381 !ShouldSkipEvacuationSlotRecording(code)) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3499 void MarkCompactCollector::SweepAbortedPages() { | 3476 void MarkCompactCollector::SweepAbortedPages() { |
| 3500 // Second pass on aborted pages. | 3477 // Second pass on aborted pages. |
| 3501 for (Page* p : evacuation_candidates_) { | 3478 for (Page* p : evacuation_candidates_) { |
| 3502 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { | 3479 if (p->IsFlagSet(Page::COMPACTION_WAS_ABORTED)) { |
| 3503 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); | 3480 p->ClearFlag(MemoryChunk::COMPACTION_WAS_ABORTED); |
| 3504 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3481 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3505 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3482 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3506 switch (space->identity()) { | 3483 switch (space->identity()) { |
| 3507 case OLD_SPACE: | 3484 case OLD_SPACE: |
| 3508 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3485 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
| 3509 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3486 IGNORE_FREE_SPACE>(space, p, nullptr); |
| 3510 break; | 3487 break; |
| 3511 case CODE_SPACE: | 3488 case CODE_SPACE: |
| 3512 if (FLAG_zap_code_space) { | 3489 if (FLAG_zap_code_space) { |
| 3513 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, | 3490 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, |
| 3514 ZAP_FREE_SPACE>(space, NULL, p, nullptr); | 3491 ZAP_FREE_SPACE>(space, p, nullptr); |
| 3515 } else { | 3492 } else { |
| 3516 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, | 3493 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, REBUILD_SKIP_LIST, |
| 3517 IGNORE_FREE_SPACE>(space, NULL, p, nullptr); | 3494 IGNORE_FREE_SPACE>(space, p, nullptr); |
| 3518 } | 3495 } |
| 3519 break; | 3496 break; |
| 3520 default: | 3497 default: |
| 3521 UNREACHABLE(); | 3498 UNREACHABLE(); |
| 3522 break; | 3499 break; |
| 3523 } | 3500 } |
| 3501 { |
| 3502 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); |
| 3503 swept_pages(space->identity())->Add(p); |
| 3504 } |
| 3524 } | 3505 } |
| 3525 } | 3506 } |
| 3526 } | 3507 } |
| 3527 | 3508 |
| 3528 | 3509 |
| 3529 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 3510 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 3530 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); | 3511 GCTracer::Scope gc_scope(heap()->tracer(), GCTracer::Scope::MC_EVACUATE); |
| 3531 Heap::RelocationLock relocation_lock(heap()); | 3512 Heap::RelocationLock relocation_lock(heap()); |
| 3532 | 3513 |
| 3533 { | 3514 { |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3706 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", | 3687 PrintF("Sweeping 0x%" V8PRIxPTR " during evacuation.\n", |
| 3707 reinterpret_cast<intptr_t>(p)); | 3688 reinterpret_cast<intptr_t>(p)); |
| 3708 } | 3689 } |
| 3709 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3690 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3710 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); | 3691 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); |
| 3711 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3692 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3712 | 3693 |
| 3713 switch (space->identity()) { | 3694 switch (space->identity()) { |
| 3714 case OLD_SPACE: | 3695 case OLD_SPACE: |
| 3715 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, | 3696 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, |
| 3716 IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>(space, NULL, p, | 3697 IGNORE_SKIP_LIST, IGNORE_FREE_SPACE>(space, p, |
| 3717 &updating_visitor); | 3698 &updating_visitor); |
| 3718 break; | 3699 break; |
| 3719 case CODE_SPACE: | 3700 case CODE_SPACE: |
| 3720 if (FLAG_zap_code_space) { | 3701 if (FLAG_zap_code_space) { |
| 3721 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, | 3702 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, |
| 3722 REBUILD_SKIP_LIST, ZAP_FREE_SPACE>(space, NULL, p, | 3703 REBUILD_SKIP_LIST, ZAP_FREE_SPACE>(space, p, |
| 3723 &updating_visitor); | 3704 &updating_visitor); |
| 3724 } else { | 3705 } else { |
| 3725 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, | 3706 Sweep<SWEEP_AND_VISIT_LIVE_OBJECTS, SWEEP_ON_MAIN_THREAD, |
| 3726 REBUILD_SKIP_LIST, IGNORE_FREE_SPACE>(space, NULL, p, | 3707 REBUILD_SKIP_LIST, IGNORE_FREE_SPACE>(space, p, |
| 3727 &updating_visitor); | 3708 &updating_visitor); |
| 3728 } | 3709 } |
| 3729 break; | 3710 break; |
| 3730 default: | 3711 default: |
| 3731 UNREACHABLE(); | 3712 UNREACHABLE(); |
| 3732 break; | 3713 break; |
| 3733 } | 3714 } |
| 3734 } | 3715 } |
| 3735 } | 3716 } |
| 3736 } | 3717 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3747 EvacuationWeakObjectRetainer evacuation_object_retainer; | 3728 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 3748 heap()->ProcessWeakListRoots(&evacuation_object_retainer); | 3729 heap()->ProcessWeakListRoots(&evacuation_object_retainer); |
| 3749 } | 3730 } |
| 3750 } | 3731 } |
| 3751 | 3732 |
| 3752 | 3733 |
| 3753 void MarkCompactCollector::ReleaseEvacuationCandidates() { | 3734 void MarkCompactCollector::ReleaseEvacuationCandidates() { |
| 3754 for (Page* p : evacuation_candidates_) { | 3735 for (Page* p : evacuation_candidates_) { |
| 3755 if (!p->IsEvacuationCandidate()) continue; | 3736 if (!p->IsEvacuationCandidate()) continue; |
| 3756 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 3737 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 3757 space->Free(p->area_start(), p->area_size()); | |
| 3758 p->ResetLiveBytes(); | 3738 p->ResetLiveBytes(); |
| 3759 CHECK(p->SweepingDone()); | 3739 CHECK(p->SweepingDone()); |
| 3760 space->ReleasePage(p, true); | 3740 space->ReleasePage(p); |
| 3761 } | 3741 } |
| 3762 evacuation_candidates_.Rewind(0); | 3742 evacuation_candidates_.Rewind(0); |
| 3763 compacting_ = false; | 3743 compacting_ = false; |
| 3764 heap()->FreeQueuedChunks(); | 3744 heap()->FreeQueuedChunks(); |
| 3765 } | 3745 } |
| 3766 | 3746 |
| 3767 | 3747 |
| 3768 int MarkCompactCollector::SweepInParallel(PagedSpace* space, | 3748 int MarkCompactCollector::SweepInParallel(PagedSpace* space, |
| 3769 int required_freed_bytes, | 3749 int required_freed_bytes, |
| 3770 int max_pages) { | 3750 int max_pages) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3789 | 3769 |
| 3790 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { | 3770 int MarkCompactCollector::SweepInParallel(Page* page, PagedSpace* space) { |
| 3791 int max_freed = 0; | 3771 int max_freed = 0; |
| 3792 if (page->mutex()->TryLock()) { | 3772 if (page->mutex()->TryLock()) { |
| 3793 // If this page was already swept in the meantime, we can return here. | 3773 // If this page was already swept in the meantime, we can return here. |
| 3794 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { | 3774 if (page->concurrent_sweeping_state().Value() != Page::kSweepingPending) { |
| 3795 page->mutex()->Unlock(); | 3775 page->mutex()->Unlock(); |
| 3796 return 0; | 3776 return 0; |
| 3797 } | 3777 } |
| 3798 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3778 page->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3799 FreeList* free_list; | |
| 3800 FreeList private_free_list(space); | |
| 3801 if (space->identity() == OLD_SPACE) { | 3779 if (space->identity() == OLD_SPACE) { |
| 3802 free_list = free_list_old_space_.get(); | 3780 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, |
| 3803 max_freed = | 3781 IGNORE_FREE_SPACE>(space, page, NULL); |
| 3804 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, | |
| 3805 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | |
| 3806 } else if (space->identity() == CODE_SPACE) { | 3782 } else if (space->identity() == CODE_SPACE) { |
| 3807 free_list = free_list_code_space_.get(); | 3783 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, |
| 3808 max_freed = | 3784 IGNORE_FREE_SPACE>(space, page, NULL); |
| 3809 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, REBUILD_SKIP_LIST, | |
| 3810 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | |
| 3811 } else { | 3785 } else { |
| 3812 free_list = free_list_map_space_.get(); | 3786 max_freed = Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, |
| 3813 max_freed = | 3787 IGNORE_FREE_SPACE>(space, page, NULL); |
| 3814 Sweep<SWEEP_ONLY, SWEEP_IN_PARALLEL, IGNORE_SKIP_LIST, | |
| 3815 IGNORE_FREE_SPACE>(space, &private_free_list, page, NULL); | |
| 3816 } | 3788 } |
| 3817 free_list->Concatenate(&private_free_list); | 3789 { |
| 3790 base::LockGuard<base::Mutex> guard(&swept_pages_mutex_); |
| 3791 swept_pages(space->identity())->Add(page); |
| 3792 } |
| 3818 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone); | 3793 page->concurrent_sweeping_state().SetValue(Page::kSweepingDone); |
| 3819 page->mutex()->Unlock(); | 3794 page->mutex()->Unlock(); |
| 3820 } | 3795 } |
| 3821 return max_freed; | 3796 return max_freed; |
| 3822 } | 3797 } |
| 3823 | 3798 |
| 3824 | 3799 |
| 3825 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { | 3800 void MarkCompactCollector::StartSweepSpace(PagedSpace* space) { |
| 3826 space->ClearStats(); | 3801 space->ClearStats(); |
| 3827 | 3802 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3841 continue; | 3816 continue; |
| 3842 } | 3817 } |
| 3843 | 3818 |
| 3844 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { | 3819 if (p->IsFlagSet(Page::NEVER_ALLOCATE_ON_PAGE)) { |
| 3845 // We need to sweep the page to get it into an iterable state again. Note | 3820 // We need to sweep the page to get it into an iterable state again. Note |
| 3846 // that this adds unusable memory into the free list that is later on | 3821 // that this adds unusable memory into the free list that is later on |
| 3847 // (in the free list) dropped again. Since we only use the flag for | 3822 // (in the free list) dropped again. Since we only use the flag for |
| 3848 // testing this is fine. | 3823 // testing this is fine. |
| 3849 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); | 3824 p->concurrent_sweeping_state().SetValue(Page::kSweepingInProgress); |
| 3850 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, | 3825 Sweep<SWEEP_ONLY, SWEEP_ON_MAIN_THREAD, IGNORE_SKIP_LIST, |
| 3851 IGNORE_FREE_SPACE>(space, nullptr, p, nullptr); | 3826 IGNORE_FREE_SPACE>(space, p, nullptr); |
| 3852 continue; | 3827 continue; |
| 3853 } | 3828 } |
| 3854 | 3829 |
| 3855 // One unused page is kept, all further are released before sweeping them. | 3830 // One unused page is kept, all further are released before sweeping them. |
| 3856 if (p->LiveBytes() == 0) { | 3831 if (p->LiveBytes() == 0) { |
| 3857 if (unused_page_present) { | 3832 if (unused_page_present) { |
| 3858 if (FLAG_gc_verbose) { | 3833 if (FLAG_gc_verbose) { |
| 3859 PrintIsolate(isolate(), "sweeping: released page: %p", p); | 3834 PrintIsolate(isolate(), "sweeping: released page: %p", p); |
| 3860 } | 3835 } |
| 3861 space->ReleasePage(p, false); | 3836 space->ReleasePage(p); |
| 3862 continue; | 3837 continue; |
| 3863 } | 3838 } |
| 3864 unused_page_present = true; | 3839 unused_page_present = true; |
| 3865 } | 3840 } |
| 3866 | 3841 |
| 3867 p->concurrent_sweeping_state().SetValue(Page::kSweepingPending); | 3842 p->concurrent_sweeping_state().SetValue(Page::kSweepingPending); |
| 3868 sweeping_list(space).push_back(p); | 3843 sweeping_list(space).push_back(p); |
| 3869 int to_sweep = p->area_size() - p->LiveBytes(); | 3844 int to_sweep = p->area_size() - p->LiveBytes(); |
| 3870 space->accounting_stats_.ShrinkSpace(to_sweep); | 3845 space->accounting_stats_.ShrinkSpace(to_sweep); |
| 3871 will_be_swept++; | 3846 will_be_swept++; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3957 MarkBit mark_bit = Marking::MarkBitFrom(host); | 3932 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 3958 if (Marking::IsBlack(mark_bit)) { | 3933 if (Marking::IsBlack(mark_bit)) { |
| 3959 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); | 3934 RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host); |
| 3960 RecordRelocSlot(host, &rinfo, target); | 3935 RecordRelocSlot(host, &rinfo, target); |
| 3961 } | 3936 } |
| 3962 } | 3937 } |
| 3963 } | 3938 } |
| 3964 | 3939 |
| 3965 } // namespace internal | 3940 } // namespace internal |
| 3966 } // namespace v8 | 3941 } // namespace v8 |
| OLD | NEW |