ruby-changes:30625
From: nobu <ko1@a...>
Date: Tue, 27 Aug 2013 16:46:28 +0900 (JST)
Subject: [ruby-changes:30625] nobu:r42704 (trunk): array.c: optimized equality
nobu 2013-08-27 16:46:08 +0900 (Tue, 27 Aug 2013) New Revision: 42704 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42704 Log: array.c: optimized equality * array.c (rb_ary_index, rb_ary_rindex): use optimized equality to improve performance. [Feature #8820] * vm_insnhelper.c (rb_equal_opt): optimized equality function. Modified files: trunk/ChangeLog trunk/array.c trunk/internal.h trunk/vm_insnhelper.c Index: array.c =================================================================== --- array.c (revision 42703) +++ array.c (revision 42704) @@ -1414,8 +1414,9 @@ rb_ary_fetch(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/array.c#L1414 static VALUE rb_ary_index(int argc, VALUE *argv, VALUE ary) { + const VALUE *ptr; VALUE val; - long i; + long i, len; if (argc == 0) { RETURN_ENUMERATOR(ary, 0, 0); @@ -1426,12 +1427,24 @@ rb_ary_index(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/array.c#L1427 } return Qnil; } - rb_scan_args(argc, argv, "1", &val); + rb_check_arity(argc, 0, 1); + val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used"); - for (i=0; i<RARRAY_LEN(ary); i++) { - if (rb_equal(RARRAY_AREF(ary, i), val)) + len = RARRAY_LEN(ary); + ptr = RARRAY_RAWPTR(ary); + for (i=0; i<len; i++) { + VALUE e = ptr[i]; + switch (rb_equal_opt(e, val)) { + case Qundef: + if (!rb_equal(e, val)) break; + case Qtrue: return LONG2NUM(i); + case Qfalse: + continue; + } + len = RARRAY_LEN(ary); + ptr = RARRAY_RAWPTR(ary); } return Qnil; } @@ -1463,8 +1476,9 @@ rb_ary_index(int argc, VALUE *argv, VALU https://github.com/ruby/ruby/blob/trunk/array.c#L1476 static VALUE rb_ary_rindex(int argc, VALUE *argv, VALUE ary) { + const VALUE *ptr; VALUE val; - long i = RARRAY_LEN(ary); + long i = RARRAY_LEN(ary), len; if (argc == 0) { RETURN_ENUMERATOR(ary, 0, 0); @@ -1477,15 +1491,25 @@ rb_ary_rindex(int argc, VALUE *argv, VAL https://github.com/ruby/ruby/blob/trunk/array.c#L1491 } return Qnil; } - rb_scan_args(argc, argv, "1", &val); + rb_check_arity(argc, 0, 1); + val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used"); + ptr = RARRAY_RAWPTR(ary); while (i--) { - if (rb_equal(RARRAY_AREF(ary, i), val)) + VALUE e = ptr[i]; + switch (rb_equal_opt(e, val)) { + case Qundef: + if (!rb_equal(e, val)) break; + case Qtrue: return LONG2NUM(i); - if (i > RARRAY_LEN(ary)) { - i = RARRAY_LEN(ary); + case Qfalse: + continue; + } + if (i > (len = RARRAY_LEN(ary))) { + i = len; } + ptr = RARRAY_RAWPTR(ary); } return Qnil; } Index: ChangeLog =================================================================== --- ChangeLog (revision 42703) +++ ChangeLog (revision 42704) @@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Tue Aug 27 16:46:05 2013 Nobuyoshi Nakada <nobu@r...> + + * array.c (rb_ary_index, rb_ary_rindex): use optimized equality to + improve performance. [Feature #8820] + + * vm_insnhelper.c (rb_equal_opt): optimized equality function. + Tue Aug 27 16:11:05 2013 Nobuyoshi Nakada <nobu@r...> * vm_insnhelper.c (opt_eq_func): use RBASIC_CLASS() instead of HEAP_CLASS_OF(). Index: internal.h =================================================================== --- internal.h (revision 42703) +++ internal.h (revision 42704) @@ -483,6 +483,9 @@ typedef void rb_check_funcall_hook(int, https://github.com/ruby/ruby/blob/trunk/internal.h#L483 VALUE rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv, rb_check_funcall_hook *hook, VALUE arg); +/* vm_insnhelper.c */ +VALUE rb_equal_opt(VALUE obj1, VALUE obj2); + /* vm_method.c */ void Init_eval_method(void); int rb_method_defined_by(VALUE obj, ID mid, VALUE (*cfunc)(ANYARGS)); Index: vm_insnhelper.c =================================================================== --- vm_insnhelper.c (revision 42703) +++ vm_insnhelper.c (revision 42704) @@ -918,6 +918,18 @@ opt_eq_func(VALUE recv, VALUE obj, CALL_ https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L918 return Qundef; } +VALUE +rb_equal_opt(VALUE obj1, VALUE obj2) +{ + rb_call_info_t ci; + ci.mid = idEq; + ci.klass = 0; + ci.vmstat = 0; + ci.me = NULL; + ci.defined_class = 0; + return opt_eq_func(obj1, obj2, &ci); +} + static VALUE check_match(VALUE pattern, VALUE target, enum vm_check_match_type type) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/