From 65e63af377bb493dea4d0207627ed87d5da360a8 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Sat, 1 Jun 2019 13:15:43 +0900 Subject: [PATCH] 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. --- internal.h | 1 + numeric.c | 6 +++--- vm.c | 2 +- vm_insnhelper.c | 4 ++++ 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 &&