| 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/code-stubs.h" | 10 #include "src/code-stubs.h" |
| 10 #include "src/compilation-cache.h" | 11 #include "src/compilation-cache.h" |
| 11 #include "src/cpu-profiler.h" | 12 #include "src/cpu-profiler.h" |
| 12 #include "src/deoptimizer.h" | 13 #include "src/deoptimizer.h" |
| 13 #include "src/execution.h" | 14 #include "src/execution.h" |
| 14 #include "src/frames-inl.h" | 15 #include "src/frames-inl.h" |
| 15 #include "src/gdb-jit.h" | 16 #include "src/gdb-jit.h" |
| 16 #include "src/global-handles.h" | 17 #include "src/global-handles.h" |
| 17 #include "src/heap/array-buffer-tracker.h" | 18 #include "src/heap/array-buffer-tracker.h" |
| 18 #include "src/heap/gc-tracer.h" | 19 #include "src/heap/gc-tracer.h" |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 } | 566 } |
| 566 | 567 |
| 567 ParallelSweepSpacesComplete(); | 568 ParallelSweepSpacesComplete(); |
| 568 sweeping_in_progress_ = false; | 569 sweeping_in_progress_ = false; |
| 569 RefillFreeList(heap()->paged_space(OLD_SPACE)); | 570 RefillFreeList(heap()->paged_space(OLD_SPACE)); |
| 570 RefillFreeList(heap()->paged_space(CODE_SPACE)); | 571 RefillFreeList(heap()->paged_space(CODE_SPACE)); |
| 571 RefillFreeList(heap()->paged_space(MAP_SPACE)); | 572 RefillFreeList(heap()->paged_space(MAP_SPACE)); |
| 572 heap()->paged_space(OLD_SPACE)->ResetUnsweptFreeBytes(); | 573 heap()->paged_space(OLD_SPACE)->ResetUnsweptFreeBytes(); |
| 573 heap()->paged_space(CODE_SPACE)->ResetUnsweptFreeBytes(); | 574 heap()->paged_space(CODE_SPACE)->ResetUnsweptFreeBytes(); |
| 574 heap()->paged_space(MAP_SPACE)->ResetUnsweptFreeBytes(); | 575 heap()->paged_space(MAP_SPACE)->ResetUnsweptFreeBytes(); |
| 575 | |
| 576 #ifdef VERIFY_HEAP | 576 #ifdef VERIFY_HEAP |
| 577 if (FLAG_verify_heap && !evacuation()) { | 577 if (FLAG_verify_heap && !evacuation()) { |
| 578 VerifyEvacuation(heap_); | 578 VerifyEvacuation(heap_); |
| 579 } | 579 } |
| 580 #endif | 580 #endif |
| 581 } | 581 } |
| 582 | 582 |
| 583 | 583 |
| 584 bool MarkCompactCollector::IsSweepingCompleted() { | 584 bool MarkCompactCollector::IsSweepingCompleted() { |
| 585 if (!pending_sweeper_tasks_semaphore_.WaitFor( | 585 if (!pending_sweeper_tasks_semaphore_.WaitFor( |
| 586 base::TimeDelta::FromSeconds(0))) { | 586 base::TimeDelta::FromSeconds(0))) { |
| 587 return false; | 587 return false; |
| 588 } | 588 } |
| 589 pending_sweeper_tasks_semaphore_.Signal(); | 589 pending_sweeper_tasks_semaphore_.Signal(); |
| 590 return true; | 590 return true; |
| 591 } | 591 } |
| 592 | 592 |
| 593 | 593 |
| 594 void MarkCompactCollector::RefillFreeList(PagedSpace* space) { | 594 void MarkCompactCollector::RefillFreeList(PagedSpace* space) { |
| 595 FreeList* free_list; | 595 FreeList* free_list; |
| 596 | |
| 597 if (space == heap()->old_space()) { | 596 if (space == heap()->old_space()) { |
| 598 free_list = free_list_old_space_.get(); | 597 free_list = free_list_old_space_.get(); |
| 599 } else if (space == heap()->code_space()) { | 598 } else if (space == heap()->code_space()) { |
| 600 free_list = free_list_code_space_.get(); | 599 free_list = free_list_code_space_.get(); |
| 601 } else if (space == heap()->map_space()) { | 600 } else if (space == heap()->map_space()) { |
| 602 free_list = free_list_map_space_.get(); | 601 free_list = free_list_map_space_.get(); |
| 603 } else { | 602 } else { |
| 604 // Any PagedSpace might invoke RefillFreeLists, so we need to make sure | 603 // Any PagedSpace might invoke RefillFreeLists, so we need to make sure |
| 605 // to only refill them for the old space. | 604 // to only refill them for the old space. |
| 606 return; | 605 return; |
| (...skipping 2756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3363 } | 3362 } |
| 3364 | 3363 |
| 3365 // Clear marking bits for current cell. | 3364 // Clear marking bits for current cell. |
| 3366 *cell = 0; | 3365 *cell = 0; |
| 3367 } | 3366 } |
| 3368 p->ResetLiveBytes(); | 3367 p->ResetLiveBytes(); |
| 3369 return true; | 3368 return true; |
| 3370 } | 3369 } |
| 3371 | 3370 |
| 3372 | 3371 |
| 3372 int MarkCompactCollector::NumberOfParallelCompactionTasks() { |
| 3373 if (!FLAG_parallel_compaction) return 1; |
| 3374 // We cap the number of parallel compaction tasks by |
| 3375 // - (#cores - 1) |
| 3376 // - a value depending on the list of evacuation candidates |
| 3377 // - a hard limit |
| 3378 const int kPagesPerCompactionTask = 4; |
| 3379 const int kMaxCompactionTasks = 8; |
| 3380 return Min(kMaxCompactionTasks, |
| 3381 Min(1 + evacuation_candidates_.length() / kPagesPerCompactionTask, |
| 3382 Max(1, base::SysInfo::NumberOfProcessors() - 1))); |
| 3383 } |
| 3384 |
| 3385 |
| 3373 void MarkCompactCollector::EvacuatePagesInParallel() { | 3386 void MarkCompactCollector::EvacuatePagesInParallel() { |
| 3374 if (evacuation_candidates_.length() == 0) return; | 3387 if (evacuation_candidates_.length() == 0) return; |
| 3375 | 3388 |
| 3376 int num_tasks = 1; | 3389 const int num_tasks = NumberOfParallelCompactionTasks(); |
| 3377 if (FLAG_parallel_compaction) { | |
| 3378 num_tasks = NumberOfParallelCompactionTasks(); | |
| 3379 } | |
| 3380 | 3390 |
| 3381 // Set up compaction spaces. | 3391 // Set up compaction spaces. |
| 3382 CompactionSpaceCollection** compaction_spaces_for_tasks = | 3392 CompactionSpaceCollection** spaces_for_tasks = |
| 3383 new CompactionSpaceCollection*[num_tasks]; | 3393 new CompactionSpaceCollection*[num_tasks]; |
| 3384 for (int i = 0; i < num_tasks; i++) { | 3394 for (int i = 0; i < num_tasks; i++) { |
| 3385 compaction_spaces_for_tasks[i] = new CompactionSpaceCollection(heap()); | 3395 spaces_for_tasks[i] = new CompactionSpaceCollection(heap()); |
| 3386 } | 3396 } |
| 3387 | 3397 heap()->old_space()->DivideMemory(spaces_for_tasks, num_tasks, 1 * MB); |
| 3388 compaction_spaces_for_tasks[0]->Get(OLD_SPACE)->MoveOverFreeMemory( | 3398 heap()->code_space()->DivideMemory(spaces_for_tasks, num_tasks, 1 * MB); |
| 3389 heap()->old_space()); | |
| 3390 compaction_spaces_for_tasks[0] | |
| 3391 ->Get(CODE_SPACE) | |
| 3392 ->MoveOverFreeMemory(heap()->code_space()); | |
| 3393 | 3399 |
| 3394 compaction_in_progress_ = true; | 3400 compaction_in_progress_ = true; |
| 3395 // Kick off parallel tasks. | 3401 // Kick off parallel tasks. |
| 3396 for (int i = 1; i < num_tasks; i++) { | 3402 for (int i = 1; i < num_tasks; i++) { |
| 3397 concurrent_compaction_tasks_active_++; | 3403 concurrent_compaction_tasks_active_++; |
| 3398 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 3404 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 3399 new CompactionTask(heap(), compaction_spaces_for_tasks[i]), | 3405 new CompactionTask(heap(), spaces_for_tasks[i]), |
| 3400 v8::Platform::kShortRunningTask); | 3406 v8::Platform::kShortRunningTask); |
| 3401 } | 3407 } |
| 3402 | 3408 |
| 3403 // Contribute in main thread. Counter and signal are in principal not needed. | 3409 // Perform compaction on the main thread. |
| 3404 concurrent_compaction_tasks_active_++; | 3410 EvacuatePages(spaces_for_tasks[0], &migration_slots_buffer_); |
| 3405 EvacuatePages(compaction_spaces_for_tasks[0], &migration_slots_buffer_); | |
| 3406 pending_compaction_tasks_semaphore_.Signal(); | |
| 3407 | 3411 |
| 3408 WaitUntilCompactionCompleted(); | 3412 WaitUntilCompactionCompleted(); |
| 3409 | 3413 |
| 3410 // Merge back memory (compacted and unused) from compaction spaces. | 3414 // Merge back memory (compacted and unused) from compaction spaces. |
| 3411 for (int i = 0; i < num_tasks; i++) { | 3415 for (int i = 0; i < num_tasks; i++) { |
| 3412 heap()->old_space()->MergeCompactionSpace( | 3416 heap()->old_space()->MergeCompactionSpace( |
| 3413 compaction_spaces_for_tasks[i]->Get(OLD_SPACE)); | 3417 spaces_for_tasks[i]->Get(OLD_SPACE)); |
| 3414 heap()->code_space()->MergeCompactionSpace( | 3418 heap()->code_space()->MergeCompactionSpace( |
| 3415 compaction_spaces_for_tasks[i]->Get(CODE_SPACE)); | 3419 spaces_for_tasks[i]->Get(CODE_SPACE)); |
| 3416 delete compaction_spaces_for_tasks[i]; | 3420 delete spaces_for_tasks[i]; |
| 3417 } | 3421 } |
| 3418 delete[] compaction_spaces_for_tasks; | 3422 delete[] spaces_for_tasks; |
| 3419 | 3423 |
| 3420 // Finalize sequentially. | 3424 // Finalize sequentially. |
| 3421 const int num_pages = evacuation_candidates_.length(); | 3425 const int num_pages = evacuation_candidates_.length(); |
| 3422 int abandoned_pages = 0; | 3426 int abandoned_pages = 0; |
| 3423 for (int i = 0; i < num_pages; i++) { | 3427 for (int i = 0; i < num_pages; i++) { |
| 3424 Page* p = evacuation_candidates_[i]; | 3428 Page* p = evacuation_candidates_[i]; |
| 3425 switch (p->parallel_compaction_state().Value()) { | 3429 switch (p->parallel_compaction_state().Value()) { |
| 3426 case MemoryChunk::ParallelCompactingState::kCompactingAborted: | 3430 case MemoryChunk::ParallelCompactingState::kCompactingAborted: |
| 3427 // We have partially compacted the page, i.e., some objects may have | 3431 // We have partially compacted the page, i.e., some objects may have |
| 3428 // moved, others are still in place. | 3432 // moved, others are still in place. |
| (...skipping 1160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4589 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4593 MarkBit mark_bit = Marking::MarkBitFrom(host); |
| 4590 if (Marking::IsBlack(mark_bit)) { | 4594 if (Marking::IsBlack(mark_bit)) { |
| 4591 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); | 4595 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); |
| 4592 RecordRelocSlot(&rinfo, target); | 4596 RecordRelocSlot(&rinfo, target); |
| 4593 } | 4597 } |
| 4594 } | 4598 } |
| 4595 } | 4599 } |
| 4596 | 4600 |
| 4597 } // namespace internal | 4601 } // namespace internal |
| 4598 } // namespace v8 | 4602 } // namespace v8 |
| OLD | NEW |