mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Make Array#min/max optimization respect refined methods
Pass in ec to vm_opt_newarray_{max,min}. Avoids having to call GET_EC inside the functions, for better performance. While here, add a test for Array#min/max being redefined to test_optimization.rb. Fixes [Bug #18180]
This commit is contained in:
parent
a55a5fc684
commit
1f5f8a187a
Notes:
git
2021-10-01 07:18:36 +09:00
Merged: https://github.com/ruby/ruby/pull/4911 Merged-By: jeremyevans <code@jeremyevans.net>
4 changed files with 51 additions and 6 deletions
|
@ -834,7 +834,7 @@ opt_newarray_max
|
||||||
// attr bool leaf = false; /* has rb_funcall() */
|
// attr bool leaf = false; /* has rb_funcall() */
|
||||||
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
|
// 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
|
DEFINE_INSN
|
||||||
|
@ -846,7 +846,7 @@ opt_newarray_min
|
||||||
// attr bool leaf = false; /* has rb_funcall() */
|
// attr bool leaf = false; /* has rb_funcall() */
|
||||||
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
|
// 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 */
|
/* super(args) # args.size => num */
|
||||||
|
|
|
@ -150,6 +150,18 @@ class TestRubyOptimization < Test::Unit::TestCase
|
||||||
assert_redefine_method('String', '-@', 'assert_nil(-"foo")')
|
assert_redefine_method('String', '-@', 'assert_nil(-"foo")')
|
||||||
end
|
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
|
def test_trace_optimized_methods
|
||||||
bug14870 = "[ruby-core:87638]"
|
bug14870 = "[ruby-core:87638]"
|
||||||
expected = [:-@, :max, :min, :+, :-, :*, :/, :%, :==, :<, :<=, :>, :>=, :<<,
|
expected = [:-@, :max, :min, :+, :-, :*, :/, :%, :==, :<, :<=, :>, :>=, :<<,
|
||||||
|
|
|
@ -2537,6 +2537,25 @@ class TestRefinement < Test::Unit::TestCase
|
||||||
assert_equal(:second, klass.new.foo)
|
assert_equal(:second, klass.new.foo)
|
||||||
end
|
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
|
class Bug17822
|
||||||
module Ext
|
module Ext
|
||||||
refine(Bug17822) do
|
refine(Bug17822) do
|
||||||
|
|
|
@ -4655,7 +4655,7 @@ vm_opt_str_freeze(VALUE str, int bop, ID id)
|
||||||
#define id_cmp idCmp
|
#define id_cmp idCmp
|
||||||
|
|
||||||
static VALUE
|
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 (BASIC_OP_UNREDEFINED_P(BOP_MAX, ARRAY_REDEFINED_OP_FLAG)) {
|
||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
|
@ -4676,12 +4676,19 @@ vm_opt_newarray_max(rb_num_t num, const VALUE *ptr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALUE ary = rb_ary_new4(num, ptr);
|
VALUE ary = rb_ary_new4(num, ptr);
|
||||||
|
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);
|
return rb_funcall(ary, idMax, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
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 (BASIC_OP_UNREDEFINED_P(BOP_MIN, ARRAY_REDEFINED_OP_FLAG)) {
|
||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
|
@ -4702,9 +4709,16 @@ vm_opt_newarray_min(rb_num_t num, const VALUE *ptr)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
VALUE ary = rb_ary_new4(num, ptr);
|
VALUE ary = rb_ary_new4(num, ptr);
|
||||||
|
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);
|
return rb_funcall(ary, idMin, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#undef id_cmp
|
#undef id_cmp
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue