Skip to content

Commit 122937f

Browse files
addaleaxBethGriggs
authored andcommitted
deps: V8: cherry-pick 4b1447e4bb0e
Original commit message: Improve V8 GC logic for external memory The logic for V8 GC normally only takes the external memory growth since last mark-compact into account. Unfortunately, the amount of external memory recorded at the end of MC is often too high. The reason is that it might take a while for the external memory associated with the GCed objects to be released (e.g. V8 itself post a task to release external memory for ArrayBuffer backing stores). In a worst case scenario GC is driven only by external memory and none of the external memory is released by the end of the MC. Then each MC will record the external memory at its highest point and the GC logic will allow the external memory to grow a bit higher each time which can lead to excessive memory use. This patch improves the situation a bit by calculating the growth from the lowest external memory seen since the last MC. That way the growth calculation will be offset from a level presumably closer to the intended one (to what it would have been if the external memory associated with the GCed objects was released during the MC). Now, this fix is not perfect because it can be thrown off by external memory growth occurring before the lingering memory is released. However, it seems to work rather well in practice (e.g. when playing MSE video on YT). Bug: v8:10185 Change-Id: Ifcdd87eb45f3ae4a99d2aeec667c3ae4ca9a52b6 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2042711 Reviewed-by: Ulan Degenbaev <[email protected]> Reviewed-by: Dominik Inführ <[email protected]> Reviewed-by: Jakob Gruber <[email protected]> Commit-Queue: Dominik Inführ <[email protected]> Cr-Commit-Position: refs/heads/master@{#66193} Refs: v8/v8@4b1447e PR-URL: #32885 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Ujjwal Sharma <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]> Reviewed-By: Beth Griggs <[email protected]>
1 parent f98668a commit 122937f

File tree

7 files changed

+39
-32
lines changed

7 files changed

+39
-32
lines changed

common.gypi

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

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

4040
##### V8 defaults for Node.js #####
4141

deps/v8/include/v8-internal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,10 @@ class Internals {
160160
kNumIsolateDataSlots * kApiSystemPointerSize;
161161
static const int kExternalMemoryLimitOffset =
162162
kExternalMemoryOffset + kApiInt64Size;
163-
static const int kExternalMemoryAtLastMarkCompactOffset =
163+
static const int kExternalMemoryLowSinceMarkCompactOffset =
164164
kExternalMemoryLimitOffset + kApiInt64Size;
165165
static const int kIsolateFastCCallCallerFpOffset =
166-
kExternalMemoryAtLastMarkCompactOffset + kApiInt64Size;
166+
kExternalMemoryLowSinceMarkCompactOffset + kApiInt64Size;
167167
static const int kIsolateFastCCallCallerPcOffset =
168168
kIsolateFastCCallCallerFpOffset + kApiSystemPointerSize;
169169
static const int kIsolateStackGuardOffset =

deps/v8/include/v8.h

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11854,9 +11854,9 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
1185411854
reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryOffset);
1185511855
int64_t* external_memory_limit = reinterpret_cast<int64_t*>(
1185611856
reinterpret_cast<uint8_t*>(this) + I::kExternalMemoryLimitOffset);
11857-
int64_t* external_memory_at_last_mc =
11857+
int64_t* external_memory_low_since_mc =
1185811858
reinterpret_cast<int64_t*>(reinterpret_cast<uint8_t*>(this) +
11859-
I::kExternalMemoryAtLastMarkCompactOffset);
11859+
I::kExternalMemoryLowSinceMarkCompactOffset);
1186011860

1186111861
// Embedders are weird: we see both over- and underflows here. Perform the
1186211862
// addition with unsigned types to avoid undefined behavior.
@@ -11865,23 +11865,22 @@ int64_t Isolate::AdjustAmountOfExternalAllocatedMemory(
1186511865
static_cast<uint64_t>(*external_memory));
1186611866
*external_memory = amount;
1186711867

