Search papers, labs, and topics across Lattice.
This paper introduces ZJIT, a new method-based just-in-time (JIT) compiler for Ruby that enhances optimization capabilities beyond those of the existing YJIT. By lifting local variables into static single assignment (SSA) form, ZJIT addresses the challenges of compiling Ruby's local variables more efficiently than previous compilers, which typically rely on memory loads and stores. The results show that ZJIT can implement advanced optimizations, paving the way for improved performance and encouraging further contributions to Ruby's compilation ecosystem.
ZJIT revolutionizes Ruby compilation by lifting local variables into SSA form, enabling advanced optimizations that previous JIT compilers couldn't achieve.
Ruby is a dynamically typed and object-oriented programming language. Its primary implementation, CRuby, contains a bytecode virtual machine and a mature lazy basic block versioning (LBBV) just-in-time (JIT) compiler called YJIT. In order to both implement more advanced optimizations than YJIT supports and also encourage more outside contributions, we present a new method-based JIT called ZJIT. Like YJIT, ZJIT compiles from bytecode to machine code. Unlike YJIT, ZJIT has multiple global and local optimization passes. ZJIT's high-level intermediate representation is in static single assignment (SSA) form. In order to optimize Ruby's local variables, ZJIT lifts local variables into SSA values. This is a departure from how other Ruby compilers handle locals: other JIT compilers either leave local variables as memory loads and stores or do advanced partial evaluation to recover SSA values from memory. While implementing locals, we (re-)discovered what features make local variables in Ruby especially challenging to compile correctly and efficiently. We demonstrate these features and illustrate how we solved these problems in ZJIT.