// 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/handles/global-handles.h" #include "src/heap/gc-tracer.h" #include "src/heap/incremental-marking.h" #include "src/heap/spaces.h" #include "src/init/v8.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()) {} ~MockPlatform() override { for (auto& task : worker_tasks_) { CcTest::default_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 PostNonNestableTask(std::unique_ptr task) override { PostTask(std::move(task)); } void PostDelayedTask(std::unique_ptr task, double delay_in_seconds) override { PostTask(std::move(task)); } void PostNonNestableDelayedTask(std::unique_ptr task, double delay_in_seconds) override { PostTask(std::move(task)); } void PostIdleTask(std::unique_ptr task) override { UNREACHABLE(); } bool IdleTasksEnabled() override { return false; } bool NonNestableTasksEnabled() const override { return true; } bool NonNestableDelayedTasksEnabled() const override { return true; } 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_; }; TEST_WITH_PLATFORM(IncrementalMarkingUsingTasks, MockPlatform) { if (!i::v8_flags.incremental_marking) return; v8_flags.stress_concurrent_allocation = false; // For SimulateFullSpace. v8_flags.stress_incremental_marking = false; v8::Isolate* isolate = CcTest::isolate(); { v8::HandleScope handle_scope(isolate); v8::Local context = CcTest::NewContext(isolate); v8::Context::Scope context_scope(context); Isolate* i_isolate = reinterpret_cast(isolate); Heap* heap = i_isolate->heap(); i::heap::SimulateFullSpace(heap->old_space()); i::IncrementalMarking* marking = heap->incremental_marking(); marking->Stop(); { IsolateSafepointScope scope(heap); heap->tracer()->StartCycle( GarbageCollector::MARK_COMPACTOR, GarbageCollectionReason::kTesting, "collector cctest", GCTracer::MarkingType::kIncremental); marking->Start(GarbageCollector::MARK_COMPACTOR, i::GarbageCollectionReason::kTesting); } CHECK(platform.PendingTask()); while (platform.PendingTask()) { platform.PerformTask(); } CHECK(marking->IsStopped()); } } } // namespace heap } // namespace internal } // namespace v8