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 15namespace v8 { 16namespace internal { 17 18class ArrayBufferExtension; 19class Heap; 20 21// Singly linked-list of ArrayBufferExtensions that stores head and tail of the 22// list to allow for concatenation of lists. 23struct ArrayBufferList final { 24 bool IsEmpty() const; 25 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. 46class 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 62 const ArrayBufferList& young() const { return young_; } 63 const ArrayBufferList& old() const { return old_; } 64 65 // Bytes accounted in the young generation. Rebuilt during sweeping. 66 size_t YoungBytes() const { return young().ApproximateBytes(); } 67 // Bytes accounted in the old generation. Rebuilt during sweeping. 68 size_t OldBytes() const { return old().ApproximateBytes(); } 69 70 private: 71 struct SweepingJob; 72 73 enum class SweepingState { kInProgress, kDone }; 74 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