diff --git a/Source/JavaScriptCore/runtime/DeferredWorkTimer.cpp b/Source/JavaScriptCore/runtime/DeferredWorkTimer.cpp index 4d3699ca36390..592e0f7afe700 100644 --- a/Source/JavaScriptCore/runtime/DeferredWorkTimer.cpp +++ b/Source/JavaScriptCore/runtime/DeferredWorkTimer.cpp @@ -152,7 +152,7 @@ void DeferredWorkTimer::runRunLoop() RunLoop::run(); } -DeferredWorkTimer::Ticket DeferredWorkTimer::addPendingWork(VM& vm, JSObject* target, Vector>&& dependencies) +DeferredWorkTimer::Ticket DeferredWorkTimer::addPendingWork(VM& vm, JSObject* target, Vector>&& dependencies, WorkKind workKind) { ASSERT(vm.currentThreadIsHoldingAPILock() || (Thread::mayBeGCThread() && vm.heap.worldIsStopped())); for (unsigned i = 0; i < dependencies.size(); ++i) @@ -166,8 +166,13 @@ DeferredWorkTimer::Ticket DeferredWorkTimer::addPendingWork(VM& vm, JSObject* ta Ticket ticket = ticketData.get(); dataLogLnIf(DeferredWorkTimerInternal::verbose, "Adding new pending ticket: ", RawPointer(ticket)); - auto result = m_pendingTickets.add(WTFMove(ticketData)); - RELEASE_ASSERT(result.isNewEntry); + if (onAddPendingWork) { + onAddPendingWork(WTFMove(ticketData), workKind); + } else { + auto result = m_pendingTickets.add(WTFMove(ticketData)); + RELEASE_ASSERT(result.isNewEntry); + } + return ticket; } @@ -192,6 +197,11 @@ bool DeferredWorkTimer::hasDependancyInPendingWork(Ticket ticket, JSCell* depend void DeferredWorkTimer::scheduleWorkSoon(Ticket ticket, Task&& task) { + if (onScheduleWorkSoon) { + onScheduleWorkSoon(ticket, WTFMove(task)); + return; + } + Locker locker { m_taskLock }; m_tasks.append(std::make_tuple(ticket, WTFMove(task))); if (!isScheduled() && !m_currentlyRunningTask) @@ -210,6 +220,10 @@ bool DeferredWorkTimer::cancelPendingWork(Ticket ticket) result = true; } + if (onCancelPendingWork) { + onCancelPendingWork(ticket); + } + return result; } diff --git a/Source/JavaScriptCore/runtime/DeferredWorkTimer.h b/Source/JavaScriptCore/runtime/DeferredWorkTimer.h index 1d68a922d27cb..6b3c55c1d53c6 100644 --- a/Source/JavaScriptCore/runtime/DeferredWorkTimer.h +++ b/Source/JavaScriptCore/runtime/DeferredWorkTimer.h @@ -45,6 +45,12 @@ class JS_EXPORT_PRIVATE DeferredWorkTimer final : public JSRunLoopTimer { public: using Base = JSRunLoopTimer; + enum class WorkKind : uint8_t { + Other, + Atomics, + WebAssembly, + }; + struct TicketData { private: WTF_MAKE_FAST_ALLOCATED; @@ -65,7 +71,7 @@ class JS_EXPORT_PRIVATE DeferredWorkTimer final : public JSRunLoopTimer { void doWork(VM&) final; - Ticket addPendingWork(VM&, JSObject* target, Vector>&& dependencies); + Ticket addPendingWork(VM&, JSObject* target, Vector>&& dependencies, WorkKind kind = WorkKind::Other); bool hasPendingWork(Ticket); bool hasDependancyInPendingWork(Ticket, JSCell* dependency); bool cancelPendingWork(Ticket); @@ -83,6 +89,10 @@ class JS_EXPORT_PRIVATE DeferredWorkTimer final : public JSRunLoopTimer { void runRunLoop(); static Ref create(VM& vm) { return adoptRef(*new DeferredWorkTimer(vm)); } + + WTF::Function, WorkKind)> onAddPendingWork; + WTF::Function onScheduleWorkSoon; + WTF::Function onCancelPendingWork; private: DeferredWorkTimer(VM&); diff --git a/Source/JavaScriptCore/runtime/WaiterListManager.h b/Source/JavaScriptCore/runtime/WaiterListManager.h index 0097bbb10a561..20a870c800c8e 100644 --- a/Source/JavaScriptCore/runtime/WaiterListManager.h +++ b/Source/JavaScriptCore/runtime/WaiterListManager.h @@ -48,7 +48,7 @@ class Waiter final : public WTF::BasicRawSentinelNode, public ThreadSafe Waiter(JSPromise* promise) : m_vm(&promise->vm()) - , m_ticket(m_vm->deferredWorkTimer->addPendingWork(*m_vm, promise, { })) + , m_ticket(m_vm->deferredWorkTimer->addPendingWork(*m_vm, promise, { }, DeferredWorkTimer::WorkKind::Atomics)) , m_isAsync(true) { } diff --git a/Source/JavaScriptCore/wasm/WasmStreamingCompiler.cpp b/Source/JavaScriptCore/wasm/WasmStreamingCompiler.cpp index dcaa8c78e490e..6740ec80d4100 100644 --- a/Source/JavaScriptCore/wasm/WasmStreamingCompiler.cpp +++ b/Source/JavaScriptCore/wasm/WasmStreamingCompiler.cpp @@ -51,7 +51,7 @@ StreamingCompiler::StreamingCompiler(VM& vm, CompilerMode compilerMode, JSGlobal dependencies.append(Strong(vm, globalObject)); if (importObject) dependencies.append(Strong(vm, importObject)); - m_ticket = vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies)); + m_ticket = vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies), DeferredWorkTimer::WorkKind::WebAssembly); ASSERT(vm.deferredWorkTimer->hasPendingWork(m_ticket)); ASSERT(vm.deferredWorkTimer->hasDependancyInPendingWork(m_ticket, globalObject)); ASSERT(!importObject || vm.deferredWorkTimer->hasDependancyInPendingWork(m_ticket, importObject)); diff --git a/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp b/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp index ab95507ce8d4f..42b81de2f87dd 100644 --- a/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp +++ b/Source/JavaScriptCore/wasm/js/JSWebAssembly.cpp @@ -147,7 +147,7 @@ void JSWebAssembly::webAssemblyModuleValidateAsync(JSGlobalObject* globalObject, Vector> dependencies; dependencies.append(Strong(vm, globalObject)); - auto ticket = vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies)); + auto ticket = vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies), DeferredWorkTimer::WorkKind::WebAssembly); Wasm::Module::validateAsync(vm, WTFMove(source), createSharedTask([ticket, promise, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable { vm.deferredWorkTimer->scheduleWorkSoon(ticket, [promise, globalObject, result = WTFMove(result), &vm](DeferredWorkTimer::Ticket) mutable { auto scope = DECLARE_THROW_SCOPE(vm); @@ -186,7 +186,7 @@ static void instantiate(VM& vm, JSGlobalObject* globalObject, JSPromise* promise dependencies.append(Strong(vm, promise)); scope.release(); - auto ticket = vm.deferredWorkTimer->addPendingWork(vm, instance, WTFMove(dependencies)); + auto ticket = vm.deferredWorkTimer->addPendingWork(vm, instance, WTFMove(dependencies), DeferredWorkTimer::WorkKind::WebAssembly); // Note: This completion task may or may not get called immediately. module->module().compileAsync(vm, instance->memoryMode(), createSharedTask([ticket, promise, instance, module, resolveKind, creationMode, &vm] (Ref&& refCalleeGroup) mutable { RefPtr calleeGroup = WTFMove(refCalleeGroup); @@ -238,7 +238,7 @@ static void compileAndInstantiate(VM& vm, JSGlobalObject* globalObject, JSPromis Vector> dependencies; dependencies.append(Strong(vm, importObject)); dependencies.append(Strong(vm, moduleKeyCell)); - auto ticket = vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies)); + auto ticket = vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies), DeferredWorkTimer::WorkKind::WebAssembly); Wasm::Module::validateAsync(vm, WTFMove(source), createSharedTask([ticket, promise, importObject, moduleKeyCell, globalObject, resolveKind, creationMode, &vm] (Wasm::Module::ValidationResult&& result) mutable { vm.deferredWorkTimer->scheduleWorkSoon(ticket, [promise, importObject, moduleKeyCell, globalObject, result = WTFMove(result), resolveKind, creationMode, &vm](DeferredWorkTimer::Ticket) mutable { auto scope = DECLARE_THROW_SCOPE(vm);