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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 migration_slots_buffer_(nullptr), | 58 migration_slots_buffer_(nullptr), |
59 heap_(heap), | 59 heap_(heap), |
60 marking_deque_memory_(NULL), | 60 marking_deque_memory_(NULL), |
61 marking_deque_memory_committed_(0), | 61 marking_deque_memory_committed_(0), |
62 code_flusher_(NULL), | 62 code_flusher_(NULL), |
63 have_code_to_deoptimize_(false), | 63 have_code_to_deoptimize_(false), |
64 compacting_(false), | 64 compacting_(false), |
65 sweeping_in_progress_(false), | 65 sweeping_in_progress_(false), |
66 compaction_in_progress_(false), | 66 compaction_in_progress_(false), |
67 pending_sweeper_tasks_semaphore_(0), | 67 pending_sweeper_tasks_semaphore_(0), |
68 pending_compaction_tasks_semaphore_(0), | 68 pending_compaction_tasks_semaphore_(0) { |
69 concurrent_compaction_tasks_active_(0) { | |
70 } | 69 } |
71 | 70 |
72 #ifdef VERIFY_HEAP | 71 #ifdef VERIFY_HEAP |
73 class VerifyMarkingVisitor : public ObjectVisitor { | 72 class VerifyMarkingVisitor : public ObjectVisitor { |
74 public: | 73 public: |
75 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} | 74 explicit VerifyMarkingVisitor(Heap* heap) : heap_(heap) {} |
76 | 75 |
77 void VisitPointers(Object** start, Object** end) override { | 76 void VisitPointers(Object** start, Object** end) override { |
78 for (Object** current = start; current < end; current++) { | 77 for (Object** current = start; current < end; current++) { |
79 if ((*current)->IsHeapObject()) { | 78 if ((*current)->IsHeapObject()) { |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 | 473 |
475 LargeObjectIterator it(heap_->lo_space()); | 474 LargeObjectIterator it(heap_->lo_space()); |
476 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { | 475 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { |
477 Marking::MarkWhite(Marking::MarkBitFrom(obj)); | 476 Marking::MarkWhite(Marking::MarkBitFrom(obj)); |
478 Page::FromAddress(obj->address())->ResetProgressBar(); | 477 Page::FromAddress(obj->address())->ResetProgressBar(); |
479 Page::FromAddress(obj->address())->ResetLiveBytes(); | 478 Page::FromAddress(obj->address())->ResetLiveBytes(); |
480 } | 479 } |
481 } | 480 } |
482 | 481 |
483 | 482 |
484 class MarkCompactCollector::CompactionTask : public v8::Task { | 483 class MarkCompactCollector::CompactionTask : public CancelableTask { |
485 public: | 484 public: |
486 explicit CompactionTask(Heap* heap, CompactionSpaceCollection* spaces) | 485 explicit CompactionTask(Heap* heap, CompactionSpaceCollection* spaces) |
487 : heap_(heap), spaces_(spaces) {} | 486 : CancelableTask(heap->isolate()), spaces_(spaces) {} |
488 | 487 |
489 virtual ~CompactionTask() {} | 488 virtual ~CompactionTask() {} |
490 | 489 |
491 private: | 490 private: |
492 // v8::Task overrides. | 491 // v8::internal::CancelableTask overrides. |
493 void Run() override { | 492 void RunInternal() override { |
494 MarkCompactCollector* mark_compact = heap_->mark_compact_collector(); | 493 MarkCompactCollector* mark_compact = |
| 494 isolate()->heap()->mark_compact_collector(); |
495 SlotsBuffer* evacuation_slots_buffer = nullptr; | 495 SlotsBuffer* evacuation_slots_buffer = nullptr; |
496 mark_compact->EvacuatePages(spaces_, &evacuation_slots_buffer); | 496 mark_compact->EvacuatePages(spaces_, &evacuation_slots_buffer); |
497 mark_compact->AddEvacuationSlotsBufferSynchronized(evacuation_slots_buffer); | 497 mark_compact->AddEvacuationSlotsBufferSynchronized(evacuation_slots_buffer); |
498 mark_compact->pending_compaction_tasks_semaphore_.Signal(); | 498 mark_compact->pending_compaction_tasks_semaphore_.Signal(); |
499 } | 499 } |
500 | 500 |
501 Heap* heap_; | |
502 CompactionSpaceCollection* spaces_; | 501 CompactionSpaceCollection* spaces_; |
503 | 502 |
504 DISALLOW_COPY_AND_ASSIGN(CompactionTask); | 503 DISALLOW_COPY_AND_ASSIGN(CompactionTask); |
505 }; | 504 }; |
506 | 505 |
507 | 506 |
508 class MarkCompactCollector::SweeperTask : public v8::Task { | 507 class MarkCompactCollector::SweeperTask : public v8::Task { |
509 public: | 508 public: |
510 SweeperTask(Heap* heap, PagedSpace* space) : heap_(heap), space_(space) {} | 509 SweeperTask(Heap* heap, PagedSpace* space) : heap_(heap), space_(space) {} |
511 | 510 |
(...skipping 2680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3192 intptr_t live_bytes = 0; | 3191 intptr_t live_bytes = 0; |
3193 intptr_t compaction_speed = 0; | 3192 intptr_t compaction_speed = 0; |
3194 if (FLAG_trace_fragmentation) { | 3193 if (FLAG_trace_fragmentation) { |
3195 for (Page* page : evacuation_candidates_) { | 3194 for (Page* page : evacuation_candidates_) { |
3196 live_bytes += page->LiveBytes(); | 3195 live_bytes += page->LiveBytes(); |
3197 } | 3196 } |
3198 compaction_speed = heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); | 3197 compaction_speed = heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); |
3199 } | 3198 } |
3200 const int num_tasks = NumberOfParallelCompactionTasks(); | 3199 const int num_tasks = NumberOfParallelCompactionTasks(); |
3201 | 3200 |
3202 | |
3203 // Set up compaction spaces. | 3201 // Set up compaction spaces. |
3204 CompactionSpaceCollection** compaction_spaces_for_tasks = | 3202 CompactionSpaceCollection** compaction_spaces_for_tasks = |
3205 new CompactionSpaceCollection*[num_tasks]; | 3203 new CompactionSpaceCollection*[num_tasks]; |
3206 for (int i = 0; i < num_tasks; i++) { | 3204 for (int i = 0; i < num_tasks; i++) { |
3207 compaction_spaces_for_tasks[i] = new CompactionSpaceCollection(heap()); | 3205 compaction_spaces_for_tasks[i] = new CompactionSpaceCollection(heap()); |
3208 } | 3206 } |
3209 | 3207 |
3210 heap()->old_space()->DivideUponCompactionSpaces(compaction_spaces_for_tasks, | 3208 heap()->old_space()->DivideUponCompactionSpaces(compaction_spaces_for_tasks, |
3211 num_tasks); | 3209 num_tasks); |
3212 heap()->code_space()->DivideUponCompactionSpaces(compaction_spaces_for_tasks, | 3210 heap()->code_space()->DivideUponCompactionSpaces(compaction_spaces_for_tasks, |
3213 num_tasks); | 3211 num_tasks); |
3214 | 3212 |
3215 compaction_in_progress_ = true; | 3213 uint32_t* task_ids = new uint32_t[num_tasks - 1]; |
3216 // Kick off parallel tasks. | 3214 // Kick off parallel tasks. |
3217 for (int i = 1; i < num_tasks; i++) { | 3215 StartParallelCompaction(compaction_spaces_for_tasks, task_ids, num_tasks); |
3218 concurrent_compaction_tasks_active_++; | 3216 // Wait for unfinished and not-yet-started tasks. |
3219 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 3217 WaitUntilCompactionCompleted(task_ids, num_tasks - 1); |
3220 new CompactionTask(heap(), compaction_spaces_for_tasks[i]), | 3218 delete[] task_ids; |
3221 v8::Platform::kShortRunningTask); | |
3222 } | |
3223 | |
3224 // Contribute in main thread. Counter and signal are in principal not needed. | |
3225 EvacuatePages(compaction_spaces_for_tasks[0], &migration_slots_buffer_); | |
3226 | |
3227 WaitUntilCompactionCompleted(); | |
3228 | 3219 |
3229 double compaction_duration = 0.0; | 3220 double compaction_duration = 0.0; |
3230 intptr_t compacted_memory = 0; | 3221 intptr_t compacted_memory = 0; |
3231 // Merge back memory (compacted and unused) from compaction spaces. | 3222 // Merge back memory (compacted and unused) from compaction spaces. |
3232 for (int i = 0; i < num_tasks; i++) { | 3223 for (int i = 0; i < num_tasks; i++) { |
3233 heap()->old_space()->MergeCompactionSpace( | 3224 heap()->old_space()->MergeCompactionSpace( |
3234 compaction_spaces_for_tasks[i]->Get(OLD_SPACE)); | 3225 compaction_spaces_for_tasks[i]->Get(OLD_SPACE)); |
3235 heap()->code_space()->MergeCompactionSpace( | 3226 heap()->code_space()->MergeCompactionSpace( |
3236 compaction_spaces_for_tasks[i]->Get(CODE_SPACE)); | 3227 compaction_spaces_for_tasks[i]->Get(CODE_SPACE)); |
3237 compacted_memory += compaction_spaces_for_tasks[i]->bytes_compacted(); | 3228 compacted_memory += compaction_spaces_for_tasks[i]->bytes_compacted(); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3283 "tasks=%d cores=%d live_bytes=%" V8_PTR_PREFIX | 3274 "tasks=%d cores=%d live_bytes=%" V8_PTR_PREFIX |
3284 "d compaction_speed=%" V8_PTR_PREFIX "d\n", | 3275 "d compaction_speed=%" V8_PTR_PREFIX "d\n", |
3285 isolate()->time_millis_since_init(), FLAG_parallel_compaction, | 3276 isolate()->time_millis_since_init(), FLAG_parallel_compaction, |
3286 num_pages, abandoned_pages, num_tasks, | 3277 num_pages, abandoned_pages, num_tasks, |
3287 base::SysInfo::NumberOfProcessors(), live_bytes, | 3278 base::SysInfo::NumberOfProcessors(), live_bytes, |
3288 compaction_speed); | 3279 compaction_speed); |
3289 } | 3280 } |
3290 } | 3281 } |
3291 | 3282 |
3292 | 3283 |
3293 void MarkCompactCollector::WaitUntilCompactionCompleted() { | 3284 void MarkCompactCollector::StartParallelCompaction( |
3294 while (concurrent_compaction_tasks_active_ > 0) { | 3285 CompactionSpaceCollection** compaction_spaces, uint32_t* task_ids, |
3295 pending_compaction_tasks_semaphore_.Wait(); | 3286 int len) { |
3296 concurrent_compaction_tasks_active_--; | 3287 compaction_in_progress_ = true; |
| 3288 for (int i = 1; i < len; i++) { |
| 3289 CompactionTask* task = new CompactionTask(heap(), compaction_spaces[i]); |
| 3290 task_ids[i - 1] = task->id(); |
| 3291 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 3292 task, v8::Platform::kShortRunningTask); |
| 3293 } |
| 3294 |
| 3295 // Contribute in main thread. |
| 3296 EvacuatePages(compaction_spaces[0], &migration_slots_buffer_); |
| 3297 } |
| 3298 |
| 3299 |
| 3300 void MarkCompactCollector::WaitUntilCompactionCompleted(uint32_t* task_ids, |
| 3301 int len) { |
| 3302 // Try to cancel compaction tasks that have not been run (as they might be |
| 3303 // stuck in a worker queue). Tasks that cannot be canceled, have either |
| 3304 // already completed or are still running, hence we need to wait for their |
| 3305 // semaphore signal. |
| 3306 for (int i = 0; i < len; i++) { |
| 3307 if (!heap()->isolate()->cancelable_task_manager()->TryAbort(task_ids[i])) { |
| 3308 pending_compaction_tasks_semaphore_.Wait(); |
| 3309 } |
3297 } | 3310 } |
3298 compaction_in_progress_ = false; | 3311 compaction_in_progress_ = false; |
3299 } | 3312 } |
3300 | 3313 |
3301 | 3314 |
3302 void MarkCompactCollector::EvacuatePages( | 3315 void MarkCompactCollector::EvacuatePages( |
3303 CompactionSpaceCollection* compaction_spaces, | 3316 CompactionSpaceCollection* compaction_spaces, |
3304 SlotsBuffer** evacuation_slots_buffer) { | 3317 SlotsBuffer** evacuation_slots_buffer) { |
3305 for (int i = 0; i < evacuation_candidates_.length(); i++) { | 3318 for (int i = 0; i < evacuation_candidates_.length(); i++) { |
3306 Page* p = evacuation_candidates_[i]; | 3319 Page* p = evacuation_candidates_[i]; |
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4476 MarkBit mark_bit = Marking::MarkBitFrom(host); | 4489 MarkBit mark_bit = Marking::MarkBitFrom(host); |
4477 if (Marking::IsBlack(mark_bit)) { | 4490 if (Marking::IsBlack(mark_bit)) { |
4478 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); | 4491 RelocInfo rinfo(pc, RelocInfo::CODE_TARGET, 0, host); |
4479 RecordRelocSlot(&rinfo, target); | 4492 RecordRelocSlot(&rinfo, target); |
4480 } | 4493 } |
4481 } | 4494 } |
4482 } | 4495 } |
4483 | 4496 |
4484 } // namespace internal | 4497 } // namespace internal |
4485 } // namespace v8 | 4498 } // namespace v8 |
OLD | NEW |