From b7fa7320798067af40eff6b3ecc29ea8559220d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BA=D0=BE=D0=B2=D0=BE=D1=80=D0=BE=D0=B4=D0=B0=20?= =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=B8=D1=82=D0=B0=20=D0=90=D0=BD=D0=B4=D1=80?= =?UTF-8?q?=D0=B5=D0=B5=D0=B2=D0=B8=D1=87?= Date: Tue, 17 Dec 2019 21:46:18 +0300 Subject: [PATCH] deps: V8: cherry-pick 687d865fe251 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [heap] Perform GCs on v8::BackingStore allocation This adds heuristics to perform young and full GCs on allocation of external ArrayBuffer backing stores. Young GCs are performed proactively based on the external backing store bytes for the young generation. Full GCs are performed only if the allocation fails. Subsequent CLs will add heuristics to start incremental full GCs based on the external backing store bytes. This will allow us to remove AdjustAmountOfExternalMemory for ArrayBuffers. Bug: v8:9701, chromium:1008938 Change-Id: I0e8688f582989518926c38260b5cf14e2ca93f84 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1803614 Commit-Queue: Ulan Degenbaev Reviewed-by: Dominik Inführ Reviewed-by: Hannes Payer Cr-Commit-Position: refs/heads/master@{#65480} Refs: https://github.com/v8/v8/commit/687d865fe251602ad1219cde7ae7cb38d4cb7471 Refs: https://github.com/nodejs/node/issues/1671 --- common.gypi | 2 +- deps/v8/src/heap/heap.cc | 8 ++++++++ deps/v8/src/heap/heap.h | 4 ---- deps/v8/src/heap/spaces.h | 24 ++++++++++++++++-------- deps/v8/test/cctest/heap/test-heap.cc | 21 +++++++++++++++++++++ 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/common.gypi b/common.gypi index 758d6eba189736..dc3376573e87cd 100644 --- a/common.gypi +++ b/common.gypi @@ -39,7 +39,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.25', + 'v8_embedder_string': '-node.26', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/heap/heap.cc b/deps/v8/src/heap/heap.cc index 45b2273c50d688..7cfc36662d052f 100644 --- a/deps/v8/src/heap/heap.cc +++ b/deps/v8/src/heap/heap.cc @@ -2761,6 +2761,14 @@ HeapObject Heap::AlignWithFiller(HeapObject object, int object_size, void* Heap::AllocateExternalBackingStore( const std::function& allocate, size_t byte_length) { + size_t new_space_backing_store_bytes = + new_space()->ExternalBackingStoreBytes(); + if (new_space_backing_store_bytes >= 2 * kMaxSemiSpaceSize && + new_space_backing_store_bytes >= byte_length) { + // Performing a young generation GC amortizes over the allocated backing + // store bytes and may free enough external bytes for this allocation. + CollectGarbage(NEW_SPACE, GarbageCollectionReason::kExternalMemoryPressure); + } // TODO(ulan): Perform GCs proactively based on the byte_length and // the current external backing store counters. void* result = allocate(byte_length); diff --git a/deps/v8/src/heap/heap.h b/deps/v8/src/heap/heap.h index 182096f29c78d2..877aba01c09aa3 100644 --- a/deps/v8/src/heap/heap.h +++ b/deps/v8/src/heap/heap.h @@ -1793,10 +1793,6 @@ class Heap { void FinalizePartialMap(Map map); - // Allocate empty fixed typed array of given type. - V8_WARN_UNUSED_RESULT AllocationResult - AllocateEmptyFixedTypedArray(ExternalArrayType array_type); - void set_force_oom(bool value) { force_oom_ = value; } // =========================================================================== diff --git a/deps/v8/src/heap/spaces.h b/deps/v8/src/heap/spaces.h index 5652042d20c131..5ec281ee074aee 100644 --- a/deps/v8/src/heap/spaces.h +++ b/deps/v8/src/heap/spaces.h @@ -2804,14 +2804,14 @@ class V8_EXPORT_PRIVATE NewSpace void Shrink(); // Return the allocated bytes in the active semispace. - size_t Size() override { + size_t Size() final { DCHECK_GE(top(), to_space_.page_low()); return to_space_.pages_used() * MemoryChunkLayout::AllocatableMemoryInDataPage() + static_cast(top() - to_space_.page_low()); } - size_t SizeOfObjects() override { return Size(); } + size_t SizeOfObjects() final { return Size(); } // Return the allocatable capacity of a semispace. size_t Capacity() { @@ -2829,30 +2829,38 @@ class V8_EXPORT_PRIVATE NewSpace // Committed memory for NewSpace is the committed memory of both semi-spaces // combined. - size_t CommittedMemory() override { + size_t CommittedMemory() final { return from_space_.CommittedMemory() + to_space_.CommittedMemory(); } - size_t MaximumCommittedMemory() override { + size_t MaximumCommittedMemory() final { return from_space_.MaximumCommittedMemory() + to_space_.MaximumCommittedMemory(); } // Approximate amount of physical memory committed for this space. - size_t CommittedPhysicalMemory() override; + size_t CommittedPhysicalMemory() final; // Return the available bytes without growing. - size_t Available() override { + size_t Available() final { DCHECK_GE(Capacity(), Size()); return Capacity() - Size(); } - size_t ExternalBackingStoreBytes( - ExternalBackingStoreType type) const override { + size_t ExternalBackingStoreBytes(ExternalBackingStoreType type) const final { DCHECK_EQ(0, from_space_.ExternalBackingStoreBytes(type)); return to_space_.ExternalBackingStoreBytes(type); } + size_t ExternalBackingStoreBytes() { + size_t result = 0; + for (int i = 0; i < ExternalBackingStoreType::kNumTypes; i++) { + result += + ExternalBackingStoreBytes(static_cast(i)); + } + return result; + } + size_t AllocatedSinceLastGC() { const Address age_mark = to_space_.age_mark(); DCHECK_NE(age_mark, kNullAddress); diff --git a/deps/v8/test/cctest/heap/test-heap.cc b/deps/v8/test/cctest/heap/test-heap.cc index 03f98c64537f22..53454f3e2f409a 100644 --- a/deps/v8/test/cctest/heap/test-heap.cc +++ b/deps/v8/test/cctest/heap/test-heap.cc @@ -6823,6 +6823,27 @@ TEST(CodeObjectRegistry) { CHECK(MemoryChunk::FromAddress(code2_address)->Contains(code2_address)); } +TEST(Regress9701) { + ManualGCScope manual_gc_scope; + if (!FLAG_incremental_marking) return; + CcTest::InitializeVM(); + Heap* heap = CcTest::heap(); + // Start with an empty new space. + CcTest::CollectGarbage(NEW_SPACE); + CcTest::CollectGarbage(NEW_SPACE); + + int mark_sweep_count_before = heap->ms_count(); + // Allocate many short living array buffers. + for (int i = 0; i < 1000; i++) { + HandleScope scope(heap->isolate()); + CcTest::i_isolate()->factory()->NewJSArrayBufferAndBackingStore( + 64 * KB, InitializedFlag::kZeroInitialized); + } + int mark_sweep_count_after = heap->ms_count(); + // We expect only scavenges, no full GCs. + CHECK_EQ(mark_sweep_count_before, mark_sweep_count_after); +} + } // namespace heap } // namespace internal } // namespace v8