aboutsummaryrefslogtreecommitdiffstats
path: root/vm_args.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-28 07:06:06 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-28 07:06:06 +0000
commit1aa98ba6f26ac270ed063a4cebabed61317f43c4 (patch)
treed7216e0981d100da40540800bdd38d6ac7e73a50 /vm_args.c
parent9d9628eb9a7caeae26fffe61161ea8836d938f6a (diff)
downloadruby-1aa98ba6f26ac270ed063a4cebabed61317f43c4.tar.gz
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@gmail.com>. * array.c (rb_ary_behead): added to remove first n elements. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64583 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_args.c')
-rw-r--r--vm_args.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/vm_args.c b/vm_args.c
index 12e6e70cf5..4e989574ea 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -22,6 +22,7 @@ struct args_info {
/* 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 {
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, const int min_argc)
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 over_argc)
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)
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)
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)
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 *args, VALUE *kw_hash_ptr)
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_info *args)
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
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_info *args, int opt_max, VALUE *locals)
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_context_t * const ec, const rb_iseq_t * co
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_context_t * const ec, const rb_iseq_t * co
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);
}