Skip to content

Commit 678517b

Browse files
committed
YJIT: Abort expandarray optimization if method_missing is defined
1 parent 1e6079d commit 678517b

3 files changed

Lines changed: 24 additions & 0 deletions

File tree

bootstraptest/test_yjit.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,22 @@ def expandarray_redefined_nilclass
26802680
expandarray_redefined_nilclass
26812681
}
26822682

2683+
assert_equal 'not_array', %q{
2684+
def expandarray_not_array(obj)
2685+
a, = obj
2686+
a
2687+
end
2688+
2689+
obj = Object.new
2690+
def obj.method_missing(m, *args, &block)
2691+
return [:not_array] if m == :to_ary
2692+
super
2693+
end
2694+
2695+
expandarray_not_array(obj)
2696+
expandarray_not_array(obj)
2697+
}
2698+
26832699
assert_equal '[1, 2, nil]', %q{
26842700
def expandarray_rhs_too_small
26852701
a, b, c = [1, 2]

yjit/src/codegen.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,6 +2270,13 @@ fn gen_expandarray(
22702270
return None;
22712271
}
22722272

2273+
// If method_missing is overridden, the object might respond to to_ary
2274+
// so we can't assume to_ary won't be called.
2275+
if !assume_method_basic_definition(jit, asm, comptime_recv.class_of(), ID!(method_missing)) {
2276+
gen_counter_incr(jit, asm, Counter::expandarray_to_ary);
2277+
return None;
2278+
}
2279+
22732280
// invalidate compile block if to_ary is later defined
22742281
jit.assume_method_lookup_stable(asm, target_cme);
22752282

yjit/src/cruby.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,7 @@ pub(crate) mod ids {
816816
def_ids! {
817817
name: NULL content: b""
818818
name: respond_to_missing content: b"respond_to_missing?"
819+
name: method_missing content: b"method_missing"
819820
name: to_ary content: b"to_ary"
820821
name: to_s content: b"to_s"
821822
name: eq content: b"=="

0 commit comments

Comments
 (0)