Skip to content

Commit 596c5e7

Browse files
committed
ZJIT: Fold LoadField on frozen objects to constants
When accessing instance variables from frozen objects via attr_reader/ attr_accessor, fold the LoadField instruction to a constant at compile time. This enables further optimizations like constant propagation. - Add fold_getinstancevariable_frozen optimization in Function::optimize - Check if receiver type has a known ruby_object() that is frozen - Read the field value at compile time and replace with Const instruction - Add 10 unit tests covering various value types (fixnum, string, symbol, nil, true/false) and negative cases (unfrozen, dynamic receiver)
1 parent 330ddcc commit 596c5e7

2 files changed

Lines changed: 417 additions & 0 deletions

File tree

zjit/src/hir.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,6 +3682,19 @@ impl Function {
36823682
// Don't bother re-inferring the type of val; we already know it.
36833683
continue;
36843684
}
3685+
3686+
// LoadField is a common pattern for getting fields from Ruby objects, we want to fold away the pattern if the object is frozen. Cast recv to VALUE* and do an unsafe cast at compile time.
3687+
Insn::LoadField { recv, offset, return_type, .. } if return_type.is_subtype(types::BasicObject) => {
3688+
let recv = self.type_of(recv);
3689+
if let Some(recv) = recv.ruby_object() && recv.is_frozen() {
3690+
let recv = recv.as_ptr() as *const VALUE;
3691+
let val = unsafe { *recv.add(offset as usize / SIZEOF_VALUE) };
3692+
self.new_insn(Insn::Const { val: Const::Value(val) })
3693+
} else {
3694+
insn_id
3695+
}
3696+
}
3697+
36853698
Insn::AnyToString { str, .. } if self.is_a(str, types::String) => {
36863699
self.make_equal_to(insn_id, str);
36873700
// Don't bother re-inferring the type of str; we already know it.

0 commit comments

Comments
 (0)