Skip to content

Commit b9ba3a7

Browse files
caiolimaaduh95
authored andcommitted
deps: V8: backport fe81545e6d14
Original commit message: [api] Adding total allocated bytes in HeapStatistics This change exposes total allocated bytes in v8::HeapStatistics API by introducing a new total_allocated_bytes() method that tracks all heap allocations since an Isolate creation. The implementation adds: - uint64_t total_allocated_bytes_ field to HeapStatistics. - An atomic total allocation counter is stored in the Heap class. - The counter is incremented whenever a RestLab is called. This approach can overestimate the total allocation for cases where the LAB is not fully used, but the leftover compared to the LAB itself is quite small, so it seems tolerable. Design doc reference: https://docs.google.com/document/d/1O4JPsoaxTQsX_7T5Fz4rsGeHMiM16jUrvDuq9FrtbNM Change-Id: Ic531698aaeb1578f943b7fdd346b9159ffd9b6c9 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6996467 Reviewed-by: Dominik Inführ <dinfuehr@chromium.org> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Commit-Queue: Dmitry Bezhetskov <dima00782@gmail.com> Cr-Commit-Position: refs/heads/main@{#103296} Refs: v8/v8@fe81545 Co-authored-by: Caio Lima <caiolima@igalia.com> PR-URL: #60429 Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent bf0de92 commit b9ba3a7

File tree

8 files changed

+199
-9
lines changed

8 files changed

+199
-9
lines changed

common.gypi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
# Reset this number to 0 on major V8 upgrades.
4040
# Increment by one for each non-official patch applied to deps/v8.
41-
'v8_embedder_string': '-node.12',
41+
'v8_embedder_string': '-node.13',
4242

4343
##### V8 defaults for Node.js #####
4444

