diff options
Diffstat (limited to 'src/vm.c')
| -rw-r--r-- | src/vm.c | 353 |
1 files changed, 177 insertions, 176 deletions
@@ -1,4 +1,4 @@ - /* +/* ** vm.c - virtual machine for mruby ** ** See Copyright Notice in mruby.h @@ -7,22 +7,22 @@ #include <stddef.h> #include <stdarg.h> #include <math.h> -#include "mruby.h" -#include "mruby/array.h" -#include "mruby/class.h" -#include "mruby/hash.h" -#include "mruby/irep.h" -#include "mruby/numeric.h" -#include "mruby/proc.h" -#include "mruby/range.h" -#include "mruby/string.h" -#include "mruby/variable.h" -#include "mruby/error.h" -#include "mruby/opcode.h" +#include <mruby.h> +#include <mruby/array.h> +#include <mruby/class.h> +#include <mruby/hash.h> +#include <mruby/irep.h> +#include <mruby/numeric.h> +#include <mruby/proc.h> +#include <mruby/range.h> +#include <mruby/string.h> +#include <mruby/variable.h> +#include <mruby/error.h> +#include <mruby/opcode.h> #include "value_array.h" -#include "mrb_throw.h" +#include <mruby/throw.h> -#ifndef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO #if defined(__cplusplus) extern "C" { #endif @@ -32,20 +32,6 @@ void abort(void); #endif #endif -#define SET_TRUE_VALUE(r) MRB_SET_VALUE(r, MRB_TT_TRUE, value.i, 1) -#define SET_FALSE_VALUE(r) MRB_SET_VALUE(r, MRB_TT_FALSE, value.i, 1) -#define SET_NIL_VALUE(r) MRB_SET_VALUE(r, MRB_TT_FALSE, value.i, 0) -#define SET_INT_VALUE(r,n) MRB_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n)) -#define SET_SYM_VALUE(r,v) MRB_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) -#define SET_OBJ_VALUE(r,v) MRB_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) -#ifdef MRB_NAN_BOXING -#define SET_FLT_VALUE(mrb,r,v) r.f = (v) -#elif defined(MRB_WORD_BOXING) -#define SET_FLT_VALUE(mrb,r,v) r = mrb_float_value(mrb, (v)) -#else -#define SET_FLT_VALUE(mrb,r,v) MRB_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v)) -#endif - #define STACK_INIT_SIZE 128 #define CALLINFO_INIT_SIZE 32 @@ -66,10 +52,7 @@ The value below allows about 60000 recursive calls in the simplest case. */ # define DEBUG(x) #endif -#define TO_STR(x) TO_STR_(x) -#define TO_STR_(x) #x - -#define ARENA_RESTORE(mrb,ai) (mrb)->arena_idx = (ai) +#define ARENA_RESTORE(mrb,ai) (mrb)->gc.arena_idx = (ai) static inline void stack_clear(mrb_value *from, size_t count) @@ -174,7 +157,7 @@ stack_extend_alloc(mrb_state *mrb, int room, int keep) 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_raise(mrb, E_RUNTIME_ERROR, "stack level too deep. (limit=" TO_STR(MRB_STACK_MAX) ")"); + mrb_raise(mrb, E_SYSSTACK_ERROR, "stack level too deep. (limit=" MRB_STRINGIZE(MRB_STACK_MAX) ")"); } } @@ -237,14 +220,13 @@ cipush(mrb_state *mrb) int ridx = ci->ridx; if (ci + 1 == c->ciend) { - size_t size = ci - c->cibase; + ptrdiff_t size = ci - c->cibase; c->cibase = (mrb_callinfo *)mrb_realloc(mrb, c->cibase, sizeof(mrb_callinfo)*size*2); c->ci = c->cibase + size; c->ciend = c->cibase + size * 2; } ci = ++c->ci; - ci->nregs = 2; /* protect method_missing arg and block */ ci->eidx = eidx; ci->ridx = ridx; ci->env = 0; @@ -270,6 +252,7 @@ cipop(mrb_state *mrb) stack_copy(p, e->stack, len); } e->stack = p; + mrb_write_barrier(mrb, (struct RBasic *)e); } c->ci--; @@ -283,6 +266,7 @@ ecall(mrb_state *mrb, int i) mrb_value *self = mrb->c->stack; struct RObject *exc; + if (i<0) return; p = mrb->c->ensure[i]; if (!p) return; if (mrb->c->ci->eidx > i) @@ -306,49 +290,34 @@ ecall(mrb_state *mrb, int i) #define MRB_FUNCALL_ARGC_MAX 16 #endif -mrb_value +MRB_API mrb_value mrb_funcall(mrb_state *mrb, mrb_value self, const char *name, mrb_int argc, ...) { + mrb_value argv[MRB_FUNCALL_ARGC_MAX]; + va_list ap; + mrb_int i; mrb_sym mid = mrb_intern_cstr(mrb, name); - if (argc == 0) { - return mrb_funcall_argv(mrb, self, mid, 0, 0); - } - else if (argc == 1) { - mrb_value v; - va_list ap; - - va_start(ap, argc); - v = va_arg(ap, mrb_value); - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, 1, &v); + if (argc > MRB_FUNCALL_ARGC_MAX) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" MRB_STRINGIZE(MRB_FUNCALL_ARGC_MAX) ")"); } - else { - mrb_value argv[MRB_FUNCALL_ARGC_MAX]; - va_list ap; - mrb_int i; - - if (argc > MRB_FUNCALL_ARGC_MAX) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "Too long arguments. (limit=" TO_STR(MRB_FUNCALL_ARGC_MAX) ")"); - } - va_start(ap, argc); - for (i = 0; i < argc; i++) { - argv[i] = va_arg(ap, mrb_value); - } - va_end(ap); - return mrb_funcall_argv(mrb, self, mid, argc, argv); + va_start(ap, argc); + for (i = 0; i < argc; i++) { + argv[i] = va_arg(ap, mrb_value); } + va_end(ap); + return mrb_funcall_argv(mrb, self, mid, argc, argv); } -mrb_value +MRB_API mrb_value mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv, mrb_value blk) { mrb_value val; if (!mrb->jmp) { struct mrb_jmpbuf c_jmp; - mrb_callinfo *old_ci = mrb->c->ci; + ptrdiff_t nth_ci = mrb->c->ci - mrb->c->cibase; MRB_TRY(&c_jmp) { mrb->jmp = &c_jmp; @@ -357,7 +326,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb->jmp = 0; } MRB_CATCH(&c_jmp) { /* error */ - while (old_ci != mrb->c->ci) { + while (nth_ci < (mrb->c->ci - mrb->c->cibase)) { mrb->c->stack = mrb->c->ci->stackent; cipop(mrb); } @@ -372,6 +341,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb_sym undef = 0; mrb_callinfo *ci; int n; + ptrdiff_t voff = -1; if (!mrb->c->stack) { stack_init(mrb); @@ -395,6 +365,9 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ci->argc = argc; ci->target_class = c; mrb->c->stack = mrb->c->stack + n; + if (mrb->c->stbase <= argv && argv < mrb->c->stend) { + voff = argv - mrb->c->stbase; + } if (MRB_PROC_CFUNC_P(p)) { ci->nregs = argc + 2; stack_extend(mrb, ci->nregs, 0); @@ -403,6 +376,9 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc ci->nregs = p->body.irep->nregs + n; stack_extend(mrb, ci->nregs, argc+2); } + if (voff >= 0) { + argv = mrb->c->stbase + voff; + } mrb->c->stack[0] = self; if (undef) { mrb->c->stack[1] = mrb_symbol_value(undef); @@ -433,7 +409,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc return val; } -mrb_value +MRB_API mrb_value mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, const mrb_value *argv) { return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); @@ -458,7 +434,7 @@ mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, cons * k = Klass.new * k.send :hello, "gentle", "readers" #=> "Hello gentle readers" */ -mrb_value +MRB_API mrb_value mrb_f_send(mrb_state *mrb, mrb_value self) { mrb_sym name; @@ -497,8 +473,16 @@ mrb_f_send(mrb_state *mrb, mrb_value self) return p->body.func(mrb, self); } + if (ci->argc < 0) { + stack_extend(mrb, (p->body.irep->nregs < 3) ? 3 : p->body.irep->nregs, 3); + } + else { + stack_extend(mrb, p->body.irep->nregs, ci->argc+2); + } + ci->nregs = p->body.irep->nregs; ci = cipush(mrb); + ci->nregs = 0; ci->target_class = 0; ci->pc = p->body.irep->iseq; ci->stackent = mrb->c->stack; @@ -513,6 +497,9 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) struct RProc *p; mrb_callinfo *ci; + if (mrb_nil_p(blk)) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); + } ci = mrb->c->ci; if (ci->acc == CI_ACC_DIRECT) { return mrb_yield_with_class(mrb, blk, 0, 0, self, c); @@ -525,6 +512,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) } ci->nregs = p->body.irep->nregs; ci = cipush(mrb); + ci->nregs = 0; ci->target_class = 0; ci->pc = p->body.irep->iseq; ci->stackent = mrb->c->stack; @@ -599,7 +587,7 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) return eval_under(mrb, self, b, c); } -mrb_value +MRB_API mrb_value mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c) { struct RProc *p; @@ -646,7 +634,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value return val; } -mrb_value +MRB_API mrb_value mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv) { struct RProc *p = mrb_proc_ptr(b); @@ -654,7 +642,7 @@ mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv) return mrb_yield_with_class(mrb, b, argc, argv, p->env->stack[0], p->target_class); } -mrb_value +MRB_API mrb_value mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg) { struct RProc *p = mrb_proc_ptr(b); @@ -705,7 +693,7 @@ argnum_error(mrb_state *mrb, mrb_int num) #define ERR_PC_SET(mrb, pc) mrb->c->ci->err = pc; #define ERR_PC_CLR(mrb) mrb->c->ci->err = 0; -#ifdef ENABLE_DEBUG +#ifdef MRB_ENABLE_DEBUG_HOOK #define CODE_FETCH_HOOK(mrb, irep, pc, regs) if ((mrb)->code_fetch_hook) (mrb)->code_fetch_hook((mrb), (irep), (pc), (regs)); #else #define CODE_FETCH_HOOK(mrb, irep, pc, regs) @@ -734,12 +722,11 @@ argnum_error(mrb_state *mrb, mrb_int num) #endif -mrb_value mrb_gv_val_get(mrb_state *mrb, mrb_sym sym); -void mrb_gv_val_set(mrb_state *mrb, mrb_sym sym, mrb_value val); - #define CALL_MAXARGS 127 -mrb_value +void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value args); + +MRB_API mrb_value mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep) { /* mrb_assert(mrb_proc_cfunc_p(proc)) */ @@ -1046,7 +1033,7 @@ RETRY_TRY_BLOCK: mrb_callinfo *ci = mrb->c->ci; int n, eidx = ci->eidx; - for (n=0; n<a && eidx > ci[-1].eidx; n++) { + for (n=0; n<a && (ci == mrb->c->cibase || eidx > ci[-1].eidx); n++) { ecall(mrb, --eidx); ARENA_RESTORE(mrb, ai); } @@ -1090,9 +1077,21 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &c, mid); if (!m) { mrb_value sym = mrb_symbol_value(mid); + mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); - mid = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, mid); + m = mrb_method_search_vm(mrb, &c, missing); + if (!m) { + mrb_value args; + + if (n == CALL_MAXARGS) { + args = regs[a+1]; + } + else { + args = mrb_ary_new_from_values(mrb, n, regs+a+1); + } + mrb_method_missing(mrb, mid, recv, args); + } + mid = missing; if (n == CALL_MAXARGS) { mrb_ary_unshift(mrb, regs[a+1], sym); } @@ -1107,12 +1106,7 @@ RETRY_TRY_BLOCK: ci->mid = mid; ci->proc = m; ci->stackent = mrb->c->stack; - if (c->tt == MRB_TT_ICLASS) { - ci->target_class = c->c; - } - else { - ci->target_class = c; - } + ci->target_class = c; ci->pc = pc + 1; ci->acc = a; @@ -1243,6 +1237,13 @@ RETRY_TRY_BLOCK: int a = GETARG_A(i); int n = GETARG_C(i); + if (mid == 0) { + mrb_value exc; + + exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); + mrb->exc = mrb_obj_ptr(exc); + goto L_RAISE; + } recv = regs[0]; c = mrb->c->ci->target_class->super; m = mrb_method_search_vm(mrb, &c, mid); @@ -1277,6 +1278,12 @@ RETRY_TRY_BLOCK: mrb->c->stack[0] = recv; if (MRB_PROC_CFUNC_P(m)) { + if (n == CALL_MAXARGS) { + ci->nregs = 3; + } + else { + ci->nregs = n + 2; + } mrb->c->stack[0] = m->body.func(mrb, recv); mrb_gc_arena_restore(mrb, ai); if (mrb->exc) goto L_RAISE; @@ -1322,6 +1329,7 @@ RETRY_TRY_BLOCK: struct REnv *e = uvenv(mrb, lv-1); if (!e) { mrb_value exc; + exc = mrb_exc_new_str_lit(mrb, E_NOMETHOD_ERROR, "super called outside of method"); mrb->exc = mrb_obj_ptr(exc); goto L_RAISE; @@ -1364,14 +1372,14 @@ RETRY_TRY_BLOCK: /* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */ /* number of optional arguments times OP_JMP should follow */ mrb_aspec ax = GETARG_Ax(i); - int m1 = (ax>>18)&0x1f; - int o = (ax>>13)&0x1f; - int r = (ax>>12)&0x1; - int m2 = (ax>>7)&0x1f; + int m1 = MRB_ASPEC_REQ(ax); + int o = MRB_ASPEC_OPT(ax); + int r = MRB_ASPEC_REST(ax); + int m2 = MRB_ASPEC_POST(ax); /* unused - int k = (ax>>2)&0x1f; - int kd = (ax>>1)&0x1; - int b = (ax>>0)& 0x1; + int k = MRB_ASPEC_KEY(ax); + int kd = MRB_ASPEC_KDICT(ax); + int b = MRB_ASPEC_BLOCK(ax); */ int argc = mrb->c->ci->argc; mrb_value *argv = regs+1; @@ -1478,9 +1486,6 @@ RETRY_TRY_BLOCK: if (ci->ridx == 0) goto L_STOP; goto L_RESCUE; } - while (eidx > ci[-1].eidx) { - ecall(mrb, --eidx); - } while (ci[0].ridx == ci[-1].ridx) { cipop(mrb); ci = mrb->c->ci; @@ -1489,12 +1494,10 @@ RETRY_TRY_BLOCK: mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } - if (ci > mrb->c->cibase) { - while (eidx > ci[-1].eidx) { + if (ci == mrb->c->cibase) { + while (eidx > 0) { ecall(mrb, --eidx); } - } - else if (ci == mrb->c->cibase) { if (ci->ridx == 0) { if (mrb->c == mrb->root_c) { regs = mrb->c->stack = mrb->c->stbase; @@ -1510,6 +1513,12 @@ RETRY_TRY_BLOCK: } break; } + /* call ensure only when we skip this callinfo */ + if (ci[0].ridx == ci[-1].ridx) { + while (eidx > ci[-1].eidx) { + ecall(mrb, --eidx); + } + } } L_RESCUE: if (ci->ridx == 0) goto L_STOP; @@ -1540,6 +1549,7 @@ RETRY_TRY_BLOCK: localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; } + mrb->c->stack = mrb->c->ci->stackent; mrb->c->ci = ci; break; } @@ -1574,6 +1584,7 @@ RETRY_TRY_BLOCK: c->prev = NULL; } ci = mrb->c->ci; + mrb->c->stack = ci->stackent; mrb->c->ci = mrb->c->cibase + proc->env->cioff + 1; while (ci > mrb->c->ci) { if (ci[-1].acc == CI_ACC_SKIP) { @@ -1695,18 +1706,9 @@ RETRY_TRY_BLOCK: NEXT; } -#define attr_i value.i -#ifdef MRB_NAN_BOXING -#define attr_f f -#elif defined(MRB_WORD_BOXING) -#define attr_f value.fp->f -#else -#define attr_f value.f -#endif - #define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff)) #define OP_MATH_BODY(op,v1,v2) do {\ - regs[a].v1 = regs[a].v1 op regs[a+1].v2;\ + v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\ } while(0) CASE(OP_ADD) { @@ -1723,7 +1725,7 @@ RETRY_TRY_BLOCK: x = mrb_fixnum(regs_a[0]); y = mrb_fixnum(regs_a[1]); if (mrb_int_add_overflow(x, y, &z)) { - SET_FLT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y); + SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y); break; } SET_INT_VALUE(regs[a], z); @@ -1733,7 +1735,7 @@ RETRY_TRY_BLOCK: { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x + y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): @@ -1741,10 +1743,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x + y); + SET_FLOAT_VALUE(mrb, regs[a], x + y); } #else - OP_MATH_BODY(+,attr_f,attr_i); + OP_MATH_BODY(+,mrb_float,mrb_fixnum); #endif break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): @@ -1752,10 +1754,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x + y); + SET_FLOAT_VALUE(mrb, regs[a], x + y); } #else - OP_MATH_BODY(+,attr_f,attr_f); + OP_MATH_BODY(+,mrb_float,mrb_float); #endif break; case TYPES2(MRB_TT_STRING,MRB_TT_STRING): @@ -1781,7 +1783,7 @@ RETRY_TRY_BLOCK: x = mrb_fixnum(regs[a]); y = mrb_fixnum(regs[a+1]); if (mrb_int_sub_overflow(x, y, &z)) { - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y); break; } SET_INT_VALUE(regs[a], z); @@ -1791,7 +1793,7 @@ RETRY_TRY_BLOCK: { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x - y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): @@ -1799,10 +1801,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x - y); + SET_FLOAT_VALUE(mrb, regs[a], x - y); } #else - OP_MATH_BODY(-,attr_f,attr_i); + OP_MATH_BODY(-,mrb_float,mrb_fixnum); #endif break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): @@ -1810,10 +1812,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x - y); + SET_FLOAT_VALUE(mrb, regs[a], x - y); } #else - OP_MATH_BODY(-,attr_f,attr_f); + OP_MATH_BODY(-,mrb_float,mrb_float); #endif break; default: @@ -1842,7 +1844,7 @@ RETRY_TRY_BLOCK: break; case MRB_TT_FLOAT: { - SET_FLT_VALUE(mrb, regs[a], mrb_float(z)); + SET_FLOAT_VALUE(mrb, regs[a], mrb_float(z)); } break; default: @@ -1855,7 +1857,7 @@ RETRY_TRY_BLOCK: { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x * y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): @@ -1863,10 +1865,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x * y); + SET_FLOAT_VALUE(mrb, regs[a], x * y); } #else - OP_MATH_BODY(*,attr_f,attr_i); + OP_MATH_BODY(*,mrb_float,mrb_fixnum); #endif break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): @@ -1874,10 +1876,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x * y); + SET_FLOAT_VALUE(mrb, regs[a], x * y); } #else - OP_MATH_BODY(*,attr_f,attr_f); + OP_MATH_BODY(*,mrb_float,mrb_float); #endif break; default: @@ -1896,14 +1898,14 @@ RETRY_TRY_BLOCK: { mrb_int x = mrb_fixnum(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); } break; case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): { mrb_int x = mrb_fixnum(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x / y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x / y); } break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): @@ -1911,10 +1913,10 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_int y = mrb_fixnum(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x / y); + SET_FLOAT_VALUE(mrb, regs[a], x / y); } #else - OP_MATH_BODY(/,attr_f,attr_i); + OP_MATH_BODY(/,mrb_float,mrb_fixnum); #endif break; case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): @@ -1922,18 +1924,18 @@ RETRY_TRY_BLOCK: { mrb_float x = mrb_float(regs[a]); mrb_float y = mrb_float(regs[a+1]); - SET_FLT_VALUE(mrb, regs[a], x / y); + SET_FLOAT_VALUE(mrb, regs[a], x / y); } #else - OP_MATH_BODY(/,attr_f,attr_f); + OP_MATH_BODY(/,mrb_float,mrb_float); #endif break; default: goto L_SEND; } #ifdef MRB_NAN_BOXING - if (isnan(regs[a].attr_f)) { - regs[a] = mrb_float_value(mrb, regs[a].attr_f); + if (isnan(mrb_float(regs[a]))) { + regs[a] = mrb_float_value(mrb, mrb_float(regs[a])); } #endif NEXT; @@ -1947,25 +1949,25 @@ RETRY_TRY_BLOCK: switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: { - mrb_int x = regs[a].attr_i; + mrb_int x = mrb_fixnum(regs[a]); mrb_int y = GETARG_C(i); mrb_int z; if (mrb_int_add_overflow(x, y, &z)) { - SET_FLT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y); break; } - regs[a].attr_i = z; + SET_INT_VALUE(regs[a], z); } break; case MRB_TT_FLOAT: #ifdef MRB_WORD_BOXING { mrb_float x = mrb_float(regs[a]); - SET_FLT_VALUE(mrb, regs[a], x + GETARG_C(i)); + SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i)); } #else - regs[a].attr_f += GETARG_C(i); + mrb_float(regs[a]) += GETARG_C(i); #endif break; default: @@ -1985,15 +1987,15 @@ RETRY_TRY_BLOCK: switch (mrb_type(regs_a[0])) { case MRB_TT_FIXNUM: { - mrb_int x = regs_a[0].attr_i; + mrb_int x = mrb_fixnum(regs_a[0]); mrb_int y = GETARG_C(i); mrb_int z; if (mrb_int_sub_overflow(x, y, &z)) { - SET_FLT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y); + SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y); } else { - regs_a[0].attr_i = z; + SET_INT_VALUE(regs_a[0], z); } } break; @@ -2001,10 +2003,10 @@ RETRY_TRY_BLOCK: #ifdef MRB_WORD_BOXING { mrb_float x = mrb_float(regs[a]); - SET_FLT_VALUE(mrb, regs[a], x - GETARG_C(i)); + SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i)); } #else - regs_a[0].attr_f -= GETARG_C(i); + mrb_float(regs_a[0]) -= GETARG_C(i); #endif break; default: @@ -2015,23 +2017,23 @@ RETRY_TRY_BLOCK: NEXT; } -#define OP_CMP_BODY(op,v1,v2) (regs[a].v1 op regs[a+1].v2) +#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1])) #define OP_CMP(op) do {\ int result;\ /* need to check if - is overridden */\ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {\ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):\ - result = OP_CMP_BODY(op,attr_i,attr_i);\ + result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ break;\ case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):\ - result = OP_CMP_BODY(op,attr_i,attr_f);\ + result = OP_CMP_BODY(op,mrb_fixnum,mrb_float);\ break;\ case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):\ - result = OP_CMP_BODY(op,attr_f,attr_i);\ + result = OP_CMP_BODY(op,mrb_float,mrb_fixnum);\ break;\ case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):\ - result = OP_CMP_BODY(op,attr_f,attr_f);\ + result = OP_CMP_BODY(op,mrb_float,mrb_float);\ break;\ default:\ goto L_SEND;\ @@ -2138,33 +2140,28 @@ RETRY_TRY_BLOCK: int pre = GETARG_B(i); int post = GETARG_C(i); + struct RArray *ary; + int len, idx; + if (!mrb_array_p(v)) { - regs[a++] = mrb_ary_new_capa(mrb, 0); + v = mrb_ary_new_from_values(mrb, 1, ®s[a]); + } + ary = mrb_ary_ptr(v); + len = ary->len; + if (len > pre + post) { + regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre); while (post--) { - SET_NIL_VALUE(regs[a]); - a++; + regs[a++] = ary->ptr[len-post-1]; } } else { - struct RArray *ary = mrb_ary_ptr(v); - int len = ary->len; - int i; - - if (len > pre + post) { - regs[a++] = mrb_ary_new_from_values(mrb, len - pre - post, ary->ptr+pre); - while (post--) { - regs[a++] = ary->ptr[len-post-1]; - } + regs[a++] = mrb_ary_new_capa(mrb, 0); + for (idx=0; idx+pre<len; idx++) { + regs[a+idx] = ary->ptr[pre+idx]; } - else { - regs[a++] = mrb_ary_new_capa(mrb, 0); - for (i=0; i+pre<len; i++) { - regs[a+i] = ary->ptr[pre+i]; - } - while (i < post) { - SET_NIL_VALUE(regs[a+i]); - i++; - } + while (idx < post) { + SET_NIL_VALUE(regs[a+idx]); + idx++; } } ARENA_RESTORE(mrb, ai); @@ -2181,6 +2178,7 @@ RETRY_TRY_BLOCK: CASE(OP_STRCAT) { /* A B R(A).concat(R(B)) */ mrb_str_concat(mrb, regs[GETARG_A(i)], regs[GETARG_B(i)]); + regs = mrb->c->stack; NEXT; } @@ -2282,6 +2280,7 @@ RETRY_TRY_BLOCK: ci->proc = p; if (MRB_PROC_CFUNC_P(p)) { + ci->nregs = 0; mrb->c->stack[0] = p->body.func(mrb, recv); mrb_gc_arena_restore(mrb, ai); if (mrb->exc) goto L_RAISE; @@ -2306,8 +2305,9 @@ RETRY_TRY_BLOCK: /* A B R(A).newmethod(Syms(B),R(A+1)) */ int a = GETARG_A(i); struct RClass *c = mrb_class_ptr(regs[a]); + struct RProc *p = mrb_proc_ptr(regs[a+1]); - mrb_define_method_vm(mrb, c, syms[GETARG_B(i)], regs[a+1]); + mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], p); ARENA_RESTORE(mrb, ai); NEXT; } @@ -2340,10 +2340,10 @@ RETRY_TRY_BLOCK: CASE(OP_DEBUG) { /* A B C debug print R(A),R(B),R(C) */ -#ifdef ENABLE_DEBUG +#ifdef MRB_ENABLE_DEBUG_HOOK mrb->debug_op_hook(mrb, irep, pc, regs); #else -#ifdef ENABLE_STDIO +#ifndef MRB_DISABLE_STDIO printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); #else abort(); @@ -2395,13 +2395,13 @@ RETRY_TRY_BLOCK: MRB_END_EXC(&c_jmp); } -mrb_value +MRB_API mrb_value mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self) { return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */ } -mrb_value +MRB_API mrb_value mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_keep) { mrb_callinfo *ci; @@ -2411,6 +2411,7 @@ mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_kee return mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); } ci = cipush(mrb); + ci->nregs = 1; /* protect the receiver */ ci->acc = CI_ACC_SKIP; ci->target_class = mrb->object_class; v = mrb_context_run(mrb, proc, mrb_top_self(mrb), stack_keep); @@ -2419,7 +2420,7 @@ mrb_toplevel_run_keep(mrb_state *mrb, struct RProc *proc, unsigned int stack_kee return v; } -mrb_value +MRB_API mrb_value mrb_toplevel_run(mrb_state *mrb, struct RProc *proc) { return mrb_toplevel_run_keep(mrb, proc, 0); |
