Commit 24a232e2 authored by tzik's avatar tzik Committed by Commit Bot

Reland "Implement v8::internal::MicrotaskQueue::EnqueueMicrotask"

This is a reland of 836773c0

Original change's description:
> Implement v8::internal::MicrotaskQueue::EnqueueMicrotask
> 
> This adds `queue` and `pending_microtask_count` as members of
> v8::internal::MicrotaskQueue, and implements its EnqueueMicrotask.
> The implementation itself is similar to Isolate::EnqueueMicrotask.
> 
> Bug: v8:8124
> Change-Id: Idb5c50b2add96b72cbe9e36aeec7cb568072f0cb
> Reviewed-on: https://chromium-review.googlesource.com/1205430
> Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
> Reviewed-by: Adam Klein <adamk@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#55884}

Bug: v8:8124
Change-Id: Ibd32aec28c8fd9eab88904e62ba97a715295765d
Reviewed-on: https://chromium-review.googlesource.com/1226577Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Commit-Queue: Taiju Tsuiki <tzik@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55924}
parent 0de680bd
......@@ -27,6 +27,7 @@
#include "src/objects/js-regexp-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/microtask-inl.h"
#include "src/objects/microtask-queue-inl.h"
#include "src/objects/module-inl.h"
#include "src/objects/promise-inl.h"
#include "src/objects/scope-info.h"
......@@ -1621,6 +1622,16 @@ Handle<PromiseResolveThenableJobTask> Factory::NewPromiseResolveThenableJobTask(
return microtask;
}
Handle<MicrotaskQueue> Factory::NewMicrotaskQueue() {
// MicrotaskQueue should be TENURED, as it outlives Context, and is mostly
// as long-living as Context is.
Handle<MicrotaskQueue> microtask_queue =
Handle<MicrotaskQueue>::cast(NewStruct(MICROTASK_QUEUE_TYPE, TENURED));
microtask_queue->set_queue(*empty_fixed_array());
microtask_queue->set_pending_microtask_count(0);
return microtask_queue;
}
Handle<Foreign> Factory::NewForeign(Address addr, PretenureFlag pretenure) {
// Statically ensure that it is safe to allocate foreigns in paged spaces.
STATIC_ASSERT(Foreign::kSize <= kMaxRegularHeapObjectSize);
......
......@@ -439,6 +439,8 @@ class V8_EXPORT_PRIVATE Factory {
Handle<JSPromise> promise_to_resolve, Handle<JSReceiver> then,
Handle<JSReceiver> thenable, Handle<Context> context);
Handle<MicrotaskQueue> NewMicrotaskQueue();
// Foreign objects are pretenured when allocated by the bootstrapper.
Handle<Foreign> NewForeign(Address addr,
PretenureFlag pretenure = NOT_TENURED);
......
......@@ -1284,7 +1284,12 @@ void PromiseReactionJobTask::PromiseReactionJobTaskVerify(Isolate* isolate) {
promise_or_capability()->IsPromiseCapability());
}
void MicrotaskQueue::MicrotaskQueueVerify(Isolate* isolate) { UNIMPLEMENTED(); }
void MicrotaskQueue::MicrotaskQueueVerify(Isolate* isolate) {
CHECK(IsMicrotaskQueue());
VerifyHeapPointer(isolate, queue());
VerifySmiField(kPendingMicrotaskCountOffset);
CHECK_LE(pending_microtask_count(), queue()->length());
}
void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskVerify(
Isolate* isolate) {
......
......@@ -2198,7 +2198,10 @@ void UncompiledDataWithPreParsedScope::UncompiledDataWithPreParsedScopePrint(
}
void MicrotaskQueue::MicrotaskQueuePrint(std::ostream& os) { // NOLINT
UNIMPLEMENTED();
HeapObject::PrintHeader(os, "MicrotaskQueue");
os << "\n - pending_microtask_count: " << pending_microtask_count();
os << "\n - queue: " << Brief(queue());
os << "\n";
}
void InterpreterData::InterpreterDataPrint(std::ostream& os) { // NOLINT
......
......@@ -16,6 +16,9 @@ namespace v8 {
namespace internal {
CAST_ACCESSOR(MicrotaskQueue)
ACCESSORS(MicrotaskQueue, queue, FixedArray, kQueueOffset)
SMI_ACCESSORS(MicrotaskQueue, pending_microtask_count,
kPendingMicrotaskCountOffset)
} // namespace internal
} // namespace v8
......
......@@ -9,10 +9,26 @@
namespace v8 {
namespace internal {
// DCHECK requires this for taking the reference of it.
constexpr int MicrotaskQueue::kMinimumQueueCapacity;
// static
void MicrotaskQueue::EnqueueMicrotask(Handle<MicrotaskQueue> microtask_queue,
void MicrotaskQueue::EnqueueMicrotask(Isolate* isolate,
Handle<MicrotaskQueue> microtask_queue,
Handle<Microtask> microtask) {
UNIMPLEMENTED();
Handle<FixedArray> queue(microtask_queue->queue(), isolate);
int num_tasks = microtask_queue->pending_microtask_count();
DCHECK_LE(num_tasks, queue->length());
if (num_tasks == queue->length()) {
queue = isolate->factory()->CopyFixedArrayAndGrow(
queue, std::max(num_tasks, kMinimumQueueCapacity));
microtask_queue->set_queue(*queue);
}
DCHECK_LE(kMinimumQueueCapacity, queue->length());
DCHECK_LT(num_tasks, queue->length());
DCHECK(queue->get(num_tasks)->IsUndefined(isolate));
queue->set(num_tasks, *microtask);
microtask_queue->set_pending_microtask_count(num_tasks + 1);
}
// static
......
......@@ -14,17 +14,34 @@
namespace v8 {
namespace internal {
class MicrotaskQueue : public Struct {
class V8_EXPORT_PRIVATE MicrotaskQueue : public Struct {
public:
DECL_CAST(MicrotaskQueue)
DECL_VERIFIER(MicrotaskQueue)
DECL_PRINTER(MicrotaskQueue)
static void EnqueueMicrotask(Handle<MicrotaskQueue> microtask_queue,
// A FixedArray that the queued microtasks are stored.
// The first |pending_microtask_count| slots contains Microtask instance
// for each, and followings are undefined_value if any.
DECL_ACCESSORS(queue, FixedArray)
// The number of microtasks queued in |queue|. This must be less or equal to
// the length of |queue|.
DECL_INT_ACCESSORS(pending_microtask_count)
// Enqueues |microtask| to |microtask_queue|.
static void EnqueueMicrotask(Isolate* isolate,
Handle<MicrotaskQueue> microtask_queue,
Handle<Microtask> microtask);
// Runs all enqueued microtasks.
static void RunMicrotasks(Handle<MicrotaskQueue> microtask_queue);
static const int kSize = HeapObject::kHeaderSize;
static constexpr int kMinimumQueueCapacity = 8;
static const int kQueueOffset = HeapObject::kHeaderSize;
static const int kPendingMicrotaskCountOffset = kQueueOffset + kPointerSize;
static const int kSize = kPendingMicrotaskCountOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(MicrotaskQueue);
......
......@@ -183,6 +183,7 @@ v8_source_set("unittests_sources") {
"libplatform/worker-thread-unittest.cc",
"locked-queue-unittest.cc",
"object-unittest.cc",
"objects/microtask-queue-unittest.cc",
"parser/ast-value-unittest.cc",
"parser/preparser-unittest.cc",
"register-configuration-unittest.cc",
......
// 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.
#include "src/objects/microtask-queue.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
void NoopCallback(void*) {}
class MicrotaskQueueTest : public TestWithIsolate {
public:
Handle<Microtask> NewMicrotask() {
MicrotaskCallback callback = &NoopCallback;
void* data = nullptr;
return factory()->NewCallbackTask(
factory()->NewForeign(reinterpret_cast<Address>(callback)),
factory()->NewForeign(reinterpret_cast<Address>(data)));
}
};
TEST_F(MicrotaskQueueTest, EnqueueMicrotask) {
Handle<MicrotaskQueue> microtask_queue = factory()->NewMicrotaskQueue();
Handle<Microtask> microtask = NewMicrotask();
EXPECT_EQ(0, microtask_queue->pending_microtask_count());
MicrotaskQueue::EnqueueMicrotask(isolate(), microtask_queue, microtask);
EXPECT_EQ(1, microtask_queue->pending_microtask_count());
ASSERT_LE(1, microtask_queue->queue()->length());
EXPECT_EQ(*microtask, microtask_queue->queue()->get(0));
std::vector<Handle<Microtask>> microtasks;
microtasks.push_back(microtask);
// Queue microtasks until the reallocation.
int queue_capacity = microtask_queue->queue()->length();
for (int i = 0; i < queue_capacity; ++i) {
microtask = NewMicrotask();
MicrotaskQueue::EnqueueMicrotask(isolate(), microtask_queue, microtask);
microtasks.push_back(microtask);
}
int num_tasks = static_cast<int>(microtasks.size());
EXPECT_EQ(num_tasks, microtask_queue->pending_microtask_count());
ASSERT_LE(num_tasks, microtask_queue->queue()->length());
for (int i = 0; i < num_tasks; ++i) {
EXPECT_EQ(*microtasks[i], microtask_queue->queue()->get(i));
}
}
} // namespace internal
} // namespace v8
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