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 |