1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
// Copyright 2020 The Chromium Authors
// 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_THREAD_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_
#include "base/compiler_specific.h"
#include "base/functional/callback_forward.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_manager.h"
#include "third_party/blink/renderer/platform/heap/forward.h"
#include "third_party/blink/renderer/platform/heap/thread_state_storage.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "v8/include/cppgc/common.h" // IWYU pragma: export (for ThreadState::StackState alias)
#include "v8/include/cppgc/heap-consistency.h"
#include "v8/include/v8-callbacks.h"
#include "v8/include/v8-cppgc.h"
#include "v8/include/v8-profiler.h"
namespace v8 {
class CppHeap;
class EmbedderRootsHandler;
} // namespace v8
namespace blink {
class ActiveScriptWrappableManager;
class BlinkGCMemoryDumpProvider;
// ThreadState manages garbage collections together with V8. This includes the
// setup and teardown of the GC wiring as well as custom weakness and clearing
// logic. The state is aware of which Isolate it is attached to and the
// ownership of the underlying CppHeap.
class PLATFORM_EXPORT ThreadState final {
public:
class GCForbiddenScope;
class NoAllocationScope;
using StackState = cppgc::EmbedderStackState;
using DevToolsCountersCallback = void (*)(v8::Isolate*);
ALWAYS_INLINE static ThreadState* Current() {
return &ThreadStateStorage::Current()->thread_state();
}
// Attaches a ThreadState to the main-thread.
static ThreadState* AttachMainThread();
// Attaches a ThreadState to the currently running thread. Must not be the
// main thread and must be called after AttachMainThread().
static ThreadState* AttachCurrentThread();
static void DetachCurrentThread();
// Attaches custom GC handling to an Isolate. CppHeap is already owned by the
// Isolate at this point.
void AttachToIsolate(v8::Isolate* isolate, DevToolsCountersCallback);
// Detaches custom GC handling from an Isolate. CppHeap is still owned by the
// Isolate afterwards.
void DetachFromIsolate();
// Releases ownership of the CppHeap which is transferred to the v8::Isolate.
std::unique_ptr<v8::CppHeap> ReleaseCppHeap();
ALWAYS_INLINE cppgc::HeapHandle& heap_handle() const { return heap_handle_; }
ALWAYS_INLINE v8::CppHeap& cpp_heap() const { return *cpp_heap_; }
bool IsMainThread() const {
return this ==
&ThreadStateStorage::MainThreadStateStorage()->thread_state();
}
bool IsCreationThread() const { return thread_id_ == CurrentThread(); }
bool IsAllocationAllowed() const {
return cppgc::subtle::DisallowGarbageCollectionScope::
IsGarbageCollectionAllowed(cpp_heap().GetHeapHandle());
}
// Waits until sweeping is done and invokes the given callback with
// the total sizes of live objects in Node and CSS arenas.
void CollectNodeAndCssStatistics(
base::OnceCallback<void(size_t allocated_node_bytes,
size_t allocated_css_bytes)>);
// Returns true if incremental marking is currently running, and false
// otherwise.
bool IsIncrementalMarking() const;
// Returns true if the current thread is currently sweeping, i.e., whether the
// caller is invoked from a destructor, and false otherwise.
bool IsSweepingOnOwningThread() const;
// Returns true during heap snapshot generation, and false otherwise.
bool IsTakingHeapSnapshot() const;
// Copies a string into the V8 heap profiler, and returns a pointer to the
// copy. Only valid while taking a heap snapshot.
const char* CopyNameForHeapSnapshot(const char* name) const;
ActiveScriptWrappableManager* GetActiveScriptWrappableManager() {
return active_script_wrappable_manager_.Get();
}
static ThreadState* AttachMainThreadForTesting(v8::Platform*);
static ThreadState* AttachCurrentThreadForTesting(v8::Platform*);
// Forced garbage collection for testing.
//
// Collects garbage as long as live memory decreases (capped at 5).
void CollectAllGarbageForTesting(
StackState stack_state = StackState::kNoHeapPointers);
// Perform stop-the-world garbage collection in young generation for testing.
void CollectGarbageInYoungGenerationForTesting(
StackState stack_state = StackState::kNoHeapPointers);
void EnableDetachedGarbageCollectionsForTesting();
// Transfers ownership of a CppHeap back to ThreadState on Isolate teardown.
// Only used in test drivers.
void RecoverCppHeapAfterIsolateTearDownForTesting();
// Takes a heap snapshot that can be loaded into DevTools. Requires that
// `ThreadState` is attached to a `v8::Isolate`.
//
// `filename` specifies the path on the system to store the snapshot. If no
// filename is provided, the snapshot will be emitted to `stdout`.
//
// Writing to a file requires a disabled sandbox.
void TakeHeapSnapshotForTesting(const char* filename) const;
private:
static void RecoverCppHeapTrampoline(std::unique_ptr<v8::CppHeap>);
// Prologue and epilogue callbacks for unified heap garbage collections. Set
// and released during `AttachToIsolate()` and `DetachFromIsolate()`,
// respectively.
static void GcPrologue(v8::Isolate*, v8::GCType, v8::GCCallbackFlags);
static void GcEpilogue(v8::Isolate*, v8::GCType, v8::GCCallbackFlags);
explicit ThreadState(v8::Platform*);
~ThreadState();
void RecoverCppHeap(std::unique_ptr<v8::CppHeap>);
// During setup of a page ThreadState owns CppHeap. The ownership is
// transferred to the v8::Isolate on its creation.
std::unique_ptr<v8::CppHeap> owning_cpp_heap_;
// Even when not owning the CppHeap (as the heap is owned by a v8::Isolate),
// this pointer will keep a reference to the current CppHeap.
v8::CppHeap* cpp_heap_;
std::unique_ptr<v8::EmbedderRootsHandler> embedder_roots_handler_;
cppgc::HeapHandle& heap_handle_;
v8::Isolate* isolate_ = nullptr;
base::PlatformThreadId thread_id_;
size_t gc_callback_depth_ = 0;
Persistent<ActiveScriptWrappableManager> active_script_wrappable_manager_;
// TODO(mlippautz): Refactor to proper base::CheckedObserver once there's more
// users that want to listen to GC events.
DevToolsCountersCallback dev_tools_counters_callback_;
friend class BlinkGCMemoryDumpProvider;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_
|