JSC B3 Wasm GC array opcodes
Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
WebKit의 OMG(Optimizing Multi-tiered JIT)는 type이 지정된 SSA 중간 표현인 B3를 사용해 hot WebAssembly 함수를 컴파일합니다. B3는 machine code로 낮추기 전에 CSE(common subexpression elimination), range analysis, strength reduction pass를 수행합니다. 이 commit 이전에는 Wasm GC array 연산 — array.get, array.set, array.new, array.len — 이 IR 생성 단계에서 즉시 raw memory load/store로 낮춰졌습니다. 그 결과 optimizer가 활용할 수 있는 의미 정보가 사라졌습니다.
이 commit은 WasmArrayGet, WasmArraySet, WasmArrayNew, WasmArrayLength 네 가지 새로운 B3 opcode를 추가합니다. 이 opcode들은 optimization pipeline 전체에 걸쳐 array 수준의 의미를 보존합니다. bounds check는 access 연산에 포함시키지 않고 별도의 WasmArrayLength 노드로 표현합니다. 덕분에 CSE는 불필요한 length load를 제거할 수 있고, 향후 range analysis는 bounds check 자체가 불필요함을 증명할 수 있게 됩니다.
WasmArrayNew는 type 정보를 담고 있어, 배열이 allocation에서 비롯된 경우(null을 반환할 수 없음) B3가 WasmArrayLength의 null-trap check를 제거할 수 있습니다. 한편 AbstractHeapRepository는 로컬 구조에서 B3::Procedure로 이동되었습니다. 이를 통해 모든 pass에서 alias 정보가 일관성을 유지합니다. 최종적으로 concrete memory 연산으로의 lowering은 B3LowerMacros에서 수행됩니다.
Before (immediate lowering):
OMGIRGenerator B3 pipeline
array.get ──► Load(base+off) ──► CSE (sees raw Load, can't alias)
array.len ──► Load(arr+lenOff) ──► (bounds check inlined, opaque)
After (high-level opcodes preserved):
OMGIRGenerator B3 pipeline
array.get ──► WasmArrayGet ──► CSE (understands array identity)
array.len ──► WasmArrayLength ──► de-trap: if fed by WasmArrayNew, null check removed
──► future range analysis: eliminate redundant length checks
array.new ──► WasmArrayNew ──► proves result non-null; size foldable
──► B3LowerMacros (final lowering to Load/Store)
Significance
OMG 티어가 루프에 걸쳐 불필요한 array length load를 제거하고, 방금 할당된 배열에 대한 bounds check가 불필요함을 증명할 수 있게 되었습니다. tight loop에서 배열을 집중적으로 다루는 Wasm GC workload에 의미 있는 최적화입니다. 이 방식은 JSC의 DFG/FTL 티어가 JavaScript array 연산을 처리하는 접근과 동일합니다. 최적화 과정 내내 고수준 의미를 유지한 뒤 마지막에 lowering하는 전략입니다. packed type(array.get_s/array.get_u를 통한 i8/i16)이 지원된 만큼, lowering 경로에서의 sign extension 정확성이 type safety를 좌우하는 핵심이 됩니다.