summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-09-26 17:25:54 -0700
committerJeremy Evans <code@jeremyevans.net>2019-09-26 19:24:58 -0700
commit660c7e050f6cb050fd5618f812129c211af29810 (patch)
treef02c96afc73682c13bd8bca49a3751c059ea4d45 /vm_eval.c
parent0c6f36668a11902903d85ada61a812d297d02de5 (diff)
Fix more keyword separation issues
This fixes instance_exec and similar methods. It also fixes Enumerator::Yielder#yield, rb_yield_block, and a couple of cases with Proc#{<<,>>}. This support requires the addition of rb_yield_values_kw, similar to rb_yield_values2, for passing the keyword flag. Unlike earlier attempts at this, this does not modify the rb_block_call_func type or add a separate function type. The functions of type rb_block_call_func are called by Ruby with a separate VM frame, and we can get the keyword flag information from the VM frame flags, so it doesn't need to be passed as a function argument. These changes require the following VM functions accept a keyword flag: * vm_yield_with_cref * vm_yield * vm_yield_with_block
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2493
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c50
1 files changed, 39 insertions, 11 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 0fd4f573ef..b97e3527b6 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -16,9 +16,9 @@ struct local_var_list {
};
static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat);
-static inline VALUE vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, const rb_cref_t *cref, int is_lambda);
-static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv);
-static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler);
+static inline VALUE vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat, const rb_cref_t *cref, int is_lambda);
+static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat);
+static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler, int kw_splat);
static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
VALUE vm_exec(rb_execution_context_t *ec, int mjit_enable_p);
static void vm_set_eval_stack(rb_execution_context_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref, const struct rb_block *base_block);
@@ -1199,9 +1199,18 @@ rb_f_public_send(int argc, VALUE *argv, VALUE recv)
/* yield */
static inline VALUE
+rb_yield_0_kw(int argc, const VALUE * argv, int kw_splat)
+{
+ VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
+ VALUE ret = vm_yield(GET_EC(), argc, argv, kw_splat);
+ rb_free_tmp_buffer(&v);
+ return ret;
+}
+
+static inline VALUE
rb_yield_0(int argc, const VALUE * argv)
{
- return vm_yield(GET_EC(), argc, argv);
+ return vm_yield(GET_EC(), argc, argv, RB_NO_KEYWORDS);
}
VALUE
@@ -1251,6 +1260,12 @@ rb_yield_values2(int argc, const VALUE *argv)
}
VALUE
+rb_yield_values_kw(int argc, const VALUE *argv, int kw_splat)
+{
+ return rb_yield_0_kw(argc, argv, kw_splat);
+}
+
+VALUE
rb_yield_splat(VALUE values)
{
VALUE tmp = rb_check_array_type(values);
@@ -1270,10 +1285,15 @@ rb_yield_force_blockarg(VALUE values)
}
VALUE
-rb_yield_block(VALUE val, VALUE arg, int argc, const VALUE *argv, VALUE blockarg)
+rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(val, arg))
{
- return vm_yield_with_block(GET_EC(), argc, argv,
- NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg);
+ int kw_splat = RB_PASS_CALLED_KEYWORDS;
+ VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
+ VALUE ret = vm_yield_with_block(GET_EC(), argc, argv,
+ NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
+ kw_splat);
+ rb_free_tmp_buffer(&v);
+ return ret;
}
static VALUE
@@ -1772,6 +1792,10 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
const VALUE *ep = NULL;
rb_cref_t *cref;
int is_lambda = FALSE;
+ VALUE v = 0, ret;
+ int kw_splat = RB_PASS_CALLED_KEYWORDS;
+
+ v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
if (block_handler != VM_BLOCK_HANDLER_NONE) {
again:
@@ -1791,8 +1815,10 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
goto again;
case block_handler_type_symbol:
- return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
- argc, argv, VM_NO_KEYWORDS, VM_BLOCK_HANDLER_NONE);
+ ret = rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
+ argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE);
+ rb_free_tmp_buffer(&v);
+ return ret;
}
new_captured.self = self;
@@ -1802,7 +1828,9 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv)
}
cref = vm_cref_push(ec, under, ep, TRUE);
- return vm_yield_with_cref(ec, argc, argv, cref, is_lambda);
+ ret = vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
+ rb_free_tmp_buffer(&v);
+ return ret;
}
VALUE
@@ -1823,7 +1851,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements)
CREF_REFINEMENTS_SET(cref, refinements);
VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler);
new_captured.self = refinement;
- return vm_yield_with_cref(ec, 0, NULL, cref, FALSE);
+ return vm_yield_with_cref(ec, 0, NULL, RB_NO_KEYWORDS, cref, FALSE);
}
}