11868-
int64_t allocation_diff_since_last_mc =
11869-
static_cast<int64_t>(static_cast<uint64_t>(*external_memory) -
11870-
static_cast<uint64_t>(*external_memory_at_last_mc));
11868+
if (amount < *external_memory_low_since_mc) {
11869+
*external_memory_low_since_mc = amount;
11870+
*external_memory_limit = amount + I::kExternalAllocationSoftLimit;
11871+
}
11872+
11873+
if (change_in_bytes <= 0) return *external_memory;
11874+
11875+
int64_t allocation_diff_since_last_mc = static_cast<int64_t>(
11876+
static_cast<uint64_t>(*external_memory) -
11877+
static_cast<uint64_t>(*external_memory_low_since_mc));
1187111878
// Only check memory pressure and potentially trigger GC if the amount of
1187211879
// external memory increased.
1187311880
if (allocation_diff_since_last_mc > kMemoryReducerActivationLimit) {
1187411881
CheckMemoryPressure();
1187511882
}
11876-
11877-
if (change_in_bytes < 0) {
11878-
const int64_t lower_limit =
11879-
static_cast<int64_t>(static_cast<uint64_t>(*external_memory_limit) +
11880-
static_cast<uint64_t>(change_in_bytes));
11881-
if (lower_limit > I::kExternalAllocationSoftLimit) {
11882-
*external_memory_limit = lower_limit;
11883-
}
11884-
} else if (change_in_bytes > 0 && amount > *external_memory_limit) {
11883+
if (amount > *external_memory_limit) {
1188511884
ReportExternalAllocationLimitReached();
1188611885
}
1188711886
return *external_memory;

deps/v8/src/execution/isolate-data.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class IsolateData final {
117117
V(kEmbedderDataOffset, Internals::kNumIsolateDataSlots* kSystemPointerSize) \
118118
V(kExternalMemoryOffset, kInt64Size) \
119119
V(kExternalMemoryLlimitOffset, kInt64Size) \
120-
V(kExternalMemoryAtLastMarkCompactOffset, kInt64Size) \
120+
V(kExternalMemoryLowSinceMarkCompactOffset, kInt64Size) \
121121
V(kFastCCallCallerFPOffset, kSystemPointerSize) \
122122
V(kFastCCallCallerPCOffset, kSystemPointerSize) \
123123
V(kStackGuardOffset, StackGuard::kSizeInBytes) \
@@ -151,7 +151,7 @@ class IsolateData final {
151151
int64_t external_memory_limit_ = kExternalAllocationSoftLimit;
152152

153153
// Caches the amount of external memory registered at the last MC.
154-
int64_t external_memory_at_last_mark_compact_ = 0;
154+
int64_t external_memory_low_since_mark_compact_ = 0;
155155

156156
// Stores the state of the caller for TurboAssembler::CallCFunction so that
157157
// the sampling CPU profiler can iterate the stack during such calls. These
@@ -220,8 +220,9 @@ void IsolateData::AssertPredictableLayout() {
220220
kExternalMemoryOffset);
221221
STATIC_ASSERT(offsetof(IsolateData, external_memory_limit_) ==
222222
kExternalMemoryLlimitOffset);
223-
STATIC_ASSERT(offsetof(IsolateData, external_memory_at_last_mark_compact_) ==
224-
kExternalMemoryAtLastMarkCompactOffset);
223+
STATIC_ASSERT(
224+
offsetof(IsolateData, external_memory_low_since_mark_compact_) ==
225+
kExternalMemoryLowSinceMarkCompactOffset);
225226
STATIC_ASSERT(offsetof(IsolateData, fast_c_call_caller_fp_) ==
226227
kFastCCallCallerFPOffset);
227228
STATIC_ASSERT(offsetof(IsolateData, fast_c_call_caller_pc_) ==

deps/v8/src/execution/isolate.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,10 +2900,10 @@ void Isolate::CheckIsolateLayout() {
29002900
CHECK_EQ(static_cast<int>(
29012901
OFFSET_OF(Isolate, isolate_data_.external_memory_limit_)),
29022902
Internals::kExternalMemoryLimitOffset);
2903-
CHECK_EQ(Internals::kExternalMemoryAtLastMarkCompactOffset % 8, 0);
2903+
CHECK_EQ(Internals::kExternalMemoryLowSinceMarkCompactOffset % 8, 0);
29042904
CHECK_EQ(static_cast<int>(OFFSET_OF(
2905-
Isolate, isolate_data_.external_memory_at_last_mark_compact_)),
2906-
Internals::kExternalMemoryAtLastMarkCompactOffset);
2905+
Isolate, isolate_data_.external_memory_low_since_mark_compact_)),
2906+
Internals::kExternalMemoryLowSinceMarkCompactOffset);
29072907
}
29082908

29092909
void Isolate::ClearSerializerData() {

deps/v8/src/heap/heap-inl.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,23 @@ int64_t Heap::external_memory() {
6565
}
6666

6767
void Heap::update_external_memory(int64_t delta) {
68-
isolate()->isolate_data()->external_memory_ += delta;
68+
const int64_t amount = isolate()->isolate_data()->external_memory_ + delta;
69+
isolate()->isolate_data()->external_memory_ = amount;
70+
if (amount <
71+
isolate()->isolate_data()->external_memory_low_since_mark_compact_) {
72+
isolate()->isolate_data()->external_memory_low_since_mark_compact_ = amount;
73+
isolate()->isolate_data()->external_memory_limit_ =
74+
amount + kExternalAllocationSoftLimit;
75+
}
6976
}
7077

7178
void Heap::update_external_memory_concurrently_freed(uintptr_t freed) {
7279
external_memory_concurrently_freed_ += freed;
7380
}
7481

7582
void Heap::account_external_memory_concurrently_freed() {
76-
isolate()->isolate_data()->external_memory_ -=
77-
external_memory_concurrently_freed_;
83+
update_external_memory(
84+
-static_cast<int64_t>(external_memory_concurrently_freed_));
7885
external_memory_concurrently_freed_ = 0;
7986
}
8087

deps/v8/src/heap/heap.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,7 +1452,7 @@ void Heap::ReportExternalMemoryPressure() {
14521452
kGCCallbackFlagSynchronousPhantomCallbackProcessing |
14531453
kGCCallbackFlagCollectAllExternalMemory);
14541454
if (isolate()->isolate_data()->external_memory_ >
1455-
(isolate()->isolate_data()->external_memory_at_last_mark_compact_ +
1455+
(isolate()->isolate_data()->external_memory_low_since_mark_compact_ +
14561456
external_memory_hard_limit())) {
14571457
CollectAllGarbage(
14581458
kReduceMemoryFootprintMask,
@@ -2143,7 +2143,7 @@ void Heap::RecomputeLimits(GarbageCollector collector) {
21432143

21442144
if (collector == MARK_COMPACTOR) {
21452145
// Register the amount of external allocated memory.
2146-
isolate()->isolate_data()->external_memory_at_last_mark_compact_ =
2146+
isolate()->isolate_data()->external_memory_low_since_mark_compact_ =
21472147
isolate()->isolate_data()->external_memory_;
21482148
isolate()->isolate_data()->external_memory_limit_ =
21492149
isolate()->isolate_data()->external_memory_ +
@@ -4743,12 +4743,12 @@ size_t Heap::GlobalSizeOfObjects() {
47434743
uint64_t Heap::PromotedExternalMemorySize() {
47444744
IsolateData* isolate_data = isolate()->isolate_data();
47454745
if (isolate_data->external_memory_ <=
4746-
isolate_data->external_memory_at_last_mark_compact_) {
4746+
isolate_data->external_memory_low_since_mark_compact_) {
47474747
return 0;
47484748
}
47494749
return static_cast<uint64_t>(
47504750
isolate_data->external_memory_ -
4751-
isolate_data->external_memory_at_last_mark_compact_);
4751+
isolate_data->external_memory_low_since_mark_compact_);
47524752
}
47534753

47544754
bool Heap::AllocationLimitOvershotByLargeMargin() {
@@ -4871,7 +4871,7 @@ Heap::IncrementalMarkingLimit Heap::IncrementalMarkingLimitReached() {
48714871
double gained_since_last_gc =
48724872
PromotedSinceLastGC() +
48734873
(isolate()->isolate_data()->external_memory_ -
4874-
isolate()->isolate_data()->external_memory_at_last_mark_compact_);
4874+
isolate()->isolate_data()->external_memory_low_since_mark_compact_);
48754875
double size_before_gc =
48764876
OldGenerationObjectsAndPromotedExternalMemorySize() -
48774877
gained_since_last_gc;

0 commit comments

Comments
 (0)