nodejs/deps/v8/test/unittests/heap/strong-root-allocator-unittest.cc

260 lines
6.8 KiB
C++
Raw Permalink Normal View History

// Copyright 2023 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 <list>
#include <set>
#include <vector>
#include "src/heap/heap.h"
#include "test/unittests/heap/heap-utils.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
using StrongRootAllocatorTest = TestWithHeapInternals;
TEST_F(StrongRootAllocatorTest, AddressRetained) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
StrongRootAllocator<Address> allocator(heap());
Address* allocated = allocator.allocate(10);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
allocated[7] = h->ptr();
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_FALSE(weak.IsEmpty());
allocator.deallocate(allocated, 10);
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
TEST_F(StrongRootAllocatorTest, StructNotRetained) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
struct Wrapped {
Address content;
};
StrongRootAllocator<Wrapped> allocator(heap());
Wrapped* allocated = allocator.allocate(10);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
allocated[7].content = h->ptr();
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
allocator.deallocate(allocated, 10);
}
TEST_F(StrongRootAllocatorTest, VectorRetained) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
{
StrongRootAllocator<Address> allocator(heap());
std::vector<Address, StrongRootAllocator<Address>> v(10, allocator);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
v[7] = h->ptr();
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_FALSE(weak.IsEmpty());
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
TEST_F(StrongRootAllocatorTest, VectorOfStructNotRetained) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
struct Wrapped {
Address content;
};
StrongRootAllocator<Wrapped> allocator(heap());
std::vector<Wrapped, StrongRootAllocator<Wrapped>> v(10, allocator);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
v[7].content = h->ptr();
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
TEST_F(StrongRootAllocatorTest, ListNotRetained) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
StrongRootAllocator<Address> allocator(heap());
std::list<Address, StrongRootAllocator<Address>> list(allocator);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
list.push_back(h->ptr());
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
TEST_F(StrongRootAllocatorTest, SetNotRetained) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
StrongRootAllocator<Address> allocator(heap());
std::set<Address, std::less<Address>, StrongRootAllocator<Address>> s(
allocator);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
s.insert(h->ptr());
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
TEST_F(StrongRootAllocatorTest, LocalVector) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
{
v8::HandleScope outer_scope(v8_isolate());
// LocalVector uses the StrongRootAllocator for its backing store.
LocalVector<v8::FixedArray> v(v8_isolate(), 10);
{
v8::EscapableHandleScope inner_scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
weak.Reset(v8_isolate(), l);
weak.SetWeak();
v[7] = inner_scope.Escape(l);
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_FALSE(weak.IsEmpty());
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
#ifdef V8_ENABLE_DIRECT_HANDLE
TEST_F(StrongRootAllocatorTest, LocalVectorWithDirect) {
ManualGCScope manual_gc_scope(i_isolate());
Global<v8::FixedArray> weak;
{
// LocalVector uses the StrongRootAllocator for its backing store.
LocalVector<v8::FixedArray> v(v8_isolate(), 10);
{
v8::HandleScope scope(v8_isolate());
DirectHandle<FixedArray> h =
factory()->NewFixedArray(10, AllocationType::kOld);
Local<v8::FixedArray> l = Utils::FixedArrayToLocal(h);
// This is legal without escaping, because locals are direct.
v[7] = l;
weak.Reset(v8_isolate(), l);
weak.SetWeak();
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_FALSE(weak.IsEmpty());
}
{
DisableConservativeStackScanningScopeForTesting no_stack_scanning(heap());
InvokeMajorGC();
}
EXPECT_TRUE(weak.IsEmpty());
}
#endif // V8_ENABLE_DIRECT_HANDLE
} // namespace internal
} // namespace v8