11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 61cb0ef41Sopenharmony_ci#define V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <memory> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/base/logging.h" 111cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h" 121cb0ef41Sopenharmony_ci#include "src/objects/js-array-buffer.h" 131cb0ef41Sopenharmony_ci#include "src/tasks/cancelable-task.h" 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace v8 { 161cb0ef41Sopenharmony_cinamespace internal { 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciclass ArrayBufferExtension; 191cb0ef41Sopenharmony_ciclass Heap; 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci// Singly linked-list of ArrayBufferExtensions that stores head and tail of the 221cb0ef41Sopenharmony_ci// list to allow for concatenation of lists. 231cb0ef41Sopenharmony_cistruct ArrayBufferList final { 241cb0ef41Sopenharmony_ci bool IsEmpty() const; 251cb0ef41Sopenharmony_ci size_t ApproximateBytes() const { return bytes_; } 261cb0ef41Sopenharmony_ci size_t BytesSlow() const; 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci void Append(ArrayBufferExtension* extension); 291cb0ef41Sopenharmony_ci void Append(ArrayBufferList* list); 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci V8_EXPORT_PRIVATE bool ContainsSlow(ArrayBufferExtension* extension) const; 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci private: 341cb0ef41Sopenharmony_ci ArrayBufferExtension* head_ = nullptr; 351cb0ef41Sopenharmony_ci ArrayBufferExtension* tail_ = nullptr; 361cb0ef41Sopenharmony_ci // Bytes are approximate as they may be subtracted eagerly, while the 371cb0ef41Sopenharmony_ci // `ArrayBufferExtension` is still in the list. The extension will only be 381cb0ef41Sopenharmony_ci // dropped on next sweep. 391cb0ef41Sopenharmony_ci size_t bytes_ = 0; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci friend class ArrayBufferSweeper; 421cb0ef41Sopenharmony_ci}; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci// The ArrayBufferSweeper iterates and deletes ArrayBufferExtensions 451cb0ef41Sopenharmony_ci// concurrently to the application. 461cb0ef41Sopenharmony_ciclass ArrayBufferSweeper final { 471cb0ef41Sopenharmony_ci public: 481cb0ef41Sopenharmony_ci enum class SweepingType { kYoung, kFull }; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci explicit ArrayBufferSweeper(Heap* heap); 511cb0ef41Sopenharmony_ci ~ArrayBufferSweeper(); 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci void RequestSweep(SweepingType sweeping_type); 541cb0ef41Sopenharmony_ci void EnsureFinished(); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci // Track the given ArrayBufferExtension for the given JSArrayBuffer. 571cb0ef41Sopenharmony_ci void Append(JSArrayBuffer object, ArrayBufferExtension* extension); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci // Detaches an ArrayBufferExtension from a JSArrayBuffer. 601cb0ef41Sopenharmony_ci void Detach(JSArrayBuffer object, ArrayBufferExtension* extension); 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci const ArrayBufferList& young() const { return young_; } 631cb0ef41Sopenharmony_ci const ArrayBufferList& old() const { return old_; } 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci // Bytes accounted in the young generation. Rebuilt during sweeping. 661cb0ef41Sopenharmony_ci size_t YoungBytes() const { return young().ApproximateBytes(); } 671cb0ef41Sopenharmony_ci // Bytes accounted in the old generation. Rebuilt during sweeping. 681cb0ef41Sopenharmony_ci size_t OldBytes() const { return old().ApproximateBytes(); } 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci private: 711cb0ef41Sopenharmony_ci struct SweepingJob; 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci enum class SweepingState { kInProgress, kDone }; 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci bool sweeping_in_progress() const { return job_.get(); } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci // Finishes sweeping if it is already done. 781cb0ef41Sopenharmony_ci void FinishIfDone(); 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci // Increments external memory counters outside of ArrayBufferSweeper. 811cb0ef41Sopenharmony_ci // Increment may trigger GC. 821cb0ef41Sopenharmony_ci void IncrementExternalMemoryCounters(size_t bytes); 831cb0ef41Sopenharmony_ci void DecrementExternalMemoryCounters(size_t bytes); 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci void Prepare(SweepingType type); 861cb0ef41Sopenharmony_ci void Finalize(); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci void ReleaseAll(ArrayBufferList* extension); 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci Heap* const heap_; 911cb0ef41Sopenharmony_ci std::unique_ptr<SweepingJob> job_; 921cb0ef41Sopenharmony_ci base::Mutex sweeping_mutex_; 931cb0ef41Sopenharmony_ci base::ConditionVariable job_finished_; 941cb0ef41Sopenharmony_ci ArrayBufferList young_; 951cb0ef41Sopenharmony_ci ArrayBufferList old_; 961cb0ef41Sopenharmony_ci}; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci} // namespace internal 991cb0ef41Sopenharmony_ci} // namespace v8 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci#endif // V8_HEAP_ARRAY_BUFFER_SWEEPER_H_ 102