← All issues

JSC B3 Wasm GC array opcodes

fe410e6

Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp

+ B3::Value* WasmOMGIRGenerator::emitGetArraySizeWithNullCheck(...) {
+ // WasmArrayLength 노드를 명시적으로 생성 — bounds check를 WasmArrayGet/Set과
+ // 분리하여 이후 range analysis에서 제거할 수 있도록 합니다.
+ auto* len = m_currentBlock->appendNew<B3::WasmArrayLengthValue>(
+ m_proc, origin(), array);
+ ...
+ }
+
+ PartialResult WasmOMGIRGenerator::addArrayGet(...) {
+ // bounds check는 별도의 WasmArrayLength 노드로 처리 — get의 operand에 포함시키지 않음.
+ auto* len = emitGetArraySizeWithNullCheck(...);
+ m_currentBlock->appendNew<B3::WasmArrayGetValue>(
+ m_proc, origin(), array, index, ...);
+ ...
+ }

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)

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를 좌우하는 핵심이 됩니다.

🔒

New JIT opcodes for GC array ops with separated bounds-check nodes — several correctness edges in the lowering and aliasing logic are worth auditing.

더 확인하려면 구독해 주세요