1 // Copyright 2020 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 6 #define V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 7 8 #include <memory> 9 10 #include "src/base/logging.h" 11 #include "src/base/platform/mutex.h" 12 #include "src/objects/js-array-buffer.h" 13 #include "src/tasks/cancelable-task.h" 14 15 namespace v8 { 16 namespace internal { 17 18 class ArrayBufferExtension; 19 class Heap; 20 21 // Singly linked-list of ArrayBufferExtensions that stores head and tail of the 22 // list to allow for concatenation of lists. 23 struct ArrayBufferList final { 24 bool IsEmpty() const; ApproximateBytesfinal25 size_t ApproximateBytes() const { return bytes_; } 26 size_t BytesSlow() const; 27 28 void Append(ArrayBufferExtension* extension); 29 void Append(ArrayBufferList* list); 30 31 V8_EXPORT_PRIVATE bool ContainsSlow(ArrayBufferExtension* extension) const; 32 33 private: 34 ArrayBufferExtension* head_ = nullptr; 35 ArrayBufferExtension* tail_ = nullptr; 36 // Bytes are approximate as they may be subtracted eagerly, while the 37 // `ArrayBufferExtension` is still in the list. The extension will only be 38 // dropped on next sweep. 39 size_t bytes_ = 0; 40 41 friend class ArrayBufferSweeper; 42 }; 43 44 // The ArrayBufferSweeper iterates and deletes ArrayBufferExtensions 45 // concurrently to the application. 46 class ArrayBufferSweeper final { 47 public: 48 enum class SweepingType { kYoung, kFull }; 49 50 explicit ArrayBufferSweeper(Heap* heap); 51 ~ArrayBufferSweeper(); 52 53 void RequestSweep(SweepingType sweeping_type); 54 void EnsureFinished(); 55 56 // Track the given ArrayBufferExtension for the given JSArrayBuffer. 57 void Append(JSArrayBuffer object, ArrayBufferExtension* extension); 58 59 // Detaches an ArrayBufferExtension from a JSArrayBuffer. 60 void Detach(JSArrayBuffer object, ArrayBufferExtension* extension); 61 young()62 const ArrayBufferList& young() const { return young_; } old()63 const ArrayBufferList& old() const { return old_; } 64 65 // Bytes accounted in the young generation. Rebuilt during sweeping. YoungBytes()66 size_t YoungBytes() const { return young().ApproximateBytes(); } 67 // Bytes accounted in the old generation. Rebuilt during sweeping. OldBytes()68 size_t OldBytes() const { return old().ApproximateBytes(); } 69 70 private: 71 struct SweepingJob; 72 73 enum class SweepingState { kInProgress, kDone }; 74 sweeping_in_progress()75 bool sweeping_in_progress() const { return job_.get(); } 76 77 // Finishes sweeping if it is already done. 78 void FinishIfDone(); 79 80 // Increments external memory counters outside of ArrayBufferSweeper. 81 // Increment may trigger GC. 82 void IncrementExternalMemoryCounters(size_t bytes); 83 void DecrementExternalMemoryCounters(size_t bytes); 84 85 void Prepare(SweepingType type); 86 void Finalize(); 87 88 void ReleaseAll(ArrayBufferList* extension); 89 90 Heap* const heap_; 91 std::unique_ptr<SweepingJob> job_; 92 base::Mutex sweeping_mutex_; 93 base::ConditionVariable job_finished_; 94 ArrayBufferList young_; 95 ArrayBufferList old_; 96 }; 97 98 } // namespace internal 99 } // namespace v8 100 101 #endif // V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 102