Skip to content

Commit

Permalink
Avoid clearing VM stack every time to gain performance.
Browse files Browse the repository at this point in the history
VM stack is cleared by 5c114c9, 0cb501 and c063641.
  • Loading branch information
matz committed Apr 10, 2017
1 parent 5c114c9 commit ab25eae
Showing 1 changed file with 36 additions and 41 deletions.
77 changes: 36 additions & 41 deletions src/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,22 +132,15 @@ envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
}
}

static inline void
init_new_stack_space(mrb_state *mrb, int room, int keep)
{
if (room > keep) {
/* do not leave uninitialized malloc region */
stack_clear(&(mrb->c->stack[keep]), room - keep);
}
}

/** def rec ; $deep =+ 1 ; if $deep > 1000 ; return 0 ; end ; rec ; end */

static void
stack_extend_alloc(mrb_state *mrb, int room, int keep)
stack_extend_alloc(mrb_state *mrb, int room)
{
mrb_value *oldbase = mrb->c->stbase;
size_t size = mrb->c->stend - mrb->c->stbase;
mrb_value *newstack;
size_t oldsize = mrb->c->stend - mrb->c->stbase;
size_t size = oldsize;
size_t off = mrb->c->stack - mrb->c->stbase;

if (off > size) size = off;
Expand All @@ -166,29 +159,29 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep)
size += room;
#endif

mrb->c->stbase = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
newstack = (mrb_value *)mrb_realloc(mrb, mrb->c->stbase, sizeof(mrb_value) * size);
if (newstack == NULL) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
}
stack_clear(&(newstack[oldsize]), size - oldsize);
mrb->c->stbase = newstack;
mrb->c->stack = mrb->c->stbase + off;
mrb->c->stend = mrb->c->stbase + size;
envadjust(mrb, oldbase, mrb->c->stbase);

/* Raise an exception if the new stack size will be too large,
to prevent infinite recursion. However, do this only after resizing the stack, so mrb_raise has stack space to work with. */
if (size > MRB_STACK_MAX) {
init_new_stack_space(mrb, room, keep);
mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err));
}
}

static inline void
stack_extend(mrb_state *mrb, int room, int keep)
stack_extend(mrb_state *mrb, int room)
{
if (room < keep) {
room = keep;
}
if (mrb->c->stack + room >= mrb->c->stend) {
stack_extend_alloc(mrb, room, keep);
stack_extend_alloc(mrb, room);
}
init_new_stack_space(mrb, room, keep);
}

static inline struct REnv*
Expand Down Expand Up @@ -419,19 +412,19 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
}
if (MRB_PROC_CFUNC_P(p)) {
ci->nregs = argc + 2;
stack_extend(mrb, ci->nregs, 0);
stack_extend(mrb, ci->nregs);
}
else if (argc >= CALL_MAXARGS) {
mrb_value args = mrb_ary_new_from_values(mrb, argc, argv);
stack_extend(mrb, ci->nregs, 0);
stack_extend(mrb, ci->nregs);
mrb->c->stack[1] = args;
ci->argc = -1;
argc = 1;
}
else {
if (argc < 0) argc = 1;
ci->nregs = p->body.irep->nregs + argc;
stack_extend(mrb, ci->nregs, argc+2);
stack_extend(mrb, ci->nregs);
}
if (voff >= 0) {
argv = mrb->c->stbase + voff;
Expand Down Expand Up @@ -477,10 +470,10 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p)
return p->body.func(mrb, self);
}
if (ci->argc < 0) {
stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs, 3);
stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs);
}
else {
stack_extend(mrb, p->body.irep->nregs, ci->argc+2);
stack_extend(mrb, p->body.irep->nregs);
}

