Loading…
Our Experience Porting the YJIT Ruby Compiler to Rust
2023-10-18
- Source
- Shopify
- Published
- Added to Yomu
Summary
Shopify’s YJIT team moved the CRuby JIT compiler from C99 to Rust after finding that C’s limited complexity-management tools made the growing project difficult to maintain. The port had to preserve a non-trivial interface with CRuby, including parsing bytecode and manipulating Ruby’s primitive types, while compiling the Rust project into a static library linked through CRuby’s makefile. The team translated functions and structs largely one by one, retaining the original architecture while using Rust features such as pattern matching, macros, Cargo features, and borrow checking. Completed in three months, the port was judged more maintainable and pleasant to work with, although the team identified challenges around C interoperability, unsafe code, tooling, ecosystem maturity, and limited use of idiomatic Rust.
Context
YJIT’s growing complexity became difficult to manage in plain C. The compiler also needed to evolve toward a custom intermediate representation and eventual ARM64 support, while integrating with the large, decades-old CRuby C99 codebase through internal APIs.
Approach / What changed
The team ported YJIT from C99 to Rust through a mostly direct translation: they commented out the C implementation, then converted functions and structs one by one while preserving its general structure. They compiled the Rust project into a static library and linked it through CRuby’s build system, using Rust features such as pattern matching, macros, Cargo features, and embedded tests.
Takeaways
- A mostly direct C-to-Rust translation made the YJIT port faster and less error-prone, but initially left the code less idiomatic than a design built from scratch in Rust.
- Rust’s pattern matching, macro system, optional Cargo features, and lack of a required garbage collector were useful for YJIT, while the borrow checker and dynamic RefCell borrowing still created challenges.
- The three-month port produced code the team considered more maintainable and pleasant to work with, but C interoperability, unsafe escape hatches, cargo and bindgen issues, and ecosystem immaturity remained concerns.