diff options
Diffstat (limited to 'deps/v8/src/execution/microtask-queue.h')
-rw-r--r-- | deps/v8/src/execution/microtask-queue.h | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/deps/v8/src/execution/microtask-queue.h b/deps/v8/src/execution/microtask-queue.h new file mode 100644 index 0000000000..4ce1498279 --- /dev/null +++ b/deps/v8/src/execution/microtask-queue.h @@ -0,0 +1,148 @@ +// Copyright 2018 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_EXECUTION_MICROTASK_QUEUE_H_ +#define V8_EXECUTION_MICROTASK_QUEUE_H_ + +#include <stdint.h> +#include <memory> +#include <vector> + +#include "include/v8-internal.h" // For Address. +#include "include/v8.h" +#include "src/base/macros.h" + +namespace v8 { +namespace internal { + +class Isolate; +class Microtask; +class Object; +class RootVisitor; + +class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { + public: + static void SetUpDefaultMicrotaskQueue(Isolate* isolate); + static std::unique_ptr<MicrotaskQueue> New(Isolate* isolate); + + ~MicrotaskQueue(); + + // Uses raw Address values because it's called via ExternalReference. + // {raw_microtask} is a tagged Microtask pointer. + // Returns a tagged Object pointer. + static Address CallEnqueueMicrotask(Isolate* isolate, + intptr_t microtask_queue_pointer, + Address raw_microtask); + + // v8::MicrotaskQueue implementations. + void EnqueueMicrotask(v8::Isolate* isolate, + v8::Local<Function> microtask) override; + void EnqueueMicrotask(v8::Isolate* isolate, v8::MicrotaskCallback callback, + void* data) override; + void PerformCheckpoint(v8::Isolate* isolate) override; + + void EnqueueMicrotask(Microtask microtask); + void AddMicrotasksCompletedCallback( + MicrotasksCompletedCallbackWithData callback, void* data) override; + void RemoveMicrotasksCompletedCallback( + MicrotasksCompletedCallbackWithData callback, void* data) override; + bool IsRunningMicrotasks() const override { return is_running_microtasks_; } + + // Runs all queued Microtasks. + // Returns -1 if the execution is terminating, otherwise, returns the number + // of microtasks that ran in this round. + int RunMicrotasks(Isolate* isolate); + + // Iterate all pending Microtasks in this queue as strong roots, so that + // builtins can update the queue directly without the write barrier. + void IterateMicrotasks(RootVisitor* visitor); + + // Microtasks scope depth represents nested scopes controlling microtasks + // invocation, which happens when depth reaches zero. + void IncrementMicrotasksScopeDepth() { ++microtasks_depth_; } + void DecrementMicrotasksScopeDepth() { --microtasks_depth_; } + int GetMicrotasksScopeDepth() const override; + + // Possibly nested microtasks suppression scopes prevent microtasks + // from running. + void IncrementMicrotasksSuppressions() { ++microtasks_suppressions_; } + void DecrementMicrotasksSuppressions() { --microtasks_suppressions_; } + bool HasMicrotasksSuppressions() const { + return microtasks_suppressions_ != 0; + } + +#ifdef DEBUG + // In debug we check that calls not intended to invoke microtasks are + // still correctly wrapped with microtask scopes. + void IncrementDebugMicrotasksScopeDepth() { ++debug_microtasks_depth_; } + void DecrementDebugMicrotasksScopeDepth() { --debug_microtasks_depth_; } + bool DebugMicrotasksScopeDepthIsZero() const { + return debug_microtasks_depth_ == 0; + } +#endif + + void set_microtasks_policy(v8::MicrotasksPolicy microtasks_policy) { + microtasks_policy_ = microtasks_policy; + } + v8::MicrotasksPolicy microtasks_policy() const { return microtasks_policy_; } + + void FireMicrotasksCompletedCallback(Isolate* isolate) const; + + intptr_t capacity() const { return capacity_; } + intptr_t size() const { return size_; } + intptr_t start() const { return start_; } + + Microtask get(intptr_t index) const; + + MicrotaskQueue* next() const { return next_; } + MicrotaskQueue* prev() const { return prev_; } + + static const size_t kRingBufferOffset; + static const size_t kCapacityOffset; + static const size_t kSizeOffset; + static const size_t kStartOffset; + static const size_t kFinishedMicrotaskCountOffset; + + static const intptr_t kMinimumCapacity; + + private: + void OnCompleted(Isolate* isolate); + + MicrotaskQueue(); + void ResizeBuffer(intptr_t new_capacity); + + // A ring buffer to hold Microtask instances. + // ring_buffer_[(start_ + i) % capacity_] contains |i|th Microtask for each + // |i| in [0, size_). + intptr_t size_ = 0; + intptr_t capacity_ = 0; + intptr_t start_ = 0; + Address* ring_buffer_ = nullptr; + + // The number of finished microtask. + intptr_t finished_microtask_count_ = 0; + + // MicrotaskQueue instances form a doubly linked list loop, so that all + // instances are reachable through |next_|. + MicrotaskQueue* next_ = nullptr; + MicrotaskQueue* prev_ = nullptr; + + int microtasks_depth_ = 0; + int microtasks_suppressions_ = 0; +#ifdef DEBUG + int debug_microtasks_depth_ = 0; +#endif + + v8::MicrotasksPolicy microtasks_policy_ = v8::MicrotasksPolicy::kAuto; + + bool is_running_microtasks_ = false; + using CallbackWithData = + std::pair<MicrotasksCompletedCallbackWithData, void*>; + std::vector<CallbackWithData> microtasks_completed_callbacks_; +}; + +} // namespace internal +} // namespace v8 + +#endif // V8_EXECUTION_MICROTASK_QUEUE_H_ |