Commit 6e6f6d09 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[heap] Implement LocalHeap::Current using thread_local

This is needed for write-barrier and persistent-handle code that does
not otherwise get an instance of LocalHeap

Bug: v8:10315
Change-Id: I480e31f32141510f2f9e678af3449d5841e3156e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2284492
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68720}
parent 2d5017a0
......@@ -14,6 +14,12 @@
namespace v8 {
namespace internal {
namespace {
thread_local LocalHeap* current_local_heap = nullptr;
} // namespace
LocalHeap* LocalHeap::Current() { return current_local_heap; }
LocalHeap::LocalHeap(Heap* heap,
std::unique_ptr<PersistentHandles> persistent_handles)
: heap_(heap),
......@@ -29,6 +35,8 @@ LocalHeap::LocalHeap(Heap* heap,
if (persistent_handles_) {
persistent_handles_->Attach(this);
}
DCHECK_NULL(current_local_heap);
current_local_heap = this;
}
LocalHeap::~LocalHeap() {
......@@ -39,6 +47,9 @@ LocalHeap::~LocalHeap() {
EnsureParkedBeforeDestruction();
heap_->safepoint()->RemoveLocalHeap(this);
DCHECK_EQ(current_local_heap, this);
current_local_heap = nullptr;
}
Handle<Object> LocalHeap::NewPersistentHandle(Address value) {
......
......@@ -21,12 +21,11 @@ class Safepoint;
class LocalHandles;
class PersistentHandles;
class LocalHeap {
class V8_EXPORT_PRIVATE LocalHeap {
public:
V8_EXPORT_PRIVATE explicit LocalHeap(
Heap* heap,
std::unique_ptr<PersistentHandles> persistent_handles = nullptr);
V8_EXPORT_PRIVATE ~LocalHeap();
LocalHeap(Heap* heap,
std::unique_ptr<PersistentHandles> persistent_handles = nullptr);
~LocalHeap();
// Invoked by main thread to signal this thread that it needs to halt in a
// safepoint.
......@@ -34,13 +33,12 @@ class LocalHeap {
// Frequently invoked by local thread to check whether safepoint was requested
// from the main thread.
V8_EXPORT_PRIVATE void Safepoint();
void Safepoint();
LocalHandles* handles() { return handles_.get(); }
V8_EXPORT_PRIVATE Handle<Object> NewPersistentHandle(Address value);
V8_EXPORT_PRIVATE std::unique_ptr<PersistentHandles>
DetachPersistentHandles();
Handle<Object> NewPersistentHandle(Address value);
std::unique_ptr<PersistentHandles> DetachPersistentHandles();
bool IsParked();
......@@ -59,6 +57,13 @@ class LocalHeap {
// iterable heap.
void MakeLinearAllocationAreaIterable();
// Fetches a pointer to the local heap from the thread local storage.
// It is intended to be used in handle and write barrier code where it is
// difficult to get a pointer to the current instance of local heap otherwise.
// The result may be a nullptr if there is no local heap instance associated
// with the current thread.
static LocalHeap* Current();
private:
enum class ThreadState {
// Threads in this state need to be stopped in a safepoint.
......@@ -70,8 +75,8 @@ class LocalHeap {
Safepoint
};
V8_EXPORT_PRIVATE void Park();
V8_EXPORT_PRIVATE void Unpark();
void Park();
void Unpark();
void EnsureParkedBeforeDestruction();
bool IsSafepointRequested();
......
......@@ -16,22 +16,68 @@ using LocalHeapTest = TestWithIsolate;
TEST_F(LocalHeapTest, Initialize) {
Heap* heap = i_isolate()->heap();
CHECK(!heap->safepoint()->ContainsAnyLocalHeap());
{
LocalHeap lh1(heap);
CHECK(heap->safepoint()->ContainsLocalHeap(&lh1));
LocalHeap lh2(heap);
CHECK(heap->safepoint()->ContainsLocalHeap(&lh2));
LocalHeap lh(heap);
CHECK(heap->safepoint()->ContainsLocalHeap(&lh));
}
CHECK(!heap->safepoint()->ContainsAnyLocalHeap());
}
TEST_F(LocalHeapTest, Current) {
Heap* heap = i_isolate()->heap();
CHECK_NULL(LocalHeap::Current());
{
LocalHeap lh(heap);
CHECK_EQ(&lh, LocalHeap::Current());
}
CHECK_NULL(LocalHeap::Current());
{
LocalHeap lh(heap);
CHECK_EQ(&lh, LocalHeap::Current());
}
CHECK_NULL(LocalHeap::Current());
}
namespace {
class BackgroundThread final : public v8::base::Thread {
public:
explicit BackgroundThread(Heap* heap)
: v8::base::Thread(base::Thread::Options("BackgroundThread")),
heap_(heap) {}
void Run() override {
CHECK_NULL(LocalHeap::Current());
{
LocalHeap lh3(heap);
CHECK(heap->safepoint()->ContainsLocalHeap(&lh3));
LocalHeap lh(heap_);
CHECK_EQ(&lh, LocalHeap::Current());
}
CHECK(heap->safepoint()->ContainsLocalHeap(&lh1));
CHECK(heap->safepoint()->ContainsLocalHeap(&lh2));
CHECK_NULL(LocalHeap::Current());
}
CHECK(!heap->safepoint()->ContainsAnyLocalHeap());
Heap* heap_;
};
} // anonymous namespace
TEST_F(LocalHeapTest, CurrentBackground) {
Heap* heap = i_isolate()->heap();
CHECK_NULL(LocalHeap::Current());
{
LocalHeap lh(heap);
auto thread = std::make_unique<BackgroundThread>(heap);
CHECK(thread->Start());
CHECK_EQ(&lh, LocalHeap::Current());
thread->Join();
CHECK_EQ(&lh, LocalHeap::Current());
}
CHECK_NULL(LocalHeap::Current());
}
} // namespace internal
......
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