mirror of
https://github.com/ruby/ruby.git
synced 2026-01-27 04:24:23 +00:00
YJIT: Abort expandarray optimization if method_missing is defined
Fixes: [Bug #21707] [AW: rewrote comments] Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
This commit is contained in:
parent
c42c6c27c3
commit
5f55c9c8fb
Notes:
git
2025-11-26 20:56:55 +00:00
@ -2680,6 +2680,22 @@ assert_equal '[1, 2]', %q{
|
||||
expandarray_redefined_nilclass
|
||||
}
|
||||
|
||||
assert_equal 'not_array', %q{
|
||||
def expandarray_not_array(obj)
|
||||
a, = obj
|
||||
a
|
||||
end
|
||||
|
||||
obj = Object.new
|
||||
def obj.method_missing(m, *args, &block)
|
||||
return [:not_array] if m == :to_ary
|
||||
super
|
||||
end
|
||||
|
||||
expandarray_not_array(obj)
|
||||
expandarray_not_array(obj)
|
||||
}
|
||||
|
||||
assert_equal '[1, 2, nil]', %q{
|
||||
def expandarray_rhs_too_small
|
||||
a, b, c = [1, 2]
|
||||
|
||||
@ -2258,7 +2258,8 @@ fn gen_expandarray(
|
||||
|
||||
let comptime_recv = jit.peek_at_stack(&asm.ctx, 0);
|
||||
|
||||
// If the comptime receiver is not an array
|
||||
// If the comptime receiver is not an array, speculate for when the `rb_check_array_type()`
|
||||
// conversion returns nil and without side-effects (e.g. arbitrary method calls).
|
||||
if !unsafe { RB_TYPE_P(comptime_recv, RUBY_T_ARRAY) } {
|
||||
// at compile time, ensure to_ary is not defined
|
||||
let target_cme = unsafe { rb_callable_method_entry_or_negative(comptime_recv.class_of(), ID!(to_ary)) };
|
||||
@ -2270,6 +2271,13 @@ fn gen_expandarray(
|
||||
return None;
|
||||
}
|
||||
|
||||
// Bail when method_missing is defined to avoid generating code to call it.
|
||||
// Also, for simplicity, bail when BasicObject#method_missing has been removed.
|
||||
if !assume_method_basic_definition(jit, asm, comptime_recv.class_of(), ID!(method_missing)) {
|
||||
gen_counter_incr(jit, asm, Counter::expandarray_method_missing);
|
||||
return None;
|
||||
}
|
||||
|
||||
// invalidate compile block if to_ary is later defined
|
||||
jit.assume_method_lookup_stable(asm, target_cme);
|
||||
|
||||
|
||||
@ -816,6 +816,7 @@ pub(crate) mod ids {
|
||||
def_ids! {
|
||||
name: NULL content: b""
|
||||
name: respond_to_missing content: b"respond_to_missing?"
|
||||
name: method_missing content: b"method_missing"
|
||||
name: to_ary content: b"to_ary"
|
||||
name: to_s content: b"to_s"
|
||||
name: eq content: b"=="
|
||||
|
||||
@ -496,6 +496,7 @@ make_counters! {
|
||||
expandarray_postarg,
|
||||
expandarray_not_array,
|
||||
expandarray_to_ary,
|
||||
expandarray_method_missing,
|
||||
expandarray_chain_max_depth,
|
||||
|
||||
// getblockparam
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user