diff --git a/libs/wpebackend-fdo/Makefile b/libs/wpebackend-fdo/Makefile index e196469..07a0f8b 100644 --- a/libs/wpebackend-fdo/Makefile +++ b/libs/wpebackend-fdo/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wpebackend-fdo PKG_VERSION:=1.16.1 -PKG_RELEASE:=1 +PKG_RELEASE:=5 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://wpewebkit.org/releases diff --git a/libs/wpebackend-fdo/patches/001-shm-do-not-export-stale-buffer-on-commit-without-attach.patch b/libs/wpebackend-fdo/patches/001-shm-do-not-export-stale-buffer-on-commit-without-attach.patch new file mode 100644 index 0000000..82b2d02 --- /dev/null +++ b/libs/wpebackend-fdo/patches/001-shm-do-not-export-stale-buffer-on-commit-without-attach.patch @@ -0,0 +1,74 @@ +From 38cbc2156017aaabd1a176b15dc660c820676a4c Mon Sep 17 00:00:00 2001 +From: Mirko Vogt +Date: Sat, 18 Jul 2026 21:58:31 +0000 +Subject: [PATCH] ws: do not export a stale buffer on a commit without attach + +Surface::shmBuffer (and, in the EGL implementation, also dmabufBuffer) +is set at wl_surface.attach and was never cleared: a commit without a +fresh attach - e.g. one issued only for frame-callback pacing - +re-exported the previous buffer pointer. Once the client had destroyed +that buffer after its release, the embedder received a dangling +wl_shm_buffer whose metadata reads as garbage (observed as negative +width/stride crashing cog's drm renderer copy loop). + +Consume the attached buffer state at commit and export nothing when no +buffer was attached. Apply to both ImplSHM and ImplEGL - the code is +duplicated between ws-shm.cpp and ws-egl.cpp. + +Signed-off-by: Mirko Vogt +--- + src/ws-egl.cpp | 18 ++++++++++++++---- + src/ws-shm.cpp | 15 +++++++++++++-- + 2 files changed, 27 insertions(+), 6 deletions(-) + +--- a/src/ws-egl.cpp ++++ b/src/ws-egl.cpp +@@ -102,10 +102,20 @@ void ImplEGL::surfaceCommit(Surface& sur + struct wl_resource* bufferResource = surface.bufferResource; + surface.bufferResource = nullptr; + +- if (surface.dmabufBuffer) +- surface.apiClient->exportLinuxDmabuf(surface.dmabufBuffer); +- else if (surface.shmBuffer) +- surface.apiClient->exportShmBuffer(bufferResource, surface.shmBuffer); ++ // Consume the buffer state (see ws-shm.cpp): stale dmabuf/shm pointers ++ // must never be re-exported on a commit without a fresh attach. ++ const struct linux_dmabuf_buffer* dmabufBuffer = surface.dmabufBuffer; ++ surface.dmabufBuffer = nullptr; ++ struct wl_shm_buffer* shmBuffer = surface.shmBuffer; ++ surface.shmBuffer = nullptr; ++ ++ if (!bufferResource) ++ return; ++ ++ if (dmabufBuffer) ++ surface.apiClient->exportLinuxDmabuf(dmabufBuffer); ++ else if (shmBuffer) ++ surface.apiClient->exportShmBuffer(bufferResource, shmBuffer); + else + surface.apiClient->exportBufferResource(bufferResource); + } +--- a/src/ws-shm.cpp ++++ b/src/ws-shm.cpp +@@ -47,8 +47,19 @@ void ImplSHM::surfaceCommit(Surface& sur + struct wl_resource* bufferResource = surface.bufferResource; + surface.bufferResource = nullptr; + +- if (surface.shmBuffer) +- surface.apiClient->exportShmBuffer(bufferResource, surface.shmBuffer); ++ // Consume the buffer state: it belongs to the buffer attached for THIS ++ // commit. Leaving it set would re-export a stale - and, once the client ++ // destroyed the released buffer, dangling - pointer on a commit that ++ // did not attach a new buffer (e.g. a commit issued only for ++ // frame-callback pacing), handing the embedder garbage metadata. ++ struct wl_shm_buffer* shmBuffer = surface.shmBuffer; ++ surface.shmBuffer = nullptr; ++ ++ if (!bufferResource) ++ return; ++ ++ if (shmBuffer) ++ surface.apiClient->exportShmBuffer(bufferResource, shmBuffer); + else + surface.apiClient->exportBufferResource(bufferResource); + } diff --git a/libs/wpewebkit/Makefile b/libs/wpewebkit/Makefile index 8a9b2f8..f39e70c 100644 --- a/libs/wpewebkit/Makefile +++ b/libs/wpewebkit/Makefile @@ -1,12 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wpewebkit -PKG_VERSION:=2.52.3 +PKG_VERSION:=2.52.6 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://wpewebkit.org/releases -PKG_HASH:=b51b1db1e6ee99d1771f4a358c128fde27a77984df20ee6cb59858e520662d0b +PKG_HASH:=b2bafef2751625b7fdf530f230ff0f542ff0eeba3590c3a989d931b2a55c858e PKG_MAINTAINER:=Daniel Golle PKG_LICENSE:=LGPL-2.1-or-later BSD-2-Clause diff --git a/libs/wpewebkit/patches/131-JavaScriptCore-forward-MacroAssemblerRISCV64-header.patch b/libs/wpewebkit/patches/131-JavaScriptCore-forward-MacroAssemblerRISCV64-header.patch index aab5b45..c0881b1 100644 --- a/libs/wpewebkit/patches/131-JavaScriptCore-forward-MacroAssemblerRISCV64-header.patch +++ b/libs/wpewebkit/patches/131-JavaScriptCore-forward-MacroAssemblerRISCV64-header.patch @@ -1,5 +1,8 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Golle -Subject: [PATCH] JavaScriptCore: forward MacroAssemblerRISCV64.h and friends to PrivateHeaders +Date: Sat, 9 May 2026 01:37:44 +0100 +Subject: [PATCH] JavaScriptCore: forward MacroAssemblerRISCV64.h and friends + to PrivateHeaders JSC's CMakeLists copies a curated list of assembler headers into PrivateHeaders/JavaScriptCore/ so that external consumers (WebCore, @@ -27,9 +30,15 @@ Add the three RISCV64 headers to the forwarding-headers list, matching what is already done for the other architectures. Signed-off-by: Daniel Golle +--- + Source/JavaScriptCore/CMakeLists.txt | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt +index 16110d15..b6b47d18 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt -@@ -609,7 +609,10 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEA +@@ -626,7 +626,10 @@ set(JavaScriptCore_PRIVATE_FRAMEWORK_HEADERS assembler/MacroAssemblerARMv7.h assembler/MacroAssemblerCodeRef.h assembler/MacroAssemblerHelpers.h @@ -40,3 +49,6 @@ Signed-off-by: Daniel Golle assembler/MaxFrameExtentForSlowPathCall.h assembler/OSCheck.h assembler/Printer.h +-- +2.55.0 + diff --git a/libs/wpewebkit/patches/141-JavaScriptCore-BBQJIT-gate-canTierUpToOMG.patch b/libs/wpewebkit/patches/141-JavaScriptCore-BBQJIT-gate-canTierUpToOMG.patch index 20a3469..2591781 100644 --- a/libs/wpewebkit/patches/141-JavaScriptCore-BBQJIT-gate-canTierUpToOMG.patch +++ b/libs/wpewebkit/patches/141-JavaScriptCore-BBQJIT-gate-canTierUpToOMG.patch @@ -1,6 +1,30 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 9 May 2026 01:37:44 +0100 +Subject: [PATCH] JavaScriptCore: BBQJIT: gate canTierUpToOMG on + WEBASSEMBLY_OMGJIT + +BBQJIT::canTierUpToOMG() can be reached on architectures where the +OMG/FTL tier is not compiled in at all (RISCV64 currently has no OMG +JIT). Make it return false directly when !ENABLE(WEBASSEMBLY_OMGJIT), +before touching Options::useOMGJIT() or any other OMG-only state. + +emitEntryTierUpCheck()'s non-OMG branch previously hit +RELEASE_ASSERT_NOT_REACHED() unconditionally. canTierUpToOMG() is +gated only on per-function thresholds, not on whether OMG itself is +compiled in, so it can still legitimately return true here; skip +emitting the tier-up counter check silently instead of aborting. + +Signed-off-by: Daniel Golle +--- + Source/JavaScriptCore/wasm/WasmBBQJIT.cpp | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +index 5bb5491e..a210845f 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp -@@ -735,6 +735,9 @@ BBQJIT::BBQJIT(CompilationContext& compi +@@ -747,6 +747,9 @@ BBQJIT::BBQJIT(CompilationContext& compilationContext, const TypeDefinition& sig bool BBQJIT::canTierUpToOMG() const { @@ -10,7 +34,7 @@ if (!Options::useOMGJIT()) return false; -@@ -746,6 +749,7 @@ bool BBQJIT::canTierUpToOMG() const +@@ -758,6 +761,7 @@ bool BBQJIT::canTierUpToOMG() const return false; } return true; @@ -18,7 +42,7 @@ } void BBQJIT::emitIncrementCallProfileCount(unsigned callProfileIndex) -@@ -3126,7 +3130,10 @@ void BBQJIT::emitEntryTierUpCheck() +@@ -3138,7 +3142,10 @@ void BBQJIT::emitEntryTierUpCheck() jit.jump(tierUpResume); }); #else @@ -30,3 +54,6 @@ #endif } +-- +2.55.0 + diff --git a/libs/wpewebkit/patches/146-JavaScriptCore-Wasm-BBQ-sext-i32-ccall-args-RISCV64.patch b/libs/wpewebkit/patches/146-JavaScriptCore-Wasm-BBQ-sext-i32-ccall-args-RISCV64.patch index 8f7e657..0f66e22 100644 --- a/libs/wpewebkit/patches/146-JavaScriptCore-Wasm-BBQ-sext-i32-ccall-args-RISCV64.patch +++ b/libs/wpewebkit/patches/146-JavaScriptCore-Wasm-BBQ-sext-i32-ccall-args-RISCV64.patch @@ -1,21 +1,33 @@ ---- a/Source/JavaScriptCore/wasm/WasmBBQJIT.h -+++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.h -@@ -2032,6 +2032,12 @@ public: - template - void saveValuesAcrossCallAndPassArguments(const Args& arguments, const CallInformation& callInfo, const TypeDefinition& signature); - -+ // On RISC-V the psABI requires 32-bit integer arguments to be sign-extended -+ // in their 64-bit argument registers; BBQ otherwise zero-extends them when -+ // loading from canonical i32 slots (lwu). Emit sext.w on any I32 arg that -+ // ends up in a register. No-op on other architectures. -+ void emitSignExtendI32ArgsForCCall(const CallInformation& callInfo, const TypeDefinition& signature); -+ - void slowPathSpillBindings(const RegisterBindings& bindings); - void slowPathRestoreBindings(const RegisterBindings&); - void restoreValuesAfterCall(const CallInformation& callInfo); +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Sat, 9 May 2026 01:37:44 +0100 +Subject: [PATCH] JavaScriptCore: RISCV64: sign-extend i32 ccall args in BBQJIT + +On RISC-V the lp64d psABI requires 32-bit integer arguments to be +sign-extended in their 64-bit argument registers by the caller. BBQ's +saveValuesAcrossCallAndPassArguments otherwise leaves them +zero-extended when loading from canonical i32 slots (lwu), which +callees compiled under the psABI assumption (e.g. GCC-compiled C +helpers doing a signed comparison) misread. + +Add BBQJIT::emitSignExtendI32ArgsForCCall(), which walks the call's +I32 arguments and emits sext.w (via signExtend32To64) on any that +ended up in a register; a no-op on other architectures. Call it from +both emitCCall overloads in WasmBBQJIT64.h, right after arguments are +placed and before the call is materialised. + +Signed-off-by: Daniel Golle +--- + Source/JavaScriptCore/wasm/WasmBBQJIT.cpp | 20 ++++++++++++++++++++ + Source/JavaScriptCore/wasm/WasmBBQJIT.h | 6 ++++++ + Source/JavaScriptCore/wasm/WasmBBQJIT64.h | 2 ++ + 3 files changed, 28 insertions(+) + +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +index a210845f..785792a5 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp -@@ -4286,6 +4286,26 @@ void BBQJIT::restoreValuesAfterCall(cons +@@ -4298,6 +4298,26 @@ void BBQJIT::restoreValuesAfterCall(const CallInformation& callInfo) // whenever they are next used. } @@ -42,9 +54,28 @@ template void BBQJIT::returnValuesFromCall(Vector& results, const FunctionSignature& functionType, const CallInformation& callInfo) { +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.h b/Source/JavaScriptCore/wasm/WasmBBQJIT.h +index 2e23ad7d..db872fa1 100644 +--- a/Source/JavaScriptCore/wasm/WasmBBQJIT.h ++++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.h +@@ -2034,6 +2034,12 @@ public: + template + void saveValuesAcrossCallAndPassArguments(const Args& arguments, const CallInformation& callInfo, const TypeDefinition& signature); + ++ // On RISC-V the psABI requires 32-bit integer arguments to be sign-extended ++ // in their 64-bit argument registers; BBQ otherwise zero-extends them when ++ // loading from canonical i32 slots (lwu). Emit sext.w on any I32 arg that ++ // ends up in a register. No-op on other architectures. ++ void emitSignExtendI32ArgsForCCall(const CallInformation& callInfo, const TypeDefinition& signature); ++ + void slowPathSpillBindings(const RegisterBindings& bindings); + void slowPathRestoreBindings(const RegisterBindings&); + void restoreValuesAfterCall(const CallInformation& callInfo); +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT64.h b/Source/JavaScriptCore/wasm/WasmBBQJIT64.h +index a42391b8..01ae6061 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT64.h +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT64.h -@@ -505,6 +505,7 @@ void BBQJIT::emitCCall(Func function, co +@@ -506,6 +506,7 @@ void BBQJIT::emitCCall(Func function, const Vector& arguments) // Preserve caller-saved registers and other info prepareForExceptions(); saveValuesAcrossCallAndPassArguments(arguments, callInfo, *functionType); @@ -52,7 +83,7 @@ // Materialize address of native function and call register void* taggedFunctionPtr = tagCFunctionPtr(function); -@@ -534,6 +535,7 @@ void BBQJIT::emitCCall(Func function, co +@@ -535,6 +536,7 @@ void BBQJIT::emitCCall(Func function, const Vector& arguments, Value& // Preserve caller-saved registers and other info prepareForExceptions(); saveValuesAcrossCallAndPassArguments(arguments, callInfo, *functionType); @@ -60,3 +91,6 @@ // Materialize address of native function and call register void* taggedFunctionPtr = tagCFunctionPtr(function); +-- +2.55.0 + diff --git a/libs/wpewebkit/patches/148-JavaScriptCore-RISCV64-A-extension-atomics.patch b/libs/wpewebkit/patches/148-JavaScriptCore-RISCV64-A-extension-atomics.patch index 8c39a4c..309fa9e 100644 --- a/libs/wpewebkit/patches/148-JavaScriptCore-RISCV64-A-extension-atomics.patch +++ b/libs/wpewebkit/patches/148-JavaScriptCore-RISCV64-A-extension-atomics.patch @@ -1,5 +1,8 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Golle -Subject: [PATCH] JavaScriptCore: RISCV64: wire up A-extension atomics in BBQJIT +Date: Sat, 9 May 2026 01:37:44 +0100 +Subject: [PATCH] JavaScriptCore: RISCV64: wire up A-extension atomics in + BBQJIT OpenWrt's RISC-V baseline is rv64gc/lp64d, which always includes the standard A-extension. Replace the UNIMPLEMENTED_METHOD stubs in @@ -33,46 +36,14 @@ modes on a StarFive VisionFive 2. Signed-off-by: Daniel Golle --- ---- a/Source/JavaScriptCore/assembler/RISCV64Assembler.h -+++ b/Source/JavaScriptCore/assembler/RISCV64Assembler.h -@@ -1832,6 +1832,37 @@ public: - void remwInsn(RegisterID rd, RegisterID rs1, RegisterID rs2) { insn(RISCV64Instructions::REMW::construct(rd, rs1, rs2)); } - void remuwInsn(RegisterID rd, RegisterID rs1, RegisterID rs2) { insn(RISCV64Instructions::REMUW::construct(rd, rs1, rs2)); } - -+ // RV{32,64}A standard A-extension (always present in rv64gc). -+ // For sequential consistency pass { Acquire, Release } (.aqrl). -+ void lr_wInsn(RegisterID rd, RegisterID rs1, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::LR_W::construct(rd, rs1, RegisterID::zero, aqrl)); } -+ void lr_dInsn(RegisterID rd, RegisterID rs1, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::LR_D::construct(rd, rs1, RegisterID::zero, aqrl)); } -+ void sc_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::SC_W::construct(rd, rs1, rs2, aqrl)); } -+ void sc_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::SC_D::construct(rd, rs1, rs2, aqrl)); } -+ void amoswap_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOSWAP_W::construct(rd, rs1, rs2, aqrl)); } -+ void amoswap_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOSWAP_D::construct(rd, rs1, rs2, aqrl)); } -+ void amoadd_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOADD_W::construct(rd, rs1, rs2, aqrl)); } -+ void amoadd_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOADD_D::construct(rd, rs1, rs2, aqrl)); } -+ void amoxor_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOXOR_W::construct(rd, rs1, rs2, aqrl)); } -+ void amoxor_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOXOR_D::construct(rd, rs1, rs2, aqrl)); } -+ void amoand_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOAND_W::construct(rd, rs1, rs2, aqrl)); } -+ void amoand_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOAND_D::construct(rd, rs1, rs2, aqrl)); } -+ void amoor_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOOR_W::construct(rd, rs1, rs2, aqrl)); } -+ void amoor_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) -+ { insn(RISCV64Instructions::AMOOR_D::construct(rd, rs1, rs2, aqrl)); } -+ - using FCVTType = RISCV64Instructions::FCVTType; - using FMVType = RISCV64Instructions::FMVType; - + .../assembler/MacroAssemblerRISCV64.h | 172 +++++++++++++++--- + .../assembler/RISCV64Assembler.h | 31 ++++ + Source/JavaScriptCore/wasm/WasmBBQJIT.h | 5 + + Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp | 159 +++++++++++----- + 4 files changed, 292 insertions(+), 75 deletions(-) + +diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h b/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h +index d567a76b..b6848736 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerRISCV64.h @@ -2448,55 +2448,169 @@ public: @@ -274,9 +245,53 @@ Signed-off-by: Daniel Golle // Additional SIMD vector noop stubs uncovered by enabling BBQJIT. MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorSplat); MACRO_ASSEMBLER_RISCV64_TEMPLATED_NOOP_METHOD(vectorUshl8); +diff --git a/Source/JavaScriptCore/assembler/RISCV64Assembler.h b/Source/JavaScriptCore/assembler/RISCV64Assembler.h +index 88835cfc..72c094dc 100644 +--- a/Source/JavaScriptCore/assembler/RISCV64Assembler.h ++++ b/Source/JavaScriptCore/assembler/RISCV64Assembler.h +@@ -1832,6 +1832,37 @@ public: + void remwInsn(RegisterID rd, RegisterID rs1, RegisterID rs2) { insn(RISCV64Instructions::REMW::construct(rd, rs1, rs2)); } + void remuwInsn(RegisterID rd, RegisterID rs1, RegisterID rs2) { insn(RISCV64Instructions::REMUW::construct(rd, rs1, rs2)); } + ++ // RV{32,64}A standard A-extension (always present in rv64gc). ++ // For sequential consistency pass { Acquire, Release } (.aqrl). ++ void lr_wInsn(RegisterID rd, RegisterID rs1, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::LR_W::construct(rd, rs1, RegisterID::zero, aqrl)); } ++ void lr_dInsn(RegisterID rd, RegisterID rs1, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::LR_D::construct(rd, rs1, RegisterID::zero, aqrl)); } ++ void sc_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::SC_W::construct(rd, rs1, rs2, aqrl)); } ++ void sc_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::SC_D::construct(rd, rs1, rs2, aqrl)); } ++ void amoswap_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOSWAP_W::construct(rd, rs1, rs2, aqrl)); } ++ void amoswap_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOSWAP_D::construct(rd, rs1, rs2, aqrl)); } ++ void amoadd_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOADD_W::construct(rd, rs1, rs2, aqrl)); } ++ void amoadd_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOADD_D::construct(rd, rs1, rs2, aqrl)); } ++ void amoxor_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOXOR_W::construct(rd, rs1, rs2, aqrl)); } ++ void amoxor_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOXOR_D::construct(rd, rs1, rs2, aqrl)); } ++ void amoand_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOAND_W::construct(rd, rs1, rs2, aqrl)); } ++ void amoand_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOAND_D::construct(rd, rs1, rs2, aqrl)); } ++ void amoor_wInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOOR_W::construct(rd, rs1, rs2, aqrl)); } ++ void amoor_dInsn(RegisterID rd, RegisterID rs1, RegisterID rs2, std::initializer_list aqrl) ++ { insn(RISCV64Instructions::AMOOR_D::construct(rd, rs1, rs2, aqrl)); } ++ + using FCVTType = RISCV64Instructions::FCVTType; + using FMVType = RISCV64Instructions::FMVType; + +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.h b/Source/JavaScriptCore/wasm/WasmBBQJIT.h +index db872fa1..203dc58b 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT.h +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.h -@@ -1335,6 +1335,11 @@ public: +@@ -1337,6 +1337,11 @@ public: template void emitAtomicOpGeneric(ExtAtomicOpType op, Address address, Location old, Location cur, const Functor& functor); @@ -288,9 +303,11 @@ Signed-off-by: Daniel Golle [[nodiscard]] Value emitAtomicLoadOp(ExtAtomicOpType loadOp, Type valueType, Location pointer, uint32_t uoffset); [[nodiscard]] PartialResult atomicLoad(ExtAtomicOpType loadOp, Type valueType, ExpressionType pointer, ExpressionType& result, uint32_t uoffset); +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp +index dfdefd45..b49347be 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp -@@ -540,6 +540,47 @@ void BBQJIT::emitSanitizeAtomicResult(Ex +@@ -540,6 +540,47 @@ void BBQJIT::emitSanitizeAtomicResult(ExtAtomicOpType op, TypeKind resultType, G emitSanitizeAtomicResult(op, resultType, result, result); } @@ -338,7 +355,7 @@ Signed-off-by: Daniel Golle template void BBQJIT::emitAtomicOpGeneric(ExtAtomicOpType op, Address address, GPRReg oldGPR, GPRReg scratchGPR, const Functor& functor) { -@@ -573,14 +614,14 @@ void BBQJIT::emitAtomicOpGeneric(ExtAtom +@@ -573,14 +614,14 @@ void BBQJIT::emitAtomicOpGeneric(ExtAtomicOpType op, Address address, GPRReg old #endif break; case Width32: @@ -355,7 +372,7 @@ Signed-off-by: Daniel Golle m_jit.loadLinkAcq64(address, oldGPR); #else m_jit.load64(address, oldGPR); -@@ -629,28 +670,25 @@ void BBQJIT::emitAtomicOpGeneric(ExtAtom +@@ -629,28 +670,25 @@ void BBQJIT::emitAtomicOpGeneric(ExtAtomicOpType op, Address address, GPRReg old } m_jit.branchTest32(ResultCondition::NonZero, scratchGPR).linkTo(reloopLabel, &m_jit); #elif CPU(RISCV64) @@ -389,7 +406,7 @@ Signed-off-by: Daniel Golle #endif } -@@ -671,9 +709,16 @@ void BBQJIT::emitAtomicOpGeneric(ExtAtom +@@ -671,9 +709,16 @@ void BBQJIT::emitAtomicOpGeneric(ExtAtomicOpType op, Address address, GPRReg old if (!(isARM64_LSE() || isX86_64())) { ScratchScope<1, 0> scratches(*this); @@ -408,7 +425,7 @@ Signed-off-by: Daniel Golle emitSanitizeAtomicResult(loadOp, valueType.kind, resultLocation.asGPR()); return result; } -@@ -778,9 +823,16 @@ void BBQJIT::emitAtomicStoreOp(ExtAtomic +@@ -778,9 +823,16 @@ void BBQJIT::emitAtomicStoreOp(ExtAtomicOpType storeOp, Type, Location pointer, consume(value); if (!(isARM64_LSE() || isX86_64())) { @@ -427,7 +444,7 @@ Signed-off-by: Daniel Golle return; } -@@ -1135,7 +1187,7 @@ Value BBQJIT::emitAtomicBinaryRMWOp(ExtA +@@ -1135,7 +1187,7 @@ Value BBQJIT::emitAtomicBinaryRMWOp(ExtAtomicOpType op, Type valueType, Location break; } @@ -436,7 +453,7 @@ Signed-off-by: Daniel Golle switch (op) { case ExtAtomicOpType::I32AtomicRmw16AddU: case ExtAtomicOpType::I32AtomicRmw8AddU: -@@ -1205,7 +1257,13 @@ Value BBQJIT::emitAtomicBinaryRMWOp(ExtA +@@ -1205,7 +1257,13 @@ Value BBQJIT::emitAtomicBinaryRMWOp(ExtAtomicOpType op, Type valueType, Location RELEASE_ASSERT_NOT_REACHED(); break; } @@ -451,7 +468,7 @@ Signed-off-by: Daniel Golle emitSanitizeAtomicResult(op, valueType.kind, resultLocation.asGPR()); return result; } -@@ -1285,46 +1343,55 @@ Value BBQJIT::emitAtomicBinaryRMWOp(ExtA +@@ -1285,46 +1343,55 @@ Value BBQJIT::emitAtomicBinaryRMWOp(ExtAtomicOpType op, Type valueType, Location } #if CPU(RISCV64) @@ -537,3 +554,6 @@ Signed-off-by: Daniel Golle UNUSED_PARAM(scratchGPR); return; #endif +-- +2.55.0 + diff --git a/libs/wpewebkit/patches/152-JavaScriptCore-BBQJIT-RISCV64-tail-call.patch b/libs/wpewebkit/patches/152-JavaScriptCore-BBQJIT-RISCV64-tail-call.patch index 9e2d04a..314c56f 100644 --- a/libs/wpewebkit/patches/152-JavaScriptCore-BBQJIT-RISCV64-tail-call.patch +++ b/libs/wpewebkit/patches/152-JavaScriptCore-BBQJIT-RISCV64-tail-call.patch @@ -1,4 +1,6 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Golle +Date: Sat, 9 May 2026 01:37:44 +0100 Subject: [PATCH] JavaScriptCore: BBQJIT: implement wasm tail call on RISCV64 emitTailCall (direct) and emitIndirectTailCall in WasmBBQJIT.cpp branch @@ -21,9 +23,14 @@ return_call inside try-catch. Signed-off-by: Daniel Golle --- + Source/JavaScriptCore/wasm/WasmBBQJIT.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +index 785792a5..1d635b07 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp -@@ -4381,7 +4381,7 @@ void BBQJIT::emitTailCall(FunctionSpaceI +@@ -4393,7 +4393,7 @@ void BBQJIT::emitTailCall(FunctionSpaceIndex functionIndexSpace, const TypeDefin m_jit.loadPtr(Address(MacroAssembler::framePointerRegister), callerFramePointer); resolvedArguments.append(Value::pinned(pointerType(), Location::fromStack(sizeof(Register)))); parameterLocations.append(Location::fromStack(tailCallStackOffsetFromFP + Checked(sizeof(Register)))); @@ -32,7 +39,7 @@ Signed-off-by: Daniel Golle m_jit.loadPairPtr(MacroAssembler::framePointerRegister, callerFramePointer, MacroAssembler::linkRegister); #else UNUSED_PARAM(callerFramePointer); -@@ -4652,7 +4652,7 @@ void BBQJIT::emitIndirectTailCall(const +@@ -4664,7 +4664,7 @@ void BBQJIT::emitIndirectTailCall(const char* opcode, const Value& callee, GPRRe resolvedArguments.append(Value::pinned(pointerType(), Location::fromStack(sizeof(Register)))); parameterLocations.append(Location::fromStack(tailCallStackOffsetFromFP + Checked(sizeof(Register)))); @@ -41,7 +48,7 @@ Signed-off-by: Daniel Golle auto preserved = callingConvention.argumentGPRs(); preserved.add(importableFunction, IgnoreVectors); if constexpr (isARM64E()) -@@ -4709,7 +4709,7 @@ void BBQJIT::emitIndirectTailCall(const +@@ -4721,7 +4721,7 @@ void BBQJIT::emitIndirectTailCall(const char* opcode, const Value& callee, GPRRe m_jit.loadPtr(Address(MacroAssembler::framePointerRegister, tailCallStackOffsetFromFP), wasmScratchGPR); m_jit.addPtr(TrustedImm32(tailCallStackOffsetFromFP + Checked(sizeof(Register))), MacroAssembler::framePointerRegister, MacroAssembler::stackPointerRegister); m_jit.move(wasmScratchGPR, MacroAssembler::framePointerRegister); @@ -50,3 +57,6 @@ Signed-off-by: Daniel Golle m_jit.addPtr(TrustedImm32(tailCallStackOffsetFromFP + Checked(sizeof(CallerFrameAndPC))), MacroAssembler::framePointerRegister, MacroAssembler::stackPointerRegister); m_jit.move(callerFramePointer, MacroAssembler::framePointerRegister); #else +-- +2.55.0 + diff --git a/libs/wpewebkit/patches/155-JavaScriptCore-RISCV64-import-call-i32-sext.patch b/libs/wpewebkit/patches/155-JavaScriptCore-RISCV64-import-call-i32-sext.patch index 44ba3a2..76ef109 100644 --- a/libs/wpewebkit/patches/155-JavaScriptCore-RISCV64-import-call-i32-sext.patch +++ b/libs/wpewebkit/patches/155-JavaScriptCore-RISCV64-import-call-i32-sext.patch @@ -1,25 +1,28 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Golle -Subject: [PATCH] JavaScriptCore: RISCV64: sign-extend i32 args at wasm import call sites +Date: Sat, 9 May 2026 01:37:44 +0100 +Subject: [PATCH] JavaScriptCore: RISCV64: sign-extend i32 args at wasm import + call sites The RISCV64 lp64d psABI requires that integer arguments narrower than XLEN be sign-extended into the full 64-bit argument register by the caller, and the callee is permitted to rely on this. GCC compiles the wasm builtin and JS-import host glue (e.g. -`jsstring__substring(JSGlobalObject*, JSValue, int32_t start, int32_t end)`) -under this assumption: tests like `if (start < 0)` lower to 64-bit -`bgez` against the full argument register, not a 32-bit comparison of +jsstring__substring(JSGlobalObject*, JSValue, int32_t start, int32_t end)) +under this assumption: tests like "if (start < 0)" lower to 64-bit +bgez against the full argument register, not a 32-bit comparison of its low half. BBQ's wasm-internal calling convention leaves wasm i32 values zero-extended in 64-bit GPRs (the WebKit MacroAssembler contract for -`load32` is zero-extend, matching x86_64 and ARM64 hardware). When BBQ -emits a wasm-to-import call (going through `importFunctionStub`), the +load32 is zero-extend, matching x86_64 and ARM64 hardware). When BBQ +emits a wasm-to-import call (going through importFunctionStub), the zero-extended value is forwarded directly to the host entry point, so a negative i32 such as -2 enters the C function as 0x00000000FFFFFFFE. -The 64-bit `bgez` then sees a positive number, the negative-clamp +The 64-bit bgez then sees a positive number, the negative-clamp branch is skipped, and the builtin operates on an unclamped value. -Symptom (`stress/wasm-js-string-builtins.js`): +Symptom (stress/wasm-js-string-builtins.js): let m = await WebAssembly.instantiate(/* (import "wasm:js-string" "substring") + a relay wasm function */, @@ -27,31 +30,36 @@ Symptom (`stress/wasm-js-string-builtins.js`): m.instance.exports.relay("Hello, world", -2, 2); // expected "He" // actual on RV64: "" -The relay's `local.get $start` loads -2 with `lwu` (per the MacroAsm -contract), `addCall` for the import forwards a2 unchanged, and GCC's -`bgez s3, .Lclamp_skipped` misreads it. `start` stays at -2, gets +The relay's local.get $start loads -2 with lwu (per the MacroAsm +contract), addCall for the import forwards a2 unchanged, and GCC's +bgez s3, .Lclamp_skipped misreads it. start stays at -2, gets unsigned-cast to 4294967294, then clamped down to length(12), and substring returns "" because (clamped start) > end. -Directly invoking the builtin as `instance.exports.exported(s, -2, 2)` +Directly invoking the builtin as instance.exports.exported(s, -2, 2) works because the JS-to-Wasm trampoline sign-extends the JS Number when materialising the i32 wasm arg; only the wasm-to-import path is broken. -The existing `BBQJIT::emitSignExtendI32ArgsForCCall` is already +The existing BBQJIT::emitSignExtendI32ArgsForCCall is already RV64-guarded and does this fix-up for runtime helpers invoked through -`emitCCall`. Apply it before the import-stub call in `addCall` so the +emitCCall. Apply it before the import-stub call in addCall so the same sign-extension applies to every wasm-to-host transition. -Wasm-to-wasm direct calls (the other branch of the same `if`) do not +Wasm-to-wasm direct calls (the other branch of the same if) do not need this: a wasm callee never observes the upper 32 bits of an i32 argument and the BBQ "w-form" i32 ops mask to 32 bits. Signed-off-by: Daniel Golle --- + Source/JavaScriptCore/wasm/WasmBBQJIT.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +index 1d635b07..65a2e01b 100644 --- a/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp +++ b/Source/JavaScriptCore/wasm/WasmBBQJIT.cpp -@@ -4484,6 +4484,7 @@ void BBQJIT::emitTailCall(FunctionSpaceI +@@ -4496,6 +4496,7 @@ void BBQJIT::emitTailCall(FunctionSpaceIndex functionIndexSpace, const TypeDefin if (m_info.isImportedFunctionFromFunctionIndexSpace(functionIndexSpace)) { static_assert(sizeof(WasmOrJSImportableFunctionCallLinkInfo) * maxImports < std::numeric_limits::max()); RELEASE_ASSERT(JSWebAssemblyInstance::offsetOfImportFunctionStub(functionIndexSpace) < std::numeric_limits::max()); @@ -59,3 +67,6 @@ Signed-off-by: Daniel Golle m_jit.call(Address(GPRInfo::wasmContextInstancePointer, JSWebAssemblyInstance::offsetOfImportFunctionStub(functionIndexSpace)), WasmEntryPtrTag); } else { // Record the callee so the callee knows to look for it in updateCallsitesToCallUs. +-- +2.55.0 +