Commit 516d9068 authored by tzik's avatar tzik Committed by Commit Bot

Expose the number of microtasks from RunMicrotasks

This CL adds the number of processed microtasks to the tracing marker
of RunMicrotasks, plus let RunMicrotasks return the number.

Bug: v8:7804, v8:8124
Change-Id: Ie584e22964121fbda3a822379d760e7518fc54a7
Reviewed-on: https://chromium-review.googlesource.com/c/1425277
Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59017}
parent 45fe356e
......@@ -35,6 +35,7 @@ class MicrotaskQueueBuiltinsAssembler : public CodeStubAssembler {
TNode<IntPtrT> index);
void RunSingleMicrotask(TNode<Context> current_context,
TNode<Microtask> microtask);
void IncrementFinishedMicrotaskCount(TNode<RawPtrT> microtask_queue);
TNode<Context> GetCurrentContext();
void SetCurrentContext(TNode<Context> context);
......@@ -311,6 +312,17 @@ void MicrotaskQueueBuiltinsAssembler::RunSingleMicrotask(
BIND(&done);
}
void MicrotaskQueueBuiltinsAssembler::IncrementFinishedMicrotaskCount(
TNode<RawPtrT> microtask_queue) {
TNode<IntPtrT> count = UncheckedCast<IntPtrT>(
Load(MachineType::IntPtr(), microtask_queue,
IntPtrConstant(MicrotaskQueue::kFinishedMicrotaskCountOffset)));
TNode<IntPtrT> new_count = IntPtrAdd(count, IntPtrConstant(1));
StoreNoWriteBarrier(
MachineType::PointerRepresentation(), microtask_queue,
IntPtrConstant(MicrotaskQueue::kFinishedMicrotaskCountOffset), new_count);
}
TNode<Context> MicrotaskQueueBuiltinsAssembler::GetCurrentContext() {
auto ref = ExternalReference::Create(kContextAddress, isolate());
return TNode<Context>::UncheckedCast(
......@@ -531,6 +543,7 @@ TF_BUILTIN(RunMicrotasks, MicrotaskQueueBuiltinsAssembler) {
SetMicrotaskQueueStart(microtask_queue, new_start);
RunSingleMicrotask(current_context, microtask);
IncrementFinishedMicrotaskCount(microtask_queue);
Goto(&loop);
BIND(&done);
......
......@@ -25,6 +25,8 @@ const size_t MicrotaskQueue::kCapacityOffset =
OFFSET_OF(MicrotaskQueue, capacity_);
const size_t MicrotaskQueue::kSizeOffset = OFFSET_OF(MicrotaskQueue, size_);
const size_t MicrotaskQueue::kStartOffset = OFFSET_OF(MicrotaskQueue, start_);
const size_t MicrotaskQueue::kFinishedMicrotaskCountOffset =
OFFSET_OF(MicrotaskQueue, finished_microtask_count_);
const intptr_t MicrotaskQueue::kMinimumCapacity = 8;
......@@ -114,20 +116,27 @@ int MicrotaskQueue::RunMicrotasks(Isolate* isolate) {
return 0;
}
intptr_t base_count = finished_microtask_count_;
HandleScope handle_scope(isolate);
MaybeHandle<Object> maybe_exception;
MaybeHandle<Object> maybe_result;
int processed_microtask_count;
{
SetIsRunningMicrotasks scope(&is_running_microtasks_);
v8::Isolate::SuppressMicrotaskExecutionScope suppress(
reinterpret_cast<v8::Isolate*>(isolate));
HandleScopeImplementer::EnteredContextRewindScope rewind_scope(
isolate->handle_scope_implementer());
TRACE_EVENT0("v8.execute", "RunMicrotasks");
TRACE_EVENT_BEGIN0("v8.execute", "RunMicrotasks");
TRACE_EVENT_CALL_STATS_SCOPED(isolate, "v8", "V8.RunMicrotasks");
maybe_result = Execution::TryRunMicrotasks(isolate, this, &maybe_exception);
processed_microtask_count =
static_cast<int>(finished_microtask_count_ - base_count);
TRACE_EVENT_END1("v8.execute", "RunMicrotasks", "microtask_count",
processed_microtask_count);
}
// If execution is terminating, clean up and propagate that to TryCatch scope.
......@@ -144,8 +153,7 @@ int MicrotaskQueue::RunMicrotasks(Isolate* isolate) {
DCHECK_EQ(0, size());
OnCompleted(isolate);
// TODO(tzik): Return the number of microtasks run in this round.
return 0;
return processed_microtask_count;
}
void MicrotaskQueue::IterateMicrotasks(RootVisitor* visitor) {
......
......@@ -37,9 +37,9 @@ class V8_EXPORT_PRIVATE MicrotaskQueue {
void EnqueueMicrotask(Microtask microtask);
// Returns -1 if the execution is terminating, otherwise, returns 0.
// TODO(tzik): Update the implementation to return the number of processed
// 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
......@@ -86,6 +86,7 @@ class V8_EXPORT_PRIVATE MicrotaskQueue {
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;
......@@ -103,6 +104,9 @@ class V8_EXPORT_PRIVATE MicrotaskQueue {
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;
......
......@@ -88,7 +88,7 @@ TEST_F(MicrotaskQueueTest, EnqueueAndRun) {
}));
EXPECT_EQ(MicrotaskQueue::kMinimumCapacity, microtask_queue()->capacity());
EXPECT_EQ(1, microtask_queue()->size());
microtask_queue()->RunMicrotasks(isolate());
EXPECT_EQ(1, microtask_queue()->RunMicrotasks(isolate()));
EXPECT_TRUE(ran);
EXPECT_EQ(0, microtask_queue()->size());
}
......@@ -100,7 +100,7 @@ TEST_F(MicrotaskQueueTest, BufferGrowth) {
// Enqueue and flush the queue first to have non-zero |start_|.
microtask_queue()->EnqueueMicrotask(
*NewMicrotask([&count] { EXPECT_EQ(0, count++); }));
microtask_queue()->RunMicrotasks(isolate());
EXPECT_EQ(1, microtask_queue()->RunMicrotasks(isolate()));
EXPECT_LT(0, microtask_queue()->capacity());
EXPECT_EQ(0, microtask_queue()->size());
......@@ -122,7 +122,8 @@ TEST_F(MicrotaskQueueTest, BufferGrowth) {
EXPECT_EQ(MicrotaskQueue::kMinimumCapacity + 1, microtask_queue()->size());
// Run all pending Microtasks to ensure they run in the proper order.
microtask_queue()->RunMicrotasks(isolate());
EXPECT_EQ(MicrotaskQueue::kMinimumCapacity + 1,
microtask_queue()->RunMicrotasks(isolate()));
EXPECT_EQ(MicrotaskQueue::kMinimumCapacity + 2, count);
}
......@@ -163,7 +164,8 @@ TEST_F(MicrotaskQueueTest, VisitRoot) {
for (int i = 0; i < MicrotaskQueue::kMinimumCapacity / 2 + 1; ++i) {
microtask_queue()->EnqueueMicrotask(*NewMicrotask([] {}));
}
microtask_queue()->RunMicrotasks(isolate());
EXPECT_EQ(MicrotaskQueue::kMinimumCapacity / 2 + 1,
microtask_queue()->RunMicrotasks(isolate()));
std::vector<Object> expected;
for (int i = 0; i < MicrotaskQueue::kMinimumCapacity / 2 + 1; ++i) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment