Commit a35d0e8c authored by Maya Lekova's avatar Maya Lekova Committed by Commit Bot

Revert "cppgc: Port concurrent sweeper"

This reverts commit 9a0e6bd5.

Reason for revert: Speculative revert for https://ci.chromium.org/p/v8/builders/ci/V8%20Linux64%20-%20builder/47777

Original change's description:
> cppgc: Port concurrent sweeper
> 
> This moves concurrent and incremental sweeping from Blink. This also
> adds TestPlatform that makes it easier to test concurrent and
> incremental sweeping.
> 
> Drive-by: fix unmarking of large pages.
> 
> Bug: chromium:1056170
> Change-Id: Ifd50ff67b9df17ff117a5f4d4eb5a2937d3023be
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2207132
> Commit-Queue: Anton Bikineev <bikineev@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Reviewed-by: Omer Katz <omerkatz@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#67969}

TBR=ulan@chromium.org,mlippautz@chromium.org,bikineev@chromium.org,omerkatz@chromium.org

Change-Id: I5530f11f7b8560116324bb156ba98e426c0feb35
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:1056170
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2215057Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67970}
parent 9a0e6bd5
......@@ -10,16 +10,13 @@
namespace cppgc {
// TODO(v8:10346): Put PageAllocator and Platform in a non-V8 include header to
// avoid depending on namespace v8.
// TODO(v8:10346): Put PageAllocator in a non-V8 include header to avoid
// depending on namespace v8.
using PageAllocator = v8::PageAllocator;
using Platform = v8::Platform;
// Initializes the garbage collector with the provided platform. Must be called
// before creating a Heap.
V8_EXPORT void InitializePlatform(Platform* platform);
V8_EXPORT Platform* GetPlatform();
V8_EXPORT void InitializePlatform(PageAllocator* page_allocator);
// Must be called after destroying the last used heap.
V8_EXPORT void ShutdownPlatform();
......
......@@ -73,15 +73,6 @@ const BasePage* BasePage::FromInnerAddress(const Heap* heap,
heap->page_backend()->Lookup(static_cast<ConstAddress>(address)));
}
// static
void BasePage::Destroy(BasePage* page) {
if (page->is_large()) {
LargePage::Destroy(LargePage::From(page));
} else {
NormalPage::Destroy(NormalPage::From(page));
}
}
HeapObjectHeader& BasePage::ObjectHeaderFromInnerAddress(void* address) const {
return const_cast<HeapObjectHeader&>(
ObjectHeaderFromInnerAddress(const_cast<const void*>(address)));
......
......@@ -28,8 +28,6 @@ class V8_EXPORT_PRIVATE BasePage {
static BasePage* FromInnerAddress(const Heap*, void*);
static const BasePage* FromInnerAddress(const Heap*, const void*);
static void Destroy(BasePage*);
BasePage(const BasePage&) = delete;
BasePage& operator=(const BasePage&) = delete;
......@@ -143,15 +141,15 @@ class V8_EXPORT_PRIVATE NormalPage final : public BasePage {
static size_t PayloadSize();
bool PayloadContains(ConstAddress address) const {
return (PayloadStart() <= address) && (address < PayloadEnd());
}
ObjectStartBitmap& object_start_bitmap() { return object_start_bitmap_; }
const ObjectStartBitmap& object_start_bitmap() const {
return object_start_bitmap_;
}
bool PayloadContains(ConstAddress address) const {
return (PayloadStart() <= address) && (address < PayloadEnd());
}
private:
NormalPage(Heap* heap, BaseSpace* space);
~NormalPage();
......
......@@ -7,7 +7,6 @@
#include <algorithm>
#include "src/base/logging.h"
#include "src/base/platform/mutex.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/object-start-bitmap-inl.h"
......@@ -18,13 +17,11 @@ BaseSpace::BaseSpace(RawHeap* heap, size_t index, PageType type)
: heap_(heap), index_(index), type_(type) {}
void BaseSpace::AddPage(BasePage* page) {
v8::base::LockGuard<v8::base::Mutex> lock(&pages_mutex_);
DCHECK_EQ(pages_.cend(), std::find(pages_.cbegin(), pages_.cend(), page));
pages_.push_back(page);
}
void BaseSpace::RemovePage(BasePage* page) {
v8::base::LockGuard<v8::base::Mutex> lock(&pages_mutex_);
auto it = std::find(pages_.cbegin(), pages_.cend(), page);
DCHECK_NE(pages_.cend(), it);
pages_.erase(it);
......
......@@ -9,7 +9,6 @@
#include "src/base/logging.h"
#include "src/base/macros.h"
#include "src/base/platform/mutex.h"
#include "src/heap/cppgc/free-list.h"
namespace cppgc {
......@@ -54,7 +53,6 @@ class V8_EXPORT_PRIVATE BaseSpace {
private:
RawHeap* heap_;
Pages pages_;
v8::base::Mutex pages_mutex_;
const size_t index_;
const PageType type_;
};
......
......@@ -116,7 +116,7 @@ void Heap::CollectGarbage(GCConfig config) {
marker_.reset();
{
NoGCScope no_gc(this);
sweeper_.Start(config.sweep_type);
sweeper_.Start(Sweeper::Config::kAtomic);
}
}
......
......@@ -68,14 +68,10 @@ class V8_EXPORT_PRIVATE Heap final : public cppgc::Heap {
struct GCConfig {
using StackState = Heap::StackState;
using SweepType = Sweeper::Config;
static GCConfig Default() {
return {StackState::kMayContainHeapPointers, SweepType::kAtomic};
}
static GCConfig Default() { return {StackState::kMayContainHeapPointers}; }
StackState stack_state = StackState::kMayContainHeapPointers;
SweepType sweep_type = SweepType::kAtomic;
};
static Heap* From(cppgc::Heap* heap) { return static_cast<Heap*>(heap); }
......
......@@ -10,18 +10,16 @@
namespace cppgc {
namespace internal {
static Platform* g_platform;
static PageAllocator* g_page_allocator;
} // namespace internal
void InitializePlatform(Platform* platform) {
internal::g_platform = platform;
internal::GlobalGCInfoTable::Create(internal::g_platform->GetPageAllocator());
void InitializePlatform(PageAllocator* page_allocator) {
internal::g_page_allocator = page_allocator;
internal::GlobalGCInfoTable::Create(page_allocator);
}
Platform* GetPlatform() { return internal::g_platform; }
void ShutdownPlatform() { internal::g_platform = nullptr; }
void ShutdownPlatform() { internal::g_page_allocator = nullptr; }
namespace internal {
......
This diff is collapsed.
......@@ -44,7 +44,6 @@ v8_source_set("cppgc_unittests_sources") {
testonly = true
sources = [
"heap/cppgc/concurrent-sweeper-unittest.cc",
"heap/cppgc/custom-spaces-unittest.cc",
"heap/cppgc/finalizer-trait-unittest.cc",
"heap/cppgc/free-list-unittest.cc",
......@@ -64,8 +63,6 @@ v8_source_set("cppgc_unittests_sources") {
"heap/cppgc/source-location-unittest.cc",
"heap/cppgc/stack-unittest.cc",
"heap/cppgc/sweeper-unittest.cc",
"heap/cppgc/test-platform.cc",
"heap/cppgc/test-platform.h",
"heap/cppgc/tests.cc",
"heap/cppgc/tests.h",
"heap/cppgc/visitor-unittest.cc",
......
// Copyright 2020 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 <algorithm>
#include <set>
#include <vector>
#include "include/cppgc/allocation.h"
#include "include/cppgc/platform.h"
#include "include/v8-platform.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap-object-header-inl.h"
#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/heap-space.h"
#include "src/heap/cppgc/heap-visitor.h"
#include "src/heap/cppgc/page-memory-inl.h"
#include "src/heap/cppgc/raw-heap.h"
#include "src/heap/cppgc/sweeper.h"
#include "test/unittests/heap/cppgc/test-platform.h"
#include "test/unittests/heap/cppgc/tests.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cppgc {
namespace internal {
namespace {
class ResetLocalAllocationBufferVisitor final
: public HeapVisitor<ResetLocalAllocationBufferVisitor> {
public:
bool VisitLargePageSpace(LargePageSpace*) { return true; }
bool VisitNormalPageSpace(NormalPageSpace* space) {
space->ResetLinearAllocationBuffer();
return true;
}
};
void ResetLocalAllocationBuffers(Heap* heap) {
ResetLocalAllocationBufferVisitor visitor;
visitor.Traverse(&heap->raw_heap());
}
size_t g_destructor_callcount;
template <size_t Size>
class Finalizable : public GarbageCollected<Finalizable<Size>> {
public:
Finalizable() : creation_thread_{v8::base::OS::GetCurrentThreadId()} {}
virtual ~Finalizable() {
++g_destructor_callcount;
EXPECT_EQ(creation_thread_, v8::base::OS::GetCurrentThreadId());
}
virtual void Trace(cppgc::Visitor*) const {}
private:
char array_[Size];
int creation_thread_;
};
using NormalFinalizable = Finalizable<32>;
using LargeFinalizable = Finalizable<kLargeObjectSizeThreshold * 2>;
template <size_t Size>
class NonFinalizable : public GarbageCollected<NonFinalizable<Size>> {
public:
virtual void Trace(cppgc::Visitor*) const {}
private:
char array_[Size];
};
using NormalNonFinalizable = NonFinalizable<32>;
using LargeNonFinalizable = NonFinalizable<kLargeObjectSizeThreshold * 2>;
class ConcurrentSweeperTest : public testing::TestWithHeap {
public:
ConcurrentSweeperTest() { g_destructor_callcount = 0; }
void StartSweeping() {
Heap* heap = Heap::From(GetHeap());
ResetLocalAllocationBuffers(heap);
Sweeper& sweeper = heap->sweeper();
sweeper.Start(Sweeper::Config::kIncrementalAndConcurrent);
}
void FinishSweeping() {
Heap* heap = Heap::From(GetHeap());
Sweeper& sweeper = heap->sweeper();
sweeper.Finish();
}
const RawHeap& GetRawHeap() const {
const Heap* heap = Heap::From(GetHeap());
return heap->raw_heap();
}
void CheckFreeListEntries(const std::vector<void*>& objects) {
const Heap* heap = Heap::From(GetHeap());
const PageBackend* backend = heap->page_backend();
for (auto* object : objects) {
// The corresponding page could be removed.
if (!backend->Lookup(static_cast<ConstAddress>(object))) continue;
const auto* header =
BasePage::FromPayload(object)->TryObjectHeaderFromInnerAddress(
object);
// TryObjectHeaderFromInnerAddress returns nullptr for freelist entries.
EXPECT_EQ(nullptr, header);
}
}
void CheckPageRemoved(const BasePage* page) {
const Heap* heap = Heap::From(GetHeap());
const PageBackend* backend = heap->page_backend();
EXPECT_EQ(nullptr, backend->Lookup(reinterpret_cast<ConstAddress>(page)));
}
bool FreeListContains(const BaseSpace* space,
const std::vector<void*>& objects) {
const Heap* heap = Heap::From(GetHeap());
const PageBackend* backend = heap->page_backend();
const auto& freelist = NormalPageSpace::From(space)->free_list();
for (void* object : objects) {
// The corresponding page could be removed.
if (!backend->Lookup(static_cast<ConstAddress>(object))) continue;
if (!freelist.Contains({object, 0})) return false;
}
return true;
}
};
} // namespace
TEST_F(ConcurrentSweeperTest, BackgroundSweepOfNormalPage) {
// Non finalizable objects are swept right away.
using GCedType = NormalNonFinalizable;
auto* unmarked_object = MakeGarbageCollected<GCedType>(GetHeap());
auto* marked_object = MakeGarbageCollected<GCedType>(GetHeap());
HeapObjectHeader::FromPayload(marked_object).TryMarkAtomic();
auto* page = BasePage::FromPayload(unmarked_object);
auto* space = page->space();
// The test requires objects to be allocated on the same page;
ASSERT_EQ(page, BasePage::FromPayload(marked_object));
StartSweeping();
// Wait for concurrent sweeping to finish.
GetPlatform().WaitAllBackgroundTasks();
// Check that the marked object was unmarked.
EXPECT_FALSE(HeapObjectHeader::FromPayload(marked_object).IsMarked());
// Check that free list entries are created right away for non-finalizable
// objects, but not immediately returned to the space's freelist.
CheckFreeListEntries({unmarked_object});
EXPECT_FALSE(FreeListContains(space, {unmarked_object}));
FinishSweeping();
// Check that finalizable objects are swept and put into the freelist of the
// corresponding space.
EXPECT_TRUE(FreeListContains(space, {unmarked_object}));
}
TEST_F(ConcurrentSweeperTest, BackgroundSweepOfLargePage) {
// Non finalizable objects are swept right away.
using GCedType = LargeNonFinalizable;
auto* unmarked_object = MakeGarbageCollected<GCedType>(GetHeap());
auto* marked_object = MakeGarbageCollected<GCedType>(GetHeap());
HeapObjectHeader::FromPayload(marked_object).TryMarkAtomic();
auto* unmarked_page = BasePage::FromPayload(unmarked_object);
auto* marked_page = BasePage::FromPayload(marked_object);
auto* space = unmarked_page->space();
ASSERT_EQ(space, marked_page->space());
StartSweeping();
// Wait for concurrent sweeping to finish.
GetPlatform().WaitAllBackgroundTasks();
// Check that the marked object was unmarked.
EXPECT_FALSE(HeapObjectHeader::FromPayload(marked_object).IsMarked());
// Check that free list entries are created right away for non-finalizable
// objects, but not immediately returned to the space's freelist.
CheckPageRemoved(unmarked_page);
// Check that marked pages are returned to space right away.
EXPECT_NE(space->end(), std::find(space->begin(), space->end(), marked_page));
FinishSweeping();
}
TEST_F(ConcurrentSweeperTest, DeferredFinalizationOfNormalPage) {
static constexpr size_t kNumberOfObjects = 10;
// Finalizable types are left intact by concurrent sweeper.
using GCedType = NormalFinalizable;
std::set<BasePage*> pages;
std::vector<void*> objects;
BaseSpace* space = nullptr;
for (size_t i = 0; i < kNumberOfObjects; ++i) {
auto* object = MakeGarbageCollected<GCedType>(GetHeap());
objects.push_back(object);
auto* page = BasePage::FromPayload(object);
pages.insert(page);
if (!space) space = page->space();
}
StartSweeping();
// Wait for concurrent sweeping to finish.
GetPlatform().WaitAllBackgroundTasks();
// Check that pages are not returned right away.
for (auto* page : pages) {
EXPECT_EQ(space->end(), std::find(space->begin(), space->end(), page));
}
// Check that finalizable objects are left intact in pages.
EXPECT_FALSE(FreeListContains(space, objects));
// No finalizers have been executed.
EXPECT_EQ(0u, g_destructor_callcount);
FinishSweeping();
// Check that finalizable objects are swept and turned into freelist entries.
CheckFreeListEntries(objects);
// Check that space's freelist contains these entries.
EXPECT_TRUE(FreeListContains(space, objects));
// Check that finalizers have been executed.
EXPECT_EQ(kNumberOfObjects, g_destructor_callcount);
}
TEST_F(ConcurrentSweeperTest, DeferredFinalizationOfLargePage) {
using GCedType = LargeFinalizable;
auto* object = MakeGarbageCollected<GCedType>(GetHeap());
auto* page = BasePage::FromPayload(object);
auto* space = page->space();
StartSweeping();
// Wait for concurrent sweeping to finish.
GetPlatform().WaitAllBackgroundTasks();
// Check that the page is not returned to the space.
EXPECT_EQ(space->end(), std::find(space->begin(), space->end(), page));
// Check that no destructors have been executed yet.
EXPECT_EQ(0u, g_destructor_callcount);
FinishSweeping();
// Check that the destructor was executed.
EXPECT_EQ(1u, g_destructor_callcount);
// Check that page was unmapped.
CheckPageRemoved(page);
}
TEST_F(ConcurrentSweeperTest, IncrementalSweeping) {
testing::TestPlatform::DisableBackgroundTasksScope disable_concurrent_sweeper(
&GetPlatform());
auto task_runner = GetPlatform().GetForegroundTaskRunner(nullptr);
// Create two unmarked objects.
MakeGarbageCollected<NormalFinalizable>(GetHeap());
MakeGarbageCollected<LargeFinalizable>(GetHeap());
// Create two marked objects.
auto* marked_normal_object =
MakeGarbageCollected<NormalFinalizable>(GetHeap());
auto* marked_large_object = MakeGarbageCollected<LargeFinalizable>(GetHeap());
auto& marked_normal_header =
HeapObjectHeader::FromPayload(marked_normal_object);
auto& marked_large_header =
HeapObjectHeader::FromPayload(marked_large_object);
marked_normal_header.TryMarkAtomic();
marked_large_header.TryMarkAtomic();
StartSweeping();
EXPECT_EQ(0u, g_destructor_callcount);
EXPECT_TRUE(marked_normal_header.IsMarked());
EXPECT_TRUE(marked_large_header.IsMarked());
// Wait for incremental sweeper to finish.
GetPlatform().WaitAllForegroundTasks();
EXPECT_EQ(2u, g_destructor_callcount);
EXPECT_FALSE(marked_normal_header.IsMarked());
EXPECT_FALSE(marked_large_header.IsMarked());
FinishSweeping();
}
} // namespace internal
} // namespace cppgc
......@@ -245,25 +245,5 @@ TEST_F(SweeperTest, SweepDoesNotTriggerRecursiveGC) {
EXPECT_EQ(saved_epoch + 1, internal_heap->epoch());
}
TEST_F(SweeperTest, UnmarkObjects) {
auto* normal_object = MakeGarbageCollected<GCed<32>>(GetHeap());
auto* large_object =
MakeGarbageCollected<GCed<kLargeObjectSizeThreshold * 2>>(GetHeap());
auto& normal_object_header = HeapObjectHeader::FromPayload(normal_object);
auto& large_object_header = HeapObjectHeader::FromPayload(large_object);
normal_object_header.TryMarkAtomic();
large_object_header.TryMarkAtomic();
EXPECT_TRUE(normal_object_header.IsMarked());
EXPECT_TRUE(large_object_header.IsMarked());
Sweep();
EXPECT_FALSE(normal_object_header.IsMarked());
EXPECT_FALSE(large_object_header.IsMarked());
}
} // namespace internal
} // namespace cppgc
// Copyright 2020 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 "test/unittests/heap/cppgc/test-platform.h"
#include "src/base/platform/platform.h"
#include "src/base/platform/time.h"
namespace cppgc {
namespace internal {
namespace testing {
void TestTaskRunner::PostTask(std::unique_ptr<v8::Task> task) {
tasks_.push_back(std::move(task));
}
void TestTaskRunner::PostNonNestableTask(std::unique_ptr<v8::Task> task) {
PostTask(std::move(task));
}
void TestTaskRunner::PostDelayedTask(std::unique_ptr<v8::Task> task, double) {
PostTask(std::move(task));
}
void TestTaskRunner::PostNonNestableDelayedTask(std::unique_ptr<v8::Task> task,
double) {
PostTask(std::move(task));
}
void TestTaskRunner::PostIdleTask(std::unique_ptr<v8::IdleTask> task) {
idle_tasks_.push_back(std::move(task));
}
bool TestTaskRunner::RunSingleTask() {
if (!tasks_.size()) return false;
tasks_.back()->Run();
tasks_.pop_back();
return true;
}
bool TestTaskRunner::RunSingleIdleTask(double deadline_in_seconds) {
if (!idle_tasks_.size()) return false;
idle_tasks_.back()->Run(deadline_in_seconds);
idle_tasks_.pop_back();
return true;
}
void TestTaskRunner::RunUntilIdle() {
for (auto& task : tasks_) {
task->Run();
}
tasks_.clear();
for (auto& task : idle_tasks_) {
task->Run(std::numeric_limits<double>::infinity());
}
idle_tasks_.clear();
}
class TestPlatform::TestJobHandle : public v8::JobHandle {
public:
explicit TestJobHandle(const std::shared_ptr<JobThread>& thread)
: thread_(thread) {
const bool success = thread_->Start();
USE(success);
}
void NotifyConcurrencyIncrease() override {}
void Join() override { thread_->Join(); }
void Cancel() override { Join(); }
bool IsRunning() override { return true; }
private:
std::shared_ptr<JobThread> thread_;
};
TestPlatform::TestPlatform()
: foreground_task_runner_(std::make_unique<TestTaskRunner>()) {}
TestPlatform::~TestPlatform() V8_NOEXCEPT { WaitAllBackgroundTasks(); }
void TestPlatform::CallOnWorkerThread(std::unique_ptr<v8::Task> task) {
if (AreBackgroundTasksDisabled()) return;
auto thread = std::make_unique<WorkerThread>(std::move(task));
if (thread->Start()) {
threads_.push_back(std::move(thread));
}
}
void TestPlatform::CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
double) {
CallOnWorkerThread(std::move(task));
}
std::unique_ptr<v8::JobHandle> TestPlatform::PostJob(
v8::TaskPriority, std::unique_ptr<v8::JobTask> job_task) {
if (AreBackgroundTasksDisabled()) return {};
auto thread = std::make_shared<JobThread>(std::move(job_task));
job_threads_.push_back(thread);
return std::make_unique<TestJobHandle>(std::move(thread));
}
double TestPlatform::MonotonicallyIncreasingTime() {
return v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
static_cast<double>(v8::base::Time::kMicrosecondsPerSecond);
}
double TestPlatform::CurrentClockTimeMillis() {
return v8::base::OS::TimeCurrentMillis();
}
void TestPlatform::WaitAllForegroundTasks() {
foreground_task_runner_->RunUntilIdle();
}
void TestPlatform::WaitAllBackgroundTasks() {
for (auto& thread : threads_) {
thread->Join();
}
threads_.clear();
for (auto& thread : job_threads_) {
thread->Join();
}
threads_.clear();
}
TestPlatform::DisableBackgroundTasksScope::DisableBackgroundTasksScope(
TestPlatform* platform)
: platform_(platform) {
++platform_->disabled_background_tasks_;
}
TestPlatform::DisableBackgroundTasksScope::~DisableBackgroundTasksScope()
V8_NOEXCEPT {
--platform_->disabled_background_tasks_;
}
} // namespace testing
} // namespace internal
} // namespace cppgc
// Copyright 2020 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_UNITTESTS_HEAP_CPPGC_TEST_PLATFORM_H_
#define V8_UNITTESTS_HEAP_CPPGC_TEST_PLATFORM_H_
#include <memory>
#include <vector>
#include "include/cppgc/platform.h"
#include "src/base/page-allocator.h"
#include "src/base/platform/platform.h"
namespace cppgc {
namespace internal {
namespace testing {
class TestTaskRunner : public v8::TaskRunner {
public:
void PostTask(std::unique_ptr<v8::Task> task) override;
void PostNonNestableTask(std::unique_ptr<v8::Task> task) override;
void PostDelayedTask(std::unique_ptr<v8::Task> task, double) override;
void PostNonNestableDelayedTask(std::unique_ptr<v8::Task> task,
double) override;
void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override;
bool IdleTasksEnabled() override { return true; }
bool RunSingleTask();
bool RunSingleIdleTask(double duration_in_seconds);
void RunUntilIdle();
private:
std::vector<std::unique_ptr<v8::Task>> tasks_;
std::vector<std::unique_ptr<v8::IdleTask>> idle_tasks_;
};
class TestPlatform : public Platform {
public:
class DisableBackgroundTasksScope {
public:
explicit DisableBackgroundTasksScope(TestPlatform*);
~DisableBackgroundTasksScope() V8_NOEXCEPT;
private:
TestPlatform* platform_;
};
TestPlatform();
~TestPlatform() V8_NOEXCEPT override;
PageAllocator* GetPageAllocator() override { return &page_allocator_; }
int NumberOfWorkerThreads() override {
return static_cast<int>(threads_.size());
}
std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner(
v8::Isolate*) override {
return foreground_task_runner_;
}
void CallOnWorkerThread(std::unique_ptr<v8::Task> task) override;
void CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task,
double) override;
bool IdleTasksEnabled(v8::Isolate*) override { return true; }
std::unique_ptr<v8::JobHandle> PostJob(
v8::TaskPriority, std::unique_ptr<v8::JobTask> job_task) override;
double MonotonicallyIncreasingTime() override;
double CurrentClockTimeMillis() override;
v8::TracingController* GetTracingController() override {
return &tracing_controller_;
}
void WaitAllForegroundTasks();
void WaitAllBackgroundTasks();
private:
class TestJobHandle;
class WorkerThread : public v8::base::Thread {
public:
explicit WorkerThread(std::unique_ptr<v8::Task> task)
: Thread(Options("worker")), task_(std::move(task)) {}
void Run() override {
if (task_) std::move(task_)->Run();
}
private:
std::unique_ptr<v8::Task> task_;
};
class JobThread : public v8::base::Thread {
public:
explicit JobThread(std::unique_ptr<v8::JobTask> task)
: Thread(Options("job")), task_(std::move(task)) {}
void Run() override {
class JobDelegate : public v8::JobDelegate {
public:
bool ShouldYield() override { return false; }
void NotifyConcurrencyIncrease() override {}
} delegate;
if (task_) task_->Run(&delegate);
}
private:
std::unique_ptr<v8::JobTask> task_;
};
bool AreBackgroundTasksDisabled() const {
return disabled_background_tasks_ > 0;
}
v8::base::PageAllocator page_allocator_;
std::shared_ptr<TestTaskRunner> foreground_task_runner_;
std::vector<std::unique_ptr<WorkerThread>> threads_;
std::vector<std::shared_ptr<JobThread>> job_threads_;
v8::TracingController tracing_controller_;
size_t disabled_background_tasks_ = 0;
};
} // namespace testing
} // namespace internal
} // namespace cppgc
#endif // V8_UNITTESTS_HEAP_CPPGC_TEST_PLATFORM_H_
......@@ -6,25 +6,23 @@
#include <memory>
#include "test/unittests/heap/cppgc/test-platform.h"
namespace cppgc {
namespace internal {
namespace testing {
// static
std::unique_ptr<TestPlatform> TestWithPlatform::platform_;
std::unique_ptr<cppgc::PageAllocator> TestWithPlatform::page_allocator_;
// static
void TestWithPlatform::SetUpTestSuite() {
platform_ = std::make_unique<TestPlatform>();
cppgc::InitializePlatform(platform_.get());
page_allocator_ = std::make_unique<v8::base::PageAllocator>();
cppgc::InitializePlatform(page_allocator_.get());
}
// static
void TestWithPlatform::TearDownTestSuite() {
cppgc::ShutdownPlatform();
platform_.reset();
page_allocator_.reset();
}
TestWithHeap::TestWithHeap() : heap_(Heap::Create()) {}
......
......@@ -7,8 +7,8 @@
#include "include/cppgc/heap.h"
#include "include/cppgc/platform.h"
#include "src/base/page-allocator.h"
#include "src/heap/cppgc/heap.h"
#include "test/unittests/heap/cppgc/test-platform.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace cppgc {
......@@ -20,10 +20,8 @@ class TestWithPlatform : public ::testing::Test {
static void SetUpTestSuite();
static void TearDownTestSuite();
TestPlatform& GetPlatform() const { return *platform_; }
private:
static std::unique_ptr<TestPlatform> platform_;
static std::unique_ptr<cppgc::PageAllocator> page_allocator_;
};
class TestWithHeap : public TestWithPlatform {
......
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