diff --git a/insns.def b/insns.def index cf09809ba1..43690be52e 100644 --- a/insns.def +++ b/insns.def @@ -834,7 +834,7 @@ opt_newarray_max // attr bool leaf = false; /* has rb_funcall() */ // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; { - val = vm_opt_newarray_max(num, STACK_ADDR_FROM_TOP(num)); + val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num)); } DEFINE_INSN @@ -846,7 +846,7 @@ opt_newarray_min // attr bool leaf = false; /* has rb_funcall() */ // attr rb_snum_t sp_inc = 1 - (rb_snum_t)num; { - val = vm_opt_newarray_min(num, STACK_ADDR_FROM_TOP(num)); + val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num)); } /* super(args) # args.size => num */ diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index 2075bf3513..cbae6d5e8c 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -150,6 +150,18 @@ class TestRubyOptimization < Test::Unit::TestCase assert_redefine_method('String', '-@', 'assert_nil(-"foo")') end + def test_array_min + assert_equal 1, [1, 2, 4].min + assert_redefine_method('Array', 'min', 'assert_nil([1, 2, 4].min)') + assert_redefine_method('Array', 'min', 'assert_nil([1 + 0, 2, 4].min)') + end + + def test_array_max + assert_equal 4, [1, 2, 4].max + assert_redefine_method('Array', 'max', 'assert_nil([1, 2, 4].max)') + assert_redefine_method('Array', 'max', 'assert_nil([1 + 0, 2, 4].max)') + end + def test_trace_optimized_methods bug14870 = "[ruby-core:87638]" expected = [:-@, :max, :min, :+, :-, :*, :/, :%, :==, :<, :<=, :>, :>=, :<<, diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index a623432cf1..96baab03ee 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -2537,6 +2537,25 @@ class TestRefinement < Test::Unit::TestCase assert_equal(:second, klass.new.foo) end + class Bug18180 + module M + refine Array do + def min; :min; end + def max; :max; end + end + end + + using M + + def t + [[1+0, 2, 4].min, [1, 2, 4].min, [1+0, 2, 4].max, [1, 2, 4].max] + end + end + + def test_refine_array_min_max + assert_equal([:min, :min, :max, :max], Bug18180.new.t) + end + class Bug17822 module Ext refine(Bug17822) do diff --git a/vm_insnhelper.c b/vm_insnhelper.c index bbb62d8397..d4740ecc4e 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -4655,7 +4655,7 @@ vm_opt_str_freeze(VALUE str, int bop, ID id) #define id_cmp idCmp static VALUE -vm_opt_newarray_max(rb_num_t num, const VALUE *ptr) +vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr) { if (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) { if (num == 0) { @@ -4676,12 +4676,19 @@ vm_opt_newarray_max(rb_num_t num, const VALUE *ptr) } else { VALUE ary = rb_ary_new4(num, ptr); - return rb_funcall(ary, idMax, 0); + const rb_callable_method_entry_t *me = + rb_callable_method_entry_with_refinements(rb_cArray, idMax, NULL); + if (me) { + return rb_vm_call0(ec, ary, idMax, 0, NULL, me, RB_NO_KEYWORDS); + } + else { + return rb_funcall(ary, idMax, 0); + } } } static VALUE -vm_opt_newarray_min(rb_num_t num, const VALUE *ptr) +vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr) { if (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) { if (num == 0) { @@ -4702,7 +4709,14 @@ vm_opt_newarray_min(rb_num_t num, const VALUE *ptr) } else { VALUE ary = rb_ary_new4(num, ptr); - return rb_funcall(ary, idMin, 0); + const rb_callable_method_entry_t *me = + rb_callable_method_entry_with_refinements(rb_cArray, idMin, NULL); + if (me) { + return rb_vm_call0(ec, ary, idMin, 0, NULL, me, RB_NO_KEYWORDS); + } + else { + return rb_funcall(ary, idMin, 0); + } } }