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
|
// 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/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 EmbedderGraph;
class EmbedderRootsHandler;
} // namespace v8
namespace blink {
class BlinkGCMemoryDumpProvider;
using V8BuildEmbedderGraphCallback = void (*)(v8::Isolate*,
v8::EmbedderGraph*,
void*);
class PLATFORM_EXPORT ThreadState final {
public:
class GCForbiddenScope;
class NoAllocationScope;
using StackState = cppgc::EmbedderStackState;
ALWAYS_INLINE static ThreadState* Current() {
return &ThreadStateStorage::Current()->thread_state();
}
// Returns true if the current thread is currently sweeping, i.e., whether the
// caller is invoked from a destructor.
ALWAYS_INLINE static bool IsSweepingOnOwningThread(
ThreadStateStorage& storage);
// 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();
void AttachToIsolate(v8::Isolate* isolate, V8BuildEmbedderGraphCallback);
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)>);
bool IsIncrementalMarking();
// 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();
static ThreadState* AttachMainThreadForTesting(v8::Platform*);
static ThreadState* AttachCurrentThreadForTesting(v8::Platform*);
void RecoverCppHeapAfterIsolateTearDown();
void SetCppHeap(std::unique_ptr<v8::CppHeap> cpp_heap);
// 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;
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;
private:
explicit ThreadState(v8::Platform*);
~ThreadState();
// 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_;
friend class BlinkGCMemoryDumpProvider;
};
// static
bool ThreadState::IsSweepingOnOwningThread(ThreadStateStorage& storage) {
return cppgc::subtle::HeapState::IsSweepingOnOwningThread(
storage.heap_handle());
}
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_THREAD_STATE_H_
|