5 #include "src/microtask-queue.h" 10 #include "src/base/logging.h" 11 #include "src/handles-inl.h" 12 #include "src/isolate.h" 13 #include "src/objects/microtask.h" 14 #include "src/roots-inl.h" 15 #include "src/visitors.h" 20 const size_t MicrotaskQueue::kRingBufferOffset =
21 offsetof(MicrotaskQueue, ring_buffer_);
22 const size_t MicrotaskQueue::kCapacityOffset =
23 offsetof(MicrotaskQueue, capacity_);
24 const size_t MicrotaskQueue::kSizeOffset = offsetof(MicrotaskQueue, size_);
25 const size_t MicrotaskQueue::kStartOffset = offsetof(MicrotaskQueue, start_);
27 const intptr_t MicrotaskQueue::kMinimumCapacity = 8;
30 void MicrotaskQueue::SetUpDefaultMicrotaskQueue(Isolate* isolate) {
31 DCHECK_NULL(isolate->default_microtask_queue());
33 MicrotaskQueue* microtask_queue =
new MicrotaskQueue;
34 microtask_queue->next_ = microtask_queue;
35 microtask_queue->prev_ = microtask_queue;
36 isolate->set_default_microtask_queue(microtask_queue);
40 std::unique_ptr<MicrotaskQueue> MicrotaskQueue::New(Isolate* isolate) {
41 DCHECK_NOT_NULL(isolate->default_microtask_queue());
43 std::unique_ptr<MicrotaskQueue> microtask_queue(
new MicrotaskQueue);
46 MicrotaskQueue* last = isolate->default_microtask_queue()->prev_;
47 microtask_queue->next_ = last->next_;
48 microtask_queue->prev_ = last;
49 last->next_->prev_ = microtask_queue.get();
50 last->next_ = microtask_queue.get();
52 return microtask_queue;
55 MicrotaskQueue::MicrotaskQueue() =
default;
57 MicrotaskQueue::~MicrotaskQueue() {
59 DCHECK_NE(prev_,
this);
63 delete[] ring_buffer_;
67 Object* MicrotaskQueue::CallEnqueueMicrotask(Isolate* isolate,
68 intptr_t microtask_queue_pointer,
69 Microtask* microtask) {
70 reinterpret_cast<MicrotaskQueue*
>(microtask_queue_pointer)
71 ->EnqueueMicrotask(microtask);
72 return ReadOnlyRoots(isolate).undefined_value();
75 void MicrotaskQueue::EnqueueMicrotask(Microtask* microtask) {
76 if (size_ == capacity_) {
79 intptr_t new_capacity = std::max(kMinimumCapacity, capacity_ << 1);
80 ResizeBuffer(new_capacity);
83 DCHECK_LT(size_, capacity_);
84 ring_buffer_[(start_ + size_) % capacity_] = microtask;
88 int MicrotaskQueue::RunMicrotasks(Isolate* isolate) {
89 HandleScope scope(isolate);
90 MaybeHandle<Object> maybe_exception;
94 DCHECK_EQ(
this, isolate->default_microtask_queue());
95 MaybeHandle<Object> maybe_result = Execution::RunMicrotasks(
96 isolate, Execution::MessageHandling::kReport, &maybe_exception);
99 if (maybe_result.is_null() && maybe_exception.is_null()) {
100 delete[] ring_buffer_;
101 ring_buffer_ =
nullptr;
112 void MicrotaskQueue::IterateMicrotasks(RootVisitor* visitor) {
116 visitor->VisitRootPointers(
117 Root::kStrongRoots,
nullptr, ObjectSlot(ring_buffer_ + start_),
118 ObjectSlot(ring_buffer_ + std::min(start_ + size_, capacity_)));
119 visitor->VisitRootPointers(
120 Root::kStrongRoots,
nullptr, ObjectSlot(ring_buffer_),
121 ObjectSlot(ring_buffer_ + std::max(start_ + size_ - capacity_,
122 static_cast<intptr_t>(0))));
125 if (capacity_ <= kMinimumCapacity) {
129 intptr_t new_capacity = capacity_;
130 while (new_capacity > 2 * size_) {
133 new_capacity = std::max(new_capacity, kMinimumCapacity);
134 if (new_capacity < capacity_) {
135 ResizeBuffer(new_capacity);
139 void MicrotaskQueue::ResizeBuffer(intptr_t new_capacity) {
140 DCHECK_LE(size_, new_capacity);
141 Object** new_ring_buffer =
new Object*[new_capacity];
142 for (intptr_t
i = 0;
i < size_; ++
i) {
143 new_ring_buffer[
i] = ring_buffer_[(start_ +
i) % capacity_];
146 delete[] ring_buffer_;
147 ring_buffer_ = new_ring_buffer;
148 capacity_ = new_capacity;