summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-01-08 08:20:36 +0900
committerKoichi Sasada <ko1@atdot.net>2020-02-22 09:58:59 +0900
commitf2286925f08406bc857f7b03ad6779a5d61443ae (patch)
tree62d056c0a8c253f17fccd4a506ddb6cbf1f7bed5 /vm_insnhelper.c
parenta1eb1fabef1bca0696449cd358d93f5a644d5914 (diff)
VALUE size packed callinfo (ci).
Now, rb_call_info contains how to call the method with tuple of (mid, orig_argc, flags, kwarg). Most of cases, kwarg == NULL and mid+argc+flags only requires 64bits. So this patch packed rb_call_info to VALUE (1 word) on such cases. If we can not represent it in VALUE, then use imemo_callinfo which contains conventional callinfo (rb_callinfo, renamed from rb_call_info). iseq->body->ci_kw_size is removed because all of callinfo is VALUE size (packed ci or a pointer to imemo_callinfo). To access ci information, we need to use these functions: vm_ci_mid(ci), _flag(ci), _argc(ci), _kwarg(ci). struct rb_call_info_kw_arg is renamed to rb_callinfo_kwarg. rb_funcallv_with_cc() and rb_method_basic_definition_p_with_cc() is temporary removed because cd->ci should be marked.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2888
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c224
1 files changed, 110 insertions, 114 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 54377dd7d0..e25c0dbb33 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -221,6 +221,8 @@ static bool vm_stack_canary_was_born = false;
MJIT_FUNC_EXPORTED void
vm_check_canary(const rb_execution_context_t *ec, VALUE *sp)
{
+ return;
+
const struct rb_control_frame_struct *reg_cfp = ec->cfp;
const struct rb_iseq_struct *iseq;
@@ -1444,7 +1446,7 @@ __attribute__((__artificial__))
static inline vm_call_handler
calccall(const struct rb_call_data *cd, const rb_callable_method_entry_t *me)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
const struct rb_call_cache *cc = &cd->cc;
if (UNLIKELY(!me)) {
@@ -1464,7 +1466,7 @@ calccall(const struct rb_call_data *cd, const rb_callable_method_entry_t *me)
* formerly-private method now publicised is an absolutely safe thing.
* Calling a private method without specifying a receiver is also safe. */
else if ((METHOD_ENTRY_VISI(cc->me) != METHOD_VISI_PUBLIC) &&
- !(ci->flag & VM_CALL_FCALL)) {
+ !(vm_ci_flag(ci) & VM_CALL_FCALL)) {
RB_DEBUG_COUNTER_INC(mc_miss_by_visi);
return vm_call_general;
}
@@ -1478,10 +1480,11 @@ calccall(const struct rb_call_data *cd, const rb_callable_method_entry_t *me)
MJIT_FUNC_EXPORTED void
rb_vm_search_method_slowpath(struct rb_call_data *cd, VALUE klass)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
struct rb_call_cache *cc = &cd->cc;
+
const rb_callable_method_entry_t *me =
- rb_callable_method_entry(klass, ci->mid);
+ rb_callable_method_entry(klass, vm_ci_mid(ci));
const vm_call_handler call = calccall(cd, me);
struct rb_call_cache buf = {
GET_GLOBAL_METHOD_STATE(),
@@ -1783,19 +1786,25 @@ opt_eql_func(VALUE recv, VALUE obj, CALL_DATA cd)
#undef BUILTIN_CLASS_P
#undef EQ_UNREDEFINED_P
+#define vm_ci_new_id(mid) vm_ci_new_runtime(mid, 0, 0, NULL)
+
VALUE
rb_equal_opt(VALUE obj1, VALUE obj2)
{
- struct rb_call_data cd = { .ci = { .mid = idEq, }, };
+ static const struct rb_callinfo *ci = NULL;
+ if (ci == NULL) {
+ ci = vm_ci_new_id(idEq);
+ rb_gc_register_mark_object((VALUE)ci);
+ }
+ struct rb_call_data cd = { .ci = ci, };
return opt_eq_func(obj1, obj2, &cd);
}
VALUE
rb_eql_opt(VALUE obj1, VALUE obj2)
{
- struct rb_call_data cd = { .ci = { .mid = idEqlP, }, };
-
+ struct rb_call_data cd = { .ci = vm_ci_new_id(idEqlP), };
return opt_eql_func(obj1, obj2, &cd);
}
@@ -1905,7 +1914,7 @@ static VALUE vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t
static VALUE vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd);
static inline VALUE vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd);
-static vm_call_handler vm_call_iseq_setup_func(const struct rb_call_info *ci, const int param_size, const int local_size);
+static vm_call_handler vm_call_iseq_setup_func(const struct rb_callinfo *ci, const int param_size, const int local_size);
static VALUE
vm_call_iseq_setup_tailcall_0start(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
@@ -1966,12 +1975,12 @@ rb_iseq_only_kwparam_p(const rb_iseq_t *iseq)
static inline void
CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp,
struct rb_calling_info *restrict calling,
- const struct rb_call_info *restrict ci)
+ const struct rb_callinfo *restrict ci)
{
if (UNLIKELY(IS_ARGS_SPLAT(ci))) {
VALUE final_hash;
/* This expands the rest argument to the stack.
- * So, ci->flag & VM_CALL_ARGS_SPLAT is now inconsistent.
+ * So, vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT is now inconsistent.
*/
vm_caller_setup_arg_splat(cfp, calling);
if (!IS_ARGS_KW_OR_KW_SPLAT(ci) &&
@@ -1985,7 +1994,7 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp,
if (UNLIKELY(IS_ARGS_KEYWORD(ci))) {
/* This converts VM_CALL_KWARG style to VM_CALL_KW_SPLAT style
* by creating a keyword hash.
- * So, ci->flag & VM_CALL_KWARG is now inconsistent.
+ * So, vm_ci_flag(ci) & VM_CALL_KWARG is now inconsistent.
*/
vm_caller_setup_arg_kw(cfp, calling, ci);
}
@@ -1994,12 +2003,12 @@ CALLER_SETUP_ARG(struct rb_control_frame_struct *restrict cfp,
static inline void
CALLER_REMOVE_EMPTY_KW_SPLAT(struct rb_control_frame_struct *restrict cfp,
struct rb_calling_info *restrict calling,
- const struct rb_call_info *restrict ci)
+ const struct rb_callinfo *restrict ci)
{
if (UNLIKELY(calling->kw_splat)) {
/* This removes the last Hash object if it is empty.
- * So, ci->flag & VM_CALL_KW_SPLAT is now inconsistent.
- * However, you can use ci->flag & VM_CALL_KW_SPLAT to
+ * So, vm_ci_flag(ci) & VM_CALL_KW_SPLAT is now inconsistent.
+ * However, you can use vm_ci_flag(ci) & VM_CALL_KW_SPLAT to
* determine whether a hash should be added back with
* warning (for backwards compatibility in cases where
* the method does not have the number of required
@@ -2093,16 +2102,15 @@ vm_call_iseq_setup_kwparm_kwarg(rb_execution_context_t *ec, rb_control_frame_t *
struct rb_calling_info *calling,
struct rb_call_data *cd)
{
- const struct rb_kwarg_call_data *kcd = (void *)cd;
- const struct rb_call_info_with_kwarg *ci_kw = &kcd->ci_kw;
- const struct rb_call_cache *cc = &kcd->cc;
+ const struct rb_callinfo *ci = cd->ci;
+ const struct rb_call_cache *cc = &cd->cc;
- VM_ASSERT(ci_kw->ci.flag & VM_CALL_KWARG);
+ VM_ASSERT(vm_ci_flag(ci) & VM_CALL_KWARG);
RB_DEBUG_COUNTER_INC(ccf_iseq_kw1);
const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def);
const struct rb_iseq_param_keyword *kw_param = iseq->body->param.keyword;
- const struct rb_call_info_kw_arg *kw_arg = ci_kw->kw_arg;
+ const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci);
const int ci_kw_len = kw_arg->keyword_len;
const VALUE * const ci_keywords = kw_arg->keywords;
VALUE *argv = cfp->sp - calling->argc;
@@ -2122,10 +2130,10 @@ vm_call_iseq_setup_kwparm_nokwarg(rb_execution_context_t *ec, rb_control_frame_t
struct rb_calling_info *calling,
struct rb_call_data *cd)
{
- const struct rb_call_info *MAYBE_UNUSED(ci) = &cd->ci;
+ const struct rb_callinfo *MAYBE_UNUSED(ci) = cd->ci;
const struct rb_call_cache *cc = &cd->cc;
- VM_ASSERT((ci->flag & VM_CALL_KWARG) == 0);
+ VM_ASSERT((vm_ci_flag(ci) & VM_CALL_KWARG) == 0);
RB_DEBUG_COUNTER_INC(ccf_iseq_kw2);
const rb_iseq_t *iseq = def_iseq_ptr(cc->me->def);
@@ -2151,10 +2159,10 @@ static inline int
vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd,
const rb_iseq_t *iseq, VALUE *argv, int param_size, int local_size)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
struct rb_call_cache *cc = &cd->cc;
- if (LIKELY(!(ci->flag & VM_CALL_KW_SPLAT))) {
+ if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
if (LIKELY(rb_simple_iseq_p(iseq))) {
rb_control_frame_t *cfp = ec->cfp;
CALLER_SETUP_ARG(cfp, calling, ci);
@@ -2164,7 +2172,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling,
argument_arity_error(ec, iseq, calling->argc, iseq->body->param.lead_num, iseq->body->param.lead_num);
}
- CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), vm_call_iseq_optimizable_p(&cd->ci, &cd->cc));
+ CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(ci, param_size, local_size), vm_call_iseq_optimizable_p(cd->ci, &cd->cc));
return 0;
}
else if (rb_iseq_only_optparam_p(iseq)) {
@@ -2181,7 +2189,7 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling,
argument_arity_error(ec, iseq, argc, lead_num, lead_num + opt_num);
}
- if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
+ if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
CC_SET_FASTPATH(cc, vm_call_iseq_setup_normal_opt_start,
!IS_ARGS_SPLAT(ci) && !IS_ARGS_KEYWORD(ci) &&
!(METHOD_ENTRY_VISI(cc->me) == METHOD_VISI_PROTECTED));
@@ -2204,8 +2212,8 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling,
const int argc = calling->argc;
const struct rb_iseq_param_keyword *kw_param = iseq->body->param.keyword;
- if (ci->flag & VM_CALL_KWARG) {
- const struct rb_call_info_kw_arg *kw_arg = ((struct rb_call_info_with_kwarg *)ci)->kw_arg;
+ if (vm_ci_flag(ci) & VM_CALL_KWARG) {
+ const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci);
if (argc - kw_arg->keyword_len == lead_num) {
const int ci_kw_len = kw_arg->keyword_len;
@@ -2258,10 +2266,10 @@ static inline VALUE
vm_call_iseq_setup_2(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd,
int opt_pc, int param_size, int local_size)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
const struct rb_call_cache *cc = &cd->cc;
- if (LIKELY(!(ci->flag & VM_CALL_TAILCALL))) {
+ if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_TAILCALL))) {
return vm_call_iseq_setup_normal(ec, cfp, calling, cc->me, opt_pc, param_size, local_size);
}
else {
@@ -2492,7 +2500,7 @@ vm_method_cfunc_entry(const rb_callable_method_entry_t *me)
static VALUE
vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
const struct rb_call_cache *cc = &cd->cc;
VALUE val;
const rb_callable_method_entry_t *me = cc->me;
@@ -2510,7 +2518,7 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp
}
RUBY_DTRACE_CMETHOD_ENTRY_HOOK(ec, me->owner, me->def->original_id);
- EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, ci->mid, me->owner, Qundef);
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_CALL, recv, me->def->original_id, vm_ci_mid(ci), me->owner, Qundef);
vm_push_frame(ec, NULL, frame_type, recv,
block_handler, (VALUE)me,
@@ -2525,7 +2533,7 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp
rb_vm_pop_frame(ec);
- EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, ci->mid, me->owner, val);
+ EXEC_EVENT_HOOK(ec, RUBY_EVENT_C_RETURN, recv, me->def->original_id, vm_ci_mid(ci), me->owner, val);
RUBY_DTRACE_CMETHOD_RETURN_HOOK(ec, me->owner, me->def->original_id);
return val;
@@ -2534,7 +2542,7 @@ vm_call_cfunc_with_frame(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp
static VALUE
vm_call_cfunc(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
RB_DEBUG_COUNTER_INC(ccf_cfunc);
CALLER_SETUP_ARG(reg_cfp, calling, ci);
@@ -2582,7 +2590,7 @@ vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_c
VALUE *argv;
int argc;
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
CALLER_SETUP_ARG(cfp, calling, ci);
argc = calling->argc;
@@ -2594,12 +2602,12 @@ vm_call_bmethod(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_c
}
static enum method_missing_reason
-ci_missing_reason(const struct rb_call_info *ci)
+ci_missing_reason(const struct rb_callinfo *ci)
{
enum method_missing_reason stat = MISSING_NOENTRY;
- if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
- if (ci->flag & VM_CALL_FCALL) stat |= MISSING_FCALL;
- if (ci->flag & VM_CALL_SUPER) stat |= MISSING_SUPER;
+ if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
+ if (vm_ci_flag(ci) & VM_CALL_FCALL) stat |= MISSING_FCALL;
+ if (vm_ci_flag(ci) & VM_CALL_SUPER) stat |= MISSING_SUPER;
return stat;
}
@@ -2610,11 +2618,11 @@ vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
int i;
VALUE sym;
- const struct rb_call_info *orig_ci = &orig_cd->ci;
+ ID mid;
+ const struct rb_callinfo *orig_ci = orig_cd->ci;
const struct rb_call_cache *orig_cc = &orig_cd->cc;
- struct rb_call_info *ci;
struct rb_call_cache *cc;
- struct rb_kwarg_call_data cd;
+ struct rb_call_data cd;
CALLER_SETUP_ARG(reg_cfp, calling, orig_ci);
@@ -2624,31 +2632,22 @@ vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
rb_raise(rb_eArgError, "no method name given");
}
- /* setup new ci */
- if (orig_ci->flag & VM_CALL_KWARG) {
- const struct rb_kwarg_call_data *orig_kcd = (void *)orig_cd;
- cd = *orig_kcd;
- }
- else {
- cd.ci_kw.ci = *orig_ci;
- cd.cc = *orig_cc;
- }
- ci = &cd.ci_kw.ci;
+ cd.cc = *orig_cc;
cc = &cd.cc;
sym = TOPN(i);
- if (!(ci->mid = rb_check_id(&sym))) {
+ if (!(mid = rb_check_id(&sym))) {
if (rb_method_basic_definition_p(CLASS_OF(calling->recv), idMethodMissing)) {
VALUE exc =
rb_make_no_method_exception(rb_eNoMethodError, 0, calling->recv,
rb_long2int(calling->argc), &TOPN(i),
- ci->flag & (VM_CALL_FCALL|VM_CALL_VCALL));
+ vm_ci_flag(orig_ci) & (VM_CALL_FCALL|VM_CALL_VCALL));
rb_exc_raise(exc);
}
TOPN(i) = rb_str_intern(sym);
- ci->mid = idMethodMissing;
- ec->method_missing_reason = cc->aux.method_missing_reason = ci_missing_reason(ci);
+ mid = idMethodMissing;
+ ec->method_missing_reason = cc->aux.method_missing_reason = ci_missing_reason(orig_ci);
}
else {
/* shift arguments */
@@ -2659,20 +2658,22 @@ vm_call_opt_send(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
DEC_SP(1);
}
- CC_SET_ME(cc, rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), ci->mid, NULL));
- ci->flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
+ CC_SET_ME(cc, rb_callable_method_entry_with_refinements(CLASS_OF(calling->recv), mid, NULL));
+ unsigned int new_flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
+ cd.ci = vm_ci_new_runtime(mid, new_flag, 0 /* not accessed (calling->argc is used) */, vm_ci_kwarg(orig_ci));
+
return vm_call_method(ec, reg_cfp, calling, (CALL_DATA)&cd);
}
-static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler);
+static inline VALUE vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE block_handler);
NOINLINE(static VALUE
vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler));
+ struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE block_handler));
static VALUE
vm_invoke_block_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler)
+ struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE block_handler)
{
int argc = calling->argc;
@@ -2688,7 +2689,7 @@ vm_call_opt_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct
{
RB_DEBUG_COUNTER_INC(ccf_opt_call);
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
VALUE procval = calling->recv;
return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, VM_BH_FROM_PROC(procval));
}
@@ -2698,7 +2699,7 @@ vm_call_opt_block_call(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
{
RB_DEBUG_COUNTER_INC(ccf_opt_block_call);
VALUE block_handler = VM_ENV_BLOCK_HANDLER(VM_CF_LEP(reg_cfp));
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
if (BASIC_OP_UNREDEFINED_P(BOP_CALL, PROC_REDEFINED_OP_FLAG)) {
return vm_invoke_block_opt_call(ec, reg_cfp, calling, ci, block_handler);
@@ -2715,22 +2716,19 @@ vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
{
RB_DEBUG_COUNTER_INC(ccf_method_missing);
- const struct rb_call_info *orig_ci = &orig_cd->ci;
+ const struct rb_callinfo *orig_ci = orig_cd->ci;
const struct rb_call_cache *orig_cc = &orig_cd->cc;
VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
struct rb_call_data cd = *orig_cd;
unsigned int argc;
CALLER_SETUP_ARG(reg_cfp, calling, orig_ci);
- argc = calling->argc+1;
-
- cd.ci.flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
- cd.ci.mid = idMethodMissing;
- cd.ci.orig_argc = argc;
+ argc = calling->argc + 1;
- cd.cc.me =
- rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv),
- idMethodMissing, NULL);
+ unsigned int flag = VM_CALL_FCALL | VM_CALL_OPT_SEND | (calling->kw_splat ? VM_CALL_KW_SPLAT : 0);
+ cd.ci = vm_ci_new_runtime(idMethodMissing, flag, argc, vm_ci_kwarg(orig_ci));
+ cd.cc.me = rb_callable_method_entry_without_refinements(CLASS_OF(calling->recv),
+ idMethodMissing, NULL);
calling->argc = argc;
@@ -2740,7 +2738,7 @@ vm_call_method_missing(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
if (argc > 1) {
MEMMOVE(argv+1, argv, VALUE, argc-1);
}
- argv[0] = ID2SYM(orig_ci->mid);
+ argv[0] = ID2SYM(vm_ci_mid(orig_ci));
INC_SP(1);
ec->method_missing_reason = orig_cc->aux.method_missing_reason;
@@ -2753,10 +2751,10 @@ vm_call_zsuper(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_ca
{
RB_DEBUG_COUNTER_INC(ccf_method_missing);
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
struct rb_call_cache *cc = &cd->cc;
klass = RCLASS_SUPER(klass);
- CC_SET_ME(cc, klass ? rb_callable_method_entry(klass, ci->mid) : NULL);
+ CC_SET_ME(cc, klass ? rb_callable_method_entry(klass, vm_ci_mid(ci)) : NULL);
if (!cc->me) {
return vm_call_method_nome(ec, cfp, calling, cd);
@@ -2914,7 +2912,7 @@ search_refined_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, ID mi
static VALUE
vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
struct rb_call_cache *cc = &cd->cc;
switch (cc->me->def->type) {
@@ -2933,7 +2931,7 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
rb_check_arity(calling->argc, 1, 1);
cc->aux.index = 0;
- CC_SET_FASTPATH(cc, vm_call_attrset, !((ci->flag & VM_CALL_ARGS_SPLAT) || (ci->flag & VM_CALL_KWARG)));
+ CC_SET_FASTPATH(cc, vm_call_attrset, !((vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) || (vm_ci_flag(ci) & VM_CALL_KWARG)));
return vm_call_attrset(ec, cfp, calling, cd);
case VM_METHOD_TYPE_IVAR:
@@ -2941,7 +2939,7 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
CALLER_REMOVE_EMPTY_KW_SPLAT(cfp, calling, ci);
rb_check_arity(calling->argc, 0, 0);
cc->aux.index = 0;
- CC_SET_FASTPATH(cc, vm_call_ivar, !(ci->flag & VM_CALL_ARGS_SPLAT));
+ CC_SET_FASTPATH(cc, vm_call_ivar, !(vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT));
return vm_call_ivar(ec, cfp, calling, cd);
case VM_METHOD_TYPE_MISSING:
@@ -2981,7 +2979,7 @@ vm_call_method_each_type(rb_execution_context_t *ec, rb_control_frame_t *cfp, st
return vm_call_zsuper(ec, cfp, calling, cd, RCLASS_ORIGIN(cc->me->defined_class));
case VM_METHOD_TYPE_REFINED:
- if (search_refined_method(ec, cfp, ci->mid, cc))
+ if (search_refined_method(ec, cfp, vm_ci_mid(ci), cc))
return vm_call_method(ec, cfp, calling, cd);
else
return vm_call_method_nome(ec, cfp, calling, cd);
@@ -2996,11 +2994,11 @@ static VALUE
vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
/* method missing */
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
struct rb_call_cache *cc = &cd->cc;
const int stat = ci_missing_reason(ci);
- if (ci->mid == idMethodMissing) {
+ if (vm_ci_mid(ci) == idMethodMissing) {
rb_control_frame_t *reg_cfp = cfp;
VALUE *argv = STACK_ADDR_FROM_TOP(calling->argc);
vm_raise_method_missing(ec, calling->argc, argv, calling->recv, stat);
@@ -3015,7 +3013,7 @@ vm_call_method_nome(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct
static inline VALUE
vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
struct rb_call_cache *cc = &cd->cc;
VM_ASSERT(callable_method_entry_p(cc->me));
@@ -3026,9 +3024,9 @@ vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_ca
return vm_call_method_each_type(ec, cfp, calling, cd);
case METHOD_VISI_PRIVATE:
- if (!(ci->flag & VM_CALL_FCALL)) {
+ if (!(vm_ci_flag(ci) & VM_CALL_FCALL)) {
enum method_missing_reason stat = MISSING_PRIVATE;
- if (ci->flag & VM_CALL_VCALL) stat |= MISSING_VCALL;
+ if (vm_ci_flag(ci) & VM_CALL_VCALL) stat |= MISSING_VCALL;
cc->aux.method_missing_reason = stat;
CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
@@ -3037,7 +3035,7 @@ vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_ca
return vm_call_method_each_type(ec, cfp, calling, cd);
case METHOD_VISI_PROTECTED:
- if (!(ci->flag & VM_CALL_OPT_SEND)) {
+ if (!(vm_ci_flag(ci) & VM_CALL_OPT_SEND)) {
if (!rb_obj_is_kind_of(cfp->self, cc->me->defined_class)) {
cc->aux.method_missing_reason = MISSING_PROTECTED;
return vm_call_method_missing(ec, cfp, calling, cd);
@@ -3045,15 +3043,8 @@ vm_call_method(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_ca
else {
/* caching method info to dummy cc */
VM_ASSERT(cc->me != NULL);
- if (ci->flag & VM_CALL_KWARG) {
- struct rb_kwarg_call_data *kcd = (void *)cd;
- struct rb_kwarg_call_data cd_entry = *kcd;
- return vm_call_method_each_type(ec, cfp, calling, (void *)&cd_entry);
- }
- else {
- struct rb_call_data cd_entry = *cd;
- return vm_call_method_each_type(ec, cfp, calling, &cd_entry);
- }
+ struct rb_call_data cd_entry = *cd;
+ return vm_call_method_each_type(ec, cfp, calling, &cd_entry);
}
}
return vm_call_method_each_type(ec, cfp, calling, cd);
@@ -3111,8 +3102,6 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
{
VALUE current_defined_class, klass;
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(reg_cfp);
- struct rb_call_info *ci = &cd->ci;
- struct rb_call_cache *cc = &cd->cc;
if (!me) {
vm_super_outside();
@@ -3138,22 +3127,29 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
}
}
- if (me->def->type == VM_METHOD_TYPE_BMETHOD && (ci->flag & VM_CALL_ZSUPER)) {
+ if (me->def->type == VM_METHOD_TYPE_BMETHOD && (vm_ci_flag(cd->ci) & VM_CALL_ZSUPER)) {
rb_raise(rb_eRuntimeError,
"implicit argument passing of super from method defined"
" by define_method() is not supported."
" Specify all arguments explicitly.");
}
- ci->mid = me->def->original_id;
+ // update iseq. really? (TODO)
+ cd->ci = vm_ci_new_runtime(me->def->original_id,
+ vm_ci_flag(cd->ci),
+ vm_ci_argc(cd->ci),
+ vm_ci_kwarg(cd->ci));
+ RB_OBJ_WRITTEN(reg_cfp->iseq, Qundef, cd->ci);
+
klass = vm_search_normal_superclass(me->defined_class);
if (!klass) {
/* bound instance method of module */
- cc->aux.method_missing_reason = MISSING_SUPER;
- CC_SET_FASTPATH(cc, vm_call_method_missing, TRUE);
+ cd->cc.aux.method_missing_reason = MISSING_SUPER;
+ CC_SET_FASTPATH(&cd->cc, vm_call_method_missing, TRUE);
}
else {
+ struct rb_call_cache *cc = &cd->cc;
#if OPT_INLINE_METHOD_CACHE
/* Unlike normal method search, we only consider the first class
* serial. Since we're testing defined_class rather than receiver,
@@ -3161,14 +3157,14 @@ vm_search_super_method(const rb_control_frame_t *reg_cfp, struct rb_call_data *c
if (LIKELY(RB_DEBUG_COUNTER_INC_UNLESS(mc_global_state_miss,
GET_GLOBAL_METHOD_STATE() == cc->method_state) &&
cc->class_serial[0] == RCLASS_SERIAL(klass)) &&
- cc->me && ci->mid == cc->me->called_id) {
+ cc->me && vm_ci_mid(cd->ci) == cc->me->called_id) {
VM_ASSERT(cc->call != NULL);
RB_DEBUG_COUNTER_INC(mc_inline_hit);
return;
}
#endif
- CC_SET_ME(cc, rb_callable_method_entry(klass, ci->mid));
+ CC_SET_ME(cc, rb_callable_method_entry(klass, vm_ci_mid(cd->ci)));
CC_SET_FASTPATH(cc, vm_call_super_method, TRUE);
cc->method_state = GET_GLOBAL_METHOD_STATE();
@@ -3267,7 +3263,7 @@ vm_callee_setup_block_arg_arg0_check(VALUE *argv)
}
static int
-vm_callee_setup_block_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t *iseq, VALUE *argv, const enum arg_setup_type arg_setup_type)
+vm_callee_setup_block_arg(rb_execution_context_t *ec, struct rb_calling_info *calling, const struct rb_callinfo *ci, const rb_iseq_t *iseq, VALUE *argv, const enum arg_setup_type arg_setup_type)
{
if (rb_simple_iseq_p(iseq)) {
rb_control_frame_t *cfp = ec->cfp;
@@ -3312,25 +3308,25 @@ static int
vm_yield_setup_args(rb_execution_context_t *ec, const rb_iseq_t *iseq, const int argc, VALUE *argv, int kw_splat, VALUE block_handler, enum arg_setup_type arg_setup_type)
{
struct rb_calling_info calling_entry, *calling;
- struct rb_call_info ci_entry, *ci;
calling = &calling_entry;
calling->argc = argc;
calling->block_handler = block_handler;
calling->kw_splat = kw_splat;
calling->recv = Qundef;
+ struct rb_callinfo dummy_ci = {
+ .flags = T_IMEMO | (imemo_callinfo << FL_USHIFT),
+ .flag = (VALUE)(kw_splat ? VM_CALL_KW_SPLAT : 0),
+ };
- ci_entry.flag = kw_splat ? VM_CALL_KW_SPLAT : 0;
- ci = &ci_entry;
-
- return vm_callee_setup_block_arg(ec, calling, ci, iseq, argv, arg_setup_type);
+ return vm_callee_setup_block_arg(ec, calling, &dummy_ci, iseq, argv, arg_setup_type);
}
/* ruby iseq -> ruby block */
static VALUE
vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling, const struct rb_call_info *ci,
+ struct rb_calling_info *calling, const struct rb_callinfo *ci,
int is_lambda, const struct rb_captured_block *captured)
{
const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq);
@@ -3353,7 +3349,7 @@ vm_invoke_iseq_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
static VALUE
vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling, const struct rb_call_info *ci,
+ struct rb_calling_info *calling, const struct rb_callinfo *ci,
VALUE symbol)
{
VALUE val;
@@ -3367,7 +3363,7 @@ vm_invoke_symbol_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
static VALUE
vm_invoke_ifunc_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling, const struct rb_call_info *ci,
+ struct rb_calling_info *calling, const struct rb_callinfo *ci,
const struct rb_captured_block *captured)
{
VALUE val;
@@ -3401,7 +3397,7 @@ vm_proc_to_block_handler(VALUE procval)
static inline VALUE
vm_invoke_block(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- struct rb_calling_info *calling, const struct rb_call_info *ci, VALUE block_handler)
+ struct rb_calling_info *calling, const struct rb_callinfo *ci, VALUE block_handler)
{
int is_lambda = FALSE;
@@ -3981,7 +3977,7 @@ vm_invokeblock_i(
struct rb_calling_info *calling,
struct rb_call_data *cd)
{
- const struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
VALUE block_handler = VM_CF_BLOCK_HANDLER(GET_CFP());
if (block_handler == VM_BLOCK_HANDLER_NONE) {
@@ -4003,10 +3999,10 @@ vm_sendish(
struct rb_call_data *cd,
VALUE recv))
{
- CALL_INFO ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
CALL_CACHE cc = &cd->cc;
VALUE val;
- int argc = ci->orig_argc;
+ int argc = vm_ci_argc(ci);
VALUE recv = TOPN(argc);
struct rb_calling_info calling;