summaryrefslogtreecommitdiff
path: root/vm_eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_eval.c')
-rw-r--r--vm_eval.c302
1 files changed, 200 insertions, 102 deletions
diff --git a/vm_eval.c b/vm_eval.c
index 229dbf03b3..84bb40ba80 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);
}
@@ -381,7 +381,7 @@ stack_check(rb_execution_context_t *ec)
if (!rb_ec_raised_p(ec, RAISED_STACKOVERFLOW) &&
rb_ec_stack_check(ec)) {
rb_ec_raised_set(ec, RAISED_STACKOVERFLOW);
- rb_ec_stack_overflow(ec, FALSE);
+ rb_ec_stack_overflow(ec, 0);
}
}
@@ -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, ID mid)
+gccct_hash(VALUE klass, VALUE box_value, ID mid)
{
- return (klass >> 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));
@@ -417,6 +417,9 @@ gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, unsigned int index, const
vm_search_method_slowpath0(vm->self, &cd, klass);
+ if (UNLIKELY(!vm->global_cc_cache_table_used)) {
+ vm->global_cc_cache_table_used = true;
+ }
return vm->global_cc_cache_table[index] = cd.cc;
}
@@ -447,7 +450,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;
+ VALUE klass, box_value;
+ const rb_box_t *box = rb_current_box();
if (!SPECIAL_CONST_P(recv)) {
klass = RBASIC_CLASS(recv);
@@ -457,8 +461,14 @@ gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct
klass = CLASS_OF(recv);
}
+ if (BOX_USER_P(box)) {
+ box_value = box->box_object;
+ }
+ else {
+ box_value = 0;
+ }
// search global method cache
- unsigned int index = (unsigned int)(gccct_hash(klass, 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];
@@ -483,6 +493,18 @@ gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, const struct
return gccct_method_search_slowpath(vm, klass, index, ci);
}
+VALUE
+rb_gccct_clear_table(void)
+{
+ rb_vm_t *vm = GET_VM();
+ if (vm->global_cc_cache_table_used) {
+ const struct rb_callcache **const table = vm->global_cc_cache_table;
+ MEMZERO(table, struct rb_callcache *, VM_GLOBAL_CC_CACHE_TABLE_SIZE);
+ vm->global_cc_cache_table_used = false;
+ }
+ return Qnil;
+}
+
/**
* @internal
* calls the specified method.
@@ -1361,6 +1383,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, ...)
@@ -1504,13 +1537,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;
@@ -1651,6 +1677,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)
@@ -1659,8 +1703,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);
@@ -1674,16 +1718,17 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
coverage_enabled = 0;
}
- pm_parse_result_t result = { 0 };
- pm_options_line_set(&result.options, line);
+ pm_parse_result_t result;
+ pm_parse_result_init(&result);
+ pm_options_line_set(result.options, line);
result.node.coverage_enabled = coverage_enabled;
- // Cout scopes, one for each parent iseq, plus one for our local scope
+ // Count scopes, one for each parent iseq, plus one for our local scope
int scopes_count = 0;
do {
scopes_count++;
} while ((iseq = ISEQ_BODY(iseq)->parent_iseq));
- pm_options_scopes_init(&result.options, scopes_count + 1);
+ pm_options_scopes_init(result.options, scopes_count + 1);
// Walk over the scope tree, adding known locals at the correct depths. The
// scope array should be deepest -> shallowest. so lower indexes in the
@@ -1705,19 +1750,19 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
VALUE iseq_value = (VALUE)iseq;
int locals_count = ISEQ_BODY(iseq)->local_table_size;
- pm_options_scope_t *options_scope = &result.options.scopes[scopes_count - scopes_index - 1];
+ pm_options_scope_t *options_scope = pm_options_scope_mut(result.options, scopes_count - scopes_index - 1);
pm_options_scope_init(options_scope, locals_count);
uint8_t forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE;
for (int local_index = 0; local_index < locals_count; local_index++) {
- pm_string_t *scope_local = &options_scope->locals[local_index];
+ pm_string_t *scope_local = pm_options_scope_local_mut(options_scope, local_index);
ID local = ISEQ_BODY(iseq)->local_table[local_index];
if (rb_is_local_id(local)) {
VALUE name_obj = rb_id2str(local);
const char *name = RSTRING_PTR(name_obj);
- size_t length = strlen(name);
+ size_t length = RSTRING_LEN(name_obj);
// Explicitly skip numbered parameters. These should not be sent
// into the eval.
@@ -1736,22 +1781,26 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
/* We need to duplicate the string because the Ruby string may
* be embedded so compaction could move the string and the pointer
* will change. */
- char *name_dup = xmalloc(length + 1);
- strlcpy(name_dup, name, length + 1);
+ char *name_dup = xmalloc(length);
+ MEMCPY(name_dup, name, char, length);
RB_GC_GUARD(name_obj);
pm_string_owned_init(scope_local, (uint8_t *) name_dup, length);
- } else if (local == idMULT) {
+ }
+ else if (local == idMULT) {
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS;
pm_string_constant_init(scope_local, FORWARDING_POSITIONALS_STR, 1);
- } else if (local == idPow) {
+ }
+ else if (local == idPow) {
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS;
pm_string_constant_init(scope_local, FORWARDING_KEYWORDS_STR, 1);
- } else if (local == idAnd) {
+ }
+ else if (local == idAnd) {
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_BLOCK;
pm_string_constant_init(scope_local, FORWARDING_BLOCK_STR, 1);
- } else if (local == idDot3) {
+ }
+ else if (local == idDot3) {
forwarding |= PM_OPTIONS_SCOPE_FORWARDING_ALL;
pm_string_constant_init(scope_local, FORWARDING_ALL_STR, 1);
}
@@ -1768,7 +1817,7 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
// Add our empty local scope at the very end of the array for our eval
// scope's locals.
- pm_options_scope_init(&result.options.scopes[scopes_count], 0);
+ pm_options_scope_init(pm_options_scope_mut(result.options, scopes_count), 0);
VALUE script_lines;
VALUE error = pm_parse_string(&result, src, fname, ruby_vm_keep_script_lines ? &script_lines : NULL);
@@ -1789,17 +1838,16 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
pm_scope_node_t *parent_scope = ruby_xcalloc(1, sizeof(pm_scope_node_t));
RUBY_ASSERT(parent_scope != NULL);
- pm_options_scope_t *options_scope = &result.options.scopes[scopes_count - scopes_index - 1];
+ const pm_options_scope_t *options_scope = pm_options_scope(result.options, scopes_count - scopes_index - 1);
parent_scope->coverage_enabled = coverage_enabled;
- parent_scope->parser = &result.parser;
- parent_scope->index_lookup_table = st_init_numtable();
-
+ parent_scope->parser = result.parser;
int locals_count = ISEQ_BODY(iseq)->local_table_size;
+ pm_index_lookup_table_init_heap(&parent_scope->index_lookup_table, (int) pm_parser_constants_size(result.parser));
parent_scope->local_table_for_iseq_size = locals_count;
pm_constant_id_list_init(&parent_scope->locals);
for (int local_index = 0; local_index < locals_count; local_index++) {
- const pm_string_t *scope_local = &options_scope->locals[local_index];
+ const pm_string_t *scope_local = pm_options_scope_local(options_scope, local_index);
pm_constant_id_t constant_id = 0;
const uint8_t *source = pm_string_source(scope_local);
@@ -1821,18 +1869,18 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line,
constant_id = PM_CONSTANT_DOT3;
break;
default:
- constant_id = pm_constant_pool_insert_constant(&result.parser.constant_pool, source, length);
+ constant_id = pm_parser_constant_find(result.parser, source, length);
break;
}
}
else {
- constant_id = pm_constant_pool_insert_constant(&result.parser.constant_pool, source, length);
+ constant_id = pm_parser_constant_find(result.parser, source, length);
}
- st_insert(parent_scope->index_lookup_table, (st_data_t) constant_id, (st_data_t) local_index);
+ pm_index_lookup_table_insert(&parent_scope->index_lookup_table, constant_id, local_index);
}
- pm_constant_id_list_append(&parent_scope->locals, constant_id);
+ pm_constant_id_list_append(result.arena, &parent_scope->locals, constant_id);
}
node->previous = parent_scope;
@@ -1850,14 +1898,13 @@ 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) {
pm_scope_node_t *next = prev->previous;
- pm_constant_id_list_free(&prev->locals);
pm_scope_node_destroy(prev);
- ruby_xfree(prev);
+ SIZED_FREE(prev);
prev = next;
}
@@ -1886,27 +1933,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);
@@ -1960,9 +1989,13 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li
block.as.captured = *VM_CFP_TO_CAPTURED_BLOCK(cfp);
block.as.captured.self = self;
- block.as.captured.code.iseq = cfp->iseq;
+ block.as.captured.code.iseq = CFP_ISEQ(cfp);
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(cfp));
+
iseq = eval_make_iseq(src, file, line, &block);
if (!iseq) {
rb_exc_raise(ec->errinfo);
@@ -2001,21 +2034,38 @@ eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
}
/*
- * call-seq:
- * eval(string [, binding [, filename [,lineno]]]) -> obj
+ * call-seq:
+ * eval(string, binding = nil, filename = default_filename, lineno = 1) -> obj
*
- * Evaluates the Ruby expression(s) in <em>string</em>. If
- * <em>binding</em> is given, which must be a Binding object, the
- * evaluation is performed in its context. If the optional
- * <em>filename</em> and <em>lineno</em> parameters are present, they
- * will be used when reporting syntax errors.
+ * Evaluates the Ruby expression(s) in +string+. Returns the result of the last
+ * expression.
*
- * def get_binding(str)
- * return binding
- * end
- * str = "hello"
- * eval "str + ' Fred'" #=> "hello Fred"
- * eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"
+ * str = "Hello"
+ * eval("str + ' World'") # => "Hello World"
+ *
+ * If +binding+ is given, which must be a Binding object, the
+ * evaluation is performed in its context. Otherwise, the
+ * evaluation is performed in the context of the caller.
+ *
+ * def get_binding(str) = binding
+ * str = "Hello"
+ * eval("str + ' World'", get_binding("Bye")) # => "Bye World"
+ *
+ * If the optional +filename+ is given, it will be used as the
+ * filename of the evaluation (for <tt>__FILE__</tt> and errors).
+ * Otherwise, it will default to <tt>(eval at __FILE__:__LINE__)</tt>
+ * where <tt>__FILE__</tt> and <tt>__LINE__</tt> are the filename and
+ * line number of the caller, respectively.
+ *
+ * eval("puts __FILE__") # => "(eval at test.rb:1)"
+ * eval("puts __FILE__", nil, "foobar.rb") # => "foobar.rb"
+ *
+ * If the optional +lineno+ is given, it will be used as the
+ * line number of the evaluation (for <tt>__LINE__</tt> and errors).
+ * Otherwise, it will default to 1.
+ *
+ * eval("puts __LINE__") # => 1
+ * eval("puts __LINE__", nil, "foobar.rb", 10) # => 10
*/
VALUE
@@ -2122,6 +2172,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();
@@ -2129,8 +2190,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);
@@ -2332,29 +2392,66 @@ rb_obj_instance_exec(int argc, const VALUE *argv, VALUE self)
/*
* call-seq:
- * mod.class_eval(string [, filename [, lineno]]) -> obj
- * mod.class_eval {|mod| block } -> obj
- * mod.module_eval(string [, filename [, lineno]]) -> obj
- * mod.module_eval {|mod| block } -> obj
+ * class_eval(string, filename = nil, lineno = 1) -> obj
+ * class_eval { |mod| ... } -> obj
+ * module_eval(string, filename = nil, lineno = 1) -> obj
+ * module_eval { |mod| ... } -> obj
*
- * Evaluates the string or block in the context of _mod_, except that when
- * a block is given, constant/class variable lookup is not affected. This
- * can be used to add methods to a class. <code>module_eval</code> returns
- * the result of evaluating its argument. The optional _filename_ and
- * _lineno_ parameters set the text for error messages.
+ * Evaluates the +string+ or block in the context of +self+.
+ * Returns the result of the last expression.
*
- * class Thing
- * end
- * a = %q{def hello() "Hello there!" end}
- * Thing.module_eval(a)
- * puts Thing.new.hello()
- * Thing.module_eval("invalid code", "dummy", 123)
+ * When +string+ is given, evaluates the given string in the
+ * context of +self+:
*
- * <em>produces:</em>
+ * class Foo; end
*
- * Hello there!
- * dummy:123:in `module_eval': undefined local variable
- * or method `code' for Thing:Class
+ * Foo.module_eval("def greeting = puts 'hello'")
+ *
+ * Foo.new.greeting # => "hello"
+ *
+ * If the optional +filename+ is given, it will be used as the
+ * filename of the evaluation (for <tt>__FILE__</tt> and errors).
+ * Otherwise, it will default to <tt>(eval at __FILE__:__LINE__)</tt>
+ * where <tt>__FILE__</tt> and <tt>__LINE__</tt> are the filename and
+ * line number of the caller, respectively:
+ *
+ * class Foo; end
+ *
+ * Foo.module_eval("puts __FILE__") # => "(eval at ../test.rb:3)"
+ * Foo.module_eval("puts __FILE__", "foobar.rb") # => "foobar.rb"
+ *
+ * If the optional +lineno+ is given, it will be used as the
+ * line number of the evaluation (for <tt>__LINE__</tt> and errors).
+ * Otherwise, it will default to 1:
+ *
+ * class Foo; end
+ *
+ * Foo.module_eval("puts __LINE__") # => 1
+ * Foo.module_eval("puts __FILE__", nil, 10) # => 10
+ *
+ * When a block is given, evaluates the block in the context
+ * of +self+:
+ *
+ * class Foo; end
+ *
+ * Foo.module_eval do
+ * def greeting = puts "hello"
+ * end
+ *
+ * Foo.new.greeting
+ *
+ * However, constant and class variable lookup differs between
+ * +string+ and block. When +string+ is given, contant and class
+ * variables are looked up in the context of +self+. When a block
+ * is given, the context of the lookup is not changed:
+ *
+ * class Foo
+ * GREETING = "hello"
+ * end
+ *
+ * Foo.module_eval("puts GREETING") # => "hello"
+ *
+ * Foo.module_eval { puts GREETING } # => NameError: uninitialized constant GREETING
*/
static VALUE
@@ -2714,9 +2811,9 @@ rb_f_local_variables(VALUE _)
local_var_list_init(&vars);
while (cfp) {
- if (cfp->iseq) {
- for (i = 0; i < ISEQ_BODY(cfp->iseq)->local_table_size; i++) {
- local_var_list_add(&vars, ISEQ_BODY(cfp->iseq)->local_table[i]);
+ if (CFP_ISEQ(cfp)) {
+ for (i = 0; i < ISEQ_BODY(CFP_ISEQ(cfp))->local_table_size; i++) {
+ local_var_list_add(&vars, ISEQ_BODY(CFP_ISEQ(cfp))->local_table[i]);
}
}
if (!VM_ENV_LOCAL_P(cfp->ep)) {
@@ -2790,10 +2887,11 @@ rb_current_realfilepath(void)
rb_control_frame_t *cfp = ec->cfp;
cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
if (cfp != NULL) {
- VALUE path = rb_iseq_realpath(cfp->iseq);
+ const rb_iseq_t *iseq = CFP_ISEQ(cfp);
+ VALUE path = rb_iseq_realpath(iseq);
if (RTEST(path)) return path;
// eval context
- path = rb_iseq_path(cfp->iseq);
+ path = rb_iseq_path(iseq);
if (path == eval_default_path) {
return Qnil;
}
@@ -2819,7 +2917,7 @@ struct vm_ifunc *
rb_current_ifunc(void)
{
// Search VM_FRAME_MAGIC_IFUNC to see ifunc imemos put on the iseq field.
- VALUE ifunc = (VALUE)GET_EC()->cfp->iseq;
+ VALUE ifunc = (VALUE)CFP_ISEQ(GET_EC()->cfp);
RUBY_ASSERT_ALWAYS(imemo_type_p(ifunc, imemo_ifunc));
return (struct vm_ifunc *)ifunc;
}