Wasm Wide Arithmetic Proposal: 128-bit Operations Across All JIT Tiers
JSTests/wasm/stress/wide-arithmetic.js
이 commit은 WebAssembly wide-arithmetic proposal을 구현한 것으로, i64.add128, i64.sub128, i64.mul_wide_s, i64.mul_wide_u 네 가지 새로운 명령어를 --useWasmWideArithmetic 플래그 하에 추가합니다. IPInt, BBQ, OMG 세 실행 tier 모두를 지원하며, x86_64와 ARM64 각각에 대해 플랫폼별 lowering이 구현되었습니다.
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
128-bit 결과는 단일 레지스터에 담을 수 없기 때문에, wide arithmetic은 구현 난도가 높습니다. add128/sub128은 carry-flag chaining을 필요로 하고(x86_64에서는 add+adc, ARM64에서는 adds+adc), mul_wide는 x86_64의 rdx:rax implicit output 쌍을 사용합니다. 이때 BBQ register allocator의 "consume" 단계와 "allocate" 단계 사이에 eax/edx를 명시적으로 clobber해야 충돌을 방지할 수 있습니다. 또한 multi-result 연산이 stack slot을 명확하게 지정할 수 있도록 BBQJIT::topValue()에 새로운 offset 파라미터가 추가되었으며, 이 변경은 기존 returnValuesFromCall 경로에도 영향을 미칩니다.
Significance
WebKit Wasm의 모든 실행 tier에 걸쳐 새로운 JIT code path가 대규모로 추가되었습니다. 복잡한 register aliasing 처리와 multi-result stack slot 관리가 맞물려 있어, 미묘한 버그가 숨어들기 쉬운 변경입니다.
가장 섬세한 부분은 BBQ의 mul_wide lowering에서 eax/edx를 명시적으로 clobber하는 처리입니다. clobber window의 순서가 어긋나거나, clobber 마커 이전에 register allocator가 해당 물리 레지스터를 재사용하면 값이 조용히 오염됩니다. 한편 topValue()의 offset 파라미터 변경은 returnValuesFromCall에도 영향을 주므로, 기존 multi-result call site에 대한 검증이 필요합니다. IPInt의 carry-flag 의존 offlineasm 매크로인 adcq/sbcq는 직전 addqs/subqs가 설정한 flag 상태가 중간에 개입하는 연산 없이 보존되는지도 확인해야 합니다.