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