summaryrefslogtreecommitdiffstats
path: root/libs/wpewebkit/patches/143-JavaScriptCore-Wasm-NaN-box-f32-args-buildFrame.patch
blob: a88a9158e5f834d424f55b87eee8a5f42db72c36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
From 27e268b65cbf4498e2971ac9f51849c336ac6dce Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Wed, 23 Sep 2026 14:33:27 +0100
Subject: [PATCH] JavaScriptCore: NaN-box f32 register arguments in buildFrame

operationJSToWasmEntryWrapperBuildFrame() packs an f32 register argument
as a bare zero-extended 32-bit value. The shared trampoline then loads
the slot with loadDouble, so on an architecture that enforces NaN-boxing
for single-precision operations, such as RV64GC, the wasm body's flw/fsw
on that FPR reads the canonical NaN rather than the value passed in.

Set the upper 32 bits to all ones so the slot holds a properly NaN-boxed
single. i32 arguments keep the plain zero-extended form.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
 Source/JavaScriptCore/wasm/WasmOperations.cpp | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

--- a/Source/JavaScriptCore/wasm/WasmOperations.cpp
+++ b/Source/JavaScriptCore/wasm/WasmOperations.cpp
@@ -133,8 +133,17 @@ JSC_DEFINE_JIT_OPERATION(operationJSToWa
 
             dataLogLnIf(WasmOperationsInternal::verbose, "* Register Arg ", i, " ", dst);
 
-            if (type.isI32() || type.isF32())
+            if (type.isI32())
                 value = static_cast<uint64_t>(static_cast<uint32_t>(value));
+            else if (type.isF32()) {
+                // Pack as NaN-boxed single (high 32 = 0xFFFFFFFF) so that
+                // the shared trampoline's loadDouble into the FPR yields a
+                // properly NaN-boxed single. Otherwise on architectures
+                // that enforce NaN-boxing for single-precision ops
+                // (RV64GC), the wasm body's subsequent flw/fsw on the f-arg
+                // sees the canonical NaN instead of the actual f32 value.
+                value = static_cast<uint64_t>(static_cast<uint32_t>(value)) | 0xFFFFFFFF00000000ULL;
+            }
             *access.operator()<uint64_t>(registerSpace, dst) = value;
         }
     }