← All reports

[JSC] Add DFG / FTL intrinsic for `%TypedArray%.prototype.set`

Component: JSC JIT | a1e5cdc

%TypedArray%.prototype.set은 원래 C++ host function으로 실행됩니다. 이 함수는 receiver를 검증하고 offset을 변환한 뒤, source가 target 범위 안에 들어가는지 확인합니다. 이어서 영역이 겹치거나 type이 다른 source를 처리하고, 마지막으로 복사를 수행합니다. 한편 DFG와 FTL은 이런 builtin을 intrinsic으로 대체할 수 있습니다. Intrinsic은 일반적인 경우를 가정해 speculation을 수행하고, 가정이 틀리면 OSR exit로 빠져나옵니다. 이때 정확성은 clobberize(reads/writes), doesGC, 그리고 생성된 코드가 어떤 runtime 조건을 다시 검사하는지에 달려 있습니다. 문제는 typed array의 length가 변경 가능한 상태라는 점입니다. Buffer는 transfer로 detach될 수도 있고, resize될 수도 있습니다.

이번 patch로 TypedArraySet node가 추가되었습니다. 이 node는 먼저 두 array의 typed-array type이 같은지, 어느 쪽도 resizable이나 detached 상태가 아닌지, 복사 범위가 target 안에 들어가는지를 speculate합니다. 조건이 모두 맞으면 memmove만 수행하는 operation을 호출합니다. 반대로 speculation이 실패하면 OSR exit가 발생하고, 해당 호출 지점에서는 intrinsic이 비활성화됩니다. 변경 범위는 bytecode parser, abstract interpreter, clobberize, doesGC, fixup, safeToExecute, SpeculativeJIT, FTL lowering에 걸쳐 있습니다.

call site ─► TypedArraySet node
               ├─ check same TypedArrayType
               ├─ check !resizable, !detached
               ├─ check offset+len <= target len
               ├─ ok   ─► operation: memmove only
               └─ fail ─► OSR exit (intrinsic disabled at site)

작은 크기의 복사에서는 host call과 인자 검증 overhead가 비용의 대부분을 차지했습니다. 이번 변경으로 typed-array-set-small은 3.3배, typed-array-set-concat은 4.1배 개선되었습니다. Typed array storage로 raw memmove를 수행하기 위한 bounds, detach, resize 검사가 이제 compiler가 생성한 코드 안에서 이루어집니다.