Wasm Wide Arithmetic Proposal: 128-bit Operations Across All JIT Tiers
JSTests/wasm/stress/wide-arithmetic.js
This commit implements the WebAssembly wide-arithmetic proposal, adding four new instructions — i64.add128, i64.sub128, i64.mul_wide_s, i64.mul_wide_u — behind the --useWasmWideArithmetic flag. All three execution tiers (IPInt, BBQ, OMG) are supported with platform-specific lowering for x86_64 and ARM64.
Wasm i64.mul_wide_u (x86_64)
Stack: [..., lhs, rhs]
│
BBQ: consume rhs → any reg
consume lhs → rax (implicit mul source)
emit: mul rhs_reg ─► rdx:rax = lhs * rhs (unsigned)
clobber eax, edx ← explicit: between consume & allocate
allocate result_lo ← rax
allocate result_hi ← rdx
push [result_hi, result_lo] onto value stack
OMG: patchpoint with constraints:
input: rax = lhs, any = rhs
clobber: rdx
output: rax = lo, rdx = hi
Wide arithmetic is especially complex because 128-bit results don't map to a single register: add128/sub128 require carry-flag chaining (add+adc on x86_64; adds+adc on ARM64), and mul_wide uses the rdx:rax implicit output pair on x86_64, requiring eax/edx to be explicitly clobbered between the "consume" and "allocate" phases of BBQ's register allocator to avoid conflicts. A new offset parameter was added to BBQJIT::topValue() to let multi-result operations name their stack slots cleanly, which also affects the existing returnValuesFromCall path.
Significance
This is a substantial addition of new JIT code paths across every WebKit Wasm execution tier, with non-trivial register aliasing workarounds and multi-result stack slot management — exactly the kind of change where subtle bugs hide.
The explicit eax/edx clobbering workaround in BBQ's mul_wide lowering is the most delicate piece: if the clobber window is mis-ordered or the register allocator reuses those physical registers before the clobber marker, you get silent value corruption. The topValue() offset parameter change also touches returnValuesFromCall — existing multi-result call sites need verification. IPInt's carry-flag-dependent adcq/sbcq offlineasm macros must guarantee the flag state from the preceding addqs/subqs is preserved across any intervening ops.