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 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 } | 328 } |
329 }; | 329 }; |
330 | 330 |
331 } // namespace | 331 } // namespace |
332 #endif // VERIFY_HEAP | 332 #endif // VERIFY_HEAP |
333 | 333 |
334 // ============================================================================= | 334 // ============================================================================= |
335 // MarkCompactCollectorBase, MinorMarkCompactCollector, MarkCompactCollector | 335 // MarkCompactCollectorBase, MinorMarkCompactCollector, MarkCompactCollector |
336 // ============================================================================= | 336 // ============================================================================= |
337 | 337 |
338 int MarkCompactCollectorBase::NumberOfParallelCompactionTasks( | 338 int MarkCompactCollectorBase::NumberOfParallelCompactionTasks(int pages) { |
339 int pages, intptr_t live_bytes) { | |
340 if (!FLAG_parallel_compaction) return 1; | 339 if (!FLAG_parallel_compaction) return 1; |
341 // Compute the number of needed tasks based on a target compaction time, the | |
342 // profiled compaction speed and marked live memory. | |
343 // | |
344 // The number of parallel compaction tasks is limited by: | |
345 // - #evacuation pages | |
346 // - #cores | |
347 const double kTargetCompactionTimeInMs = .5; | |
348 | |
349 double compaction_speed = | |
350 heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); | |
351 | |
352 const int available_cores = Max( | 340 const int available_cores = Max( |
353 1, static_cast<int>( | 341 1, static_cast<int>( |
354 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); | 342 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); |
355 int tasks; | 343 return Min(available_cores, pages); |
356 if (compaction_speed > 0) { | 344 } |
357 tasks = 1 + static_cast<int>(live_bytes / compaction_speed / | 345 |
358 kTargetCompactionTimeInMs); | 346 int MarkCompactCollectorBase::NumberOfPointerUpdateTasks(int pages) { |
359 } else { | 347 if (!FLAG_parallel_pointer_update) return 1; |
360 tasks = pages; | 348 const int available_cores = Max( |
361 } | 349 1, static_cast<int>( |
362 const int tasks_capped_pages = Min(pages, tasks); | 350 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); |
363 return Min(available_cores, tasks_capped_pages); | 351 return Min(available_cores, pages); |
364 } | 352 } |
365 | 353 |
366 MarkCompactCollector::MarkCompactCollector(Heap* heap) | 354 MarkCompactCollector::MarkCompactCollector(Heap* heap) |
367 : MarkCompactCollectorBase(heap), | 355 : MarkCompactCollectorBase(heap), |
368 page_parallel_job_semaphore_(0), | 356 page_parallel_job_semaphore_(0), |
369 #ifdef DEBUG | 357 #ifdef DEBUG |
370 state_(IDLE), | 358 state_(IDLE), |
371 #endif | 359 #endif |
372 was_marked_incrementally_(false), | 360 was_marked_incrementally_(false), |
373 evacuation_(false), | 361 evacuation_(false), |
(...skipping 3363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3737 compaction_speed = heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); | 3725 compaction_speed = heap()->tracer()->CompactionSpeedInBytesPerMillisecond(); |
3738 } | 3726 } |
3739 | 3727 |
3740 const bool profiling = | 3728 const bool profiling = |
3741 heap()->isolate()->is_profiling() || | 3729 heap()->isolate()->is_profiling() || |
3742 heap()->isolate()->logger()->is_logging_code_events() || | 3730 heap()->isolate()->logger()->is_logging_code_events() || |
3743 heap()->isolate()->heap_profiler()->is_tracking_object_moves(); | 3731 heap()->isolate()->heap_profiler()->is_tracking_object_moves(); |
3744 ProfilingMigrationObserver profiling_observer(heap()); | 3732 ProfilingMigrationObserver profiling_observer(heap()); |
3745 | 3733 |
3746 const int wanted_num_tasks = | 3734 const int wanted_num_tasks = |
3747 NumberOfParallelCompactionTasks(job->NumberOfPages(), live_bytes); | 3735 NumberOfParallelCompactionTasks(job->NumberOfPages()); |
3748 Evacuator** evacuators = new Evacuator*[wanted_num_tasks]; | 3736 Evacuator** evacuators = new Evacuator*[wanted_num_tasks]; |
3749 for (int i = 0; i < wanted_num_tasks; i++) { | 3737 for (int i = 0; i < wanted_num_tasks; i++) { |
3750 evacuators[i] = new Evacuator(collector, record_visitor); | 3738 evacuators[i] = new Evacuator(collector, record_visitor); |
3751 if (profiling) evacuators[i]->AddObserver(&profiling_observer); | 3739 if (profiling) evacuators[i]->AddObserver(&profiling_observer); |
3752 if (migration_observer != nullptr) | 3740 if (migration_observer != nullptr) |
3753 evacuators[i]->AddObserver(migration_observer); | 3741 evacuators[i]->AddObserver(migration_observer); |
3754 } | 3742 } |
3755 job->Run(wanted_num_tasks, [evacuators](int i) { return evacuators[i]; }); | 3743 job->Run(wanted_num_tasks, [evacuators](int i) { return evacuators[i]; }); |
3756 const Address top = heap()->new_space()->top(); | 3744 const Address top = heap()->new_space()->top(); |
3757 for (int i = 0; i < wanted_num_tasks; i++) { | 3745 for (int i = 0; i < wanted_num_tasks; i++) { |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4255 if (ObjectMarking::IsBlack(heap_object, | 4243 if (ObjectMarking::IsBlack(heap_object, |
4256 collector->marking_state(heap_object))) | 4244 collector->marking_state(heap_object))) |
4257 return KEEP_SLOT; | 4245 return KEEP_SLOT; |
4258 } else { | 4246 } else { |
4259 DCHECK(!heap->InNewSpace(slot_reference)); | 4247 DCHECK(!heap->InNewSpace(slot_reference)); |
4260 } | 4248 } |
4261 return REMOVE_SLOT; | 4249 return REMOVE_SLOT; |
4262 } | 4250 } |
4263 }; | 4251 }; |
4264 | 4252 |
4265 int NumberOfPointerUpdateTasks(int pages) { | |
4266 if (!FLAG_parallel_pointer_update) return 1; | |
4267 const int available_cores = Max( | |
4268 1, static_cast<int>( | |
4269 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); | |
4270 const int kPagesPerTask = 4; | |
4271 return Min(available_cores, (pages + kPagesPerTask - 1) / kPagesPerTask); | |
4272 } | |
4273 | |
4274 template <RememberedSetType type> | 4253 template <RememberedSetType type> |
4275 void UpdatePointersInParallel(Heap* heap, base::Semaphore* semaphore, | 4254 void MarkCompactCollectorBase::UpdatePointersInParallel( |
4276 const MarkCompactCollectorBase* collector) { | 4255 Heap* heap, base::Semaphore* semaphore, |
| 4256 const MarkCompactCollectorBase* collector) { |
4277 PageParallelJob<PointerUpdateJobTraits<type> > job( | 4257 PageParallelJob<PointerUpdateJobTraits<type> > job( |
4278 heap, heap->isolate()->cancelable_task_manager(), semaphore); | 4258 heap, heap->isolate()->cancelable_task_manager(), semaphore); |
4279 RememberedSet<type>::IterateMemoryChunks( | 4259 RememberedSet<type>::IterateMemoryChunks( |
4280 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); | 4260 heap, [&job](MemoryChunk* chunk) { job.AddPage(chunk, 0); }); |
4281 int num_pages = job.NumberOfPages(); | 4261 int num_pages = job.NumberOfPages(); |
4282 int num_tasks = NumberOfPointerUpdateTasks(num_pages); | 4262 int num_tasks = NumberOfPointerUpdateTasks(num_pages); |
4283 job.Run(num_tasks, [collector](int i) { return collector; }); | 4263 job.Run(num_tasks, [collector](int i) { return collector; }); |
4284 } | 4264 } |
4285 | 4265 |
4286 class ToSpacePointerUpdateJobTraits { | 4266 class ToSpacePointerUpdateJobTraits { |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4638 // The target is always in old space, we don't have to record the slot in | 4618 // The target is always in old space, we don't have to record the slot in |
4639 // the old-to-new remembered set. | 4619 // the old-to-new remembered set. |
4640 DCHECK(!heap()->InNewSpace(target)); | 4620 DCHECK(!heap()->InNewSpace(target)); |
4641 RecordRelocSlot(host, &rinfo, target); | 4621 RecordRelocSlot(host, &rinfo, target); |
4642 } | 4622 } |
4643 } | 4623 } |
4644 } | 4624 } |
4645 | 4625 |
4646 } // namespace internal | 4626 } // namespace internal |
4647 } // namespace v8 | 4627 } // namespace v8 |
OLD | NEW |