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 "src/base/platform/mutex.h" 9 #include "src/objects/js-array-buffer.h" 10 #include "src/tasks/cancelable-task.h" 11 12 namespace v8 { 13 namespace internal { 14 15 class ArrayBufferExtension; 16 class Heap; 17 18 // Singly linked-list of ArrayBufferExtensions that stores head and tail of the 19 // list to allow for concatenation of lists. 20 struct ArrayBufferList { ArrayBufferListArrayBufferList21 ArrayBufferList() : head_(nullptr), tail_(nullptr), bytes_(0) {} 22 23 ArrayBufferExtension* head_; 24 ArrayBufferExtension* tail_; 25 size_t bytes_; 26 IsEmptyArrayBufferList27 bool IsEmpty() { 28 DCHECK_IMPLIES(head_, tail_); 29 return head_ == nullptr; 30 } 31 BytesArrayBufferList32 size_t Bytes() { return bytes_; } 33 size_t BytesSlow(); 34 ResetArrayBufferList35 void Reset() { 36 head_ = tail_ = nullptr; 37 bytes_ = 0; 38 } 39 40 void Append(ArrayBufferExtension* extension); 41 void Append(ArrayBufferList* list); 42 43 V8_EXPORT_PRIVATE bool Contains(ArrayBufferExtension* extension); 44 }; 45 46 // The ArrayBufferSweeper iterates and deletes ArrayBufferExtensions 47 // concurrently to the application. 48 class ArrayBufferSweeper { 49 public: ArrayBufferSweeper(Heap * heap)50 explicit ArrayBufferSweeper(Heap* heap) 51 : heap_(heap), 52 sweeping_in_progress_(false), 53 freed_bytes_(0), 54 young_bytes_(0), 55 old_bytes_(0) {} ~ArrayBufferSweeper()56 ~ArrayBufferSweeper() { ReleaseAll(); } 57 58 void EnsureFinished(); 59 void RequestSweepYoung(); 60 void RequestSweepFull(); 61 62 void Append(JSArrayBuffer object, ArrayBufferExtension* extension); 63 young()64 ArrayBufferList young() { return young_; } old()65 ArrayBufferList old() { return old_; } 66 67 size_t YoungBytes(); 68 size_t OldBytes(); 69 70 private: 71 enum class SweepingScope { Young, Full }; 72 73 enum class SweepingState { Uninitialized, Prepared, Swept }; 74 75 struct SweepingJob { 76 CancelableTaskManager::Id id; 77 SweepingState state; 78 ArrayBufferList young; 79 ArrayBufferList old; 80 SweepingScope scope; 81 82 SweepingJob(); 83 84 static SweepingJob Prepare(ArrayBufferList young, ArrayBufferList old, 85 SweepingScope scope); 86 } job_; 87 88 void Merge(); 89 90 void DecrementExternalMemoryCounters(); 91 void IncrementExternalMemoryCounters(size_t bytes); 92 void IncrementFreedBytes(size_t bytes); 93 94 void RequestSweep(SweepingScope sweeping_task); 95 void Prepare(SweepingScope sweeping_task); 96 97 void Sweep(); 98 void SweepYoung(); 99 void SweepFull(); 100 ArrayBufferList SweepListFull(ArrayBufferList* list); 101 102 ArrayBufferList SweepYoungGen(); 103 void SweepOldGen(ArrayBufferExtension* extension); 104 105 void ReleaseAll(); 106 void ReleaseAll(ArrayBufferList* extension); 107 108 Heap* const heap_; 109 bool sweeping_in_progress_; 110 base::Mutex sweeping_mutex_; 111 base::ConditionVariable job_finished_; 112 std::atomic<size_t> freed_bytes_; 113 114 ArrayBufferList young_; 115 ArrayBufferList old_; 116 117 size_t young_bytes_; 118 size_t old_bytes_; 119 }; 120 121 } // namespace internal 122 } // namespace v8 123 124 #endif // V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 125