$30 off During Our Annual Pro Sale. View Details »

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

Takashi Kokubun
September 23, 2022

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

Rust.Tokyo 2022

Takashi Kokubun

September 23, 2022
Tweet

More Decks by Takashi Kokubun

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

  3. What’s YJIT?

    View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. View Slide

  8. How does YJIT work?

    View Slide

  9. How YJIT works
    Ruby code

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  17. Lazy Basic Block Versioning

    View Slide

  18. Lazily compile basic blocks

    View Slide

  19. 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

    View Slide

  20. Lazily compile basic blocks

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  24. 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

    View Slide

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

    View Slide

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

    View Slide

  27. Type Profiling

    View Slide

  28. Type Profiling
    getlocal a
    getlocal b
    opt_plus

    View Slide

  29. Type Profiling
    getlocal a
    getlocal b
    opt_plus

    View Slide

  30. Type Profiling
    getlocal a
    getlocal b
    jmp regenerate

    View Slide

  31. Type Profiling
    getlocal a
    getlocal b
    jmp regenerate

    View Slide

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

    View Slide

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

    View Slide

  34. Passes
    ● CodeGen -> Split -> Alloc Regs

    View Slide

  35. Passes
    ● CodeGen -> Split -> Alloc Regs

    View Slide

  36. IR

    View Slide

  37. IR
    Split

    View Slide

  38. IR
    Split
    Alloc Regs

    View Slide

  39. Rust Challenges

    View Slide

  40. Clang and Bindgen
    Clang dependency or
    Per-architecture codegen?

    View Slide

  41. Mutable Borrow

    View Slide

  42. Next steps
    ● Code GC
    ● Register allocation
    ● Method inlining

    View Slide

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

    View Slide