← All issues

Wasm multimemory support for base instructions

4ac3b92

Source/JavaScriptCore/wasm/WasmFunctionParser.h

template<> auto FunctionParser<Context>::load(LoadOpType op) -> PartialResult
{
+ uint32_t memoryIndex;
+ WASM_PARSER_FAIL_IF(!parseVarUInt32(memoryIndex), "can't get memory index");
+ WASM_PARSER_FAIL_IF(memoryIndex >= m_info.memoryCount(), "load: illegal memory index ", memoryIndex);
uint32_t alignment;
WASM_PARSER_FAIL_IF(!parseVarUInt32(alignment), "can't get load alignment");
uint32_t offset;
WASM_PARSER_FAIL_IF(!parseVarUInt32(offset), "can't get load offset");
Value value;
- WASM_TRY_ADD_TO_CONTEXT(load(op, alignment, offset, value));
+ WASM_TRY_ADD_TO_CONTEXT(load(op, memoryIndex, alignment, offset, value));

Source/JavaScriptCore/wasm/WasmBBQJIT64.h

template <typename Func>
auto emitCheckAndPrepareAndMaterializePointerApply(Value pointer, uint32_t memoryIndex, uint32_t uoffset, Func&& func)
{
+ if (memoryIndex) {
+ // non-zero memory: instance memory table에서 base와 size 조회
+ loadWebAssemblyGlobalState(/* memoryIndex */ memoryIndex);
+ }
// ... 로드된 base/size를 사용하여 bounds check 수행
}

WebAssembly multimemory 제안(phase 4)은 하나의 모듈 안에서 여러 개의 독립적인 linear memory 영역을 선언할 수 있도록 허용하는 스펙입니다. Load/store와 bulk memory instruction은 각각 bytecode 안에 memory index immediate를 인코딩합니다. 이번 변경 이전에는 WebKit이 해당 immediate를 예약된 zero byte로 처리하고, non-zero 값은 거부하는 방식으로 동작했습니다.

이 commit은 세 가지 Wasm 실행 tier 전반에 multimemory 지원을 추가합니다. 대상은 BBQ(baseline JIT), OMG(optimizing JIT), IPInt(interpreter)입니다. Function parser는 이제 모든 load/store와 bulk memory instruction에서 memory index를 읽어들입니다. 각 tier는 memory 0에 대해 기존 동작을 유지하는 fast path로, non-zero index에 대해서는 instance의 memory table에서 base와 bounds를 조회하는 새로운 slow path로 분기합니다.

Instruction stream:  i32.load  memidx=N  offset  ...
                                  │
                          FunctionParser::load()
                                  │
                    ┌─────────────┴─────────────┐
                 memidx==0                   memidx!=0
                 (fast path)               (slow path)
                    │                           │
             use cached                 fetch memories[N].base
             base/size regs            fetch memories[N].boundsSize
                    │                           │
                    └──────────┬────────────────┘
                       emitCheckAndPreparePointer()
                               │
                          bounds check + deref

이번 변경으로 attack surface가 크게 확장됩니다. 모든 Wasm tier에서 각 memory access instruction마다 파싱된 memory index에 의해 제어되는 새로운 code path가 추가됩니다. 또한 memory.fill, memory.copy, memory.init 같은 bulk memory operation이 이제 서로 다른 linear memory 영역에 걸쳐 동작할 수 있습니다.

기존에는 유효하지 않던 module bytecode(non-zero memory index)가 이제 유효한 입력으로 처리됩니다. 이에 따라 오류 메시지도 "auxiliary byte should be zero"에서 "illegal memory index"로 변경되었으며, 이는 semantic 변화를 반영한 결과입니다. Cross-memory memory.copy 경로는 완전히 새로운 로직으로, source와 destination이 각기 다른 크기의 memory를 참조하는 상황을 처리합니다.

🔒

New memory index dispatch across every access path in three JIT tiers — several edge cases in bounds checking and bulk operations are worth close investigation.

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