ruby-changes:52374
From: ko1 <ko1@a...>
Date: Tue, 28 Aug 2018 16:06:12 +0900 (JST)
Subject: [ruby-changes:52374] ko1:r64583 (trunk): rest parameter optimization [Feature #15010]
ko1 2018-08-28 16:06:06 +0900 (Tue, 28 Aug 2018) New Revision: 64583 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64583 Log: rest parameter optimization [Feature #15010] * vm_args.c: rb_ary_dup(args->rest) to be used at most once during parameter setup. [Feature #15010] A patch by chopraanmol1 (Anmol Chopra) <chopraanmol1@g...>. * array.c (rb_ary_behead): added to remove first n elements. Modified files: trunk/array.c trunk/internal.h trunk/vm_args.c Index: internal.h =================================================================== --- internal.h (revision 64582) +++ internal.h (revision 64583) @@ -1087,6 +1087,7 @@ size_t rb_ary_memsize(VALUE); https://github.com/ruby/ruby/blob/trunk/internal.h#L1087 VALUE rb_to_array_type(VALUE obj); VALUE rb_check_to_array(VALUE ary); VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *); +VALUE rb_ary_behead(VALUE, long); #if defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) #define rb_ary_new_from_args(n, ...) \ __extension__ ({ \ Index: array.c =================================================================== --- array.c (revision 64582) +++ array.c (revision 64583) @@ -1076,6 +1076,17 @@ rb_ary_shift_m(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/array.c#L1076 rb_ary_modify_check(ary); result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST); n = RARRAY_LEN(result); + rb_ary_behead(ary,n); + + return result; +} + +MJIT_FUNC_EXPORTED VALUE +rb_ary_behead(VALUE ary, long n) +{ + if(n<=0) return ary; + + rb_ary_modify_check(ary); if (ARY_SHARED_P(ary)) { if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) { setup_occupied_shared: @@ -1096,7 +1107,7 @@ rb_ary_shift_m(int argc, VALUE *argv, VA https://github.com/ruby/ruby/blob/trunk/array.c#L1107 } ARY_INCREASE_LEN(ary, -n); - return result; + return ary; } static VALUE Index: vm_args.c =================================================================== --- vm_args.c (revision 64582) +++ vm_args.c (revision 64583) @@ -22,6 +22,7 @@ struct args_info { https://github.com/ruby/ruby/blob/trunk/vm_args.c#L22 /* additional args info */ int rest_index; + int rest_dupped; const struct rb_call_info_kw_arg *kw_arg; VALUE *kw_argv; VALUE rest; @@ -32,6 +33,15 @@ enum arg_setup_type { https://github.com/ruby/ruby/blob/trunk/vm_args.c#L33 arg_setup_block }; +static inline void +arg_rest_dup(struct args_info *args) +{ + if(!args->rest_dupped) { + args->rest = rb_ary_dup(args->rest); + args->rest_dupped = TRUE; + } +} + static inline int args_argc(struct args_info *args) { @@ -49,7 +59,7 @@ args_extend(struct args_info *args, cons https://github.com/ruby/ruby/blob/trunk/vm_args.c#L59 int i; if (args->rest) { - args->rest = rb_ary_dup(args->rest); + arg_rest_dup(args); VM_ASSERT(args->rest_index == 0); for (i=args->argc + RARRAY_LENINT(args->rest); i<min_argc; i++) { rb_ary_push(args->rest, Qnil); @@ -69,7 +79,7 @@ args_reduce(struct args_info *args, int https://github.com/ruby/ruby/blob/trunk/vm_args.c#L79 const long len = RARRAY_LEN(args->rest); if (len > over_argc) { - args->rest = rb_ary_dup(args->rest); + arg_rest_dup(args); rb_ary_resize(args->rest, len - over_argc); return; } @@ -114,7 +124,7 @@ args_copy(struct args_info *args) https://github.com/ruby/ruby/blob/trunk/vm_args.c#L124 if (args->rest != Qfalse) { int argc = args->argc; args->argc = 0; - args->rest = rb_ary_dup(args->rest); /* make dup */ + arg_rest_dup(args); /* * argv: [m0, m1, m2, m3] @@ -146,6 +156,7 @@ args_copy(struct args_info *args) https://github.com/ruby/ruby/blob/trunk/vm_args.c#L156 else if (args->argc > 0) { args->rest = rb_ary_new_from_values(args->argc, args->argv); args->rest_index = 0; + args->rest_dupped = TRUE; args->argc = 0; } } @@ -162,7 +173,8 @@ args_rest_array(struct args_info *args) https://github.com/ruby/ruby/blob/trunk/vm_args.c#L173 VALUE ary; if (args->rest) { - ary = rb_ary_subseq(args->rest, args->rest_index, RARRAY_LEN(args->rest) - args->rest_index); + ary = rb_ary_behead(args->rest, args->rest_index); + args->rest_index = 0; args->rest = 0; } else { @@ -219,7 +231,7 @@ args_pop_keyword_hash(struct args_info * https://github.com/ruby/ruby/blob/trunk/vm_args.c#L231 RARRAY_ASET(args->rest, len - 1, rest_hash); } else { - args->rest = rb_ary_dup(args->rest); + arg_rest_dup(args); rb_ary_pop(args->rest); return TRUE; } @@ -269,7 +281,7 @@ args_stored_kw_argv_to_hash(struct args_ https://github.com/ruby/ruby/blob/trunk/vm_args.c#L281 args->kw_argv = NULL; if (args->rest) { - args->rest = rb_ary_dup(args->rest); + arg_rest_dup(args); rb_ary_push(args->rest, h); } else { @@ -301,7 +313,6 @@ static inline void https://github.com/ruby/ruby/blob/trunk/vm_args.c#L313 args_setup_post_parameters(struct args_info *args, int argc, VALUE *locals) { long len; - args_copy(args); len = RARRAY_LEN(args->rest); MEMCPY(locals, RARRAY_CONST_PTR(args->rest) + len - argc, VALUE, argc); rb_ary_resize(args->rest, len - argc); @@ -343,7 +354,6 @@ args_setup_opt_parameters(struct args_in https://github.com/ruby/ruby/blob/trunk/vm_args.c#L354 static inline void args_setup_rest_parameter(struct args_info *args, VALUE *locals) { - args_copy(args); *locals = args_rest_array(args); } @@ -538,6 +548,7 @@ setup_parameters_complex(rb_execution_co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L548 args = &args_body; given_argc = args->argc = calling->argc; args->argv = locals; + args->rest_dupped = FALSE; if (ci->flag & VM_CALL_KWARG) { args->kw_arg = ((struct rb_call_info_with_kwarg *)ci)->kw_arg; @@ -628,6 +639,10 @@ setup_parameters_complex(rb_execution_co https://github.com/ruby/ruby/blob/trunk/vm_args.c#L639 args_setup_lead_parameters(args, iseq->body->param.lead_num, locals + 0); } + if (iseq->body->param.flags.has_rest || iseq->body->param.flags.has_post){ + args_copy(args); + } + if (iseq->body->param.flags.has_post) { args_setup_post_parameters(args, iseq->body->param.post_num, locals + iseq->body->param.post_start); } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/