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 @@
#include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/persistent.h"
#include "include/cppgc/platform.h"
#include "include/v8-cppgc.h"
#include "include/v8.h"
#include "src/api/api-inl.h"
#include "src/heap/cppgc-js/cpp-heap.h"
#include "src/objects/objects-inl.h"
......@@ -23,7 +25,16 @@ class Wrappable final : public cppgc::GarbageCollected<Wrappable> {
~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;
......@@ -41,16 +52,14 @@ TEST_F(UnifiedHeapTest, FindingV8ToBlinkReference) {
Wrappable::destructor_callcount = 0;
EXPECT_FALSE(api_object.IsEmpty());
EXPECT_EQ(0u, Wrappable::destructor_callcount);
CollectGarbageWithoutEmbedderStack();
CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
EXPECT_EQ(0u, Wrappable::destructor_callcount);
WrapperHelper::ResetWrappableConnection(api_object);
CollectGarbageWithoutEmbedderStack();
// Calling CollectGarbage twice to force the first GC to finish sweeping.
CollectGarbageWithoutEmbedderStack();
CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
EXPECT_EQ(1u, Wrappable::destructor_callcount);
}
TEST_F(UnifiedHeapTest, WriteBarrierV8ToBlinkReference) {
TEST_F(UnifiedHeapTest, WriteBarrierV8ToCppReference) {
v8::HandleScope scope(v8_isolate());
v8::Local<v8::Context> context = v8::Context::New(v8_isolate());
v8::Context::Scope context_scope(context);
......@@ -71,10 +80,41 @@ TEST_F(UnifiedHeapTest, WriteBarrierV8ToBlinkReference) {
JSHeapConsistency::DijkstraMarkingBarrier(
params, cpp_heap().GetHeapHandle(), wrappable);
}
CollectGarbageWithoutEmbedderStack();
// Calling CollectGarbage twice to force the first GC to finish sweeping.
CollectGarbageWithoutEmbedderStack();
CollectGarbageWithoutEmbedderStack(cppgc::Heap::SweepingType::kAtomic);
EXPECT_EQ(0u, Wrappable::destructor_callcount);
}
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(kMagicAddress,
wrappable->wrapper()->GetAlignedPointerFromInternalField(1));
}
} // namespace internal
......
......@@ -18,16 +18,24 @@ UnifiedHeapTest::UnifiedHeapTest() {
isolate()->heap()->ConfigureCppHeap(std::make_unique<CppHeapCreateParams>());
}
void UnifiedHeapTest::CollectGarbageWithEmbedderStack() {
void UnifiedHeapTest::CollectGarbageWithEmbedderStack(
cppgc::Heap::SweepingType sweeping_type) {
heap()->SetEmbedderStackStateForNextFinalization(
EmbedderHeapTracer::EmbedderStackState::kMayContainHeapPointers);
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(
EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers);
CollectGarbage(OLD_SPACE);
if (sweeping_type == cppgc::Heap::SweepingType::kAtomic) {
cpp_heap().AsBase().sweeper().FinishIfRunning();
}
}
CppHeap& UnifiedHeapTest::cpp_heap() const {
......
......@@ -19,8 +19,11 @@ class UnifiedHeapTest : public TestWithHeapInternals {
UnifiedHeapTest();
~UnifiedHeapTest() override = default;
void CollectGarbageWithEmbedderStack();
void CollectGarbageWithoutEmbedderStack();
void CollectGarbageWithEmbedderStack(cppgc::Heap::SweepingType sweeping_type =
cppgc::Heap::SweepingType::kAtomic);
void CollectGarbageWithoutEmbedderStack(
cppgc::Heap::SweepingType sweeping_type =
cppgc::Heap::SweepingType::kAtomic);
CppHeap& cpp_heap() const;
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