// 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 #include "src/heap/safepoint.h" #ifdef __linux__ #include #include #include #include #include #endif #include #include "src/init/v8.h" #include "src/handles/global-handles.h" #include "src/heap/incremental-marking.h" #include "src/heap/spaces.h" #include "src/objects/objects-inl.h" #include "test/cctest/cctest.h" #include "test/cctest/heap/heap-utils.h" using v8::IdleTask; using v8::Task; using v8::Isolate; namespace v8 { namespace internal { namespace heap { class MockPlatform : public TestPlatform { public: MockPlatform() : taskrunner_(new MockTaskRunner()), old_platform_(i::V8::GetCurrentPlatform()) { // Now that it's completely constructed, make this the current platform. i::V8::SetPlatformForTesting(this); } ~MockPlatform() override { i::V8::SetPlatformForTesting(old_platform_); for (auto& task : worker_tasks_) { old_platform_->CallOnWorkerThread(std::move(task)); } worker_tasks_.clear(); } std::shared_ptr GetForegroundTaskRunner( v8::Isolate* isolate) override { return taskrunner_; } void CallOnWorkerThread(std::unique_ptr task) override { worker_tasks_.push_back(std::move(task)); } bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; } bool PendingTask() { return taskrunner_->PendingTask(); } void PerformTask() { taskrunner_->PerformTask(); } private: class MockTaskRunner : public v8::TaskRunner { public: void PostTask(std::unique_ptr task) override { task_ = std::move(task); } void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override { task_ = std::move(task); } void PostIdleTask(std::unique_ptr task) override { UNREACHABLE(); } bool IdleTasksEnabled() override { return false; } bool PendingTask() { return task_ != nullptr; } void PerformTask() { std::unique_ptr task = std::move(task_); task->Run(); } private: std::unique_ptr task_; }; std::shared_ptr taskrunner_; std::vector> worker_tasks_; v8::Platform* old_platform_; }; TEST(IncrementalMarkingUsingTasks) { if (!i::FLAG_incremental_marking) return; FLAG_stress_concurrent_allocation = false; // For SimulateFullSpace. FLAG_stress_incremental_marking = false; CcTest::InitializeVM(); MockPlatform platform; i::heap::SimulateFullSpace(CcTest::heap()->old_space()); i::IncrementalMarking* marking = CcTest::heap()->incremental_marking(); marking->Stop(); { SafepointScope scope(CcTest::heap()); marking->Start(i::GarbageCollectionReason::kTesting); } CHECK(platform.PendingTask()); while (platform.PendingTask()) { platform.PerformTask(); } CHECK(marking->IsStopped()); } } // namespace heap } // namespace internal } // namespace v8