summaryrefslogtreecommitdiffhomepage
path: root/src/vm.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2017-11-20 06:21:22 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2017-11-20 18:33:41 +0900
commit8f2c62407c0659d84126545e19505a851059e750 (patch)
tree7a073d389fc2f5fc7c14f86ffa96d0145bff9f82 /src/vm.c
parent6c06e77446f3cca4a92b3df8d0a5fe568c5fdc65 (diff)
downloadmruby-8f2c62407c0659d84126545e19505a851059e750.tar.gz
mruby-8f2c62407c0659d84126545e19505a851059e750.zip
Add `MRB_METHOD_TABLE_INLINE` option.
Now the method tables (in classes/modules and caches) keeps C function pointers without wrapping in `struct RProc` objects. For the sake of portability, `mrb_method_t` is represented by the struct and union, but if the most significant bit of the pointer is not used by the platform, `mrb_method_t` should be packed in `uintptr_t` to reduce memory usage. `MRB_METHOD_TABLE_INLINE` is turned on by default for linux.
Diffstat (limited to 'src/vm.c')
-rw-r--r--src/vm.c98
1 files changed, 55 insertions, 43 deletions
diff --git a/src/vm.c b/src/vm.c
index 8dfabdafe..170cb832d 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -400,7 +400,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
mrb->jmp = 0;
}
else {
- struct RProc *p;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci;
int n;
@@ -414,12 +414,12 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%S)", mrb_fixnum_value(argc));
}
c = mrb_class(mrb, self);
- p = mrb_method_search_vm(mrb, &c, mid);
- if (!p) {
+ m = mrb_method_search_vm(mrb, &c, mid);
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
- p = mrb_method_search_vm(mrb, &c, missing);
- if (!p) {
+ m = mrb_method_search_vm(mrb, &c, missing);
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_method_missing(mrb, mid, self, args);
}
mrb_ary_unshift(mrb, args, mrb_symbol_value(mid));
@@ -432,7 +432,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
}
ci = cipush(mrb);
ci->mid = mid;
- ci->proc = p;
ci->stackent = mrb->c->stack;
ci->argc = (int)argc;
ci->target_class = c;
@@ -440,7 +439,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
voff = argv - mrb->c->stbase;
}
- if (MRB_PROC_CFUNC_P(p)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
ci->nregs = (int)(argc + 2);
stack_extend(mrb, ci->nregs);
}
@@ -452,6 +451,8 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
argc = 1;
}
else {
+ struct RProc *p = MRB_METHOD_PROC(m);
+ ci->proc = p;
if (argc < 0) argc = 1;
ci->nregs = (int)(p->body.irep->nregs + argc);
stack_extend(mrb, ci->nregs);
@@ -465,18 +466,18 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
}
mrb->c->stack[argc+1] = blk;
- if (MRB_PROC_CFUNC_P(p)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
int ai = mrb_gc_arena_save(mrb);
ci->acc = CI_ACC_DIRECT;
- val = p->body.func(mrb, self);
+ val = MRB_METHOD_CFUNC(m)(mrb, self);
mrb->c->stack = mrb->c->ci->stackent;
cipop(mrb);
mrb_gc_arena_restore(mrb, ai);
}
else {
ci->acc = CI_ACC_SKIP;
- val = mrb_run(mrb, p, self);
+ val = mrb_run(mrb, MRB_METHOD_PROC(m), self);
}
}
mrb_gc_protect(mrb, val);
@@ -499,7 +500,7 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
ci->proc = p;
ci->target_class = MRB_PROC_TARGET_CLASS(p);
if (MRB_PROC_CFUNC_P(p)) {
- return p->body.func(mrb, self);
+ return MRB_PROC_CFUNC(p)(mrb, self);
}
ci->nregs = p->body.irep->nregs;
if (ci->argc < 0) keep = 3;
@@ -547,7 +548,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
mrb_sym name;
mrb_value block, *argv, *regs;
mrb_int argc, i, len;
- struct RProc *p;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci;
@@ -559,9 +560,8 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
}
c = mrb_class(mrb, self);
- p = mrb_method_search_vm(mrb, &c, name);
-
- if (!p) { /* call method_mising */
+ m = mrb_method_search_vm(mrb, &c, name);
+ if (MRB_METHOD_UNDEF_P(m)) { /* call method_mising */
goto funcall;
}
@@ -579,7 +579,10 @@ mrb_f_send(mrb_state *mrb, mrb_value self)
mrb_ary_shift(mrb, regs[0]);
}
- return mrb_exec_irep(mrb, self, p);
+ if (MRB_METHOD_CFUNC_P(m)) {
+ return MRB_METHOD_CFUNC(m)(mrb, self);
+ }
+ return mrb_exec_irep(mrb, self, MRB_METHOD_PROC(m));
}
static mrb_value
@@ -606,7 +609,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
mrb->c->stack[0] = self;
mrb->c->stack[1] = self;
mrb->c->stack[2] = mrb_nil_value();
- return p->body.func(mrb, self);
+ return MRB_PROC_CFUNC(p)(mrb, self);
}
ci->nregs = p->body.irep->nregs;
stack_extend(mrb, (ci->nregs < 3) ? 3 : ci->nregs);
@@ -725,7 +728,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
mrb->c->stack[argc+1] = mrb_nil_value();
if (MRB_PROC_CFUNC_P(p)) {
- val = p->body.func(mrb, self);
+ val = MRB_PROC_CFUNC(p)(mrb, self);
mrb->c->stack = mrb->c->ci->stackent;
}
else {
@@ -1376,7 +1379,7 @@ RETRY_TRY_BLOCK:
int n = GETARG_C(i);
int argc = (n == CALL_MAXARGS) ? -1 : n;
int bidx = (argc < 0) ? a+2 : a+n+1;
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci = mrb->c->ci;
mrb_value recv, blk;
@@ -1400,10 +1403,10 @@ RETRY_TRY_BLOCK:
}
c = mrb_class(mrb, recv);
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, missing);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1);
ERR_PC_SET(mrb, pc);
mrb_method_missing(mrb, mid, recv, args);
@@ -1423,7 +1426,6 @@ RETRY_TRY_BLOCK:
/* push callinfo */
ci = cipush(mrb);
ci->mid = mid;
- ci->proc = m;
ci->stackent = mrb->c->stack;
ci->target_class = c;
ci->argc = argc;
@@ -1434,9 +1436,17 @@ RETRY_TRY_BLOCK:
/* prepare stack */
mrb->c->stack += a;
- if (MRB_PROC_CFUNC_P(m)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
ci->nregs = (argc < 0) ? 3 : n+2;
- recv = m->body.func(mrb, recv);
+ if (MRB_METHOD_PROC_P(m)) {
+ struct RProc *p = MRB_METHOD_PROC(m);
+
+ ci->proc = p;
+ recv = p->body.func(mrb, recv);
+ }
+ else {
+ recv = MRB_METHOD_FUNC(m)(mrb, recv);
+ }
mrb_gc_arena_restore(mrb, ai);
mrb_gc_arena_shrink(mrb, ai);
if (mrb->exc) goto L_RAISE;
@@ -1471,8 +1481,8 @@ RETRY_TRY_BLOCK:
}
else {
/* setup environment for calling method */
- proc = mrb->c->ci->proc = m;
- irep = m->body.irep;
+ proc = ci->proc = MRB_METHOD_PROC(m);
+ irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
@@ -1511,7 +1521,7 @@ RETRY_TRY_BLOCK:
/* prepare stack */
if (MRB_PROC_CFUNC_P(m)) {
- recv = m->body.func(mrb, recv);
+ recv = MRB_PROC_CFUNC(m)(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
mrb_gc_arena_shrink(mrb, ai);
if (mrb->exc) goto L_RAISE;
@@ -1560,7 +1570,7 @@ RETRY_TRY_BLOCK:
int n = GETARG_C(i);
int argc = (n == CALL_MAXARGS) ? -1 : n;
int bidx = (argc < 0) ? a+2 : a+n+1;
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci = mrb->c->ci;
mrb_value recv, blk;
@@ -1584,10 +1594,10 @@ RETRY_TRY_BLOCK:
}
c = ci->target_class->super;
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, missing);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1);
ERR_PC_SET(mrb, pc);
mrb_method_missing(mrb, mid, recv, args);
@@ -1607,7 +1617,6 @@ RETRY_TRY_BLOCK:
/* push callinfo */
ci = cipush(mrb);
ci->mid = mid;
- ci->proc = m;
ci->stackent = mrb->c->stack;
ci->target_class = c;
ci->pc = pc + 1;
@@ -1617,10 +1626,10 @@ RETRY_TRY_BLOCK:
mrb->c->stack += a;
mrb->c->stack[0] = recv;
- if (MRB_PROC_CFUNC_P(m)) {
+ if (MRB_METHOD_CFUNC_P(m)) {
mrb_value v;
ci->nregs = (argc < 0) ? 3 : n+2;
- v = m->body.func(mrb, recv);
+ v = MRB_METHOD_CFUNC(m)(mrb, recv);
mrb_gc_arena_restore(mrb, ai);
if (mrb->exc) goto L_RAISE;
ci = mrb->c->ci;
@@ -1649,8 +1658,8 @@ RETRY_TRY_BLOCK:
ci->acc = a;
/* setup environment for calling method */
- ci->proc = m;
- irep = m->body.irep;
+ proc = ci->proc = MRB_METHOD_PROC(m);
+ irep = proc->body.irep;
pool = irep->pool;
syms = irep->syms;
ci->nregs = irep->nregs;
@@ -1934,7 +1943,7 @@ RETRY_TRY_BLOCK:
/* Fall through to OP_R_NORMAL otherwise */
if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) {
mrb_callinfo *cibase = mrb->c->cibase;
- dst = top_proc(mrb, proc);
+ dst = top_proc(mrb, proc);
if (MRB_PROC_ENV_P(dst)) {
struct REnv *e = MRB_PROC_ENV(dst);
@@ -2075,7 +2084,7 @@ RETRY_TRY_BLOCK:
int a = GETARG_A(i);
int b = GETARG_B(i);
int n = GETARG_C(i);
- struct RProc *m;
+ mrb_method_t m;
struct RClass *c;
mrb_callinfo *ci;
mrb_value recv;
@@ -2084,11 +2093,11 @@ RETRY_TRY_BLOCK:
recv = regs[a];
c = mrb_class(mrb, recv);
m = mrb_method_search_vm(mrb, &c, mid);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value sym = mrb_symbol_value(mid);
mrb_sym missing = mrb_intern_lit(mrb, "method_missing");
m = mrb_method_search_vm(mrb, &c, missing);
- if (!m) {
+ if (MRB_METHOD_UNDEF_P(m)) {
mrb_value args;
if (n == CALL_MAXARGS) {
@@ -2124,15 +2133,16 @@ RETRY_TRY_BLOCK:
/* move stack */
value_move(mrb->c->stack, &regs[a], ci->argc+1);
- if (MRB_PROC_CFUNC_P(m)) {
- mrb_value v = m->body.func(mrb, recv);
+ if (MRB_METHOD_CFUNC_P(m)) {
+ mrb_value v = MRB_METHOD_CFUNC(m)(mrb, recv);
mrb->c->stack[0] = v;
mrb_gc_arena_restore(mrb, ai);
goto L_RETURN;
}
else {
/* setup environment for calling method */
- irep = m->body.irep;
+ struct RProc *p = MRB_METHOD_PROC(m);
+ irep = p->body.irep;
pool = irep->pool;
syms = irep->syms;
if (ci->argc < 0) {
@@ -2824,8 +2834,10 @@ RETRY_TRY_BLOCK:
int a = GETARG_A(i);
struct RClass *c = mrb_class_ptr(regs[a]);
struct RProc *p = mrb_proc_ptr(regs[a+1]);
+ mrb_method_t m;
- mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p);
+ MRB_METHOD_FROM_PROC(m, p);
+ mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], m);
mrb_gc_arena_restore(mrb, ai);
NEXT;
}