The article explores how optimizing compilers track instruction side effects to enable optimizations like dead code elimination and instruction reordering. It examines two main approaches: Cinder's bitset-based representation and JavaScriptCore's hierarchical abstract heap system. These effect tracking systems help compilers determine when operations can be safely reordered or eliminated.
bernsteinbear-com
11 items from bernsteinbear-com
YJIT and ZJIT support Linux perf and samply profiling through the perf map interface. JITed code can be annotated by writing function entries to /tmp/perf-{PID}.map files. This allows JIT frames to be named in profiling output when using the --zjit-perf flag.
ZJIT, a new just-in-time compiler for Ruby, is now available in Ruby 4.0 but not enabled by default. It is faster than the interpreter but not yet as fast as YJIT, and the developers advise testing it locally before production use.
The blog post explains load and store forwarding in the Toy Optimizer, a technique that eliminates redundant loads by modeling the heap at compile-time. It demonstrates how to cache load results and invalidate them appropriately when stores occur, using abstract interpretation over traces.
GDB's JIT interface allows debugging JIT-compiled code by registering debug information. The traditional method requires generating in-memory ELF/Mach-O objects, while a newer custom interface uses specialized readers. Many projects implement these interfaces to enable proper debugging of JIT code.
The ZJIT compiler for Ruby faces a design challenge with multiple entrypoints in control-flow graphs due to Ruby's handling of default positional parameters. The article explores three approaches to address this conundrum, ultimately concluding with implementing a superblock approach.
The article describes implementing type-based alias analysis (TBAA) in the Toy Optimizer. It explains using hierarchical heap effect representation with integer ranges to model type relationships and check for aliasing through range overlap queries. This improves alias analysis by leveraging compile-time type information.
The author describes creating a fuzzer for the Toy Optimizer to automatically detect correctness bugs. The fuzzer generates random programs, verifies them against an unoptimized version, and tests the optimizer's output. It successfully catches bugs when key correctness components are disabled.
The article explains how the ZJIT team uses Perfetto tracing to visualize and analyze side-exits in Ruby's just-in-time compiler. It demonstrates how Perfetto helps identify performance bottlenecks by showing exit reasons and stack traces, with examples from Rails benchmarks. The implementation details include using Fuchsia trace format for efficiency and sampling to manage trace size.
Value numbering is a compiler optimization technique that identifies instructions known at compile-time to always produce the same value at run-time. It extends beyond static single assignment (SSA) form by enabling reuse of identical computations through hashing and mapping approaches.
The author apologized for marking all posts as unread after fixing URL formatting issues with double slashes. This RSS-only post explains the technical change that caused RSS readers to refresh content unexpectedly.