Commit d37562e5 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

heap: Improve unified heap test coverage

Add test for Cpp->JS references.

Bug: chromium:1056170
Change-Id: I7240483b6ad7393346b55a9756fcd4721e238119
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642257Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72230}
parent 96b8ec75
...@@ -4,8 +4,10 @@ ...@@ -4,8 +4,10 @@
#include "include/cppgc/allocation.h" #include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h" #include "include/cppgc/garbage-collected.h"
#include "include/cppgc/persistent.h"
#include "include/cppgc/platform.h" #include "include/cppgc/platform.h"
#include "include/v8-cppgc.h" #include "include/v8-cppgc.h"
#include "include/v8.h"
#include "src/api/api-inl.h" #include "src/api/api-inl.h"
#include "src/heap/cppgc-js/cpp-heap.h" #include "src/heap/cppgc-js/cpp-heap.h"
#include "src/objects/objects-inl.h" #include "src/objects/objects-inl.h"
...@@ -23,7 +25,16 @@ class Wrappable final : public cppgc::GarbageCollected<Wrappable> { ...@@ -23,7 +25,16 @@ class Wrappable final : public cppgc::GarbageCollected<Wrappable> {
~Wrappable() { destructor_callcount++; } ~Wrappable() { destructor_callcount++; }
void Trace(cppgc::Visitor* visitor) const {} void Trace(cppgc::Visitor* visitor) const { visitor->Trace(wrapper_); }
void SetWrapper(v8::Isolate* isolate, v8::Local<v8::Object> wrapper) {
wrapper_.Reset(isolate, wrapper);
}
TracedReference<v8::Object>& wrapper() { return wrapper_; }
private:
TracedReference<v8::Object> wrapper_;
}; };
size_t Wrappable::destructor_callcount = 0; size_t Wrappable::destructor_callcount = 0;
...@@ -41,16 +52,14 @@ TEST_F(UnifiedHeapTest, FindingV8ToBlinkReference) { ...@@ -41,16 +52,14 @@ TEST_F(UnifiedHeapTest, FindingV8ToBlinkReference) {
Wrappable::destructor_callcount = 0; Wrappable::destructor_callcount = 0;
EXPECT_FALSE(api_object.IsEmpty()); EXPECT_FALSE(api_object.IsEmpty());
EXPECT_EQ(0u, Wrappable::destructor_callcount); EXPECT_EQ(0u, Wrappable::destructor_callcount);
CollectGarbageWithoutEmbedderStack(); CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
EXPECT_EQ(0u, Wrappable::destructor_callcount); EXPECT_EQ(0u, Wrappable::destructor_callcount);
WrapperHelper::ResetWrappableConnection(api_object); WrapperHelper::ResetWrappableConnection(api_object);
CollectGarbageWithoutEmbedderStack(); CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
// Calling CollectGarbage twice to force the first GC to finish sweeping.
CollectGarbageWithoutEmbedderStack();
EXPECT_EQ(1u, Wrappable::destructor_callcount); EXPECT_EQ(1u, Wrappable::destructor_callcount);
} }
TEST_F(UnifiedHeapTest, WriteBarrierV8ToBlinkReference) { TEST_F(UnifiedHeapTest, WriteBarrierV8ToCppReference) {
v8::HandleScope scope(v8_isolate()); v8::HandleScope scope(v8_isolate());
v8::Local<v8::Context> context = v8::Context::New(v8_isolate()); v8::Local<v8::Context> context = v8::Context::New(v8_isolate());
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
...@@ -71,10 +80,41 @@ TEST_F(UnifiedHeapTest, WriteBarrierV8ToBlinkReference) { ...@@ -71,10 +80,41 @@ TEST_F(UnifiedHeapTest, WriteBarrierV8ToBlinkReference) {
JSHeapConsistency::DijkstraMarkingBarrier( JSHeapConsistency::DijkstraMarkingBarrier(
params, cpp_heap().GetHeapHandle(), wrappable); params, cpp_heap().GetHeapHandle(), wrappable);
} }
CollectGarbageWithoutEmbedderStack(); CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
// Calling CollectGarbage twice to force the first GC to finish sweeping. EXPECT_EQ(0u, Wrappable::destructor_callcount);
CollectGarbageWithoutEmbedderStack(); }
TEST_F(UnifiedHeapTest, WriteBarrierCppToV8Reference) {
v8::HandleScope scope(v8_isolate());
v8::Local<v8::Context> context = v8::Context::New(v8_isolate());
v8::Context::Scope context_scope(context);
cppgc::Persistent<Wrappable> wrappable =
cppgc::MakeGarbageCollected<Wrappable>(allocation_handle());
Wrappable::destructor_callcount = 0;
SimulateIncrementalMarking();
// Pick a sentinel to compare against.
void* kMagicAddress = &Wrappable::destructor_callcount;
{
// The following snippet shows the embedder code for implementing a GC-safe
// setter for C++ to JS references.
v8::HandleScope nested_scope(v8_isolate());
v8::Local<v8::Object> api_object =
WrapperHelper::CreateWrapper(context, nullptr);
// Setting only one field to avoid treating this as wrappable backref, see
// `LocalEmbedderHeapTracer::ExtractWrapperInfo`.
api_object->SetAlignedPointerInInternalField(1, kMagicAddress);
wrappable->SetWrapper(v8_isolate(), api_object);
JSHeapConsistency::WriteBarrierParams params;
auto barrier_type =
JSHeapConsistency::GetWriteBarrierType(wrappable->wrapper(), params);
EXPECT_EQ(JSHeapConsistency::WriteBarrierType::kMarking, barrier_type);
JSHeapConsistency::DijkstraMarkingBarrier(
params, cpp_heap().GetHeapHandle(), wrappable->wrapper());
}
CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
EXPECT_EQ(0u, Wrappable::destructor_callcount); EXPECT_EQ(0u, Wrappable::destructor_callcount);
EXPECT_EQ(kMagicAddress,
wrappable->wrapper()->GetAlignedPointerFromInternalField(1));
} }
} // namespace internal } // namespace internal
......
...@@ -18,16 +18,24 @@ UnifiedHeapTest::UnifiedHeapTest() { ...@@ -18,16 +18,24 @@ UnifiedHeapTest::UnifiedHeapTest() {
isolate()->heap()->ConfigureCppHeap(std::make_unique<CppHeapCreateParams>()); isolate()->heap()->ConfigureCppHeap(std::make_unique<CppHeapCreateParams>());
} }
void UnifiedHeapTest::CollectGarbageWithEmbedderStack() { void UnifiedHeapTest::CollectGarbageWithEmbedderStack(
cppgc::Heap::SweepingType sweeping_type) {
heap()->SetEmbedderStackStateForNextFinalization( heap()->SetEmbedderStackStateForNextFinalization(
EmbedderHeapTracer::EmbedderStackState::kMayContainHeapPointers); EmbedderHeapTracer::EmbedderStackState::kMayContainHeapPointers);
CollectGarbage(OLD_SPACE); CollectGarbage(OLD_SPACE);
if (sweeping_type == cppgc::Heap::SweepingType::kAtomic) {
cpp_heap().AsBase().sweeper().FinishIfRunning();
}
} }
void UnifiedHeapTest::CollectGarbageWithoutEmbedderStack() { void UnifiedHeapTest::CollectGarbageWithoutEmbedderStack(
cppgc::Heap::SweepingType sweeping_type) {
heap()->SetEmbedderStackStateForNextFinalization( heap()->SetEmbedderStackStateForNextFinalization(
EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers); EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers);
CollectGarbage(OLD_SPACE); CollectGarbage(OLD_SPACE);
if (sweeping_type == cppgc::Heap::SweepingType::kAtomic) {
cpp_heap().AsBase().sweeper().FinishIfRunning();
}
} }
CppHeap& UnifiedHeapTest::cpp_heap() const { CppHeap& UnifiedHeapTest::cpp_heap() const {
......
...@@ -19,8 +19,11 @@ class UnifiedHeapTest : public TestWithHeapInternals { ...@@ -19,8 +19,11 @@ class UnifiedHeapTest : public TestWithHeapInternals {
UnifiedHeapTest(); UnifiedHeapTest();
~UnifiedHeapTest() override = default; ~UnifiedHeapTest() override = default;
void CollectGarbageWithEmbedderStack(); void CollectGarbageWithEmbedderStack(cppgc::Heap::SweepingType sweeping_type =
void CollectGarbageWithoutEmbedderStack(); cppgc::Heap::SweepingType::kAtomic);
void CollectGarbageWithoutEmbedderStack(
cppgc::Heap::SweepingType sweeping_type =
cppgc::Heap::SweepingType::kAtomic);
CppHeap& cpp_heap() const; CppHeap& cpp_heap() const;
cppgc::AllocationHandle& allocation_handle(); cppgc::AllocationHandle& allocation_handle();
......
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