diff options
Diffstat (limited to 'yjit/src')
| -rw-r--r-- | yjit/src/codegen.rs | 17 | ||||
| -rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 1 | ||||
| -rw-r--r-- | yjit/src/stats.rs | 2 |
3 files changed, 20 insertions, 0 deletions
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index f360c33bcb..75986dedb1 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -7132,6 +7132,17 @@ fn gen_send_general( assert_eq!(RUBY_T_CLASS, comptime_recv_klass.builtin_type(), "objects visible to ruby code should have a T_CLASS in their klass field"); + // Don't compile calls through singleton classes to avoid retaining the receiver. + // Make an exception for class methods since classes tend to be retained anyways. + // Also compile calls on top_self to help tests. + if VALUE(0) != unsafe { FL_TEST(comptime_recv_klass, VALUE(RUBY_FL_SINGLETON as usize)) } + && comptime_recv != unsafe { rb_vm_top_self() } + && !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_CLASS) } + && !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_MODULE) } { + gen_counter_incr(asm, Counter::send_singleton_class); + return None; + } + // Points to the receiver operand on the stack let recv = asm.stack_opnd(recv_idx); let recv_opnd: YARVOpnd = recv.into(); @@ -7887,6 +7898,12 @@ fn gen_invokesuper_specialized( return None; } + // Don't compile `super` on objects with singleton class to avoid retaining the receiver. + if VALUE(0) != unsafe { FL_TEST(comptime_recv.class_of(), VALUE(RUBY_FL_SINGLETON as usize)) } { + gen_counter_incr(asm, Counter::invokesuper_singleton_class); + return None; + } + // Do method lookup let cme = unsafe { rb_callable_method_entry(comptime_superclass, mid) }; if cme.is_null() { diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index 4b49ab3ed0..394c6d013c 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -956,6 +956,7 @@ extern "C" { n: ::std::os::raw::c_long, elts: *const VALUE, ) -> VALUE; + pub fn rb_vm_top_self() -> VALUE; pub static mut rb_vm_insns_count: u64; pub fn rb_method_entry_at(obj: VALUE, id: ID) -> *const rb_method_entry_t; pub fn rb_callable_method_entry(klass: VALUE, id: ID) -> *const rb_callable_method_entry_t; diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index ac247d2fa8..dcaa9af2b5 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -300,6 +300,7 @@ make_counters! { // Method calls that fallback to dynamic dispatch send_keywords, send_kw_splat, + send_singleton_class, send_args_splat_super, send_iseq_zsuper, send_block_arg, @@ -380,6 +381,7 @@ make_counters! { invokesuper_no_me, invokesuper_not_iseq_or_cfunc, invokesuper_refinement, + invokesuper_singleton_class, invokeblock_megamorphic, invokeblock_none, |
