| 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/v8.h" | 5 #include "src/v8.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/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-cache.h" | 10 #include "src/compilation-cache.h" |
| 11 #include "src/cpu-profiler.h" | 11 #include "src/cpu-profiler.h" |
| 12 #include "src/deoptimizer.h" | 12 #include "src/deoptimizer.h" |
| 13 #include "src/execution.h" | 13 #include "src/execution.h" |
| 14 #include "src/gdb-jit.h" | 14 #include "src/gdb-jit.h" |
| 15 #include "src/global-handles.h" | 15 #include "src/global-handles.h" |
| 16 #include "src/heap/incremental-marking.h" | 16 #include "src/heap/incremental-marking.h" |
| 17 #include "src/heap/mark-compact.h" | 17 #include "src/heap/mark-compact.h" |
| 18 #include "src/heap/objects-visiting.h" | 18 #include "src/heap/objects-visiting.h" |
| 19 #include "src/heap/objects-visiting-inl.h" | 19 #include "src/heap/objects-visiting-inl.h" |
| 20 #include "src/heap/spaces-inl.h" | 20 #include "src/heap/spaces-inl.h" |
| 21 #include "src/heap/sweeper-thread.h" | |
| 22 #include "src/heap-profiler.h" | 21 #include "src/heap-profiler.h" |
| 23 #include "src/ic/ic.h" | 22 #include "src/ic/ic.h" |
| 24 #include "src/ic/stub-cache.h" | 23 #include "src/ic/stub-cache.h" |
| 25 | 24 |
| 26 namespace v8 { | 25 namespace v8 { |
| 27 namespace internal { | 26 namespace internal { |
| 28 | 27 |
| 29 | 28 |
| 30 const char* Marking::kWhiteBitPattern = "00"; | 29 const char* Marking::kWhiteBitPattern = "00"; |
| 31 const char* Marking::kBlackBitPattern = "10"; | 30 const char* Marking::kBlackBitPattern = "10"; |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 PagedSpace* space_; | 549 PagedSpace* space_; |
| 551 | 550 |
| 552 DISALLOW_COPY_AND_ASSIGN(SweeperTask); | 551 DISALLOW_COPY_AND_ASSIGN(SweeperTask); |
| 553 }; | 552 }; |
| 554 | 553 |
| 555 | 554 |
| 556 void MarkCompactCollector::StartSweeperThreads() { | 555 void MarkCompactCollector::StartSweeperThreads() { |
| 557 DCHECK(free_list_old_pointer_space_.get()->IsEmpty()); | 556 DCHECK(free_list_old_pointer_space_.get()->IsEmpty()); |
| 558 DCHECK(free_list_old_data_space_.get()->IsEmpty()); | 557 DCHECK(free_list_old_data_space_.get()->IsEmpty()); |
| 559 sweeping_in_progress_ = true; | 558 sweeping_in_progress_ = true; |
| 560 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 559 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 561 isolate()->sweeper_threads()[i]->StartSweeping(); | 560 new SweeperTask(heap(), heap()->old_data_space()), |
| 562 } | 561 v8::Platform::kShortRunningTask); |
| 563 if (FLAG_job_based_sweeping) { | 562 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 564 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 563 new SweeperTask(heap(), heap()->old_pointer_space()), |
| 565 new SweeperTask(heap(), heap()->old_data_space()), | 564 v8::Platform::kShortRunningTask); |
| 566 v8::Platform::kShortRunningTask); | |
| 567 V8::GetCurrentPlatform()->CallOnBackgroundThread( | |
| 568 new SweeperTask(heap(), heap()->old_pointer_space()), | |
| 569 v8::Platform::kShortRunningTask); | |
| 570 } | |
| 571 } | 565 } |
| 572 | 566 |
| 573 | 567 |
| 574 void MarkCompactCollector::EnsureSweepingCompleted() { | 568 void MarkCompactCollector::EnsureSweepingCompleted() { |
| 575 DCHECK(sweeping_in_progress_ == true); | 569 DCHECK(sweeping_in_progress_ == true); |
| 576 | 570 |
| 577 // If sweeping is not completed, we try to complete it here. If we do not | 571 // If sweeping is not completed or not running at all, we try to complete it |
| 578 // have sweeper threads we have to complete since we do not have a good | 572 // here. |
| 579 // indicator for a swept space in that case. | 573 if (!IsSweepingCompleted()) { |
| 580 if (!AreSweeperThreadsActivated() || !IsSweepingCompleted()) { | |
| 581 SweepInParallel(heap()->paged_space(OLD_DATA_SPACE), 0); | 574 SweepInParallel(heap()->paged_space(OLD_DATA_SPACE), 0); |
| 582 SweepInParallel(heap()->paged_space(OLD_POINTER_SPACE), 0); | 575 SweepInParallel(heap()->paged_space(OLD_POINTER_SPACE), 0); |
| 583 } | 576 } |
| 584 | 577 // Wait twice for both jobs. |
| 585 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 578 pending_sweeper_jobs_semaphore_.Wait(); |
| 586 isolate()->sweeper_threads()[i]->WaitForSweeperThread(); | 579 pending_sweeper_jobs_semaphore_.Wait(); |
| 587 } | |
| 588 if (FLAG_job_based_sweeping) { | |
| 589 // Wait twice for both jobs. | |
| 590 pending_sweeper_jobs_semaphore_.Wait(); | |
| 591 pending_sweeper_jobs_semaphore_.Wait(); | |
| 592 } | |
| 593 ParallelSweepSpacesComplete(); | 580 ParallelSweepSpacesComplete(); |
| 594 sweeping_in_progress_ = false; | 581 sweeping_in_progress_ = false; |
| 595 RefillFreeList(heap()->paged_space(OLD_DATA_SPACE)); | 582 RefillFreeList(heap()->paged_space(OLD_DATA_SPACE)); |
| 596 RefillFreeList(heap()->paged_space(OLD_POINTER_SPACE)); | 583 RefillFreeList(heap()->paged_space(OLD_POINTER_SPACE)); |
| 597 heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes(); | 584 heap()->paged_space(OLD_DATA_SPACE)->ResetUnsweptFreeBytes(); |
| 598 heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes(); | 585 heap()->paged_space(OLD_POINTER_SPACE)->ResetUnsweptFreeBytes(); |
| 599 | 586 |
| 600 #ifdef VERIFY_HEAP | 587 #ifdef VERIFY_HEAP |
| 601 if (FLAG_verify_heap) { | 588 if (FLAG_verify_heap) { |
| 602 VerifyEvacuation(heap_); | 589 VerifyEvacuation(heap_); |
| 603 } | 590 } |
| 604 #endif | 591 #endif |
| 605 } | 592 } |
| 606 | 593 |
| 607 | 594 |
| 608 bool MarkCompactCollector::IsSweepingCompleted() { | 595 bool MarkCompactCollector::IsSweepingCompleted() { |
| 609 for (int i = 0; i < isolate()->num_sweeper_threads(); i++) { | 596 if (!pending_sweeper_jobs_semaphore_.WaitFor( |
| 610 if (!isolate()->sweeper_threads()[i]->SweepingCompleted()) { | 597 base::TimeDelta::FromSeconds(0))) { |
| 611 return false; | 598 return false; |
| 612 } | |
| 613 } | 599 } |
| 614 | 600 pending_sweeper_jobs_semaphore_.Signal(); |
| 615 if (FLAG_job_based_sweeping) { | |
| 616 if (!pending_sweeper_jobs_semaphore_.WaitFor( | |
| 617 base::TimeDelta::FromSeconds(0))) { | |
| 618 return false; | |
| 619 } | |
| 620 pending_sweeper_jobs_semaphore_.Signal(); | |
| 621 } | |
| 622 | |
| 623 return true; | 601 return true; |
| 624 } | 602 } |
| 625 | 603 |
| 626 | 604 |
| 627 void MarkCompactCollector::RefillFreeList(PagedSpace* space) { | 605 void MarkCompactCollector::RefillFreeList(PagedSpace* space) { |
| 628 FreeList* free_list; | 606 FreeList* free_list; |
| 629 | 607 |
| 630 if (space == heap()->old_pointer_space()) { | 608 if (space == heap()->old_pointer_space()) { |
| 631 free_list = free_list_old_pointer_space_.get(); | 609 free_list = free_list_old_pointer_space_.get(); |
| 632 } else if (space == heap()->old_data_space()) { | 610 } else if (space == heap()->old_data_space()) { |
| 633 free_list = free_list_old_data_space_.get(); | 611 free_list = free_list_old_data_space_.get(); |
| 634 } else { | 612 } else { |
| 635 // Any PagedSpace might invoke RefillFreeLists, so we need to make sure | 613 // Any PagedSpace might invoke RefillFreeLists, so we need to make sure |
| 636 // to only refill them for old data and pointer spaces. | 614 // to only refill them for old data and pointer spaces. |
| 637 return; | 615 return; |
| 638 } | 616 } |
| 639 | 617 |
| 640 intptr_t freed_bytes = space->free_list()->Concatenate(free_list); | 618 intptr_t freed_bytes = space->free_list()->Concatenate(free_list); |
| 641 space->AddToAccountingStats(freed_bytes); | 619 space->AddToAccountingStats(freed_bytes); |
| 642 space->DecrementUnsweptFreeBytes(freed_bytes); | 620 space->DecrementUnsweptFreeBytes(freed_bytes); |
| 643 } | 621 } |
| 644 | 622 |
| 645 | 623 |
| 646 bool MarkCompactCollector::AreSweeperThreadsActivated() { | |
| 647 return isolate()->sweeper_threads() != NULL || FLAG_job_based_sweeping; | |
| 648 } | |
| 649 | |
| 650 | |
| 651 void Marking::TransferMark(Address old_start, Address new_start) { | 624 void Marking::TransferMark(Address old_start, Address new_start) { |
| 652 // This is only used when resizing an object. | 625 // This is only used when resizing an object. |
| 653 DCHECK(MemoryChunk::FromAddress(old_start) == | 626 DCHECK(MemoryChunk::FromAddress(old_start) == |
| 654 MemoryChunk::FromAddress(new_start)); | 627 MemoryChunk::FromAddress(new_start)); |
| 655 | 628 |
| 656 if (!heap_->incremental_marking()->IsMarking()) return; | 629 if (!heap_->incremental_marking()->IsMarking()) return; |
| 657 | 630 |
| 658 // If the mark doesn't move, we don't check the color of the object. | 631 // If the mark doesn't move, we don't check the color of the object. |
| 659 // It doesn't matter whether the object is black, since it hasn't changed | 632 // It doesn't matter whether the object is black, since it hasn't changed |
| 660 // size, so the adjustment to the live data count will be zero anyway. | 633 // size, so the adjustment to the live data count will be zero anyway. |
| (...skipping 3578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4239 PrintF("SweepSpace: %s (%d pages swept)\n", | 4212 PrintF("SweepSpace: %s (%d pages swept)\n", |
| 4240 AllocationSpaceName(space->identity()), pages_swept); | 4213 AllocationSpaceName(space->identity()), pages_swept); |
| 4241 } | 4214 } |
| 4242 | 4215 |
| 4243 // Give pages that are queued to be freed back to the OS. | 4216 // Give pages that are queued to be freed back to the OS. |
| 4244 heap()->FreeQueuedChunks(); | 4217 heap()->FreeQueuedChunks(); |
| 4245 } | 4218 } |
| 4246 | 4219 |
| 4247 | 4220 |
| 4248 static bool ShouldStartSweeperThreads(MarkCompactCollector::SweeperType type) { | 4221 static bool ShouldStartSweeperThreads(MarkCompactCollector::SweeperType type) { |
| 4249 return type == MarkCompactCollector::PARALLEL_SWEEPING || | 4222 return (type == MarkCompactCollector::PARALLEL_SWEEPING || |
| 4250 type == MarkCompactCollector::CONCURRENT_SWEEPING; | 4223 type == MarkCompactCollector::CONCURRENT_SWEEPING) && |
| 4224 !FLAG_predictable; |
| 4251 } | 4225 } |
| 4252 | 4226 |
| 4253 | 4227 |
| 4254 static bool ShouldWaitForSweeperThreads( | 4228 static bool ShouldWaitForSweeperThreads( |
| 4255 MarkCompactCollector::SweeperType type) { | 4229 MarkCompactCollector::SweeperType type) { |
| 4256 return type == MarkCompactCollector::PARALLEL_SWEEPING; | 4230 return type == MarkCompactCollector::PARALLEL_SWEEPING; |
| 4257 } | 4231 } |
| 4258 | 4232 |
| 4259 | 4233 |
| 4260 void MarkCompactCollector::SweepSpaces() { | 4234 void MarkCompactCollector::SweepSpaces() { |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4553 SlotsBuffer* buffer = *buffer_address; | 4527 SlotsBuffer* buffer = *buffer_address; |
| 4554 while (buffer != NULL) { | 4528 while (buffer != NULL) { |
| 4555 SlotsBuffer* next_buffer = buffer->next(); | 4529 SlotsBuffer* next_buffer = buffer->next(); |
| 4556 DeallocateBuffer(buffer); | 4530 DeallocateBuffer(buffer); |
| 4557 buffer = next_buffer; | 4531 buffer = next_buffer; |
| 4558 } | 4532 } |
| 4559 *buffer_address = NULL; | 4533 *buffer_address = NULL; |
| 4560 } | 4534 } |
| 4561 } | 4535 } |
| 4562 } // namespace v8::internal | 4536 } // namespace v8::internal |
| OLD | NEW |