summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c104
1 files changed, 59 insertions, 45 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 1f51edcfc9..707344718b 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1,6 +1,6 @@
/**********************************************************************
- vm_eval.c -
+ vm_eval.c - Included into vm.c.
$Author$
created at: Sat May 24 16:02:32 JST 2008
@@ -57,7 +57,7 @@ static inline VALUE vm_call0_cc(rb_execution_context_t *ec, VALUE recv, ID id, i
VALUE
rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *cme, int kw_splat)
{
- const struct rb_callcache cc = VM_CC_ON_STACK(Qfalse, vm_call_general, {{ 0 }}, cme);
+ const struct rb_callcache cc = VM_CC_ON_STACK(Qundef, vm_call_general, {{ 0 }}, cme);
return vm_call0_cc(ec, recv, id, argc, argv, &cc, kw_splat);
}
@@ -104,7 +104,7 @@ vm_call0_cc(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE
static VALUE
vm_call0_cme(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, const rb_callable_method_entry_t *cme)
{
- calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, {{ 0 }}, cme);
+ calling->cc = &VM_CC_ON_STACK(Qundef, vm_call_general, {{ 0 }}, cme);
return vm_call0_body(ec, calling, argv);
}
@@ -400,9 +400,9 @@ static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE rec
static inline enum method_missing_reason rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self);
static VALUE
-gccct_hash(VALUE klass, VALUE namespace, ID mid)
+gccct_hash(VALUE klass, VALUE box_value, ID mid)
{
- return ((klass ^ namespace) >> 3) ^ (VALUE)mid;
+ return ((klass ^ box_value) >> 3) ^ (VALUE)mid;
}
NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, unsigned int index, const struct rb_callinfo * ci));
@@ -447,8 +447,8 @@ scope_to_ci(call_type scope, ID mid, int argc, struct rb_callinfo *ci)
static inline const struct rb_callcache *
gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct rb_callinfo *ci)
{
- VALUE klass, ns_value;
- const rb_namespace_t *ns = rb_current_namespace();
+ VALUE klass, box_value;
+ const rb_box_t *box = rb_current_box();
if (!SPECIAL_CONST_P(recv)) {
klass = RBASIC_CLASS(recv);
@@ -458,14 +458,14 @@ gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct
klass = CLASS_OF(recv);
}
- if (NAMESPACE_USER_P(ns)) {
- ns_value = ns->ns_object;
+ if (BOX_USER_P(box)) {
+ box_value = box->box_object;
}
else {
- ns_value = 0;
+ box_value = 0;
}
// search global method cache
- unsigned int index = (unsigned int)(gccct_hash(klass, ns_value, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE);
+ unsigned int index = (unsigned int)(gccct_hash(klass, box_value, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE);
rb_vm_t *vm = rb_ec_vm_ptr(ec);
const struct rb_callcache *cc = vm->global_cc_cache_table[index];
@@ -1379,6 +1379,17 @@ rb_yield(VALUE val)
}
}
+VALUE
+rb_ec_yield(rb_execution_context_t *ec, VALUE val)
+{
+ if (UNDEF_P(val)) {
+ return vm_yield(ec, 0, NULL, RB_NO_KEYWORDS);
+ }
+ else {
+ return vm_yield(ec, 1, &val, RB_NO_KEYWORDS);
+ }
+}
+
#undef rb_yield_values
VALUE
rb_yield_values(int n, ...)
@@ -1522,13 +1533,6 @@ rb_iterate_internal(VALUE (* it_proc)(VALUE), VALUE data1,
GET_EC());
}
-VALUE
-rb_iterate(VALUE (* it_proc)(VALUE), VALUE data1,
- rb_block_call_func_t bl_proc, VALUE data2)
-{
- return rb_iterate_internal(it_proc, data1, bl_proc, data2);
-}
-
struct iter_method_arg {
VALUE obj;
ID mid;
@@ -1669,6 +1673,24 @@ get_eval_default_path(void)
return eval_default_path;
}
+static inline int
+compute_isolated_depth_from_ep(const VALUE *ep)
+{
+ int depth = 1;
+ while (1) {
+ if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) return depth;
+ if (VM_ENV_LOCAL_P(ep)) return 0;
+ ep = VM_ENV_PREV_EP(ep);
+ depth++;
+ }
+}
+
+static inline int
+compute_isolated_depth_from_block(const struct rb_block *blk)
+{
+ return compute_isolated_depth_from_ep(vm_block_ep(blk));
+}
+
static const rb_iseq_t *
pm_eval_make_iseq(VALUE src, VALUE fname, int line,
const struct rb_block *base_block)
@@ -1677,8 +1699,8 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
const rb_iseq_t *iseq = parent;
VALUE name = rb_fstring_lit("<compiled>");
- // Conditionally enable coverage depending on the current mode:
int coverage_enabled = ((rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0) ? 1 : 0;
+ int isolated_depth = compute_isolated_depth_from_block(base_block);
if (!fname) {
fname = rb_source_location(&line);
@@ -1872,7 +1894,7 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
#undef FORWARDING_ALL_STR
int error_state;
- iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, 0, &error_state);
+ iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, isolated_depth, &error_state);
pm_scope_node_t *prev = result.node.previous;
while (prev) {
@@ -1908,27 +1930,9 @@ eval_make_iseq(VALUE src, VALUE fname, int line,
rb_iseq_t *iseq = NULL;
VALUE ast_value;
rb_ast_t *ast;
- int isolated_depth = 0;
- // Conditionally enable coverage depending on the current mode:
int coverage_enabled = (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0;
-
- {
- int depth = 1;
- const VALUE *ep = vm_block_ep(base_block);
-
- while (1) {
- if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) {
- isolated_depth = depth;
- break;
- }
- else if (VM_ENV_LOCAL_P(ep)) {
- break;
- }
- ep = VM_ENV_PREV_EP(ep);
- depth++;
- }
- }
+ int isolated_depth = compute_isolated_depth_from_block(base_block);
if (!fname) {
fname = rb_source_location(&line);
@@ -1985,6 +1989,10 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li
block.as.captured.code.iseq = cfp->iseq;
block.type = block_type_iseq;
+ // EP is not escaped to the heap here, but captured and reused by another frame.
+ // ZJIT's locals are incompatible with it unlike YJIT's, so invalidate the ISEQ for ZJIT.
+ rb_zjit_invalidate_no_ep_escape(cfp->iseq);
+
iseq = eval_make_iseq(src, file, line, &block);
if (!iseq) {
rb_exc_raise(ec->errinfo);
@@ -1996,7 +2004,6 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li
cref = vm_cref_dup(orig_cref);
}
vm_set_eval_stack(ec, iseq, cref, &block);
- // TODO: set the namespace frame
/* kick */
return vm_exec(ec);
@@ -2019,8 +2026,6 @@ eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
vm_bind_update_env(scope, bind, vm_make_env_object(ec, ec->cfp));
}
- // TODO: set the namespace frame
-
/* kick */
return vm_exec(ec);
}
@@ -2147,6 +2152,17 @@ rb_eval_string_wrap(const char *str, int *pstate)
VALUE
rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
{
+ Check_Type(arg, T_ARRAY);
+ int argc = RARRAY_LENINT(arg);
+ const VALUE *argv = RARRAY_CONST_PTR(arg);
+ VALUE val = rb_eval_cmd_call_kw(cmd, argc, argv, kw_splat);
+ RB_GC_GUARD(arg);
+ return val;
+}
+
+VALUE
+rb_eval_cmd_call_kw(VALUE cmd, int argc, const VALUE *argv, int kw_splat)
+{
enum ruby_tag_type state;
volatile VALUE val = Qnil; /* OK */
rb_execution_context_t * volatile ec = GET_EC();
@@ -2154,8 +2170,7 @@ rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
if (!RB_TYPE_P(cmd, T_STRING)) {
- val = rb_funcallv_kw(cmd, idCall, RARRAY_LENINT(arg),
- RARRAY_CONST_PTR(arg), kw_splat);
+ val = rb_funcallv_kw(cmd, idCall, argc, argv, kw_splat);
}
else {
val = eval_string_with_cref(rb_vm_top_self(), cmd, NULL, 0, 0);
@@ -2886,7 +2901,6 @@ Init_vm_eval(void)
rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
- rb_define_singleton_method(rb_cModule, "gccct_clear_table", rb_gccct_clear_table, 0);
id_result = rb_intern_const("result");
id_tag = rb_intern_const("tag");
id_value = rb_intern_const("value");