ci->nregs = p->body.irep->nregs;
Expand Down Expand Up @@ -574,15 +567,15 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
ci->argc = 1;
ci->mid = ci[-1].mid;
if (MRB_PROC_CFUNC_P(p)) {
stack_extend(mrb, 3, 0);
stack_extend(mrb, 3);
mrb->c->stack[0] = self;
mrb->c->stack[1] = self;
mrb->c->stack[2] = mrb_nil_value();
return p->body.func(mrb, self);
}
ci->nregs = p->body.irep->nregs;
if (max < ci->nregs) max = ci->nregs;
stack_extend(mrb, max, 0);
stack_extend(mrb, max);
mrb->c->stack[0] = self;
mrb->c->stack[1] = self;
mrb->c->stack[2] = mrb_nil_value();
Expand Down Expand Up @@ -688,11 +681,11 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
mrb->c->stack = mrb->c->stack + n;
if (MRB_PROC_CFUNC_P(p)) {
ci->nregs = argc + 2;
stack_extend(mrb, ci->nregs, 0);
stack_extend(mrb, ci->nregs);
}
else {
ci->nregs = p->body.irep->nregs;
stack_extend(mrb, ci->nregs, argc+2);
stack_extend(mrb, ci->nregs);
}

mrb->c->stack[0] = self;
Expand Down Expand Up @@ -824,7 +817,9 @@ mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stac
if (!mrb->c->stack) {
stack_init(mrb);
}
stack_extend(mrb, irep->nregs, stack_keep);
if (stack_keep < irep->nregs)
stack_keep = irep->nregs;
stack_extend(mrb, stack_keep);
mrb->c->stack[0] = self;
return mrb_vm_exec(mrb, proc, irep->iseq);
}
Expand Down Expand Up @@ -1210,7 +1205,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
mrb_value blk = regs[bidx];
if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
if (bidx >= mrb->c->ci->nregs) {
stack_extend(mrb, bidx+1, mrb->c->ci->nregs);
stack_extend(mrb, bidx+1);
mrb->c->ci->nregs = bidx+1;
}
regs[bidx] = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
Expand Down Expand Up @@ -1239,7 +1234,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
mrb_value blk = regs[bidx];

if (a+2 > irep->nregs) {
stack_extend(mrb, a+2, a+n+1);
stack_extend(mrb, a+2);
}
regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1);
regs[a+2] = blk;
Expand Down Expand Up @@ -1303,11 +1298,11 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
ci->nregs = irep->nregs;
if (n == CALL_MAXARGS) {
ci->argc = -1;
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
}
else {
ci->argc = n;
stack_extend(mrb, irep->nregs, n+2);
stack_extend(mrb, irep->nregs);
}
pc = irep->iseq;
JUMP;
Expand Down Expand Up @@ -1366,10 +1361,10 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
syms = irep->syms;
ci->nregs = irep->nregs;
if (ci->argc < 0) {
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
}
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
stack_extend(mrb, irep->nregs);
}
if (m->env) {
regs[0] = m->env->stack[0];
Expand Down Expand Up @@ -1438,7 +1433,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
blk = regs[bidx];
if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) {
if (bidx >= ci->nregs) {
stack_extend(mrb, bidx+1, ci->nregs);
stack_extend(mrb, bidx+1);
ci->nregs = bidx+1;
}
regs[bidx] = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc");
Expand Down Expand Up @@ -1491,10 +1486,10 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
syms = irep->syms;
ci->nregs = irep->nregs;
if (n == CALL_MAXARGS) {
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
}
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
stack_extend(mrb, irep->nregs);
}
pc = irep->iseq;
JUMP;
Expand Down Expand Up @@ -1900,10 +1895,10 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
pool = irep->pool;
syms = irep->syms;
if (ci->argc < 0) {
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs, 3);
stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs);
}
else {
stack_extend(mrb, irep->nregs, ci->argc+2);
stack_extend(mrb, irep->nregs);
}
pc = irep->iseq;
}
Expand Down Expand Up @@ -2527,7 +2522,7 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc)
irep = p->body.irep;
pool = irep->pool;
syms = irep->syms;
stack_extend(mrb, irep->nregs, 1);
stack_extend(mrb, irep->nregs);
ci->nregs = irep->nregs;
pc = irep->iseq;
JUMP;
Expand Down

0 comments on commit ab25eae

Please sign in to comment.