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