deps/v8/include/v8-statistics.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,13 @@ class V8_EXPORT HeapStatistics {
154154
size_t number_of_native_contexts() { return number_of_native_contexts_; }
155155
size_t number_of_detached_contexts() { return number_of_detached_contexts_; }
156156

157+
/**
158+
* Returns the total number of bytes allocated since the Isolate was created.
159+
* This includes all heap objects allocated in any space (new, old, code,
160+
* etc.).
161+
*/
162+
uint64_t total_allocated_bytes() { return total_allocated_bytes_; }
163+
157164
/**
158165
* Returns a 0/1 boolean, which signifies whether the V8 overwrite heap
159166
* garbage with a bit pattern.
@@ -175,6 +182,7 @@ class V8_EXPORT HeapStatistics {
175182
size_t number_of_detached_contexts_;
176183
size_t total_global_handles_size_;
177184
size_t used_global_handles_size_;
185+
uint64_t total_allocated_bytes_;
178186

179187
friend class V8;
180188
friend class Isolate;

deps/v8/src/api/api.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6584,7 +6584,8 @@ HeapStatistics::HeapStatistics()
65846584
peak_malloced_memory_(0),
65856585
does_zap_garbage_(false),
65866586
number_of_native_contexts_(0),
6587-
number_of_detached_contexts_(0) {}
6587+
number_of_detached_contexts_(0),
6588+
total_allocated_bytes_(0) {}
65886589

65896590
HeapSpaceStatistics::HeapSpaceStatistics()
65906591
: space_name_(nullptr),
@@ -10438,6 +10439,7 @@ void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
1043810439
heap_statistics->number_of_native_contexts_ = heap->NumberOfNativeContexts();
1043910440
heap_statistics->number_of_detached_contexts_ =
1044010441
heap->NumberOfDetachedContexts();
10442+
heap_statistics->total_allocated_bytes_ = heap->GetTotalAllocatedBytes();
1044110443
heap_statistics->does_zap_garbage_ = i::heap::ShouldZapGarbage();
1044210444

1044310445
#if V8_ENABLE_WEBASSEMBLY

deps/v8/src/heap/heap-allocator.cc

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,25 +85,42 @@ AllocationResult HeapAllocator::AllocateRawLargeInternal(
8585
int size_in_bytes, AllocationType allocation, AllocationOrigin origin,
8686
AllocationAlignment alignment, AllocationHint hint) {
8787
DCHECK_GT(size_in_bytes, heap_->MaxRegularHeapObjectSize(allocation));
88+
AllocationResult allocation_result;
8889
switch (allocation) {
8990
case AllocationType::kYoung:
90-
return new_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
91+
allocation_result =
92+
new_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
93+
break;
9194
case AllocationType::kOld:
92-
return lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
95+
allocation_result =
96+
lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
97+
break;
9398
case AllocationType::kCode:
94-
return code_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
99+
allocation_result =
100+
code_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
101+
break;
95102
case AllocationType::kSharedOld:
96-
return shared_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
103+
allocation_result =
104+
shared_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
105+
break;
97106
case AllocationType::kTrusted:
98-
return trusted_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
107+
allocation_result =
108+
trusted_lo_space()->AllocateRaw(local_heap_, size_in_bytes, hint);
109+
break;
99110
case AllocationType::kSharedTrusted:
100-
return shared_trusted_lo_space()->AllocateRaw(local_heap_, size_in_bytes,
101-
hint);
111+
allocation_result = shared_trusted_lo_space()->AllocateRaw(
112+
local_heap_, size_in_bytes, hint);
113+
break;
102114
case AllocationType::kMap:
103115
case AllocationType::kReadOnly:
104116
case AllocationType::kSharedMap:
105117
UNREACHABLE();
106118
}
119+
if (!allocation_result.IsFailure()) {
120+
int allocated_size = ALIGN_TO_ALLOCATION_ALIGNMENT(size_in_bytes);
121+
heap_->AddTotalAllocatedBytes(allocated_size);
122+
}
123+
return allocation_result;
107124
}
108125

109126
namespace {

deps/v8/src/heap/heap.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7717,6 +7717,10 @@ int Heap::NextStackTraceId() {
77177717
return last_id;
77187718
}
77197719

7720+
uint64_t Heap::GetTotalAllocatedBytes() {
7721+
return total_allocated_bytes_.load(std::memory_order_relaxed);
7722+
}
7723+
77207724
EmbedderStackStateScope::EmbedderStackStateScope(
77217725
Heap* heap, EmbedderStackStateOrigin origin, StackState stack_state)
77227726
: heap_(heap),

deps/v8/src/heap/heap.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,11 @@ class Heap final {
17071707
bool ShouldUseBackgroundThreads() const;
17081708
bool ShouldUseIncrementalMarking() const;
17091709

1710+
void AddTotalAllocatedBytes(size_t size) {
1711+
total_allocated_bytes_.fetch_add(size, std::memory_order_relaxed);
1712+
}
1713+
uint64_t GetTotalAllocatedBytes();
1714+
17101715
HeapAllocator* allocator() { return heap_allocator_; }
17111716
const HeapAllocator* allocator() const { return heap_allocator_; }
17121717

@@ -2499,6 +2504,8 @@ class Heap final {
24992504
// no value was provided this will be 0.
25002505
uint64_t physical_memory_;
25012506

2507+
std::atomic<uint64_t> total_allocated_bytes_ = 0;
2508+
25022509
// Classes in "heap" can be friends.
25032510
friend class ActivateMemoryReducerTask;
25042511
friend class AlwaysAllocateScope;

deps/v8/src/heap/main-allocator.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,12 @@ void MainAllocator::ResetLab(Address start, Address end, Address extended_end) {
297297
MemoryChunkMetadata::UpdateHighWaterMark(top());
298298
}
299299

300+
// This is going to overestimate a bit of the total allocated bytes, since the
301+
// LAB was not used yet. However the leftover compared to the LAB itself is
302+
// quite small, so it seems tolerable.
303+
if (local_heap_) {
304+
local_heap_->heap()->AddTotalAllocatedBytes(end - start);
305+
}
300306
allocation_info().Reset(start, end);
301307
extended_limit_ = extended_end;
302308

deps/v8/test/cctest/test-api.cc

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17656,6 +17656,152 @@ TEST(GetHeapSpaceStatistics) {
1765617656
CHECK_EQ(total_physical_size, heap_statistics.total_physical_size());
1765717657
}
1765817658

17659+
UNINITIALIZED_TEST(GetHeapTotalAllocatedBytes) {
17660+
// This test is incompatible with concurrent allocation, which may occur
17661+
// while collecting the statistics and break the final `CHECK_EQ`s.
17662+
if (i::v8_flags.stress_concurrent_allocation) return;
17663+
17664+
v8::Isolate::CreateParams create_params;
17665+
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17666+
v8::Isolate* isolate = v8::Isolate::New(create_params);
17667+
17668+
const uint32_t number_of_elements = 1;
17669+
const uint32_t allocation_size = i::FixedArray::SizeFor(number_of_elements);
17670+
const uint32_t trusted_allocation_size =
17671+
i::TrustedFixedArray::SizeFor(number_of_elements);
17672+
const uint32_t lo_number_of_elements = 256 * 1024;
17673+
const uint32_t lo_allocation_size =
17674+
i::FixedArray::SizeFor(lo_number_of_elements);
17675+
const uint32_t trusted_lo_allocation_size =
17676+
i::TrustedFixedArray::SizeFor(lo_number_of_elements);
17677+
const uint32_t expected_allocation_size =
17678+
allocation_size * 2 + lo_allocation_size * 2 + trusted_allocation_size +
17679+
trusted_lo_allocation_size;
17680+
17681+
{
17682+
v8::Isolate::Scope isolate_scope(isolate);
17683+
v8::HandleScope handle_scope(isolate);
17684+
LocalContext env(isolate);
17685+
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
17686+
17687+
v8::HeapStatistics heap_stats_before;
17688+
isolate->GetHeapStatistics(&heap_stats_before);
17689+
size_t initial_allocated = heap_stats_before.total_allocated_bytes();
17690+
17691+
i::MaybeHandle<i::FixedArray> young_alloc =
17692+
i_isolate->factory()->TryNewFixedArray(number_of_elements,
17693+
i::AllocationType::kYoung);
17694+
USE(young_alloc);
17695+
i::MaybeHandle<i::FixedArray> old_alloc =
17696+
i_isolate->factory()->TryNewFixedArray(number_of_elements,
17697+
i::AllocationType::kOld);
17698+
USE(old_alloc);
17699+
i::Handle<i::TrustedFixedArray> trusted_alloc =
17700+
i_isolate->factory()->NewTrustedFixedArray(number_of_elements,
17701+
i::AllocationType::kTrusted);
17702+
USE(trusted_alloc);
17703+
i::MaybeHandle<i::FixedArray> old_lo_alloc =
17704+
i_isolate->factory()->TryNewFixedArray(lo_number_of_elements,
17705+
i::AllocationType::kOld);
17706+
USE(old_lo_alloc);
17707+
17708+
{
17709+
v8::HandleScope inner_handle_scope(isolate);
17710+
auto young_lo_alloc = i_isolate->factory()->TryNewFixedArray(
17711+
lo_number_of_elements, i::AllocationType::kYoung);
17712+
USE(young_lo_alloc);
17713+
}
17714+
17715+
auto trusted_lo_alloc = i_isolate->factory()->NewTrustedFixedArray(
17716+
lo_number_of_elements, i::AllocationType::kTrusted);
17717+
USE(trusted_lo_alloc);
17718+
17719+
v8::HeapStatistics heap_stats_after;
17720+
isolate->GetHeapStatistics(&heap_stats_after);
17721+
uint64_t final_allocated = heap_stats_after.total_allocated_bytes();
17722+
17723+
CHECK_GT(final_allocated, initial_allocated);
17724+
uint64_t allocated_diff = final_allocated - initial_allocated;
17725+
CHECK_GE(allocated_diff, expected_allocation_size);
17726+
17727+
// This either tests counting happening when a LAB freed and validate
17728+
// there's no double counting on evacuated/promoted objects.
17729+
v8::internal::heap::InvokeAtomicMajorGC(i_isolate->heap());
17730+
17731+
v8::HeapStatistics heap_stats_after_gc;
17732+
isolate->GetHeapStatistics(&heap_stats_after_gc);
17733+
uint64_t total_allocation_after_gc =
17734+
heap_stats_after_gc.total_allocated_bytes();
17735+
17736+
CHECK_EQ(total_allocation_after_gc, final_allocated);
17737+
}
17738+
17739+
isolate->Dispose();
17740+
}
17741+
17742+
#if V8_CAN_CREATE_SHARED_HEAP_BOOL
17743+
17744+
UNINITIALIZED_TEST(GetHeapTotalAllocatedBytesSharedSpaces) {
17745+
// This test is incompatible with concurrent allocation, which may occur
17746+
// while collecting the statistics and break the final `CHECK_EQ`s.
17747+
if (i::v8_flags.stress_concurrent_allocation) return;
17748+
if (COMPRESS_POINTERS_IN_MULTIPLE_CAGES_BOOL) return;
17749+
17750+
i::v8_flags.shared_heap = true;
17751+
i::FlagList::EnforceFlagImplications();
17752+
17753+
v8::Isolate::CreateParams create_params;
17754+
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17755+
v8::Isolate* isolate = v8::Isolate::New(create_params);
17756+
17757+
{
17758+
v8::Isolate::Scope isolate_scope(isolate);
17759+
v8::HandleScope handle_scope(isolate);
17760+
LocalContext env(isolate);
17761+
17762+
v8::HeapStatistics heap_stats_before;
17763+
isolate->GetHeapStatistics(&heap_stats_before);
17764+
size_t initial_allocated = heap_stats_before.total_allocated_bytes();
17765+
17766+
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
17767+
17768+
const uint32_t number_of_elements = 1;
17769+
const uint32_t allocation_size = i::FixedArray::SizeFor(number_of_elements);
17770+
const uint32_t trusted_allocation_size =
17771+
i::TrustedFixedArray::SizeFor(number_of_elements);
17772+
const uint32_t lo_number_of_elements = 256 * 1024;
17773+
const uint32_t lo_allocation_size =
17774+
i::FixedArray::SizeFor(lo_number_of_elements);
17775+
const uint32_t expected_allocation_size =
17776+
allocation_size + trusted_allocation_size + lo_allocation_size;
17777+
17778+
i::MaybeHandle<i::FixedArray> shared_alloc =
17779+
i_isolate->factory()->TryNewFixedArray(number_of_elements,
17780+
i::AllocationType::kSharedOld);
17781+
USE(shared_alloc);
17782+
i::Handle<i::TrustedFixedArray> shared_trusted_alloc =
17783+
i_isolate->factory()->NewTrustedFixedArray(
17784+
number_of_elements, i::AllocationType::kSharedTrusted);
17785+
USE(shared_trusted_alloc);
17786+
i::MaybeHandle<i::FixedArray> shared_lo_alloc =
17787+
i_isolate->factory()->TryNewFixedArray(lo_number_of_elements,
17788+
i::AllocationType::kSharedOld);
17789+
USE(shared_lo_alloc);
17790+
17791+
v8::HeapStatistics heap_stats_after;
17792+
isolate->GetHeapStatistics(&heap_stats_after);
17793+
uint64_t final_allocated = heap_stats_after.total_allocated_bytes();
17794+
17795+
CHECK_GT(final_allocated, initial_allocated);
17796+
uint64_t allocated_diff = final_allocated - initial_allocated;
17797+
CHECK_GE(allocated_diff, expected_allocation_size);
17798+
}
17799+
17800+
isolate->Dispose();
17801+
}
17802+
17803+
#endif // V8_CAN_CREATE_SHARED_HEAP_BOOL
17804+
1765917805
TEST(NumberOfNativeContexts) {
1766017806
static const size_t kNumTestContexts = 10;
1766117807
i::Isolate* isolate = CcTest::i_isolate();

0 commit comments

Comments
 (0)