Commit db179a0d authored by Anton Bikineev's avatar Anton Bikineev Committed by Commit Bot

Oilpan: Incremental Marking using Tasks

This patch moves incremental marking steps in Oilpan
from safe points to V8 task runner thereby letting
scheduler know about GC existence.

This is expected to regress atomic-pause duration,
since incremental steps are not as prioritized as
they used to be, but at the same time latency should
improve.

Bug: 1002998

Change-Id: I1f0fa3468160a3505fcf71f85655c0fd41dc1c67
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1607642
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#708724}
parent 7a6cc5af
...@@ -49,8 +49,7 @@ IncrementalMarkingTestDriver::~IncrementalMarkingTestDriver() { ...@@ -49,8 +49,7 @@ IncrementalMarkingTestDriver::~IncrementalMarkingTestDriver() {
} }
void IncrementalMarkingTestDriver::Start() { void IncrementalMarkingTestDriver::Start() {
thread_state_->IncrementalMarkingStart( thread_state_->IncrementalMarkingStartForTesting();
BlinkGC::GCReason::kForcedGCForTesting);
} }
bool IncrementalMarkingTestDriver::SingleStep(BlinkGC::StackState stack_state) { bool IncrementalMarkingTestDriver::SingleStep(BlinkGC::StackState stack_state) {
...@@ -75,7 +74,7 @@ void IncrementalMarkingTestDriver::FinishGC(bool complete_sweep) { ...@@ -75,7 +74,7 @@ void IncrementalMarkingTestDriver::FinishGC(bool complete_sweep) {
FinishSteps(BlinkGC::StackState::kNoHeapPointersOnStack); FinishSteps(BlinkGC::StackState::kNoHeapPointersOnStack);
CHECK_EQ(ThreadState::kIncrementalMarkingFinalizeScheduled, CHECK_EQ(ThreadState::kIncrementalMarkingFinalizeScheduled,
thread_state_->GetGCState()); thread_state_->GetGCState());
thread_state_->RunScheduledGC(BlinkGC::StackState::kNoHeapPointersOnStack); thread_state_->IncrementalMarkingFinalize();
CHECK(!thread_state_->IsIncrementalMarking()); CHECK(!thread_state_->IsIncrementalMarking());
if (complete_sweep) { if (complete_sweep) {
thread_state_->CompleteSweep(); thread_state_->CompleteSweep();
......
...@@ -253,7 +253,6 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -253,7 +253,6 @@ class PLATFORM_EXPORT ThreadState final {
void PerformConcurrentSweep(); void PerformConcurrentSweep();
void SchedulePreciseGC(); void SchedulePreciseGC();
void ScheduleIncrementalGC(BlinkGC::GCReason);
void ScheduleForcedGCForTesting(); void ScheduleForcedGCForTesting();
void ScheduleGCIfNeeded(); void ScheduleGCIfNeeded();
void WillStartV8GC(BlinkGC::V8GCType); void WillStartV8GC(BlinkGC::V8GCType);
...@@ -261,6 +260,10 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -261,6 +260,10 @@ class PLATFORM_EXPORT ThreadState final {
GCState GetGCState() const { return gc_state_; } GCState GetGCState() const { return gc_state_; }
void SetGCPhase(GCPhase); void SetGCPhase(GCPhase);
// Immediately starts incremental marking and schedules further steps if
// necessary.
void StartIncrementalMarking(BlinkGC::GCReason);
// Returns true if marking is in progress. // Returns true if marking is in progress.
bool IsMarkingInProgress() const { return gc_phase_ == GCPhase::kMarking; } bool IsMarkingInProgress() const { return gc_phase_ == GCPhase::kMarking; }
...@@ -286,9 +289,6 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -286,9 +289,6 @@ class PLATFORM_EXPORT ThreadState final {
void EnableCompactionForNextGCForTesting(); void EnableCompactionForNextGCForTesting();
void IncrementalMarkingStart(BlinkGC::GCReason);
void IncrementalMarkingStep(BlinkGC::StackState);
void IncrementalMarkingFinalize();
bool FinishIncrementalMarkingIfRunning(BlinkGC::StackState, bool FinishIncrementalMarkingIfRunning(BlinkGC::StackState,
BlinkGC::MarkingType, BlinkGC::MarkingType,
BlinkGC::SweepingType, BlinkGC::SweepingType,
...@@ -382,6 +382,13 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -382,6 +382,13 @@ class PLATFORM_EXPORT ThreadState final {
bool IsVerifyMarkingEnabled() const; bool IsVerifyMarkingEnabled() const;
private: private:
class IncrementalMarkingScheduler;
// Duration of one incremental marking step. Should be short enough that it
// doesn't cause jank even though it is scheduled as a normal task.
static constexpr base::TimeDelta kDefaultIncrementalMarkingStepDuration =
base::TimeDelta::FromMilliseconds(2);
// Stores whether some ThreadState is currently in incremental marking. // Stores whether some ThreadState is currently in incremental marking.
static AtomicEntryFlag incremental_marking_flag_; static AtomicEntryFlag incremental_marking_flag_;
...@@ -482,9 +489,15 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -482,9 +489,15 @@ class PLATFORM_EXPORT ThreadState final {
// Visit all DOM wrappers allocatd on this thread. // Visit all DOM wrappers allocatd on this thread.
void VisitDOMWrappers(Visitor*); void VisitDOMWrappers(Visitor*);
// Incremental marking implementation functions.
void IncrementalMarkingStartForTesting();
void IncrementalMarkingStart(BlinkGC::GCReason);
void IncrementalMarkingStep(
BlinkGC::StackState,
base::TimeDelta duration = kDefaultIncrementalMarkingStepDuration);
void IncrementalMarkingFinalize();
// Schedule helpers. // Schedule helpers.
void ScheduleIncrementalMarkingStep();
void ScheduleIncrementalMarkingFinalize();
void ScheduleIdleLazySweep(); void ScheduleIdleLazySweep();
void ScheduleConcurrentAndLazySweep(); void ScheduleConcurrentAndLazySweep();
...@@ -493,8 +506,6 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -493,8 +506,6 @@ class PLATFORM_EXPORT ThreadState final {
void RunScheduledGC(BlinkGC::StackState); void RunScheduledGC(BlinkGC::StackState);
void UpdateIncrementalMarkingStepDuration();
void SynchronizeAndFinishConcurrentSweeping(); void SynchronizeAndFinishConcurrentSweeping();
void InvokePreFinalizers(); void InvokePreFinalizers();
...@@ -540,9 +551,6 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -540,9 +551,6 @@ class PLATFORM_EXPORT ThreadState final {
size_t gc_forbidden_count_ = 0; size_t gc_forbidden_count_ = 0;
size_t static_persistent_registration_disabled_count_ = 0; size_t static_persistent_registration_disabled_count_ = 0;
base::TimeDelta next_incremental_marking_step_duration_;
base::TimeDelta previous_incremental_marking_time_left_;
GCState gc_state_ = GCState::kNoGCScheduled; GCState gc_state_ = GCState::kNoGCScheduled;
GCPhase gc_phase_ = GCPhase::kNone; GCPhase gc_phase_ = GCPhase::kNone;
BlinkGC::GCReason reason_for_scheduled_gc_ = BlinkGC::GCReason reason_for_scheduled_gc_ =
...@@ -583,6 +591,8 @@ class PLATFORM_EXPORT ThreadState final { ...@@ -583,6 +591,8 @@ class PLATFORM_EXPORT ThreadState final {
}; };
GCData current_gc_data_; GCData current_gc_data_;
std::unique_ptr<IncrementalMarkingScheduler> incremental_marking_scheduler_;
std::unique_ptr<CancelableTaskScheduler> marker_scheduler_; std::unique_ptr<CancelableTaskScheduler> marker_scheduler_;
uint8_t active_markers_ = 0; uint8_t active_markers_ = 0;
base::Lock active_concurrent_markers_lock_; base::Lock active_concurrent_markers_lock_;
......
...@@ -2,15 +2,30 @@ ...@@ -2,15 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h" #include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h" #include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/thread_state_scopes.h" #include "third_party/blink/renderer/platform/heap/thread_state_scopes.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink { namespace blink {
namespace {
void RunLoop() {
base::RunLoop rl;
// Push quit task.
ThreadScheduler::Current()->V8TaskRunner()->PostNonNestableTask(
FROM_HERE, WTF::Bind(rl.QuitWhenIdleClosure()));
rl.Run();
}
} // namespace
class ThreadStateSchedulingTest : public TestSupportingGC { class ThreadStateSchedulingTest : public TestSupportingGC {
public: public:
void SetUp() override { void SetUp() override {
...@@ -26,13 +41,8 @@ class ThreadStateSchedulingTest : public TestSupportingGC { ...@@ -26,13 +41,8 @@ class ThreadStateSchedulingTest : public TestSupportingGC {
EXPECT_FALSE(state_->IsSweepingInProgress()); EXPECT_FALSE(state_->IsSweepingInProgress());
} }
void StartIncrementalMarking() { BlinkGC::GCReason LastReason() const {
EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState()); return state_->reason_for_scheduled_gc_;
state_->ScheduleIncrementalGC(BlinkGC::GCReason::kForcedGCForTesting);
state_->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
state_->GetGCState());
EXPECT_TRUE(state_->IsMarkingInProgress());
} }
void StartLazySweepingForPreciseGC() { void StartLazySweepingForPreciseGC() {
...@@ -58,21 +68,17 @@ class ThreadStateSchedulingTest : public TestSupportingGC { ...@@ -58,21 +68,17 @@ class ThreadStateSchedulingTest : public TestSupportingGC {
int initial_gc_age_; int initial_gc_age_;
}; };
TEST_F(ThreadStateSchedulingTest, ScheduleIncrementalV8FollowupGCAgain) { TEST_F(ThreadStateSchedulingTest, RunIncrementalGCForTesting) {
ThreadStateSchedulingTest* test = this; ThreadStateSchedulingTest* test = this;
EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState()); EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
test->state()->ScheduleIncrementalGC( test->state()->StartIncrementalMarking(
BlinkGC::GCReason::kIncrementalV8FollowupGC); BlinkGC::GCReason::kForcedGCForTesting);
EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState()); EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
test->state()->GetGCState());
// Calling ScheduleIncrementalV8FollowupGC() while one is already scheduled
// will do nothing.
test->state()->ScheduleIncrementalGC(
BlinkGC::GCReason::kIncrementalV8FollowupGC);
EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState()); RunLoop();
EXPECT_EQ(0, test->GCCount()); EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
} }
TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileLazySweeping) { TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileLazySweeping) {
...@@ -87,27 +93,13 @@ TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileLazySweeping) { ...@@ -87,27 +93,13 @@ TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileLazySweeping) {
EXPECT_EQ(ThreadState::kPreciseGCScheduled, test->state()->GetGCState()); EXPECT_EQ(ThreadState::kPreciseGCScheduled, test->state()->GetGCState());
} }
TEST_F(ThreadStateSchedulingTest,
ScheduleIncrementalV8FollowupGCWhileLazySweeping) {
ThreadStateSchedulingTest* test = this;
test->StartLazySweepingForPreciseGC();
test->state()->ScheduleIncrementalGC(
BlinkGC::GCReason::kIncrementalV8FollowupGC);
// Scheduling a IncrementalV8FollowupGC should finish lazy sweeping.
EXPECT_FALSE(test->state()->IsSweepingInProgress());
EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
}
TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileIncrementalMarking) { TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileIncrementalMarking) {
ThreadStateSchedulingTest* test = this; ThreadStateSchedulingTest* test = this;
base::test::ScopedFeatureList scoped_feature_list; base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature( scoped_feature_list.InitAndEnableFeature(
blink::features::kBlinkHeapIncrementalMarking); blink::features::kBlinkHeapIncrementalMarking);
test->state()->StartIncrementalMarking(
test->StartIncrementalMarking(); BlinkGC::GCReason::kForcedGCForTesting);
test->state()->SchedulePreciseGC(); test->state()->SchedulePreciseGC();
// Scheduling a precise GC should cancel incremental marking tasks. // Scheduling a precise GC should cancel incremental marking tasks.
EXPECT_EQ(ThreadState::kPreciseGCScheduled, test->state()->GetGCState()); EXPECT_EQ(ThreadState::kPreciseGCScheduled, test->state()->GetGCState());
...@@ -122,54 +114,10 @@ TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileIncrementalMarking) { ...@@ -122,54 +114,10 @@ TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileIncrementalMarking) {
EXPECT_EQ(0, test->GCCount()); EXPECT_EQ(0, test->GCCount());
test->state()->CompleteSweep(); test->state()->CompleteSweep();
EXPECT_EQ(1, test->GCCount()); EXPECT_EQ(1, test->GCCount());
}
TEST_F(ThreadStateSchedulingTest,
ScheduleIncrementalV8FollowupGCWhileIncrementalMarking) {
ThreadStateSchedulingTest* test = this;
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(
blink::features::kBlinkHeapIncrementalMarking);
test->StartIncrementalMarking();
test->state()->ScheduleIncrementalGC(
BlinkGC::GCReason::kIncrementalV8FollowupGC);
// Scheduling another incremental GC should not cancel incremental marking
// tasks.
EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
test->state()->GetGCState());
}
TEST_F(ThreadStateSchedulingTest,
ScheduleIncrementalV8FollowupGCWhileGCForbidden) {
ThreadStateSchedulingTest* test = this;
EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
test->state()->ScheduleIncrementalGC(
BlinkGC::GCReason::kIncrementalV8FollowupGC);
EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
ThreadState::GCForbiddenScope gc_forbidden_scope(test->state());
test->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
// Starting an IncrementalV8FollowupGC while GC is forbidden should do // Check that incremental GC hasn't been run.
// nothing. RunLoop();
EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState()); EXPECT_EQ(1, test->GCCount());
EXPECT_EQ(0, GCCount());
}
TEST_F(ThreadStateSchedulingTest, RunIncrementalV8FollowupGC) {
ThreadStateSchedulingTest* test = this;
EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
test->state()->ScheduleIncrementalGC(
BlinkGC::GCReason::kIncrementalV8FollowupGC);
EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
test->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
test->state()->GetGCState());
} }
} // namespace blink } // namespace blink
...@@ -50,13 +50,12 @@ void UnifiedHeapController::TracePrologue( ...@@ -50,13 +50,12 @@ void UnifiedHeapController::TracePrologue(
BlinkGC::kConcurrentAndLazySweeping, BlinkGC::kConcurrentAndLazySweeping,
thread_state_->current_gc_data_.reason); thread_state_->current_gc_data_.reason);
// Reset any previously scheduled garbage collections.
thread_state_->SetGCState(ThreadState::kNoGCScheduled); thread_state_->SetGCState(ThreadState::kNoGCScheduled);
BlinkGC::GCReason gc_reason = BlinkGC::GCReason gc_reason =
(v8_flags & v8::EmbedderHeapTracer::TraceFlags::kReduceMemory) (v8_flags & v8::EmbedderHeapTracer::TraceFlags::kReduceMemory)
? BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC ? BlinkGC::GCReason::kUnifiedHeapForMemoryReductionGC
: BlinkGC::GCReason::kUnifiedHeapGC; : BlinkGC::GCReason::kUnifiedHeapGC;
thread_state_->IncrementalMarkingStart(gc_reason); thread_state_->StartIncrementalMarking(gc_reason);
is_tracing_done_ = false; is_tracing_done_ = false;
} }
......
...@@ -29,7 +29,9 @@ ...@@ -29,7 +29,9 @@
#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
#include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/heap/thread_state.h"
#include "third_party/blink/renderer/platform/lifecycle_notifier.h" #include "third_party/blink/renderer/platform/lifecycle_notifier.h"
#include "third_party/blink/renderer/platform/lifecycle_observer.h" #include "third_party/blink/renderer/platform/lifecycle_observer.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
...@@ -149,8 +151,8 @@ TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) { ...@@ -149,8 +151,8 @@ TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) {
{blink::features::kBlinkHeapIncrementalMarking}, {blink::features::kBlinkHeapIncrementalMarking},
{blink::features::kBlinkHeapConcurrentMarking, {blink::features::kBlinkHeapConcurrentMarking,
blink::features::kBlinkHeapConcurrentSweeping}); blink::features::kBlinkHeapConcurrentSweeping});
ThreadState* thread_state = ThreadState::Current(); IncrementalMarkingTestDriver driver(ThreadState::Current());
thread_state->IncrementalMarkingStart(BlinkGC::GCReason::kForcedGCForTesting); driver.Start();
auto* context = MakeGarbageCollected<DummyContext>(); auto* context = MakeGarbageCollected<DummyContext>();
...@@ -163,10 +165,7 @@ TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) { ...@@ -163,10 +165,7 @@ TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) {
EXPECT_TRUE(observer->ContextDestroyedCalled()); EXPECT_TRUE(observer->ContextDestroyedCalled());
context = nullptr; context = nullptr;
while (thread_state->GetGCState() == driver.FinishGC();
ThreadState::kIncrementalMarkingStepScheduled)
thread_state->IncrementalMarkingStep(BlinkGC::kNoHeapPointersOnStack);
thread_state->IncrementalMarkingFinalize();
} }
TEST(LifecycleContextTest, ForEachObserver) { TEST(LifecycleContextTest, ForEachObserver) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment