Commit 35dcecf6 authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

cppgc: Add HeapState API

The API allows for querying
- IsAllocationAllowed: Certain GC phases prohibit allocation which can
  be queried; Should be mostly used for debugging checks.
- IsMarking: Allows for querying whether the garbage collector is
  currently marking.

Bug: chromium:1056170
Change-Id: I20ba5fb5be9de6694e8418fa885920eb04bd75ad
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2649257
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarOmer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72359}
parent 4b03f024
...@@ -132,6 +132,31 @@ class HeapConsistency final { ...@@ -132,6 +132,31 @@ class HeapConsistency final {
HeapConsistency() = delete; HeapConsistency() = delete;
}; };
/**
* Helpers to peek into heap-internal state.
*/
class V8_EXPORT HeapState final {
public:
/**
* Returns whether the garbage collector is marking. This API is experimental
* and is expected to be removed in future.
*
* \param heap_handle The corresponding heap.
* \returns true if the garbage collector is currently marking, and false
* otherwise.
*/
static bool IsMarking(HeapHandle& heap_handle);
/**
* \param heap_handle The corresponding heap.
* \returns true if allocations are allowed, and false otherwise.
*/
static bool IsAllocationAllowed(HeapHandle& heap_handle);
private:
HeapState() = delete;
};
/** /**
* Avoids invoking garbage collection finalizations. Already running garbage * Avoids invoking garbage collection finalizations. Already running garbage
* collection phase are unaffected by this scope. * collection phase are unaffected by this scope.
......
...@@ -104,6 +104,7 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle { ...@@ -104,6 +104,7 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
Compactor& compactor() { return compactor_; } Compactor& compactor() { return compactor_; }
ObjectAllocator& object_allocator() { return object_allocator_; } ObjectAllocator& object_allocator() { return object_allocator_; }
const ObjectAllocator& object_allocator() const { return object_allocator_; }
Sweeper& sweeper() { return sweeper_; } Sweeper& sweeper() { return sweeper_; }
......
...@@ -32,5 +32,17 @@ NoGarbageCollectionScope::NoGarbageCollectionScope( ...@@ -32,5 +32,17 @@ NoGarbageCollectionScope::NoGarbageCollectionScope(
NoGarbageCollectionScope::~NoGarbageCollectionScope() { Leave(heap_handle_); } NoGarbageCollectionScope::~NoGarbageCollectionScope() { Leave(heap_handle_); }
// static
bool HeapState::IsMarking(HeapHandle& heap_handle) {
const auto& heap_base = internal::HeapBase::From(heap_handle);
return heap_base.marker();
}
// static
bool HeapState::IsAllocationAllowed(HeapHandle& heap_handle) {
const auto& heap_base = internal::HeapBase::From(heap_handle);
return heap_base.object_allocator().is_allocation_allowed();
}
} // namespace subtle } // namespace subtle
} // namespace cppgc } // namespace cppgc
...@@ -59,14 +59,14 @@ class V8_EXPORT_PRIVATE ObjectAllocator final : public cppgc::AllocationHandle { ...@@ -59,14 +59,14 @@ class V8_EXPORT_PRIVATE ObjectAllocator final : public cppgc::AllocationHandle {
// Terminate the allocator. Subsequent allocation calls result in a crash. // Terminate the allocator. Subsequent allocation calls result in a crash.
void Terminate(); void Terminate();
bool is_allocation_allowed() const { return no_allocation_scope_ == 0; }
private: private:
// Returns the initially tried SpaceType to allocate an object of |size| bytes // Returns the initially tried SpaceType to allocate an object of |size| bytes
// on. Returns the largest regular object size bucket for large objects. // on. Returns the largest regular object size bucket for large objects.
inline static RawHeap::RegularSpaceType GetInitialSpaceIndexForSize( inline static RawHeap::RegularSpaceType GetInitialSpaceIndexForSize(
size_t size); size_t size);
bool is_allocation_allowed() const { return no_allocation_scope_ == 0; }
inline void* AllocateObjectOnSpace(NormalPageSpace* space, size_t size, inline void* AllocateObjectOnSpace(NormalPageSpace* space, size_t size,
GCInfoIndex gcinfo); GCInfoIndex gcinfo);
void* OutOfLineAllocate(NormalPageSpace*, size_t, GCInfoIndex); void* OutOfLineAllocate(NormalPageSpace*, size_t, GCInfoIndex);
......
...@@ -174,6 +174,28 @@ TEST_F(GCHeapTest, NoGarbageCollectionScope) { ...@@ -174,6 +174,28 @@ TEST_F(GCHeapTest, NoGarbageCollectionScope) {
EXPECT_EQ(epoch_after_gc, epoch_before); EXPECT_EQ(epoch_after_gc, epoch_before);
} }
TEST_F(GCHeapTest, IsAllocationAllowed) {
EXPECT_TRUE(
subtle::HeapState::IsAllocationAllowed(GetHeap()->GetHeapHandle()));
{
ObjectAllocator::NoAllocationScope no_allocation(
Heap::From(GetHeap())->object_allocator());
EXPECT_FALSE(
subtle::HeapState::IsAllocationAllowed(GetHeap()->GetHeapHandle()));
}
}
TEST_F(GCHeapTest, IsIncrementalMarking) {
GarbageCollector::Config config =
GarbageCollector::Config::PreciseIncrementalConfig();
auto* heap = Heap::From(GetHeap());
EXPECT_FALSE(subtle::HeapState::IsMarking(*heap));
heap->StartIncrementalGarbageCollection(config);
EXPECT_TRUE(subtle::HeapState::IsMarking(*heap));
heap->FinalizeIncrementalGarbageCollectionIfRunning(config);
EXPECT_FALSE(subtle::HeapState::IsMarking(*heap));
}
TEST_F(GCHeapTest, TerminateEmptyHeap) { Heap::From(GetHeap())->Terminate(); } TEST_F(GCHeapTest, TerminateEmptyHeap) { Heap::From(GetHeap())->Terminate(); }
TEST_F(GCHeapTest, TerminateClearsPersistent) { TEST_F(GCHeapTest, TerminateClearsPersistent) {
......
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