v8/test/unittests/heap/shared-heap-unittest.cc
Clemens Backes 7d3d3a780c [heap] Use v8_flags for accessing flag values
Avoid the deprecated FLAG_* syntax, access flag values via the
{v8_flags} struct instead.

R=mlippautz@chromium.org

Bug: v8:12887
Change-Id: Id12f9d8270dd9fed651e1b3596c06e45aae9d6d1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3846151
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Auto-Submit: Clemens Backes <clemensb@chromium.org>
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82969}
2022-09-05 10:59:05 +00:00

270 lines
8.2 KiB
C++

// Copyright 2021 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 "src/base/platform/platform.h"
#include "src/heap/heap.h"
#include "src/heap/parked-scope.h"
#include "test/unittests/heap/heap-utils.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#if V8_CAN_CREATE_SHARED_HEAP_BOOL
namespace v8 {
namespace internal {
using SharedHeapTest = TestJSSharedMemoryWithIsolate;
class SharedHeapNoClientsTest : public TestJSSharedMemoryWithPlatform {
public:
SharedHeapNoClientsTest() {
bool created;
shared_isolate_ = Isolate::GetProcessWideSharedIsolate(&created);
CHECK(created);
}
~SharedHeapNoClientsTest() override {
Isolate::DeleteProcessWideSharedIsolate();
}
v8::Isolate* shared_isolate() {
return reinterpret_cast<v8::Isolate*>(i_shared_isolate());
}
Isolate* i_shared_isolate() { return shared_isolate_; }
private:
Isolate* shared_isolate_;
};
namespace {
const int kNumIterations = 2000;
template <typename Callback>
void SetupClientIsolateAndRunCallback(Callback callback) {
IsolateWrapper isolate_wrapper(kNoCounters);
v8::Isolate* client_isolate = isolate_wrapper.isolate();
Isolate* i_client_isolate = reinterpret_cast<Isolate*>(client_isolate);
callback(client_isolate, i_client_isolate);
}
class SharedOldSpaceAllocationThread final : public ParkingThread {
public:
SharedOldSpaceAllocationThread()
: ParkingThread(base::Thread::Options("SharedOldSpaceAllocationThread")) {
}
void Run() override {
SetupClientIsolateAndRunCallback(
[](v8::Isolate* client_isolate, Isolate* i_client_isolate) {
HandleScope scope(i_client_isolate);
for (int i = 0; i < kNumIterations; i++) {
i_client_isolate->factory()->NewFixedArray(
10, AllocationType::kSharedOld);
}
CollectGarbage(OLD_SPACE, client_isolate);
v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(),
client_isolate);
});
}
};
} // namespace
TEST_F(SharedHeapTest, ConcurrentAllocationInSharedOldSpace) {
std::vector<std::unique_ptr<SharedOldSpaceAllocationThread>> threads;
const int kThreads = 4;
ParkedScope parked(i_isolate()->main_thread_local_isolate());
for (int i = 0; i < kThreads; i++) {
auto thread = std::make_unique<SharedOldSpaceAllocationThread>();
CHECK(thread->Start());
threads.push_back(std::move(thread));
}
for (auto& thread : threads) {
thread->ParkedJoin(parked);
}
}
namespace {
class SharedLargeOldSpaceAllocationThread final : public ParkingThread {
public:
SharedLargeOldSpaceAllocationThread()
: ParkingThread(base::Thread::Options("SharedOldSpaceAllocationThread")) {
}
void Run() override {
SetupClientIsolateAndRunCallback(
[](v8::Isolate* client_isolate, Isolate* i_client_isolate) {
HandleScope scope(i_client_isolate);
const int kNumIterations = 50;
for (int i = 0; i < kNumIterations; i++) {
HandleScope scope(i_client_isolate);
Handle<FixedArray> fixed_array =
i_client_isolate->factory()->NewFixedArray(
kMaxRegularHeapObjectSize / kTaggedSize,
AllocationType::kSharedOld);
CHECK(MemoryChunk::FromHeapObject(*fixed_array)->IsLargePage());
}
CollectGarbage(OLD_SPACE, client_isolate);
v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(),
client_isolate);
});
}
};
} // namespace
TEST_F(SharedHeapTest, ConcurrentAllocationInSharedLargeOldSpace) {
std::vector<std::unique_ptr<SharedLargeOldSpaceAllocationThread>> threads;
const int kThreads = 4;
ParkedScope parked(i_isolate()->main_thread_local_isolate());
for (int i = 0; i < kThreads; i++) {
auto thread = std::make_unique<SharedLargeOldSpaceAllocationThread>();
CHECK(thread->Start());
threads.push_back(std::move(thread));
}
for (auto& thread : threads) {
thread->ParkedJoin(parked);
}
}
namespace {
class SharedMapSpaceAllocationThread final : public ParkingThread {
public:
SharedMapSpaceAllocationThread()
: ParkingThread(base::Thread::Options("SharedMapSpaceAllocationThread")) {
}
void Run() override {
SetupClientIsolateAndRunCallback(
[](v8::Isolate* client_isolate, Isolate* i_client_isolate) {
HandleScope scope(i_client_isolate);
for (int i = 0; i < kNumIterations; i++) {
i_client_isolate->factory()->NewMap(
NATIVE_CONTEXT_TYPE, kVariableSizeSentinel,
TERMINAL_FAST_ELEMENTS_KIND, 0, AllocationType::kSharedMap);
}
CollectGarbage(OLD_SPACE, client_isolate);
v8::platform::PumpMessageLoop(i::V8::GetCurrentPlatform(),
client_isolate);
});
}
};
} // namespace
TEST_F(SharedHeapTest, ConcurrentAllocationInSharedMapSpace) {
std::vector<std::unique_ptr<SharedMapSpaceAllocationThread>> threads;
const int kThreads = 4;
ParkedScope parked(i_isolate()->main_thread_local_isolate());
for (int i = 0; i < kThreads; i++) {
auto thread = std::make_unique<SharedMapSpaceAllocationThread>();
CHECK(thread->Start());
threads.push_back(std::move(thread));
}
for (auto& thread : threads) {
thread->ParkedJoin(parked);
}
}
TEST_F(SharedHeapNoClientsTest, SharedCollectionWithoutClients) {
DCHECK_NULL(i_shared_isolate()->heap()->new_space());
DCHECK_NULL(i_shared_isolate()->heap()->new_lo_space());
::v8::internal::CollectGarbage(OLD_SPACE, shared_isolate());
}
void AllocateInSharedHeap(int iterations = 100) {
SetupClientIsolateAndRunCallback([iterations](v8::Isolate* client_isolate,
Isolate* i_client_isolate) {
HandleScope outer_scope(i_client_isolate);
std::vector<Handle<FixedArray>> arrays_in_handles;
const int kKeptAliveInHandle = 1000;
const int kKeptAliveInHeap = 100;
Handle<FixedArray> arrays_in_heap =
i_client_isolate->factory()->NewFixedArray(kKeptAliveInHeap,
AllocationType::kYoung);
for (int i = 0; i < kNumIterations * iterations; i++) {
HandleScope scope(i_client_isolate);
Handle<FixedArray> array = i_client_isolate->factory()->NewFixedArray(
100, AllocationType::kSharedOld);
if (i < kKeptAliveInHandle) {
// Keep some of those arrays alive across GCs through handles.
arrays_in_handles.push_back(scope.CloseAndEscape(array));
}
if (i < kKeptAliveInHeap) {
// Keep some of those arrays alive across GCs through client heap
// references.
arrays_in_heap->set(i, *array);
}
i_client_isolate->factory()->NewFixedArray(100, AllocationType::kYoung);
}
for (Handle<FixedArray> array : arrays_in_handles) {
CHECK_EQ(array->length(), 100);
}
for (int i = 0; i < kKeptAliveInHeap; i++) {
FixedArray array = FixedArray::cast(arrays_in_heap->get(i));
CHECK_EQ(array.length(), 100);
}
});
}
TEST_F(SharedHeapTest, SharedCollectionWithOneClient) {
v8_flags.max_old_space_size = 8;
ParkedScope parked(i_isolate()->main_thread_local_isolate());
AllocateInSharedHeap();
}
namespace {
class SharedFixedArrayAllocationThread final : public ParkingThread {
public:
SharedFixedArrayAllocationThread()
: ParkingThread(
base::Thread::Options("SharedFixedArrayAllocationThread")) {}
void Run() override { AllocateInSharedHeap(5); }
};
} // namespace
TEST_F(SharedHeapTest, SharedCollectionWithMultipleClients) {
v8_flags.max_old_space_size = 8;
std::vector<std::unique_ptr<SharedFixedArrayAllocationThread>> threads;
const int kThreads = 4;
ParkedScope parked(i_isolate()->main_thread_local_isolate());
for (int i = 0; i < kThreads; i++) {
auto thread = std::make_unique<SharedFixedArrayAllocationThread>();
CHECK(thread->Start());
threads.push_back(std::move(thread));
}
for (auto& thread : threads) {
thread->ParkedJoin(parked);
}
}
} // namespace internal
} // namespace v8
#endif // V8_CAN_CREATE_SHARED_HEAP