Slide 1

Slide 1 text

YJIT: Dive into Ruby's JIT compiler written in Rust @k0kubun / Rust.Tokyo 2022

Slide 2

Slide 2 text

Me ● @k0kubun ● Shopify ○ YJIT team ● Ruby committer ○ MJIT maintainer

Slide 3

Slide 3 text

What’s YJIT?

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

How does YJIT work?

Slide 9

Slide 9 text

How YJIT works Ruby code

Slide 10

Slide 10 text

How YJIT works 1 + 2 Parse Ruby code Abstract Syntax Tree

Slide 11

Slide 11 text

How YJIT works 1 + 2 Parse Ruby code Abstract Syntax Tree putobject 1 putobject 2 opt_plus leave Compile Bytecode

Slide 12

Slide 12 text

How YJIT works 1 + 2 Parse Ruby code Abstract Syntax Tree putobject 1 putobject 2 opt_plus leave Compile JIT Bytecode Machine code

Slide 13

Slide 13 text

How YJIT works putobject 1 putobject 2 opt_plus leave JIT ? Machine code Bytecode

Slide 14

Slide 14 text

How YJIT works: Ruby 3.1 putobject 1 putobject 2 opt_plus leave x86_64 Codegen Machine code Bytecode

Slide 15

Slide 15 text

How YJIT works: Ruby 3.2 putobject 1 putobject 2 opt_plus leave Machine code Bytecode

Slide 16

Slide 16 text

How YJIT works: Ruby 3.2 putobject 1 putobject 2 opt_plus leave Machine code Bytecode

Slide 17

Slide 17 text

Lazy Basic Block Versioning

Slide 18

Slide 18 text

Lazily compile basic blocks

Slide 19

Slide 19 text

getlocal a getlocal b opt_plus setlocal c getlocal c putobject 1 opt_gt branchunless getlocal a leave getlocal b leave Lazily compile basic blocks

Slide 20

Slide 20 text

Lazily compile basic blocks

Slide 21

Slide 21 text

getlocal a getlocal b opt_plus setlocal c getlocal c putobject 1 opt_gt branchunless Branch stub Branch stub Lazily compile basic blocks

Slide 22

Slide 22 text

getlocal a getlocal b opt_plus setlocal c getlocal c putobject 1 opt_gt branchunless getlocal a leave Branch stub Lazily compile basic blocks

Slide 23

Slide 23 text

getlocal a getlocal b opt_plus setlocal c getlocal c putobject 1 opt_gt branchunless getlocal a leave Branch stub Lazily compile basic blocks

Slide 24

Slide 24 text

getlocal a getlocal b opt_plus setlocal c getlocal c putobject 1 opt_gt branchunless getlocal a leave getlocal b leave Lazily compile basic blocks

Slide 25

Slide 25 text

Why lazy compilation? 1. Better code locality a. Only compile used paths b. Related code is put together

Slide 26

Slide 26 text

Why lazy compilation? 1. Better code locality a. Only compile used paths b. Related code is put together 2. More type information

Slide 27

Slide 27 text

Type Profiling

Slide 28

Slide 28 text

Type Profiling getlocal a getlocal b opt_plus

Slide 29

Slide 29 text

Type Profiling getlocal a getlocal b opt_plus

Slide 30

Slide 30 text

Type Profiling getlocal a getlocal b jmp regenerate

Slide 31

Slide 31 text

Type Profiling getlocal a getlocal b jmp regenerate

Slide 32

Slide 32 text

Type Profiling getlocal a getlocal b jmp regenerate a: 1 b: 2

Slide 33

Slide 33 text

Type Profiling getlocal a getlocal b opt_plus (int) setlocal c getlocal c putobject 1 opt_gt branchunless

Slide 34

Slide 34 text

Passes ● CodeGen -> Split -> Alloc Regs

Slide 35

Slide 35 text

Passes ● CodeGen -> Split -> Alloc Regs

Slide 36

Slide 36 text

IR

Slide 37

Slide 37 text

IR Split

Slide 38

Slide 38 text

IR Split Alloc Regs

Slide 39

Slide 39 text

Rust Challenges

Slide 40

Slide 40 text

Clang and Bindgen Clang dependency or Per-architecture codegen?

Slide 41

Slide 41 text

Mutable Borrow

Slide 42

Slide 42 text

Next steps ● Code GC ● Register allocation ● Method inlining

Slide 43

Slide 43 text

Conclusion ● We reviewed the architecture of YJIT ● Rust has been useful for transforming IR