diff options
Diffstat (limited to 'src/vm.c')
| -rw-r--r-- | src/vm.c | 80 |
1 files changed, 58 insertions, 22 deletions
@@ -38,6 +38,16 @@ #define STACK_INIT_SIZE 128 #define CALLINFO_INIT_SIZE 32 +static inline void +stack_copy(mrb_value *dst, const mrb_value *src, size_t size) +{ + int i; + + for (i = 0; i < size; i++) { + dst[i] = src[i]; + } +} + static void stack_init(mrb_state *mrb) { @@ -90,15 +100,16 @@ stack_extend(mrb_state *mrb, int room, int keep) envadjust(mrb, oldbase, mrb->stbase); } if (room > keep) { -#ifndef MRB_NAN_BOXING - memset(mrb->stack+keep, 0, sizeof(mrb_value) * (room-keep)); -#else int i; for (i=keep; i<room; i++) { +#ifndef MRB_NAN_BOXING + static const mrb_value mrb_value_zero = { { 0 } }; + mrb->stack[i] = mrb_value_zero; +#else SET_NIL_VALUE(mrb->stack[i]); - } #endif + } } } @@ -170,7 +181,7 @@ cipop(mrb_state *mrb) mrb_value *p = (mrb_value *)mrb_malloc(mrb, sizeof(mrb_value)*len); e->cioff = -1; - memcpy(p, e->stack, sizeof(mrb_value)*len); + stack_copy(p, e->stack, len); e->stack = p; } @@ -226,7 +237,7 @@ mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, int argc, ...) mrb_value argv[MRB_FUNCALL_ARGC_MAX]; if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=%d)", MRB_FUNCALL_ARGC_MAX); } va_start(ap, argc); @@ -267,7 +278,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr } n = mrb->ci->nregs; if (argc < 0) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); + mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative argc for funcall (%d)", argc); } c = mrb_class(mrb, self); p = mrb_method_search_vm(mrb, &c, mid); @@ -296,10 +307,10 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr mrb->stack[0] = self; if (undef) { mrb->stack[1] = mrb_symbol_value(undef); - memcpy(mrb->stack+2, argv, sizeof(mrb_value)*(argc-1)); + stack_copy(mrb->stack+2, argv, argc-1); } else if (argc > 0) { - memcpy(mrb->stack+1, argv, sizeof(mrb_value)*argc); + stack_copy(mrb->stack+1, argv, argc); } mrb->stack[argc+1] = blk; @@ -351,7 +362,7 @@ mrb_yield_internal(mrb_state *mrb, mrb_value b, int argc, mrb_value *argv, mrb_v stack_extend(mrb, ci->nregs, 0); mrb->stack[0] = self; if (argc > 0) { - memcpy(mrb->stack+1, argv, sizeof(mrb_value)*argc); + stack_copy(mrb->stack+1, argv, argc); } mrb->stack[argc+1] = mrb_nil_value(); @@ -455,7 +466,6 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) int ai = mrb->arena_idx; jmp_buf *prev_jmp = (jmp_buf *)mrb->jmp; jmp_buf c_jmp; - ptrdiff_t ciidx = mrb->ci - mrb->cibase; #ifdef DIRECT_THREADED static void *optable[] = { @@ -990,12 +1000,12 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) } regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); rest = mrb_ary_ptr(regs[a]); - memcpy(rest->ptr, stack, sizeof(mrb_value)*m1); + stack_copy(rest->ptr, stack, m1); if (len > 0) { - memcpy(rest->ptr+m1, pp, sizeof(mrb_value)*len); + stack_copy(rest->ptr+m1, pp, len); } if (m2 > 0) { - memcpy(rest->ptr+m1+len, stack+m1+1, sizeof(mrb_value)*m2); + stack_copy(rest->ptr+m1+len, stack+m1+1, m2); } rest->len = m1+len+m2; } @@ -1096,14 +1106,10 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci; eidx = mrb->ci->eidx; if (ci == mrb->cibase) goto L_STOP; - if (ciidx == ci - mrb->cibase){ - mrb->jmp = prev_jmp; - longjmp(*(jmp_buf*)mrb->jmp, 1); - } while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->ci; - if (ci->acc < 0) { + if (ci[1].acc < 0 && prev_jmp) { mrb->jmp = prev_jmp; longjmp(*(jmp_buf*)mrb->jmp, 1); } @@ -1131,6 +1137,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) switch (GETARG_B(i)) { case OP_R_NORMAL: + NORMAL_RETURN: if (ci == mrb->cibase) { localjump_error(mrb, "return"); goto L_RAISE; @@ -1145,6 +1152,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) ci = mrb->ci = mrb->cibase + proc->env->cioff + 1; break; case OP_R_RETURN: + if (!proc->env) goto NORMAL_RETURN; if (proc->env->cioff < 0) { localjump_error(mrb, "return"); goto L_RAISE; @@ -1436,7 +1444,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) /* need to check if + is overridden */ switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: - regs[a].attr_i += GETARG_C(i); + { + mrb_int x = regs[a].attr_i; + mrb_int y = GETARG_C(i); + mrb_int z = x + y; + + if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { + /* integer overflow */ + SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y); + break; + } + regs[a].attr_i = z; + } break; case MRB_TT_FLOAT: regs[a].attr_f += GETARG_C(i); @@ -1456,7 +1475,18 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) /* need to check if + is overridden */ switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: - regs[a].attr_i -= GETARG_C(i); + { + mrb_int x = regs[a].attr_i; + mrb_int y = GETARG_C(i); + mrb_int z = x - y; + + if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { + /* integer overflow */ + SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y); + break; + } + regs[a].attr_i = z; + } break; case MRB_TT_FLOAT: regs[a].attr_f -= GETARG_C(i); @@ -1820,8 +1850,14 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) CASE(OP_ERR) { /* Bx raise RuntimeError with message Lit(Bx) */ mrb_value msg = pool[GETARG_Bx(i)]; - mrb_value exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, msg); + mrb_value exc; + if (GETARG_A(i) == 0) { + exc = mrb_exc_new3(mrb, E_RUNTIME_ERROR, msg); + } + else { + exc = mrb_exc_new3(mrb, E_LOCALJUMP_ERROR, msg); + } mrb->exc = (struct RObject*)mrb_object(exc); goto L_RAISE; } |
