summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYusuke Endoh <mame@ruby-lang.org>2019-06-01 13:15:43 +0900
committerYusuke Endoh <mame@ruby-lang.org>2019-06-01 13:15:43 +0900
commit65e63af377bb493dea4d0207627ed87d5da360a8 (patch)
tree06871344ac6e5800a9c06387d52f2ce942c04609
parent7df65ef67691fcc354d819da9cd54a1ade9b6247 (diff)
Make opt_aref instruction support Integer#[]
only when its receiver and the argument are both Integers. Since 6bedbf4625, Integer#[] has supported a range extraction. This means that Integer#[] now accepts multiple arguments, which made the method very slow unfortunately. This change fixes the performance issue by adding a special handling for its traditional use case: `num[idx]` where both `num` and `idx` are Integers.
-rw-r--r--internal.h1
-rw-r--r--numeric.c6
-rw-r--r--vm.c2
-rw-r--r--vm_insnhelper.c4
4 files changed, 9 insertions, 4 deletions
diff --git a/internal.h b/internal.h
index 4312f8d442..b1e6aec0dd 100644
--- a/internal.h
+++ b/internal.h
@@ -1737,6 +1737,7 @@ VALUE rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode);
VALUE rb_int2str(VALUE num, int base);
VALUE rb_dbl_hash(double d);
VALUE rb_fix_plus(VALUE x, VALUE y);
+VALUE rb_fix_aref(VALUE fix, VALUE idx);
VALUE rb_int_gt(VALUE x, VALUE y);
int rb_float_cmp(VALUE x, VALUE y);
VALUE rb_float_gt(VALUE x, VALUE y);
diff --git a/numeric.c b/numeric.c
index 336ff7066a..1fce19ac0b 100644
--- a/numeric.c
+++ b/numeric.c
@@ -4630,8 +4630,8 @@ rb_int_rshift(VALUE x, VALUE y)
return Qnil;
}
-static VALUE
-fix_aref(VALUE fix, VALUE idx)
+MJIT_FUNC_EXPORTED VALUE
+rb_fix_aref(VALUE fix, VALUE idx)
{
long val = FIX2LONG(fix);
long i;
@@ -4722,7 +4722,7 @@ int_aref1(VALUE num, VALUE arg)
one_bit:
if (FIXNUM_P(num)) {
- return fix_aref(num, arg);
+ return rb_fix_aref(num, arg);
}
else if (RB_TYPE_P(num, T_BIGNUM)) {
return rb_big_aref(num, arg);
diff --git a/vm.c b/vm.c
index 3f5a619e3c..70ec2315c1 100644
--- a/vm.c
+++ b/vm.c
@@ -1643,7 +1643,7 @@ vm_init_redefined_flag(void)
OP(GT, GT), (C(Integer), C(Float));
OP(GE, GE), (C(Integer), C(Float));
OP(LTLT, LTLT), (C(String), C(Array));
- OP(AREF, AREF), (C(Array), C(Hash));
+ OP(AREF, AREF), (C(Array), C(Hash), C(Integer));
OP(ASET, ASET), (C(Array), C(Hash));
OP(Length, LENGTH), (C(Array), C(String), C(Hash));
OP(Size, SIZE), (C(Array), C(String), C(Hash));
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 7946f9aa4f..3cd0c8df7b 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -4129,6 +4129,10 @@ static VALUE
vm_opt_aref(VALUE recv, VALUE obj)
{
if (SPECIAL_CONST_P(recv)) {
+ if (FIXNUM_P(recv) && FIXNUM_P(obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_AREF, INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_aref(recv, obj);
+ }
return Qundef;
}
else if (RBASIC_CLASS(recv) == rb_cArray &&