Skip to content

Commit 428edf1

Browse files
committed
ZJIT: Avoid NoSingletonClass patchpoint when already a singleton class
The true purpose of assume_no_singleton_classes() is to retain soundness in event of the effective class of values changing. When the effective class is already a singleton class that can never happen. (Except due to IO#reopen, but that's out of scope for now.) This deletes the patchpoint for calls on `main` that happens a lot in tests.
1 parent 5001c19 commit 428edf1

4 files changed

Lines changed: 170 additions & 221 deletions

File tree

zjit/src/cruby.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,11 @@ impl VALUE {
492492
}
493493
}
494494

495+
pub fn is_singleton_class(self) -> bool {
496+
// TODO(alan): clean up one of double check on T_CLASS
497+
unsafe { RB_TYPE_P(self, RUBY_T_CLASS) && rb_zjit_singleton_class_p(self) }
498+
}
499+
495500
/// Return true for a static (non-heap) Ruby symbol (RB_STATIC_SYM_P)
496501
pub fn static_sym_p(self) -> bool {
497502
let VALUE(cval) = self;

zjit/src/hir.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,6 +2511,11 @@ impl Function {
25112511
// This class can never have a singleton class, so no patchpoint needed.
25122512
return true;
25132513
}
2514+
if klass.is_singleton_class() {
2515+
// When a value has a singleton class, its effective class can't change anymore.
2516+
// No patchpoint needed.
2517+
return true;
2518+
}
25142519
if has_singleton_class_of(klass) {
25152520
// We've seen a singleton class for this klass. Disable the optimization
25162521
// to avoid an invalidation loop.

0 commit comments

Comments
 (0)