From 9a2370e434987bc008edebe423947cd6d0f38860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Tue, 8 Oct 2024 09:31:46 +0200 Subject: [PATCH] wasm: unifiy eventdispatcher asyncify code paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no difference between these as far as the suspend/resume functions go; the exiting difference is due to using a more modern API for the jspi implementation. Replace EM_JS() usage with EM_ASYNC_JS(). This allows using await Promise() instead of Asyncify.handleSleep(), and also removes the need for setting ASYNCIFY_IMPORTS. Remove the useJspi() function and the duplicate code paths. Task-number: QTBUG-129746 Change-Id: Id914089868763a1a3d5d575043c29845889f6624 Reviewed-by: Lorn Potter Reviewed-by: Jøger Hansegård --- cmake/QtWasmHelpers.cmake | 3 - mkspecs/common/wasm/wasm.conf | 3 - src/corelib/kernel/qeventdispatcher_wasm.cpp | 120 +++---------------- 3 files changed, 18 insertions(+), 108 deletions(-) diff --git a/cmake/QtWasmHelpers.cmake b/cmake/QtWasmHelpers.cmake index 20bd5b333d6..d154fb8d463 100644 --- a/cmake/QtWasmHelpers.cmake +++ b/cmake/QtWasmHelpers.cmake @@ -90,9 +90,6 @@ function (qt_internal_setup_wasm_target_properties wasmTarget) target_compile_definitions("${wasmTarget}" INTERFACE QT_HAVE_EMSCRIPTEN_ASYNCIFY) endif() - # Set ASYNCIFY_IMPORTS unconditionally in order to support enabling asyncify at link time. - target_link_options("${wasmTarget}" INTERFACE "SHELL:-sASYNCIFY_IMPORTS=qt_asyncify_suspend_js,qt_asyncify_resume_js") - if(QT_FEATURE_shared) set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE) diff --git a/mkspecs/common/wasm/wasm.conf b/mkspecs/common/wasm/wasm.conf index 6b967d79f24..eb883a4f744 100644 --- a/mkspecs/common/wasm/wasm.conf +++ b/mkspecs/common/wasm/wasm.conf @@ -30,9 +30,6 @@ load(emcc_ver) } } -# Declare async functions -QMAKE_LFLAGS += -s ASYNCIFY_IMPORTS=qt_asyncify_suspend_js,qt_asyncify_resume_js - EMCC_COMMON_LFLAGS += \ -s WASM=1 \ -s MAX_WEBGL_VERSION=2 \ diff --git a/src/corelib/kernel/qeventdispatcher_wasm.cpp b/src/corelib/kernel/qeventdispatcher_wasm.cpp index d9f234d4192..b6d1711fe2e 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm.cpp +++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp @@ -44,58 +44,14 @@ static bool useAsyncify() return qstdweb::haveAsyncify(); } -static bool useJspi() -{ - return qstdweb::haveJspi(); -} - // clang-format off -EM_ASYNC_JS(void, qt_jspi_suspend_js, (), { - ++Module.qtJspiSuspensionCounter; - - await new Promise(resolve => { - Module.qtAsyncifyWakeUp.push(resolve); - }); -}); - -EM_JS(bool, qt_jspi_resume_js, (), { - if (!Module.qtJspiSuspensionCounter) - return false; - - --Module.qtJspiSuspensionCounter; - - setTimeout(() => { - const wakeUp = (Module.qtAsyncifyWakeUp ?? []).pop(); - if (wakeUp) wakeUp(); - }); - return true; -}); - -EM_JS(bool, qt_jspi_can_resume_js, (), { - return Module.qtJspiSuspensionCounter > 0; -}); - -EM_JS(void, init_jspi_support_js, (), { - Module.qtAsyncifyWakeUp = []; - Module.qtJspiSuspensionCounter = 0; -}); -// clang-format on - -void initJspiSupport() { - init_jspi_support_js(); -} - -Q_CONSTRUCTOR_FUNCTION(initJspiSupport); - -// clang-format off -EM_JS(void, qt_asyncify_suspend_js, (), { +EM_ASYNC_JS(void, qt_asyncify_suspend_js, (), { if (Module.qtSuspendId === undefined) Module.qtSuspendId = 0; - let sleepFn = (wakeUp) => { - Module.qtAsyncifyWakeUp = wakeUp; - }; ++Module.qtSuspendId; - return Asyncify.handleSleep(sleepFn); + await new Promise(resolve => { + Module.qtAsyncifyWakeUp = resolve; + }); }); EM_JS(void, qt_asyncify_resume_js, (), { @@ -125,28 +81,6 @@ static bool useAsyncify() return false; } -static bool useJspi() -{ - return false; -} - -void qt_jspi_suspend_js() -{ - Q_UNREACHABLE(); -} - -bool qt_jspi_resume_js() -{ - Q_UNREACHABLE(); - return false; -} - -bool qt_jspi_can_resume_js() -{ - Q_UNREACHABLE(); - return false; -} - void qt_asyncify_suspend_js() { Q_UNREACHABLE(); @@ -453,9 +387,8 @@ void QEventDispatcherWasm::wakeUp() // event loop. Make sure the thread is unblocked or make it // process events. bool wasBlocked = wakeEventDispatcherThread(); - // JSPI does not need a scheduled call to processPostedEvents, as the stack is not unwound - // at startup. - if (!qstdweb::haveJspi() && !wasBlocked && isMainThreadEventDispatcher()) { + + if (!wasBlocked && isMainThreadEventDispatcher()) { { LOCK_GUARD(m_mutex); if (m_pendingProcessEvents) @@ -480,12 +413,10 @@ void QEventDispatcherWasm::handleApplicationExec() // using it for the one qApp exec(). // When JSPI is used, awaited async calls are allowed to be nested, so we // proceed normally. - if (!qstdweb::haveJspi()) { - const bool simulateInfiniteLoop = true; - emscripten_set_main_loop([](){ - emscripten_pause_main_loop(); - }, 0, simulateInfiniteLoop); - } + const bool simulateInfiniteLoop = true; + emscripten_set_main_loop([](){ + emscripten_pause_main_loop(); + }, 0, simulateInfiniteLoop); } void QEventDispatcherWasm::handleDialogExec() @@ -528,15 +459,12 @@ bool QEventDispatcherWasm::wait(int timeout) if (timeout > 0) qWarning() << "QEventDispatcherWasm asyncify wait with timeout is not supported; timeout will be ignored"; // FIXME - if (useJspi()) { - qt_jspi_suspend_js(); - } else { - bool didSuspend = qt_asyncify_suspend(); - if (!didSuspend) { - qWarning("QEventDispatcherWasm: current thread is already suspended; could not asyncify wait for events"); - return false; - } + bool didSuspend = qt_asyncify_suspend(); + if (!didSuspend) { + qWarning("QEventDispatcherWasm: current thread is already suspended; could not asyncify wait for events"); + return false; } + return true; } else { qWarning("QEventLoop::WaitForMoreEvents is not supported on the main thread without asyncify"); @@ -559,21 +487,9 @@ bool QEventDispatcherWasm::wakeEventDispatcherThread() } #endif Q_ASSERT(isMainThreadEventDispatcher()); - if (useJspi()) { - -#if QT_CONFIG(thread) - return qstdweb::runTaskOnMainThread( - []() { return qt_jspi_can_resume_js() && qt_jspi_resume_js(); }, &g_proxyingQueue); -#else - return qstdweb::runTaskOnMainThread( - []() { return qt_jspi_can_resume_js() && qt_jspi_resume_js(); }); -#endif - - } else { - if (!g_is_asyncify_suspended) - return false; - runOnMainThread([]() { qt_asyncify_resume(); }); - } + if (!g_is_asyncify_suspended) + return false; + runOnMainThread([]() { qt_asyncify_resume(); }); return true; }