Skip to content

Commit 7722f20

Browse files
tobiclaude
andcommitted
ZJIT: Eliminate GuardType on frozen objects
When GuardType operates on a value that is a known frozen object (from a constant), we can check at compile time if the object's type matches the guard. Since frozen objects cannot change their class, the runtime guard becomes unnecessary. This optimization eliminates redundant type guards when accessing methods on frozen constant objects, complementing the LoadField folding for ivar reads. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 4cd6661 commit 7722f20

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

zjit/src/hir.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3362,10 +3362,22 @@ impl Function {
33623362
let mut new_insns = vec![];
33633363
for insn_id in old_insns {
33643364
let replacement_id = match self.find(insn_id) {
3365-
Insn::GuardType { val, guard_type, .. } if self.is_a(val, guard_type) => {
3366-
self.make_equal_to(insn_id, val);
3367-
// Don't bother re-inferring the type of val; we already know it.
3368-
continue;
3365+
Insn::GuardType { val, guard_type, .. } => {
3366+
// If we already know the type matches, eliminate the guard
3367+
if self.is_a(val, guard_type) {
3368+
self.make_equal_to(insn_id, val);
3369+
continue;
3370+
}
3371+
// If GuardType is on a frozen object, we can check at compile time if the
3372+
// object's type matches the guard. Frozen objects can't change class.
3373+
let val_type = self.type_of(val);
3374+
if let Some(obj) = val_type.ruby_object() {
3375+
if obj.is_frozen() && Type::from_value(obj).is_subtype(guard_type) {
3376+
self.make_equal_to(insn_id, val);
3377+
continue;
3378+
}
3379+
}
3380+
insn_id
33693381
}
33703382
Insn::FixnumAdd { left, right, .. } => {
33713383
self.fold_fixnum_bop(insn_id, left, right, |l, r| match (l, r) {

0 commit comments

Comments
 (0)