"src/heap/heap-inl.h",
"src/heap/heap.cc",
"src/heap/heap.h",
+ "src/heap/incremental-marking-job.cc",
+ "src/heap/incremental-marking-job.h",
"src/heap/incremental-marking.cc",
"src/heap/incremental-marking.h",
"src/heap/mark-compact-inl.h",
case DO_NOTHING:
PrintF("no action");
break;
- case DO_INCREMENTAL_MARKING:
- PrintF("incremental marking with step %" V8_PTR_PREFIX "d / ms",
- parameter);
+ case DO_INCREMENTAL_STEP:
+ PrintF("incremental step");
if (additional_work) {
PrintF("; finalized marking");
}
case DO_FULL_GC:
PrintF("full GC");
break;
- case DO_FINALIZE_SWEEPING:
- PrintF("finalize sweeping");
- break;
}
}
return GCIdleTimeAction::Scavenge();
}
- if (heap_state.sweeping_in_progress) {
- if (heap_state.sweeping_completed) {
- return GCIdleTimeAction::FinalizeSweeping();
- } else {
- return NothingOrDone(idle_time_in_ms);
- }
- }
-
if (!FLAG_incremental_marking || heap_state.incremental_marking_stopped) {
return GCIdleTimeAction::Done();
}
- size_t step_size = EstimateMarkingStepSize(
- static_cast<size_t>(kIncrementalMarkingStepTimeInMs),
- heap_state.incremental_marking_speed_in_bytes_per_ms);
- return GCIdleTimeAction::IncrementalMarking(step_size);
+ return GCIdleTimeAction::IncrementalStep();
}
enum GCIdleTimeActionType {
DONE,
DO_NOTHING,
- DO_INCREMENTAL_MARKING,
+ DO_INCREMENTAL_STEP,
DO_SCAVENGE,
DO_FULL_GC,
- DO_FINALIZE_SWEEPING
};
static GCIdleTimeAction Done() {
GCIdleTimeAction result;
result.type = DONE;
- result.parameter = 0;
result.additional_work = false;
return result;
}
static GCIdleTimeAction Nothing() {
GCIdleTimeAction result;
result.type = DO_NOTHING;
- result.parameter = 0;
result.additional_work = false;
return result;
}
- static GCIdleTimeAction IncrementalMarking(intptr_t step_size) {
+ static GCIdleTimeAction IncrementalStep() {
GCIdleTimeAction result;
- result.type = DO_INCREMENTAL_MARKING;
- result.parameter = step_size;
+ result.type = DO_INCREMENTAL_STEP;
result.additional_work = false;
return result;
}
static GCIdleTimeAction Scavenge() {
GCIdleTimeAction result;
result.type = DO_SCAVENGE;
- result.parameter = 0;
result.additional_work = false;
return result;
}
static GCIdleTimeAction FullGC() {
GCIdleTimeAction result;
result.type = DO_FULL_GC;
- result.parameter = 0;
- result.additional_work = false;
- return result;
- }
-
- static GCIdleTimeAction FinalizeSweeping() {
- GCIdleTimeAction result;
- result.type = DO_FINALIZE_SWEEPING;
- result.parameter = 0;
result.additional_work = false;
return result;
}
void Print();
GCIdleTimeActionType type;
- intptr_t parameter;
bool additional_work;
};
}
-bool Heap::TryFinalizeIdleIncrementalMarking(
- double idle_time_in_ms, size_t size_of_objects,
- size_t final_incremental_mark_compact_speed_in_bytes_per_ms) {
- if (FLAG_overapproximate_weak_closure && incremental_marking()->IsMarking() &&
+bool Heap::TryFinalizeIdleIncrementalMarking(double idle_time_in_ms) {
+ size_t size_of_objects = static_cast<size_t>(SizeOfObjects());
+ size_t final_incremental_mark_compact_speed_in_bytes_per_ms =
+ static_cast<size_t>(
+ tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond());
+ if (FLAG_overapproximate_weak_closure &&
(incremental_marking()->IsReadyToOverApproximateWeakClosure() ||
(!incremental_marking()->weak_closure_was_overapproximated() &&
mark_compact_collector_.marking_deque()->IsEmpty() &&
heap_state.contexts_disposed = contexts_disposed_;
heap_state.contexts_disposal_rate =
tracer()->ContextDisposalRateInMilliseconds();
- heap_state.size_of_objects = static_cast<size_t>(SizeOfObjects());
heap_state.incremental_marking_stopped = incremental_marking()->IsStopped();
- heap_state.sweeping_in_progress =
- mark_compact_collector()->sweeping_in_progress();
- heap_state.sweeping_completed =
- mark_compact_collector()->IsSweepingCompleted();
heap_state.mark_compact_speed_in_bytes_per_ms =
static_cast<size_t>(tracer()->MarkCompactSpeedInBytesPerMillisecond());
- heap_state.incremental_marking_speed_in_bytes_per_ms = static_cast<size_t>(
- tracer()->IncrementalMarkingSpeedInBytesPerMillisecond());
- heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms =
- static_cast<size_t>(
- tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond());
heap_state.scavenge_speed_in_bytes_per_ms =
static_cast<size_t>(tracer()->ScavengeSpeedInBytesPerMillisecond());
heap_state.used_new_space_size = new_space_.Size();
case DONE:
result = true;
break;
- case DO_INCREMENTAL_MARKING: {
- const double remaining_idle_time_in_ms =
- AdvanceIncrementalMarking(action.parameter, deadline_in_ms,
- IncrementalMarking::IdleStepActions());
- if (remaining_idle_time_in_ms > 0.0) {
- action.additional_work = TryFinalizeIdleIncrementalMarking(
- remaining_idle_time_in_ms, heap_state.size_of_objects,
- heap_state.final_incremental_mark_compact_speed_in_bytes_per_ms);
+ case DO_INCREMENTAL_STEP: {
+ if (incremental_marking()->incremental_marking_job()->IdleTaskPending()) {
+ result = true;
+ } else {
+ incremental_marking()
+ ->incremental_marking_job()
+ ->NotifyIdleTaskProgress();
+ result = IncrementalMarkingJob::IdleTask::Step(this, deadline_in_ms) ==
+ IncrementalMarkingJob::IdleTask::kDone;
}
break;
}
case DO_SCAVENGE:
CollectGarbage(NEW_SPACE, "idle notification: scavenge");
break;
- case DO_FINALIZE_SWEEPING:
- mark_compact_collector()->EnsureSweepingCompleted();
- break;
case DO_NOTHING:
break;
}
void FinalizeIncrementalMarkingIfComplete(const char* comment);
+ bool TryFinalizeIdleIncrementalMarking(double idle_time_in_ms);
+
IncrementalMarking* incremental_marking() { return &incremental_marking_; }
// ===========================================================================
--- /dev/null
+// Copyright 2012 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/incremental-marking-job.h"
+
+#include "src/base/platform/time.h"
+#include "src/heap/heap-inl.h"
+#include "src/heap/heap.h"
+#include "src/heap/incremental-marking.h"
+#include "src/isolate.h"
+#include "src/v8.h"
+
+namespace v8 {
+namespace internal {
+
+
+void IncrementalMarkingJob::Start(Heap* heap) {
+ DCHECK(!heap->incremental_marking()->IsStopped());
+ // We don't need to reset the flags because tasks from the previous job
+ // can still be pending. We just want to ensure that tasks are posted
+ // if they are not pending.
+ // If delayed task is pending and made_progress_since_last_delayed_task_ is
+ // true, then the delayed task will clear that flag when it is rescheduled.
+ ScheduleIdleTask(heap);
+ ScheduleDelayedTask(heap);
+}
+
+
+void IncrementalMarkingJob::NotifyIdleTask() { idle_task_pending_ = false; }
+
+
+void IncrementalMarkingJob::NotifyDelayedTask() {
+ delayed_task_pending_ = false;
+}
+
+
+void IncrementalMarkingJob::NotifyIdleTaskProgress() {
+ made_progress_since_last_delayed_task_ = true;
+}
+
+
+void IncrementalMarkingJob::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);
+ }
+ }
+}
+
+
+void IncrementalMarkingJob::ScheduleDelayedTask(Heap* heap) {
+ if (!delayed_task_pending_) {
+ v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap->isolate());
+ delayed_task_pending_ = true;
+ made_progress_since_last_delayed_task_ = false;
+ auto task = new DelayedTask(heap->isolate(), this);
+ V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(isolate, task,
+ kDelayInSeconds);
+ }
+}
+
+
+IncrementalMarkingJob::IdleTask::Progress IncrementalMarkingJob::IdleTask::Step(
+ Heap* heap, double deadline_in_ms) {
+ IncrementalMarking* incremental_marking = heap->incremental_marking();
+ MarkCompactCollector* mark_compact_collector = heap->mark_compact_collector();
+ if (incremental_marking->IsStopped()) {
+ return kDone;
+ }
+ if (mark_compact_collector->sweeping_in_progress()) {
+ if (mark_compact_collector->IsSweepingCompleted()) {
+ mark_compact_collector->EnsureSweepingCompleted();
+ }
+ return kMoreWork;
+ }
+ const double remaining_idle_time_in_ms = heap->AdvanceIncrementalMarking(
+ 0, deadline_in_ms, IncrementalMarking::IdleStepActions());
+ if (remaining_idle_time_in_ms > 0.0) {
+ heap->TryFinalizeIdleIncrementalMarking(remaining_idle_time_in_ms);
+ }
+ return incremental_marking->IsStopped() ? kDone : kMoreWork;
+}
+
+
+void IncrementalMarkingJob::IdleTask::RunInternal(double deadline_in_seconds) {
+ double deadline_in_ms =
+ deadline_in_seconds *
+ static_cast<double>(base::Time::kMillisecondsPerSecond);
+ Heap* heap = isolate_->heap();
+ double start_ms = heap->MonotonicallyIncreasingTimeInMs();
+ job_->NotifyIdleTask();
+ job_->NotifyIdleTaskProgress();
+ if (Step(heap, deadline_in_ms) == kMoreWork) {
+ job_->ScheduleIdleTask(heap);
+ }
+ if (FLAG_trace_idle_notification) {
+ double current_time_ms = heap->MonotonicallyIncreasingTimeInMs();
+ double idle_time_in_ms = deadline_in_ms - start_ms;
+ double deadline_difference = deadline_in_ms - current_time_ms;
+ PrintIsolate(isolate_, "%8.0f ms: ", isolate_->time_millis_since_init());
+ PrintF(
+ "Idle task: requested idle time %.2f ms, used idle time %.2f "
+ "ms, deadline usage %.2f ms\n",
+ idle_time_in_ms, idle_time_in_ms - deadline_difference,
+ deadline_difference);
+ }
+}
+
+
+void IncrementalMarkingJob::DelayedTask::Step(Heap* heap) {
+ const int kIncrementalMarkingDelayMs = 50;
+ double deadline =
+ heap->MonotonicallyIncreasingTimeInMs() + kIncrementalMarkingDelayMs;
+ heap->AdvanceIncrementalMarking(
+ 0, deadline, i::IncrementalMarking::StepActions(
+ i::IncrementalMarking::NO_GC_VIA_STACK_GUARD,
+ i::IncrementalMarking::FORCE_MARKING,
+ i::IncrementalMarking::FORCE_COMPLETION));
+ heap->FinalizeIncrementalMarkingIfComplete(
+ "Incremental marking task: finalize incremental marking");
+}
+
+
+void IncrementalMarkingJob::DelayedTask::RunInternal() {
+ Heap* heap = isolate_->heap();
+ job_->NotifyDelayedTask();
+ IncrementalMarking* incremental_marking = heap->incremental_marking();
+ if (!incremental_marking->IsStopped()) {
+ if (job_->ShouldForceMarkingStep()) {
+ Step(heap);
+ }
+ // The Step() above could have finished incremental marking.
+ if (!incremental_marking->IsStopped()) {
+ job_->ScheduleDelayedTask(heap);
+ }
+ }
+}
+
+} // namespace internal
+} // namespace v8
--- /dev/null
+// Copyright 2012 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.
+
+#ifndef V8_HEAP_INCREMENTAL_MARKING_JOB_H_
+#define V8_HEAP_INCREMENTAL_MARKING_JOB_H_
+
+#include "src/cancelable-task.h"
+
+namespace v8 {
+namespace internal {
+
+class Heap;
+class Isolate;
+
+// The incremental marking job uses platform tasks to perform incremental
+// marking steps. The job posts an idle and a delayed task with a large delay.
+// The delayed task performs steps only if the idle task is not making progress.
+// We expect this to be a rare event since incremental marking should finish
+// quickly with the help of the mutator and the idle task.
+// The delayed task guarantees that we eventually finish incremental marking
+// even if the mutator becomes idle and the platform stops running idle tasks,
+// which can happen for background tabs in Chrome.
+class IncrementalMarkingJob {
+ public:
+ class IdleTask : public CancelableIdleTask {
+ public:
+ explicit IdleTask(Isolate* isolate, IncrementalMarkingJob* job)
+ : CancelableIdleTask(isolate), job_(job) {}
+ enum Progress { kDone, kMoreWork };
+ static Progress Step(Heap* heap, double deadline_in_ms);
+ // CancelableIdleTask overrides.
+ void RunInternal(double deadline_in_seconds) override;
+
+ private:
+ IncrementalMarkingJob* job_;
+ };
+
+ class DelayedTask : public CancelableTask {
+ public:
+ explicit DelayedTask(Isolate* isolate, IncrementalMarkingJob* job)
+ : CancelableTask(isolate), job_(job) {}
+ static void Step(Heap* heap);
+ // CancelableTask overrides.
+ void RunInternal() override;
+
+ private:
+ IncrementalMarkingJob* job_;
+ };
+
+ // Delay of the delayed task.
+ static const int kDelayInSeconds = 5;
+
+ IncrementalMarkingJob()
+ : idle_task_pending_(false),
+ delayed_task_pending_(false),
+ made_progress_since_last_delayed_task_(false) {}
+
+ bool ShouldForceMarkingStep() {
+ return !made_progress_since_last_delayed_task_;
+ }
+
+ bool IdleTaskPending() { return idle_task_pending_; }
+
+ void Start(Heap* heap);
+
+ void NotifyIdleTask();
+ void NotifyDelayedTask();
+ void NotifyIdleTaskProgress();
+ void ScheduleIdleTask(Heap* heap);
+ void ScheduleDelayedTask(Heap* heap);
+
+ private:
+ bool idle_task_pending_;
+ bool delayed_task_pending_;
+ bool made_progress_since_last_delayed_task_;
+};
+}
+} // namespace v8::internal
+
+#endif // V8_HEAP_INCREMENTAL_MARKING_JOB_H_
#include "src/heap/mark-compact-inl.h"
#include "src/heap/objects-visiting.h"
#include "src/heap/objects-visiting-inl.h"
+#include "src/v8.h"
namespace v8 {
namespace internal {
}
heap_->new_space()->LowerInlineAllocationLimit(kAllocatedThreshold);
+ incremental_marking_job()->Start(heap_);
}
#ifndef V8_HEAP_INCREMENTAL_MARKING_H_
#define V8_HEAP_INCREMENTAL_MARKING_H_
+#include "src/cancelable-task.h"
#include "src/execution.h"
+#include "src/heap/incremental-marking-job.h"
#include "src/heap/mark-compact.h"
#include "src/objects.h"
namespace v8 {
namespace internal {
-
class IncrementalMarking {
public:
enum State { STOPPED, SWEEPING, MARKING, COMPLETE };
Heap* heap() const { return heap_; }
+ IncrementalMarkingJob* incremental_marking_job() {
+ return &incremental_marking_job_;
+ }
+
private:
int64_t SpaceLeftInOldSpace();
GCRequestType request_type_;
+ IncrementalMarkingJob incremental_marking_job_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking);
};
}
}
+void V8::SetPlatformForTesting(v8::Platform* platform) { platform_ = platform; }
+
+
void V8::SetNativesBlob(StartupData* natives_blob) {
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
base::CallOnce(&init_natives_once, &SetNativesFromFile, natives_blob);
static void InitializePlatform(v8::Platform* platform);
static void ShutdownPlatform();
static v8::Platform* GetCurrentPlatform();
+ // Replaces the current platform with the given platform.
+ // Should be used only for testing.
+ static void SetPlatformForTesting(v8::Platform* platform);
static void SetNativesBlob(StartupData* natives_blob);
static void SetSnapshotBlob(StartupData* snapshot_blob);
'test-heap-profiler.cc',
'test-hydrogen-types.cc',
'test-identity-map.cc',
+ 'test-incremental-marking.cc',
'test-list.cc',
'test-liveedit.cc',
'test-lockers.cc',
--- /dev/null
+// 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 <stdlib.h>
+
+#ifdef __linux__
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <utility>
+
+#include "src/v8.h"
+
+#include "src/full-codegen/full-codegen.h"
+#include "src/global-handles.h"
+#include "test/cctest/cctest.h"
+
+using v8::IdleTask;
+using v8::Task;
+using v8::Isolate;
+
+
+class MockPlatform : public v8::Platform {
+ public:
+ explicit MockPlatform(v8::Platform* platform)
+ : platform_(platform), idle_task_(nullptr), delayed_task_(nullptr) {}
+ virtual ~MockPlatform() {
+ delete idle_task_;
+ delete delayed_task_;
+ }
+
+ void CallOnBackgroundThread(Task* task,
+ ExpectedRuntime expected_runtime) override {
+ platform_->CallOnBackgroundThread(task, expected_runtime);
+ }
+
+ void CallOnForegroundThread(Isolate* isolate, Task* task) override {
+ platform_->CallOnForegroundThread(isolate, task);
+ }
+
+ void CallDelayedOnForegroundThread(Isolate* isolate, Task* task,
+ double delay_in_seconds) override {
+ if (delayed_task_ != nullptr) {
+ delete delayed_task_;
+ }
+ delayed_task_ = task;
+ }
+
+ double MonotonicallyIncreasingTime() override {
+ return platform_->MonotonicallyIncreasingTime();
+ }
+
+ void CallIdleOnForegroundThread(Isolate* isolate, IdleTask* task) override {
+ CHECK(nullptr == idle_task_);
+ idle_task_ = task;
+ }
+
+ bool IdleTasksEnabled(Isolate* isolate) override { return true; }
+
+ bool PendingIdleTask() { return idle_task_ != nullptr; }
+
+ void PerformIdleTask(double idle_time_in_seconds) {
+ IdleTask* task = idle_task_;
+ idle_task_ = nullptr;
+ task->Run(MonotonicallyIncreasingTime() + idle_time_in_seconds);
+ delete task;
+ }
+
+ bool PendingDelayedTask() { return delayed_task_ != nullptr; }
+
+ void PerformDelayedTask() {
+ Task* task = delayed_task_;
+ delayed_task_ = nullptr;
+ task->Run();
+ delete task;
+ }
+
+ private:
+ v8::Platform* platform_;
+ IdleTask* idle_task_;
+ Task* delayed_task_;
+};
+
+
+TEST(IncrementalMarkingUsingIdleTasks) {
+ if (!i::FLAG_incremental_marking) return;
+ CcTest::InitializeVM();
+ v8::Platform* old_platform = i::V8::GetCurrentPlatform();
+ MockPlatform platform(old_platform);
+ i::V8::SetPlatformForTesting(&platform);
+ SimulateFullSpace(CcTest::heap()->old_space());
+ i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
+ marking->Stop();
+ marking->Start();
+ CHECK(platform.PendingIdleTask());
+ const double kLongIdleTimeInSeconds = 1;
+ const double kShortIdleTimeInSeconds = 0.010;
+ const int kShortStepCount = 10;
+ for (int i = 0; i < kShortStepCount && platform.PendingIdleTask(); i++) {
+ platform.PerformIdleTask(kShortIdleTimeInSeconds);
+ }
+ while (platform.PendingIdleTask()) {
+ platform.PerformIdleTask(kLongIdleTimeInSeconds);
+ }
+ CHECK(marking->IsStopped());
+ i::V8::SetPlatformForTesting(old_platform);
+}
+
+
+TEST(IncrementalMarkingUsingIdleTasksAfterGC) {
+ if (!i::FLAG_incremental_marking) return;
+ CcTest::InitializeVM();
+ v8::Platform* old_platform = i::V8::GetCurrentPlatform();
+ MockPlatform platform(old_platform);
+ i::V8::SetPlatformForTesting(&platform);
+ SimulateFullSpace(CcTest::heap()->old_space());
+ CcTest::heap()->CollectAllGarbage();
+ i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
+ marking->Stop();
+ marking->Start();
+ CHECK(platform.PendingIdleTask());
+ const double kLongIdleTimeInSeconds = 1;
+ const double kShortIdleTimeInSeconds = 0.010;
+ const int kShortStepCount = 10;
+ for (int i = 0; i < kShortStepCount && platform.PendingIdleTask(); i++) {
+ platform.PerformIdleTask(kShortIdleTimeInSeconds);
+ }
+ while (platform.PendingIdleTask()) {
+ platform.PerformIdleTask(kLongIdleTimeInSeconds);
+ }
+ CHECK(marking->IsStopped());
+ i::V8::SetPlatformForTesting(old_platform);
+}
+
+
+TEST(IncrementalMarkingUsingDelayedTasks) {
+ if (!i::FLAG_incremental_marking) return;
+ CcTest::InitializeVM();
+ v8::Platform* old_platform = i::V8::GetCurrentPlatform();
+ MockPlatform platform(old_platform);
+ i::V8::SetPlatformForTesting(&platform);
+ SimulateFullSpace(CcTest::heap()->old_space());
+ i::IncrementalMarking* marking = CcTest::heap()->incremental_marking();
+ marking->Stop();
+ marking->Start();
+ CHECK(platform.PendingIdleTask());
+ // The delayed task should be a no-op if the idle task makes progress.
+ const int kIgnoredDelayedTaskStepCount = 1000;
+ for (int i = 0; i < kIgnoredDelayedTaskStepCount; i++) {
+ // Dummy idle task progress.
+ marking->incremental_marking_job()->NotifyIdleTaskProgress();
+ CHECK(platform.PendingDelayedTask());
+ platform.PerformDelayedTask();
+ }
+ // Once we stop notifying idle task progress, the delayed tasks
+ // should finish marking.
+ while (!marking->IsStopped() && platform.PendingDelayedTask()) {
+ platform.PerformDelayedTask();
+ }
+ // There could be pending delayed task from memory reducer after GC finishes.
+ CHECK(marking->IsStopped());
+ i::V8::SetPlatformForTesting(old_platform);
+}
GCIdleTimeHandler::HeapState result;
result.contexts_disposed = 0;
result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate;
- result.size_of_objects = kSizeOfObjects;
result.incremental_marking_stopped = false;
- result.sweeping_in_progress = false;
- result.sweeping_completed = false;
result.mark_compact_speed_in_bytes_per_ms = kMarkCompactSpeed;
- result.incremental_marking_speed_in_bytes_per_ms = kMarkingSpeed;
result.scavenge_speed_in_bytes_per_ms = kScavengeSpeed;
result.used_new_space_size = 0;
result.new_space_capacity = kNewSpaceCapacity;
heap_state.contexts_disposal_rate =
GCIdleTimeHandler::kHighContextDisposalRate;
size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
- double idle_time_ms =
- static_cast<double>(heap_state.size_of_objects / speed - 1);
+ double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
}
heap_state.contexts_disposal_rate =
GCIdleTimeHandler::kHighContextDisposalRate;
size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
- double idle_time_ms =
- static_cast<double>(heap_state.size_of_objects / speed - 1);
+ double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
}
TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms;
double idle_time_ms = 10;
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_GT(speed * static_cast<size_t>(idle_time_ms),
- static_cast<size_t>(action.parameter));
- EXPECT_LT(0, action.parameter);
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, IncrementalMarking2) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- size_t speed = heap_state.incremental_marking_speed_in_bytes_per_ms;
- double idle_time_ms = 10;
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
- EXPECT_GT(speed * static_cast<size_t>(idle_time_ms),
- static_cast<size_t>(action.parameter));
- EXPECT_LT(0, action.parameter);
+ EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
}
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
heap_state.incremental_marking_stopped = true;
size_t speed = heap_state.mark_compact_speed_in_bytes_per_ms;
- double idle_time_ms =
- static_cast<double>(heap_state.size_of_objects / speed - 1);
+ double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
EXPECT_EQ(DONE, action.type);
}
-TEST_F(GCIdleTimeHandlerTest, FinalizeSweeping) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.sweeping_in_progress = true;
- heap_state.sweeping_completed = true;
- double idle_time_ms = 10.0;
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_FINALIZE_SWEEPING, action.type);
-}
-
-
-TEST_F(GCIdleTimeHandlerTest, CannotFinalizeSweeping) {
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
- heap_state.incremental_marking_stopped = true;
- heap_state.sweeping_in_progress = true;
- heap_state.sweeping_completed = false;
- double idle_time_ms = 10.0;
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
-}
-
-
TEST_F(GCIdleTimeHandlerTest, Scavenge) {
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
int idle_time_ms = 10;
EXPECT_EQ(DONE, action.type);
heap_state.incremental_marking_stopped = false;
action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_INCREMENTAL_MARKING, action.type);
+ EXPECT_EQ(DO_INCREMENTAL_STEP, action.type);
}
}
-TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnSweeping) {
- // Regression test for crbug.com/489323.
- GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
-
- // Simulate sweeping being in-progress but not complete.
- heap_state.incremental_marking_stopped = true;
- heap_state.sweeping_in_progress = true;
- heap_state.sweeping_completed = false;
- double idle_time_ms = 10.0;
- for (int i = 0; i < GCIdleTimeHandler::kMaxNoProgressIdleTimes; i++) {
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DO_NOTHING, action.type);
- }
- // We should return DONE after not making progress for some time.
- GCIdleTimeAction action = handler()->Compute(idle_time_ms, heap_state);
- EXPECT_EQ(DONE, action.type);
-}
-
-
TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
// Regression test for crbug.com/489323.
GCIdleTimeHandler::HeapState heap_state = DefaultHeapState();
'../../src/heap/heap.cc',
'../../src/heap/heap.h',
'../../src/heap/incremental-marking-inl.h',
+ '../../src/heap/incremental-marking-job.cc',
+ '../../src/heap/incremental-marking-job.h',
'../../src/heap/incremental-marking.cc',
'../../src/heap/incremental-marking.h',
'../../src/heap/mark-compact-inl.h',