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