blob: 35438e8651a32c266b5a2765b8359a73a08ecfe6 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_H_
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "v8/include/cppgc/prefinalizer.h"
#include "v8/include/v8.h"
namespace v8 {
class CppHeap;
} // namespace v8
namespace cppgc {
class AllocationHandle;
} // namespace cppgc
namespace blink {
#define USING_PRE_FINALIZER(Class, PreFinalizer) \
CPPGC_USING_PRE_FINALIZER(Class, PreFinalizer)
// ThreadAffinity indicates which threads objects can be used on. We
// distinguish between objects that can be used on the main thread
// only and objects that can be used on any thread.
//
// For objects that can only be used on the main thread, we avoid going
// through thread-local storage to get to the thread state. This is
// important for performance.
enum ThreadAffinity {
kAnyThread,
kMainThreadOnly,
};
// TODO(mlippautz): Provide specializations.
template <typename T>
struct ThreadingTrait {
STATIC_ONLY(ThreadingTrait);
static constexpr ThreadAffinity kAffinity = kAnyThread;
};
template <ThreadAffinity>
class ThreadStateFor;
class ThreadState final {
public:
static ALWAYS_INLINE ThreadState* Current() {
return *(thread_specific_.Get());
}
static ALWAYS_INLINE ThreadState* MainThreadState() {
DCHECK(Current()->IsMainThread());
return reinterpret_cast<ThreadState*>(main_thread_state_storage_);
}
// Attaches a ThreadState to the main-thread.
static ThreadState* AttachMainThread(v8::CppHeap&);
// Attaches a ThreadState to the currently running thread. Must not be the
// main thread and must be called after AttachMainThread().
static ThreadState* AttachCurrentThread(v8::CppHeap&);
static void DetachCurrentThread();
ALWAYS_INLINE cppgc::AllocationHandle& allocation_handle() const {
return allocation_handle_;
}
ALWAYS_INLINE v8::CppHeap& cpp_heap() const { return cpp_heap_; }
ALWAYS_INLINE v8::Isolate* GetIsolate() const {
// TODO(1056170): Refer to cpp_heap_ once getter for v8::Isolate is
// implemented.
return nullptr;
}
// Forced garbage collection for testing:
//
// Collects garbage as long as live memory decreases (capped at 5).
void CollectAllGarbageForTesting(
BlinkGC::StackState stack_state =
BlinkGC::StackState::kNoHeapPointersOnStack) {
// TODO(1056170): Implement.
}
private:
// Main-thread ThreadState avoids TLS completely by using a regular global.
// The object is manually managed and should not rely on global ctor/dtor.
static uint8_t main_thread_state_storage_[];
// Storage for all ThreadState objects. This includes the main-thread
// ThreadState as well.
static base::LazyInstance<WTF::ThreadSpecific<ThreadState*>>::Leaky
thread_specific_;
explicit ThreadState(v8::CppHeap&);
~ThreadState();
bool IsMainThread() const { return this == MainThreadState(); }
bool IsCreationThread() const { return thread_id_ == CurrentThread(); }
// Handle is the most frequently accessed field as it is required for
// MakeGarbageCollected().
cppgc::AllocationHandle& allocation_handle_;
v8::CppHeap& cpp_heap_;
base::PlatformThreadId thread_id_;
};
template <>
class ThreadStateFor<kMainThreadOnly> {
STATIC_ONLY(ThreadStateFor);
public:
static ThreadState* GetState() { return ThreadState::MainThreadState(); }
};
template <>
class ThreadStateFor<kAnyThread> {
STATIC_ONLY(ThreadStateFor);
public:
static ThreadState* GetState() { return ThreadState::Current(); }
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_THREAD_STATE_H_