зеркало из https://github.com/github/ruby.git
Keep the reference of imemo while argv may be used
To prevent the `v` reference from being eliminated before argv is used, calling `rb_free_tmp_buffer` against `v` explicitly.
This commit is contained in:
Родитель
f41cd4ba43
Коммит
8263459627
38
vm_eval.c
38
vm_eval.c
|
@ -235,25 +235,27 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
/* Caller should keep the reference to the return value until argv becomes useless. */
|
||||
static VALUE
|
||||
add_empty_keyword(int *argc, const VALUE **argv, int *kw_splat)
|
||||
{
|
||||
if (*kw_splat == RB_PASS_CALLED_KEYWORDS || *kw_splat == RB_PASS_EMPTY_KEYWORDS) {
|
||||
if (*kw_splat == RB_PASS_EMPTY_KEYWORDS || rb_empty_keyword_given_p()) {
|
||||
int n = *argc;
|
||||
VALUE v;
|
||||
VALUE *ptr;
|
||||
ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE));
|
||||
VALUE *ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE));
|
||||
memcpy(ptr, *argv, sizeof(VALUE)*n);
|
||||
ptr[n] = rb_hash_new();
|
||||
*argc = ++n;
|
||||
*argv = ptr;
|
||||
*kw_splat = 1;
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
*kw_splat = rb_keyword_given_p();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
@ -265,8 +267,10 @@ rb_vm_call(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VAL
|
|||
VALUE
|
||||
rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
|
||||
{
|
||||
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
|
||||
VALUE v = add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
|
||||
rb_free_tmp_buffer(&v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
|
@ -291,8 +295,10 @@ vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_sp
|
|||
return method_missing(recv, id, argc, argv, MISSING_SUPER);
|
||||
}
|
||||
else {
|
||||
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
|
||||
VALUE v = add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
|
||||
rb_free_tmp_buffer(&v);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -940,8 +946,10 @@ rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
|
|||
VALUE
|
||||
rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
|
||||
{
|
||||
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
|
||||
VALUE v = add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
|
||||
rb_free_tmp_buffer(&v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1008,8 +1016,10 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE
|
|||
vm_passed_block_handler_set(GET_EC(), passed_procval);
|
||||
}
|
||||
|
||||
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
|
||||
VALUE v = add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
|
||||
rb_free_tmp_buffer(&v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static VALUE *
|
||||
|
@ -1373,13 +1383,15 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
|
|||
{
|
||||
struct iter_method_arg arg;
|
||||
|
||||
add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
VALUE v = add_empty_keyword(&argc, &argv, &kw_splat);
|
||||
arg.obj = obj;
|
||||
arg.mid = mid;
|
||||
arg.argc = argc;
|
||||
arg.argv = argv;
|
||||
arg.kw_splat = kw_splat;
|
||||
return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
|
||||
VALUE ret = rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
|
||||
rb_free_tmp_buffer(&v);
|
||||
return ret;
|
||||
}
|
||||
|
||||
VALUE
|
||||
|
|
Загрузка…
Ссылка в новой задаче