array-buffer-sweeper.h 3.26 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_HEAP_ARRAY_BUFFER_SWEEPER_H_
#define V8_HEAP_ARRAY_BUFFER_SWEEPER_H_

#include "src/base/platform/mutex.h"
#include "src/objects/js-array-buffer.h"
#include "src/tasks/cancelable-task.h"

namespace v8 {
namespace internal {

class ArrayBufferExtension;
class Heap;

// Singly linked-list of ArrayBufferExtensions that stores head and tail of the
// list to allow for concatenation of lists.
struct ArrayBufferList {
21
  ArrayBufferList() : head_(nullptr), tail_(nullptr), bytes_(0) {}
22 23 24

  ArrayBufferExtension* head_;
  ArrayBufferExtension* tail_;
25
  size_t bytes_;
26 27 28 29 30 31

  bool IsEmpty() {
    DCHECK_IMPLIES(head_, tail_);
    return head_ == nullptr;
  }

32 33 34 35 36 37 38
  size_t Bytes() { return bytes_; }
  size_t BytesSlow();

  void Reset() {
    head_ = tail_ = nullptr;
    bytes_ = 0;
  }
39 40 41 42 43 44 45 46 47 48 49 50

  void Append(ArrayBufferExtension* extension);
  void Append(ArrayBufferList* list);

  V8_EXPORT_PRIVATE bool Contains(ArrayBufferExtension* extension);
};

// The ArrayBufferSweeper iterates and deletes ArrayBufferExtensions
// concurrently to the application.
class ArrayBufferSweeper {
 public:
  explicit ArrayBufferSweeper(Heap* heap)
51 52
      : heap_(heap),
        sweeping_in_progress_(false),
53
        freed_bytes_(0),
54 55
        young_bytes_(0),
        old_bytes_(0) {}
56 57 58 59 60 61 62 63 64 65 66
  ~ArrayBufferSweeper() { ReleaseAll(); }

  void EnsureFinished();
  void RequestSweepYoung();
  void RequestSweepFull();

  void Append(JSArrayBuffer object, ArrayBufferExtension* extension);

  ArrayBufferList young() { return young_; }
  ArrayBufferList old() { return old_; }

67 68 69
  size_t YoungBytes();
  size_t OldBytes();

70
 private:
71
  enum class SweepingScope { kYoung, kFull };
72

73
  enum class SweepingState { kInProgress, kDone };
74 75

  struct SweepingJob {
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    ArrayBufferSweeper* sweeper_;
    CancelableTaskManager::Id id_;
    std::atomic<SweepingState> state_;
    ArrayBufferList young_;
    ArrayBufferList old_;
    SweepingScope scope_;

    SweepingJob(ArrayBufferSweeper* sweeper, ArrayBufferList young,
                ArrayBufferList old, SweepingScope scope)
        : sweeper_(sweeper),
          id_(0),
          state_(SweepingState::kInProgress),
          young_(young),
          old_(old),
          scope_(scope) {}

    void Sweep();
    void SweepYoung();
    void SweepFull();
    ArrayBufferList SweepListFull(ArrayBufferList* list);
  };

  base::Optional<SweepingJob> job_;
99 100

  void Merge();
101
  void AdjustCountersAndMergeIfPossible();
102

103 104
  void DecrementExternalMemoryCounters();
  void IncrementExternalMemoryCounters(size_t bytes);
105
  void IncrementFreedBytes(size_t bytes);
106

107 108 109 110 111 112 113 114 115 116 117 118 119
  void RequestSweep(SweepingScope sweeping_task);
  void Prepare(SweepingScope sweeping_task);

  ArrayBufferList SweepYoungGen();
  void SweepOldGen(ArrayBufferExtension* extension);

  void ReleaseAll();
  void ReleaseAll(ArrayBufferList* extension);

  Heap* const heap_;
  bool sweeping_in_progress_;
  base::Mutex sweeping_mutex_;
  base::ConditionVariable job_finished_;
120
  std::atomic<size_t> freed_bytes_;
121 122 123

  ArrayBufferList young_;
  ArrayBufferList old_;
124 125 126

  size_t young_bytes_;
  size_t old_bytes_;
127 128 129 130 131 132
};

}  // namespace internal
}  // namespace v8

#endif  // V8_HEAP_ARRAY_BUFFER_SWEEPER_H_