Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions deps/v8/include/v8-microtask-dispatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ V8_EXPORT void SetMicrotaskDispatchCallback(Isolate* isolate,
V8_EXPORT void RunDispatchedMicrotask(Isolate* isolate,
DispatchedMicrotask* task);

// If the next job in the isolate's default microtask queue is a promise
// reaction job with non-undefined CPED, takes it off the queue and runs it on
// the current stack, as RunDispatchedMicrotask does, and returns true.
// Otherwise returns false and leaves the queue alone. Lets an embedder that is
// running a dispatched job keep running the dispatchable jobs right behind it
// without switching stacks for each one. Only call it while the job that was
// dispatched is still nested inside the microtask loop, so the order of jobs
// is unchanged.
V8_EXPORT bool RunNextDispatchableMicrotask(Isolate* isolate);

} // namespace v8

// Unmangled entry points, so an addon can find them with dlsym() and still
Expand All @@ -45,6 +55,7 @@ V8_EXPORT void v8_qualia_SetMicrotaskDispatchCallback(
v8::Isolate* isolate, v8::MicrotaskDispatchCallback callback, void* data);
V8_EXPORT void v8_qualia_RunDispatchedMicrotask(v8::Isolate* isolate,
v8::DispatchedMicrotask* task);
V8_EXPORT bool v8_qualia_RunNextDispatchableMicrotask(v8::Isolate* isolate);
}

#endif // INCLUDE_V8_MICROTASK_DISPATCH_H_
39 changes: 39 additions & 0 deletions deps/v8/src/runtime/runtime-promise.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "src/objects/heap-object-inl.h"
#include "src/objects/js-promise-inl.h"
#include "src/objects/microtask-inl.h"
#include "src/objects/promise-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/oddball-inl.h"
#include "src/runtime/runtime-utils.h"
Expand Down Expand Up @@ -188,6 +189,40 @@ void RunDispatchedMicrotask(Isolate* v8_isolate, DispatchedMicrotask* task) {
}
}

bool RunNextDispatchableMicrotask(Isolate* v8_isolate) {
internal::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
internal::MicrotaskQueue* queue = isolate->default_microtask_queue();
if (queue == nullptr || queue->size() == 0) return false;
internal::HandleScope handle_scope(isolate);
internal::Microtask front = queue->get(0);
if (!front.IsPromiseFulfillReactionJobTask() &&
!front.IsPromiseRejectReactionJobTask()) {
return false;
}
if (internal::PromiseReactionJobTask::cast(front)
.continuation_preserved_embedder_data()
.IsUndefined(isolate)) {
return false;
}
internal::Handle<internal::Microtask> microtask(front, isolate);
// Take it off the front of the queue the way the RunMicrotasks builtin does
// (that loop re-reads start and size before every job, so the drain this is
// nested in carries on with the job after it).
internal::Address base = reinterpret_cast<internal::Address>(queue);
intptr_t* start = reinterpret_cast<intptr_t*>(
base + internal::MicrotaskQueue::kStartOffset);
intptr_t* size = reinterpret_cast<intptr_t*>(
base + internal::MicrotaskQueue::kSizeOffset);
*start = (*start + 1) % queue->capacity();
*size -= 1;
std::unique_ptr<internal::MicrotaskQueue> private_queue =
internal::MicrotaskQueue::New(isolate);
private_queue->EnqueueMicrotask(*microtask);
RunDispatchedMicrotask(v8_isolate,
new DispatchedMicrotask{private_queue.release()});
return true;
}

} // namespace v8

extern "C" {
Expand All @@ -200,6 +235,10 @@ void v8_qualia_RunDispatchedMicrotask(v8::Isolate* isolate,
v8::DispatchedMicrotask* task) {
v8::RunDispatchedMicrotask(isolate, task);
}

bool v8_qualia_RunNextDispatchableMicrotask(v8::Isolate* isolate) {
return v8::RunNextDispatchableMicrotask(isolate);
}
}

namespace v8 {
Expand Down
Loading