#include "src/heap/heap.h"
#include "src/heap/local-heap.h"
#include "src/heap/parked-scope-inl.h"
#include "test/unittests/heap/heap-utils.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
using DirectHandlesTest = TestWithIsolate;
TEST_F(DirectHandlesTest, CreateDirectHandleFromLocal) { … }
TEST_F(DirectHandlesTest, CreateLocalFromDirectHandle) { … }
TEST_F(DirectHandlesTest, CreateMaybeDirectHandle) { … }
TEST_F(DirectHandlesTest, CreateMaybeDirectObjectHandle) { … }
TEST_F(DirectHandlesTest, IsIdenticalTo) { … }
TEST_F(DirectHandlesTest, MaybeObjectDirectHandleIsIdenticalTo) { … }
#if defined(DEBUG) && defined(V8_ENABLE_DIRECT_HANDLE)
namespace {
template <typename Callback>
void ExpectFailure(Callback callback) {
EXPECT_DEATH_IF_SUPPORTED(callback(), "");
}
}
TEST_F(DirectHandlesTest, DirectHandleOutOfStackFails) {
ExpectFailure([]() {
auto ptr = std::make_unique<i::DirectHandle<i::String>>();
USE(ptr);
});
}
namespace {
class BackgroundThread final : public v8::base::Thread {
public:
explicit BackgroundThread(i::Isolate* isolate, bool park_and_wait)
: v8::base::Thread(base::Thread::Options("BackgroundThread")),
isolate_(isolate),
park_and_wait_(park_and_wait) {}
void Run() override {
i::LocalIsolate isolate(isolate_, i::ThreadKind::kBackground);
i::UnparkedScope unparked_scope(&isolate);
i::LocalHandleScope handle_scope(&isolate);
i::DirectHandle<i::String> direct = isolate.factory()->empty_string();
if (park_and_wait_) {
isolate.heap()->ExecuteWhileParked([]() {
});
}
CHECK_EQ(0, direct->length());
}
private:
i::Isolate* isolate_;
bool park_and_wait_;
};
}
TEST_F(DirectHandlesTest, DirectHandleInBackgroundThread) {
i::LocalHeap lh(i_isolate()->heap(), i::ThreadKind::kMain);
lh.SetUpMainThreadForTesting();
auto thread = std::make_unique<BackgroundThread>(i_isolate(), false);
CHECK(thread->Start());
thread->Join();
}
TEST_F(DirectHandlesTest, DirectHandleInParkedBackgroundThread) {
i::LocalHeap lh(i_isolate()->heap(), i::ThreadKind::kMain);
lh.SetUpMainThreadForTesting();
auto thread = std::make_unique<BackgroundThread>(i_isolate(), true);
CHECK(thread->Start());
thread->Join();
}
#if V8_CAN_CREATE_SHARED_HEAP_BOOL
using DirectHandlesSharedTest = i::TestJSSharedMemoryWithIsolate;
namespace {
class ClientThread final : public i::ParkingThread {
public:
ClientThread() : ParkingThread(base::Thread::Options("ClientThread")) {}
void Run() override {
IsolateWrapper isolate_wrapper(kNoCounters);
i::DirectHandle<i::String> direct;
USE(direct);
}
};
}
TEST_F(DirectHandlesSharedTest, DirectHandleInClient) {
auto thread = std::make_unique<ClientThread>();
CHECK(thread->Start());
thread->ParkedJoin(i_isolate()->main_thread_local_isolate());
}
namespace {
class ClientMainThread final : public i::ParkingThread {
public:
explicit ClientMainThread(bool background_park_and_wait)
: ParkingThread(base::Thread::Options("ClientMainThread")),
background_park_and_wait_(background_park_and_wait) {}
void Run() override {
IsolateWrapper isolate_wrapper(kNoCounters);
i::Isolate* i_client_isolate =
reinterpret_cast<i::Isolate*>(isolate_wrapper.isolate());
i::LocalHeap lh(i_client_isolate->heap(), i::ThreadKind::kMain);
lh.SetUpMainThreadForTesting();
auto thread = std::make_unique<BackgroundThread>(i_client_isolate,
background_park_and_wait_);
CHECK(thread->Start());
thread->Join();
}
private:
bool background_park_and_wait_;
};
}
TEST_F(DirectHandlesSharedTest, DirectHandleInClientBackgroundThread) {
auto thread = std::make_unique<ClientMainThread>(false);
CHECK(thread->Start());
thread->ParkedJoin(i_isolate()->main_thread_local_isolate());
}
TEST_F(DirectHandlesSharedTest, DirectHandleInParkedClientBackgroundThread) {
auto thread = std::make_unique<ClientMainThread>(true);
CHECK(thread->Start());
thread->ParkedJoin(i_isolate()->main_thread_local_isolate());
}
#endif
#endif
}