diff options
Diffstat (limited to 'deps/v8/src/heap/scavenge-job.cc')
-rw-r--r-- | deps/v8/src/heap/scavenge-job.cc | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/deps/v8/src/heap/scavenge-job.cc b/deps/v8/src/heap/scavenge-job.cc new file mode 100644 index 0000000000..c3804436fb --- /dev/null +++ b/deps/v8/src/heap/scavenge-job.cc @@ -0,0 +1,116 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/heap/scavenge-job.h" + +#include "src/base/platform/time.h" +#include "src/heap/heap-inl.h" +#include "src/heap/heap.h" +#include "src/isolate.h" +#include "src/v8.h" + +namespace v8 { +namespace internal { + + +const double ScavengeJob::kMaxAllocationLimitAsFractionOfNewSpace = 0.8; + +void ScavengeJob::IdleTask::RunInternal(double deadline_in_seconds) { + Heap* heap = isolate_->heap(); + double deadline_in_ms = + deadline_in_seconds * + static_cast<double>(base::Time::kMillisecondsPerSecond); + double start_ms = heap->MonotonicallyIncreasingTimeInMs(); + double idle_time_in_ms = deadline_in_ms - start_ms; + size_t scavenge_speed_in_bytes_per_ms = + static_cast<size_t>(heap->tracer()->ScavengeSpeedInBytesPerMillisecond()); + size_t new_space_size = heap->new_space()->Size(); + size_t new_space_capacity = heap->new_space()->Capacity(); + + job_->NotifyIdleTask(); + + if (ReachedIdleAllocationLimit(scavenge_speed_in_bytes_per_ms, new_space_size, + new_space_capacity)) { + if (EnoughIdleTimeForScavenge( + idle_time_in_ms, scavenge_speed_in_bytes_per_ms, new_space_size)) { + heap->CollectGarbage(NEW_SPACE, "idle task: scavenge"); + } else { + // Immediately request another idle task that can get larger idle time. + job_->RescheduleIdleTask(heap); + } + } +} + + +bool ScavengeJob::ReachedIdleAllocationLimit( + size_t scavenge_speed_in_bytes_per_ms, size_t new_space_size, + size_t new_space_capacity) { + if (scavenge_speed_in_bytes_per_ms == 0) { + scavenge_speed_in_bytes_per_ms = kInitialScavengeSpeedInBytesPerMs; + } + + // Set the allocation limit to the number of bytes we can scavenge in an + // average idle task. + size_t allocation_limit = kAverageIdleTimeMs * scavenge_speed_in_bytes_per_ms; + + // Keep the limit smaller than the new space capacity. + allocation_limit = + Min(allocation_limit, + static_cast<size_t>(new_space_capacity * + kMaxAllocationLimitAsFractionOfNewSpace)); + // Adjust the limit to take into account bytes that will be allocated until + // the next check. + allocation_limit = allocation_limit < kBytesAllocatedBeforeNextIdleTask + ? 0 + : allocation_limit - kBytesAllocatedBeforeNextIdleTask; + // Keep the limit large enough to avoid scavenges in tiny new space. + allocation_limit = Max(allocation_limit, kMinAllocationLimit); + + return allocation_limit <= new_space_size; +} + + +bool ScavengeJob::EnoughIdleTimeForScavenge( + double idle_time_in_ms, size_t scavenge_speed_in_bytes_per_ms, + size_t new_space_size) { + if (scavenge_speed_in_bytes_per_ms == 0) { + scavenge_speed_in_bytes_per_ms = kInitialScavengeSpeedInBytesPerMs; + } + return new_space_size <= idle_time_in_ms * scavenge_speed_in_bytes_per_ms; +} + + +void ScavengeJob::RescheduleIdleTask(Heap* heap) { + // Make sure that we don't reschedule more than one time. + // Otherwise, we might spam the scheduler with idle tasks. + if (!idle_task_rescheduled_) { + ScheduleIdleTask(heap); + idle_task_rescheduled_ = true; + } +} + + +void ScavengeJob::ScheduleIdleTaskIfNeeded(Heap* heap, int bytes_allocated) { + bytes_allocated_since_the_last_task_ += bytes_allocated; + if (bytes_allocated_since_the_last_task_ >= + static_cast<int>(kBytesAllocatedBeforeNextIdleTask)) { + ScheduleIdleTask(heap); + bytes_allocated_since_the_last_task_ = 0; + idle_task_rescheduled_ = false; + } +} + + +void ScavengeJob::ScheduleIdleTask(Heap* heap) { + if (!idle_task_pending_) { + v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate()); + if (V8::GetCurrentPlatform()->IdleTasksEnabled(isolate)) { + idle_task_pending_ = true; + auto task = new IdleTask(heap->isolate(), this); + V8::GetCurrentPlatform()->CallIdleOnForegroundThread(isolate, task); + } + } +} +} +} // namespace v8::internal |