Update MicrotaskQueue ring buffer for pointer compression
This updates MicrotaskQueue to use pointer-compression style object reference. Bug: v8:8124 Change-Id: I7bef92a8760609f3045d2025b145b9a0ec880424 Reviewed-on: https://chromium-review.googlesource.com/c/1478320 Commit-Queue: Taiju Tsuiki <tzik@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#59762}
This commit is contained in:
parent
9b5fe7b26d
commit
8a1e927fdb
@ -100,7 +100,7 @@ void MicrotaskQueueBuiltinsAssembler::SetMicrotaskQueueStart(
|
||||
|
||||
TNode<IntPtrT> MicrotaskQueueBuiltinsAssembler::CalculateRingBufferOffset(
|
||||
TNode<IntPtrT> capacity, TNode<IntPtrT> start, TNode<IntPtrT> index) {
|
||||
return TimesSystemPointerSize(
|
||||
return TimesTaggedSize(
|
||||
WordAnd(IntPtrAdd(start, index), IntPtrSub(capacity, IntPtrConstant(1))));
|
||||
}
|
||||
|
||||
@ -482,9 +482,9 @@ TF_BUILTIN(EnqueueMicrotask, MicrotaskQueueBuiltinsAssembler) {
|
||||
|
||||
// |microtask_queue| has an unused slot to store |microtask|.
|
||||
{
|
||||
StoreNoWriteBarrier(MachineType::PointerRepresentation(), ring_buffer,
|
||||
CalculateRingBufferOffset(capacity, start, size),
|
||||
BitcastTaggedToWord(microtask));
|
||||
StoreNoWriteBarrier(
|
||||
MachineType::TaggedPointer().representation(), ring_buffer,
|
||||
CalculateRingBufferOffset(capacity, start, size), microtask);
|
||||
StoreNoWriteBarrier(MachineType::PointerRepresentation(), microtask_queue,
|
||||
IntPtrConstant(MicrotaskQueue::kSizeOffset),
|
||||
IntPtrAdd(size, IntPtrConstant(1)));
|
||||
@ -528,9 +528,8 @@ TF_BUILTIN(RunMicrotasks, MicrotaskQueueBuiltinsAssembler) {
|
||||
|
||||
TNode<IntPtrT> offset =
|
||||
CalculateRingBufferOffset(capacity, start, IntPtrConstant(0));
|
||||
TNode<RawPtrT> microtask_pointer =
|
||||
UncheckedCast<RawPtrT>(Load(MachineType::Pointer(), ring_buffer, offset));
|
||||
TNode<Microtask> microtask = CAST(BitcastWordToTagged(microtask_pointer));
|
||||
TNode<Microtask> microtask =
|
||||
CAST(Load(MachineType::TaggedPointer(), ring_buffer, offset));
|
||||
|
||||
TNode<IntPtrT> new_size = IntPtrSub(size, IntPtrConstant(1));
|
||||
TNode<IntPtrT> new_start = WordAnd(IntPtrAdd(start, IntPtrConstant(1)),
|
||||
|
@ -64,7 +64,7 @@ MicrotaskQueue::~MicrotaskQueue() {
|
||||
next_->prev_ = prev_;
|
||||
prev_->next_ = next_;
|
||||
}
|
||||
delete[] ring_buffer_;
|
||||
delete[] reinterpret_cast<Microtask*>(ring_buffer_.address());
|
||||
}
|
||||
|
||||
// static
|
||||
@ -86,7 +86,8 @@ void MicrotaskQueue::EnqueueMicrotask(Microtask microtask) {
|
||||
}
|
||||
|
||||
DCHECK_LT(size_, capacity_);
|
||||
ring_buffer_[(start_ + size_) % capacity_] = microtask.ptr();
|
||||
(ring_buffer_ + static_cast<int>((start_ + size_) % capacity_))
|
||||
.store(microtask);
|
||||
++size_;
|
||||
}
|
||||
|
||||
@ -141,8 +142,8 @@ int MicrotaskQueue::RunMicrotasks(Isolate* isolate) {
|
||||
|
||||
// If execution is terminating, clean up and propagate that to TryCatch scope.
|
||||
if (maybe_result.is_null() && maybe_exception.is_null()) {
|
||||
delete[] ring_buffer_;
|
||||
ring_buffer_ = nullptr;
|
||||
delete[] reinterpret_cast<Microtask*>(ring_buffer_.address());
|
||||
ring_buffer_ = ObjectSlot();
|
||||
capacity_ = 0;
|
||||
size_ = 0;
|
||||
start_ = 0;
|
||||
@ -161,12 +162,12 @@ void MicrotaskQueue::IterateMicrotasks(RootVisitor* visitor) {
|
||||
// Iterate pending Microtasks as root objects to avoid the write barrier for
|
||||
// all single Microtask. If this hurts the GC performance, use a FixedArray.
|
||||
visitor->VisitRootPointers(
|
||||
Root::kStrongRoots, nullptr, FullObjectSlot(ring_buffer_ + start_),
|
||||
FullObjectSlot(ring_buffer_ + std::min(start_ + size_, capacity_)));
|
||||
Root::kStrongRoots, nullptr, ring_buffer_ + static_cast<int>(start_),
|
||||
ring_buffer_ + static_cast<int>(std::min(start_ + size_, capacity_)));
|
||||
visitor->VisitRootPointers(
|
||||
Root::kStrongRoots, nullptr, FullObjectSlot(ring_buffer_),
|
||||
FullObjectSlot(ring_buffer_ + std::max(start_ + size_ - capacity_,
|
||||
static_cast<intptr_t>(0))));
|
||||
Root::kStrongRoots, nullptr, ring_buffer_,
|
||||
ring_buffer_ + static_cast<int>(
|
||||
std::max<intptr_t>(start_ + size_ - capacity_, 0)));
|
||||
}
|
||||
|
||||
if (capacity_ <= kMinimumCapacity) {
|
||||
@ -219,12 +220,14 @@ void MicrotaskQueue::OnCompleted(Isolate* isolate) {
|
||||
|
||||
void MicrotaskQueue::ResizeBuffer(intptr_t new_capacity) {
|
||||
DCHECK_LE(size_, new_capacity);
|
||||
Address* new_ring_buffer = new Address[new_capacity];
|
||||
ObjectSlot new_ring_buffer(
|
||||
reinterpret_cast<Address>(new Microtask[new_capacity]));
|
||||
for (intptr_t i = 0; i < size_; ++i) {
|
||||
new_ring_buffer[i] = ring_buffer_[(start_ + i) % capacity_];
|
||||
(new_ring_buffer + static_cast<int>(i))
|
||||
.store(*(ring_buffer_ + static_cast<int>((start_ + i) % capacity_)));
|
||||
}
|
||||
|
||||
delete[] ring_buffer_;
|
||||
delete[] reinterpret_cast<Microtask*>(ring_buffer_.address());
|
||||
ring_buffer_ = new_ring_buffer;
|
||||
capacity_ = new_capacity;
|
||||
start_ = 0;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "include/v8-internal.h" // For Address.
|
||||
#include "include/v8.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/objects/slots.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -107,7 +108,7 @@ class V8_EXPORT_PRIVATE MicrotaskQueue {
|
||||
intptr_t size_ = 0;
|
||||
intptr_t capacity_ = 0;
|
||||
intptr_t start_ = 0;
|
||||
Address* ring_buffer_ = nullptr;
|
||||
ObjectSlot ring_buffer_;
|
||||
|
||||
// The number of finished microtask.
|
||||
intptr_t finished_microtask_count_ = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user