diff --git a/insns.def b/insns.def index aaa8ec8f5d..1c2c074c5c 100644 --- a/insns.def +++ b/insns.def @@ -996,6 +996,7 @@ opt_nil_p (CALL_DATA cd) (VALUE recv) (VALUE val) +// attr bool zjit_profile = true; { val = vm_opt_nil_p(GET_ISEQ(), cd, recv); diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs index 10c5c7c903..dcb9cb5ce2 100644 --- a/zjit/src/cruby_bindings.inc.rs +++ b/zjit/src/cruby_bindings.inc.rs @@ -683,18 +683,19 @@ pub const YARVINSN_trace_setlocal_WC_1: ruby_vminsn_type = 219; pub const YARVINSN_trace_putobject_INT2FIX_0_: ruby_vminsn_type = 220; pub const YARVINSN_trace_putobject_INT2FIX_1_: ruby_vminsn_type = 221; pub const YARVINSN_zjit_opt_send_without_block: ruby_vminsn_type = 222; -pub const YARVINSN_zjit_opt_plus: ruby_vminsn_type = 223; -pub const YARVINSN_zjit_opt_minus: ruby_vminsn_type = 224; -pub const YARVINSN_zjit_opt_mult: ruby_vminsn_type = 225; -pub const YARVINSN_zjit_opt_div: ruby_vminsn_type = 226; -pub const YARVINSN_zjit_opt_mod: ruby_vminsn_type = 227; -pub const YARVINSN_zjit_opt_eq: ruby_vminsn_type = 228; -pub const YARVINSN_zjit_opt_neq: ruby_vminsn_type = 229; -pub const YARVINSN_zjit_opt_lt: ruby_vminsn_type = 230; -pub const YARVINSN_zjit_opt_le: ruby_vminsn_type = 231; -pub const YARVINSN_zjit_opt_gt: ruby_vminsn_type = 232; -pub const YARVINSN_zjit_opt_ge: ruby_vminsn_type = 233; -pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 234; +pub const YARVINSN_zjit_opt_nil_p: ruby_vminsn_type = 223; +pub const YARVINSN_zjit_opt_plus: ruby_vminsn_type = 224; +pub const YARVINSN_zjit_opt_minus: ruby_vminsn_type = 225; +pub const YARVINSN_zjit_opt_mult: ruby_vminsn_type = 226; +pub const YARVINSN_zjit_opt_div: ruby_vminsn_type = 227; +pub const YARVINSN_zjit_opt_mod: ruby_vminsn_type = 228; +pub const YARVINSN_zjit_opt_eq: ruby_vminsn_type = 229; +pub const YARVINSN_zjit_opt_neq: ruby_vminsn_type = 230; +pub const YARVINSN_zjit_opt_lt: ruby_vminsn_type = 231; +pub const YARVINSN_zjit_opt_le: ruby_vminsn_type = 232; +pub const YARVINSN_zjit_opt_gt: ruby_vminsn_type = 233; +pub const YARVINSN_zjit_opt_ge: ruby_vminsn_type = 234; +pub const VM_INSTRUCTION_SIZE: ruby_vminsn_type = 235; pub type ruby_vminsn_type = u32; pub type rb_iseq_callback = ::std::option::Option< unsafe extern "C" fn(arg1: *const rb_iseq_t, arg2: *mut ::std::os::raw::c_void), diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 3af2a6abf7..d11c13638a 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -1547,7 +1547,7 @@ impl Function { } else { let iseq_insn_idx = fun.frame_state(state).insn_idx; let Some(recv_type) = fun.profiled_type_of_at(self_val, iseq_insn_idx) else { return Err(()) }; - let Some(recv_class) = recv_type.exact_ruby_class() else { return Err(()) }; + let Some(recv_class) = recv_type.runtime_exact_ruby_class() else { return Err(()) }; (recv_class, Some(recv_type.unspecialized())) }; @@ -6659,4 +6659,21 @@ mod opt_tests { Return v5 "#]]); } + + #[test] + fn test_guard_nil_for_nil_opt() { + eval(" + def test(val) = val.nil? + + test(nil) + "); + assert_optimized_method_hir("test", expect![[r#" + fn test: + bb0(v0:BasicObject, v1:BasicObject): + PatchPoint MethodRedefined(NilClass@0x1000, nil?@0x1008) + v7:NilClassExact = GuardType v1, NilClassExact + v8:TrueClassExact = CCall nil?@0x1010, v7 + Return v8 + "#]]); + } } diff --git a/zjit/src/profile.rs b/zjit/src/profile.rs index 5b88b08b14..92d74053ff 100644 --- a/zjit/src/profile.rs +++ b/zjit/src/profile.rs @@ -51,6 +51,7 @@ pub extern "C" fn rb_zjit_profile_insn(opcode: ruby_vminsn_type, ec: EcPtr) { /// Profile a YARV instruction fn profile_insn(profiler: &mut Profiler, opcode: ruby_vminsn_type) { match opcode { + YARVINSN_opt_nil_p => profile_operands(profiler, 1), YARVINSN_opt_plus => profile_operands(profiler, 2), YARVINSN_opt_minus => profile_operands(profiler, 2), YARVINSN_opt_mult => profile_operands(profiler, 2),