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: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Omer Katz <omerkatz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72359}
This commit is contained in:
Michael Lippautz 2021-01-27 10:47:07 +01:00 committed by Commit Bot
parent 4b03f02467
commit 35dcecf607
5 changed files with 62 additions and 2 deletions

View File

@ -132,6 +132,31 @@ class HeapConsistency final {
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
* collection phase are unaffected by this scope.

View File

@ -104,6 +104,7 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
Compactor& compactor() { return compactor_; }
ObjectAllocator& object_allocator() { return object_allocator_; }
const ObjectAllocator& object_allocator() const { return object_allocator_; }
Sweeper& sweeper() { return sweeper_; }

View File

@ -32,5 +32,17 @@ NoGarbageCollectionScope::NoGarbageCollectionScope(
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 cppgc

View File

@ -59,14 +59,14 @@ class V8_EXPORT_PRIVATE ObjectAllocator final : public cppgc::AllocationHandle {
// Terminate the allocator. Subsequent allocation calls result in a crash.
void Terminate();
bool is_allocation_allowed() const { return no_allocation_scope_ == 0; }
private:
// Returns the initially tried SpaceType to allocate an object of |size| bytes
// on. Returns the largest regular object size bucket for large objects.
inline static RawHeap::RegularSpaceType GetInitialSpaceIndexForSize(
size_t size);
bool is_allocation_allowed() const { return no_allocation_scope_ == 0; }
inline void* AllocateObjectOnSpace(NormalPageSpace* space, size_t size,
GCInfoIndex gcinfo);
void* OutOfLineAllocate(NormalPageSpace*, size_t, GCInfoIndex);

View File

@ -174,6 +174,28 @@ TEST_F(GCHeapTest, NoGarbageCollectionScope) {
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, TerminateClearsPersistent) {