diff options
Diffstat (limited to 'src/vm.c')
| -rw-r--r-- | src/vm.c | 346 |
1 files changed, 150 insertions, 196 deletions
@@ -4,11 +4,6 @@ ** See Copyright Notice in mruby.h */ -#include <stddef.h> -#include <stdarg.h> -#ifndef MRB_NO_FLOAT -#include <math.h> -#endif #include <mruby.h> #include <mruby/array.h> #include <mruby/class.h> @@ -91,14 +86,10 @@ void mrb_method_missing(mrb_state *mrb, mrb_sym name, mrb_value self, mrb_value static inline void stack_clear(mrb_value *from, size_t count) { -#ifdef MRB_NAN_BOXING while (count-- > 0) { SET_NIL_VALUE(*from); from++; } -#else - memset(from, 0, sizeof(mrb_value)*count); -#endif } static inline void @@ -245,12 +236,13 @@ top_proc(mrb_state *mrb, const struct RProc *proc) return proc; } -#define CI_ACC_SKIP -1 -#define CI_ACC_DIRECT -2 -#define CI_ACC_RESUMED -3 +#define CINFO_NONE 0 +#define CINFO_SKIP 1 +#define CINFO_DIRECT 2 +#define CINFO_RESUMED 3 static inline mrb_callinfo* -cipush(mrb_state *mrb, mrb_int push_stacks, mrb_int acc, +cipush(mrb_state *mrb, mrb_int push_stacks, uint8_t cci, struct RClass *target_class, const struct RProc *proc, mrb_sym mid, mrb_int argc) { struct mrb_context *c = mrb->c; @@ -268,7 +260,7 @@ cipush(mrb_state *mrb, mrb_int push_stacks, mrb_int acc, mrb_vm_ci_proc_set(ci, proc); ci->stack = ci[-1].stack + push_stacks; ci->argc = (int16_t)argc; - ci->acc = (int16_t)acc; + ci->cci = cci; ci->u.target_class = target_class; return ci; @@ -314,7 +306,7 @@ mrb_protect_error(mrb_state *mrb, mrb_protect_error_func *body, void *userdata, mrb_value result = mrb_nil_value(); int ai = mrb_gc_arena_save(mrb); const struct mrb_context *c = mrb->c; - int ci_index = c->ci - c->cibase; + ptrdiff_t ci_index = c->ci - c->cibase; if (error) { *error = FALSE; } @@ -335,9 +327,9 @@ mrb_protect_error(mrb_state *mrb, mrb_protect_error_func *body, void *userdata, } else { // It was probably switched by mrb_fiber_resume(). - // Simply destroy all successive CI_ACC_DIRECTs once the fiber has been switched. + // Simply destroy all successive CINFO_DIRECTs once the fiber has been switched. c = mrb->c; - while (c->ci > c->cibase && c->ci->acc == CI_ACC_DIRECT) { + while (c->ci > c->cibase && c->ci->cci == CINFO_DIRECT) { cipop(mrb); } } @@ -506,12 +498,12 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc mrb->c->ci->stack[argc+1] = blk; if (MRB_METHOD_CFUNC_P(m)) { - ci->acc = CI_ACC_DIRECT; + ci->cci = CINFO_DIRECT; val = MRB_METHOD_CFUNC(m)(mrb, self); cipop(mrb); } else { - ci->acc = CI_ACC_SKIP; + ci->cci = CINFO_SKIP; val = mrb_run(mrb, MRB_METHOD_PROC(m), self); } } @@ -526,68 +518,8 @@ mrb_funcall_argv(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, cons return mrb_funcall_with_block(mrb, self, mid, argc, argv, mrb_nil_value()); } -#define DECOMPOSE32(n) (((n) >> 24) & 0xff), (((n) >> 16) & 0xff), (((n) >> 8) & 0xff), (((n) >> 0) & 0xff) -#define CATCH_HANDLER_MAKE_BYTECODE(t, b, e, j) t, DECOMPOSE32(b), DECOMPOSE32(e), DECOMPOSE32(j) -#define CATCH_HANDLER_NUM_TO_BYTE(n) ((n) * sizeof(struct mrb_irep_catch_handler)) - -static void -exec_irep_prepare_posthook(mrb_state *mrb, mrb_callinfo *ci, int nregs, mrb_func_t posthook) -{ - /* - * stack: [proc, errinfo, return value by called proc] - * - * begin - * OP_NOP # A dummy instruction built in to make the catch handler react. - * ensure - * OP_EXCEPT R1 # Save the exception object. - * OP_CALL # Call a C function for the hook. - * # The stack is kept as it is in the called proc. - * # The exception will be rethrown within the hook function. - * end - */ - static const mrb_code hook_iseq[] = { - OP_NOP, - OP_EXCEPT, 1, - OP_CALL, - CATCH_HANDLER_MAKE_BYTECODE(MRB_CATCH_ENSURE, 0, 1, 1), - }; - static const mrb_irep hook_irep = { - 1, 3, 1, MRB_IREP_STATIC, hook_iseq, - NULL, NULL, NULL, NULL, NULL, - sizeof(hook_iseq) / sizeof(hook_iseq[0]) - CATCH_HANDLER_NUM_TO_BYTE(1), - 0, 0, 0, 0 - }; - static const struct RProc hook_caller = { - NULL, NULL, MRB_TT_PROC, MRB_GC_RED, MRB_FL_OBJ_IS_FROZEN, { &hook_irep }, NULL, { NULL } - }; - - struct RProc *hook = mrb_proc_new_cfunc(mrb, posthook); - int acc = 2; - memmove(ci->stack + acc, ci->stack, sizeof(mrb_value) * nregs); - ci->stack[0] = mrb_obj_value(hook); - ci->stack[1] = mrb_nil_value(); - mrb_callinfo hook_ci = { 0, 0, ci->acc, &hook_caller, ci->stack, &hook_iseq[1], { NULL } }; - ci = cipush(mrb, acc, acc, NULL, ci[0].proc, ci[0].mid, ci[0].argc); - ci->u.env = ci[-1].u.env; - ci[-1] = hook_ci; -} - -/* - * If `posthook` is given, `posthook` will be called even if an - * exception or global jump occurs in `p`. Exception or global jump objects - * are stored in `mrb->c->stack[1]` and should be rethrown in `posthook`. - * - * if (!mrb_nil_p(mrb->c->stack[1])) { - * mrb_exc_raise(mrb, mrb->c->stack[1]); - * } - * - * If you want to return the return value by `proc` as it is, please do - * `return mrb->c->stack[2]`. - * - * However, if `proc` is a C function, it will be ignored. - */ static mrb_value -exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) +exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; int keep, nregs; @@ -600,17 +532,12 @@ exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) nregs = p->body.irep->nregs; if (ci->argc < 0) keep = 3; else keep = ci->argc + 2; - int extra = posthook ? (2 /* hook proc + errinfo */) : 0; if (nregs < keep) { - mrb_stack_extend(mrb, keep + extra); + mrb_stack_extend(mrb, keep); } else { - mrb_stack_extend(mrb, nregs + extra); - stack_clear(ci->stack+keep, nregs-keep + extra); - } - - if (posthook) { - exec_irep_prepare_posthook(mrb, ci, (nregs < keep ? keep : nregs), posthook); + mrb_stack_extend(mrb, nregs); + stack_clear(ci->stack+keep, nregs-keep); } cipush(mrb, 0, 0, NULL, NULL, 0, 0); @@ -619,16 +546,16 @@ exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) } mrb_value -mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p, mrb_func_t posthook) +mrb_exec_irep(mrb_state *mrb, mrb_value self, struct RProc *p) { mrb_callinfo *ci = mrb->c->ci; - if (ci->acc >= 0) { - return exec_irep(mrb, self, p, posthook); + if (ci->cci == CINFO_NONE) { + return exec_irep(mrb, self, p); } else { mrb_value ret; if (MRB_PROC_CFUNC_P(p)) { - cipush(mrb, 0, CI_ACC_DIRECT, mrb_vm_ci_target_class(ci), p, ci->mid, ci->argc); + cipush(mrb, 0, CINFO_DIRECT, mrb_vm_ci_target_class(ci), p, ci->mid, ci->argc); ret = MRB_PROC_CFUNC(p)(mrb, self); cipop(mrb); } @@ -675,7 +602,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self) mrb_get_args(mrb, "n*&", &name, &argv, &argc, &block); ci = mrb->c->ci; - if (ci->acc < 0) { + if (ci->cci > CINFO_NONE) { funcall: return mrb_funcall_with_block(mrb, self, name, argc, argv, block); } @@ -706,7 +633,7 @@ mrb_f_send(mrb_state *mrb, mrb_value self) } return MRB_METHOD_CFUNC(m)(mrb, self); } - return exec_irep(mrb, self, MRB_METHOD_PROC(m), NULL); + return exec_irep(mrb, self, MRB_METHOD_PROC(m)); } static mrb_value @@ -720,7 +647,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c) mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given"); } ci = mrb->c->ci; - if (ci->acc == CI_ACC_DIRECT) { + if (ci->cci == CINFO_DIRECT) { return mrb_yield_with_class(mrb, blk, 1, &self, self, c); } ci->u.target_class = c; @@ -792,21 +719,11 @@ mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self) { mrb_value a, b; - struct RClass *c; if (mrb_get_args(mrb, "|S&", &a, &b) == 1) { mrb_raise(mrb, E_NOTIMP_ERROR, "instance_eval with string not implemented"); } - switch (mrb_type(self)) { - case MRB_TT_MODULE: - case MRB_TT_CLASS: - case MRB_TT_ICLASS: - c = mrb_class_ptr(self); - break; - default: - c = mrb_singleton_class_ptr(mrb, self); - } - return eval_under(mrb, self, b, c); + return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self)); } MRB_API mrb_value @@ -827,7 +744,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value mrb_exc_raise(mrb, mrb_obj_value(mrb->stack_err)); } p = mrb_proc_ptr(b); - ci = cipush(mrb, n, CI_ACC_SKIP, c, p, mid, 0 /* dummy */); + ci = cipush(mrb, n, CINFO_SKIP, c, p, mid, 0 /* dummy */); if (argc >= CALL_MAXARGS) { ci->argc = -1; n = 3; @@ -848,7 +765,7 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value mrb->c->ci->stack[argc+1] = mrb_nil_value(); if (MRB_PROC_CFUNC_P(p)) { - ci->acc = CI_ACC_DIRECT; + ci->cci = CINFO_DIRECT; val = MRB_PROC_CFUNC(p)(mrb, self); cipop(mrb); } @@ -894,7 +811,7 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const mrb->c->ci->stack[1] = mrb_ary_new_from_values(mrb, argc, argv); mrb->c->ci->stack[2] = mrb_nil_value(); ci->argc = -1; - return exec_irep(mrb, self, p, NULL); + return exec_irep(mrb, self, p); } static struct RBreak* @@ -902,7 +819,7 @@ break_new(mrb_state *mrb, uint32_t tag, const struct RProc *p, mrb_value val) { struct RBreak *brk; - brk = (struct RBreak*)mrb_obj_alloc(mrb, MRB_TT_BREAK, NULL); + brk = MRB_OBJ_ALLOC(mrb, MRB_TT_BREAK, NULL); mrb_break_proc_set(brk, p); mrb_break_value_set(brk, val); mrb_break_tag_set(brk, tag); @@ -1079,7 +996,7 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb #ifndef DIRECT_THREADED #define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) { -#define CASE(insn,ops) case insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc; +#define CASE(insn,ops) case insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc; L_ ## insn ## _BODY: #define NEXT goto L_END_DISPATCH #define JUMP NEXT #define END_DISPATCH L_END_DISPATCH:;}} @@ -1087,7 +1004,7 @@ prepare_tagged_break(mrb_state *mrb, uint32_t tag, const struct RProc *proc, mrb #else #define INIT_DISPATCH JUMP; return mrb_nil_value(); -#define CASE(insn,ops) L_ ## insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc; +#define CASE(insn,ops) L_ ## insn: pc++; FETCH_ ## ops (); mrb->c->ci->pc = pc; L_ ## insn ## _BODY: #define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn] #define JUMP NEXT @@ -1125,19 +1042,27 @@ mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int sta return result; } -static mrb_bool +static struct RClass* check_target_class(mrb_state *mrb) { - if (!mrb_vm_ci_target_class(mrb->c->ci)) { + struct RClass *target = mrb_vm_ci_target_class(mrb->c->ci); + if (!target) { mrb_value exc = mrb_exc_new_lit(mrb, E_TYPE_ERROR, "no target class or module"); mrb_exc_set(mrb, exc); - return FALSE; } - return TRUE; + return target; +} + +mrb_value +get_send_args(mrb_state *mrb, mrb_int argc, mrb_value *regs) +{ + if (argc < 0) return regs[0]; + return mrb_ary_new_from_values(mrb, argc, regs); } mrb_value mrb_obj_missing(mrb_state *mrb, mrb_value mod); void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); +void mrb_method_added(mrb_state *mrb, struct RClass *c, mrb_sym mid); MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) @@ -1191,11 +1116,7 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_LOADL16, BS) { - goto op_loadl; - } CASE(OP_LOADL, BB) { - op_loadl: switch (pool[b].tt) { /* number */ case IREP_TT_INT32: regs[a] = mrb_int_value(mrb, (mrb_int)pool[b].u.i32); @@ -1267,11 +1188,6 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_LOADSYM16, BS) { - SET_SYM_VALUE(regs[a], syms[b]); - NEXT; - } - CASE(OP_LOADNIL, B) { SET_NIL_VALUE(regs[a]); NEXT; @@ -1552,11 +1468,18 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { mrb_sym missing = MRB_SYM(method_missing); - m = mrb_method_search_vm(mrb, &cls, missing); - if (MRB_METHOD_UNDEF_P(m) || (missing == mrb->c->ci->mid && mrb_obj_eq(mrb, regs[0], recv))) { - mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1); + mrb_value args; + + if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) { + method_missing: + args = get_send_args(mrb, argc, regs+a+1); mrb_method_missing(mrb, mid, recv, args); } + if (mid != missing) { + cls = mrb_class(mrb, recv); + } + m = mrb_method_search_vm(mrb, &cls, missing); + if (MRB_METHOD_UNDEF_P(m)) goto method_missing; /* just in case */ if (argc >= 0) { if (a+2 >= irep->nregs) { mrb_stack_extend(mrb, a+3); @@ -1570,7 +1493,7 @@ RETRY_TRY_BLOCK: } /* push callinfo */ - ci = cipush(mrb, a, a, cls, NULL, mid, argc); + ci = cipush(mrb, a, 0, cls, NULL, mid, argc); if (MRB_METHOD_CFUNC_P(m)) { if (MRB_METHOD_PROC_P(m)) { @@ -1598,7 +1521,7 @@ RETRY_TRY_BLOCK: } } if (!ci->u.target_class) { /* return from context modifying method (resume/yield) */ - if (ci->acc == CI_ACC_RESUMED) { + if (ci->cci == CINFO_RESUMED) { mrb->jmp = prev_jmp; return recv; } @@ -1614,7 +1537,6 @@ RETRY_TRY_BLOCK: /* pop stackpos */ ci = cipop(mrb); pc = ci->pc; - JUMP; } else { /* setup environment for calling method */ @@ -1624,9 +1546,9 @@ RETRY_TRY_BLOCK: syms = irep->syms; mrb_stack_extend(mrb, (argc < 0 && irep->nregs < 3) ? 3 : irep->nregs); pc = irep->iseq; - JUMP; } } + JUMP; CASE(OP_CALL, Z) { mrb_callinfo *ci; @@ -1650,7 +1572,7 @@ RETRY_TRY_BLOCK: /* pop stackpos */ ci = cipop(mrb); pc = ci->pc; - regs[ci[1].acc] = recv; + ci[1].stack[0] = recv; irep = mrb->c->ci->proc->body.irep; pool = irep->pool; syms = irep->syms; @@ -1664,7 +1586,7 @@ RETRY_TRY_BLOCK: mrb->c->ci->stack[0] = mrb_nil_value(); a = 0; c = OP_R_NORMAL; - goto L_RETURN; + goto L_OP_RETURN_BODY; } pool = irep->pool; syms = irep->syms; @@ -1712,13 +1634,12 @@ RETRY_TRY_BLOCK: else if (target_class->tt == MRB_TT_MODULE) { target_class = mrb_vm_ci_target_class(ci); if (target_class->tt != MRB_TT_ICLASS) { - mrb_value exc = mrb_exc_new_lit(mrb, E_RUNTIME_ERROR, "superclass info lost [mruby limitations]"); - mrb_exc_set(mrb, exc); - goto L_RAISE; + goto super_typeerror; } } recv = regs[0]; if (!mrb_obj_is_kind_of(mrb, recv, target_class)) { + super_typeerror: ; mrb_value exc = mrb_exc_new_lit(mrb, E_TYPE_ERROR, "self has wrong type to call super in this context"); mrb_exc_set(mrb, exc); @@ -1736,20 +1657,18 @@ RETRY_TRY_BLOCK: m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { mrb_sym missing = MRB_SYM(method_missing); + mrb_value args; if (mrb_func_basic_p(mrb, recv, missing, mrb_obj_missing)) { - mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1); + super_missing: + args = get_send_args(mrb, argc, regs+a+1); mrb_no_method_error(mrb, mid, args, "no superclass method '%n'", mid); } if (mid != missing) { cls = mrb_class(mrb, recv); } m = mrb_method_search_vm(mrb, &cls, missing); - if (MRB_METHOD_UNDEF_P(m)) { /* just in case */ - mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1); - mrb_method_missing(mrb, missing, recv, args); - } - mid = missing; + if (MRB_METHOD_UNDEF_P(m)) goto super_missing; /* just in case */ if (argc >= 0) { if (a+2 >= irep->nregs) { mrb_stack_extend(mrb, a+3); @@ -1758,7 +1677,8 @@ RETRY_TRY_BLOCK: regs[a+2] = blk; argc = -1; } - mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(ci->mid)); + mrb_ary_unshift(mrb, regs[a+1], mrb_symbol_value(mid)); + mid = missing; } /* push callinfo */ @@ -1779,7 +1699,7 @@ RETRY_TRY_BLOCK: ci = mrb->c->ci; mrb_assert(!mrb_break_p(v)); if (!mrb_vm_ci_target_class(ci)) { /* return from context modifying method (resume/yield) */ - if (ci->acc == CI_ACC_RESUMED) { + if (ci->cci == CINFO_RESUMED) { mrb->jmp = prev_jmp; return v; } @@ -1797,9 +1717,6 @@ RETRY_TRY_BLOCK: JUMP; } else { - /* fill callinfo */ - ci->acc = a; - /* setup environment for calling method */ mrb_vm_ci_proc_set(ci, (proc = MRB_METHOD_PROC(m))); irep = proc->body.irep; @@ -2086,7 +2003,7 @@ RETRY_TRY_BLOCK: } while ((ch = catch_handler_find(mrb, ci, pc, MRB_CATCH_FILTER_ALL)) == NULL) { ci = cipop(mrb); - if (ci[1].acc == CI_ACC_SKIP && prev_jmp) { + if (ci[1].cci == CINFO_SKIP && prev_jmp) { mrb->jmp = prev_jmp; MRB_THROW(prev_jmp); } @@ -2134,7 +2051,7 @@ RETRY_TRY_BLOCK: switch (c) { case OP_R_RETURN: /* Fall through to OP_R_NORMAL otherwise */ - if (ci->acc >=0 && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) { + if (ci->cci == CINFO_NONE && MRB_PROC_ENV_P(proc) && !MRB_PROC_STRICT_P(proc)) { const struct RProc *dst; mrb_callinfo *cibase; cibase = mrb->c->cibase; @@ -2150,7 +2067,7 @@ RETRY_TRY_BLOCK: } /* check jump destination */ while (cibase <= ci && ci->proc != dst) { - if (ci->acc < 0) { /* jump cross C boudary */ + if (ci->cci > CINFO_NONE) { /* jump cross C boundary */ localjump_error(mrb, LOCALJUMP_ERROR_RETURN); goto L_RAISE; } @@ -2258,7 +2175,7 @@ RETRY_TRY_BLOCK: c->prev = NULL; ci = mrb->c->ci; } - if (ci->acc < 0) { + if (ci->cci > CINFO_NONE) { ci = cipop(mrb); mrb_gc_arena_restore(mrb, ai); mrb->c->vmexec = FALSE; @@ -2284,7 +2201,7 @@ RETRY_TRY_BLOCK: } } while (mrb->c->cibase < ci && ci[-1].proc != proc->upper) { - if (ci[-1].acc == CI_ACC_SKIP) { + if (ci[-1].cci == CINFO_SKIP) { goto L_BREAK_ERROR; } CHECKPOINT_RESTORE(RBREAK_TAG_BREAK_UPPER) { @@ -2322,21 +2239,21 @@ RETRY_TRY_BLOCK: mrb->jmp = prev_jmp; return v; } - acc = ci->acc; + acc = ci->cci; ci = cipop(mrb); - if (acc == CI_ACC_SKIP || acc == CI_ACC_DIRECT) { + if (acc == CINFO_SKIP || acc == CINFO_DIRECT) { mrb_gc_arena_restore(mrb, ai); mrb->jmp = prev_jmp; return v; } - pc = ci[0].pc; + pc = ci->pc; DEBUG(fprintf(stderr, "from :%s\n", mrb_sym_name(mrb, ci->mid))); - proc = mrb->c->ci->proc; + proc = ci->proc; irep = proc->body.irep; pool = irep->pool; syms = irep->syms; - regs[acc] = v; + ci[1].stack[0] = v; mrb_gc_arena_restore(mrb, ai); } JUMP; @@ -2440,9 +2357,7 @@ RETRY_TRY_BLOCK: CASE(OP_DIV, B) { #ifndef MRB_NO_FLOAT mrb_float x, y, f; - mrb_float mrb_div_flo(mrb_float x, mrb_float y); #endif - mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y); /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { @@ -2475,7 +2390,7 @@ RETRY_TRY_BLOCK: } #ifndef MRB_NO_FLOAT - f = mrb_div_flo(x, y); + f = mrb_div_float(x, y); SET_FLOAT_VALUE(mrb, regs[a], f); #endif NEXT; @@ -2625,14 +2540,18 @@ RETRY_TRY_BLOCK: regs[a] = splat; } else { + mrb_assert(mrb_type(regs[a]) == MRB_TT_ARRAY); mrb_ary_concat(mrb, regs[a], splat); } mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_ARYPUSH, B) { - mrb_ary_push(mrb, regs[a], regs[a+1]); + CASE(OP_ARYPUSH, BB) { + mrb_assert(mrb_type(regs[a]) == MRB_TT_ARRAY); + for (mrb_int i=0; i<b; i++) { + mrb_ary_push(mrb, regs[a], regs[a+i+1]); + } NEXT; } @@ -2667,6 +2586,7 @@ RETRY_TRY_BLOCK: } CASE(OP_ASET, BBB) { + mrb_assert(mrb_type(regs[a]) == MRB_TT_ARRAY); mrb_ary_set(mrb, regs[b], c, regs[a]); NEXT; } @@ -2709,16 +2629,29 @@ RETRY_TRY_BLOCK: mrb_sym sym = mrb_intern_str(mrb, regs[a]); regs[a] = mrb_symbol_value(sym); - mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_STRING16, BS) { - goto op_string; + CASE(OP_SYMBOL, BB) { + size_t len; + mrb_sym sym; + + mrb_assert((pool[b].tt&IREP_TT_NFLAG)==0); + len = pool[b].tt >> 2; + if (pool[b].tt & IREP_TT_SFLAG) { + sym = mrb_intern_static(mrb, pool[b].u.str, len); + } + else { + sym = mrb_intern(mrb, pool[b].u.str, len); + } + regs[a] = mrb_symbol_value(sym); + NEXT; } + CASE(OP_STRING, BB) { size_t len; - op_string: + + mrb_assert((pool[b].tt&IREP_TT_NFLAG)==0); len = pool[b].tt >> 2; if (pool[b].tt & IREP_TT_SFLAG) { regs[a] = mrb_str_new_static(mrb, pool[b].u.str, len); @@ -2753,7 +2686,8 @@ RETRY_TRY_BLOCK: int i; int lim = a+b*2+1; - hash = mrb_ensure_hash_type(mrb, regs[a]); + hash = regs[a]; + mrb_ensure_hash_type(mrb, hash); for (i=a+1; i<lim; i+=2) { mrb_hash_set(mrb, hash, regs[i], regs[i+1]); } @@ -2761,8 +2695,9 @@ RETRY_TRY_BLOCK: NEXT; } CASE(OP_HASHCAT, B) { - mrb_value hash = mrb_ensure_hash_type(mrb, regs[a]); + mrb_value hash = regs[a]; + mrb_ensure_hash_type(mrb, hash); mrb_hash_merge(mrb, hash, regs[a+1]); mrb_gc_arena_restore(mrb, ai); NEXT; @@ -2795,18 +2730,6 @@ RETRY_TRY_BLOCK: c = OP_L_METHOD; goto L_MAKE_LAMBDA; } - CASE(OP_LAMBDA16, BS) { - c = OP_L_LAMBDA; - goto L_MAKE_LAMBDA; - } - CASE(OP_BLOCK16, BS) { - c = OP_L_BLOCK; - goto L_MAKE_LAMBDA; - } - CASE(OP_METHOD16, BS) { - c = OP_L_METHOD; - goto L_MAKE_LAMBDA; - } CASE(OP_RANGE_INC, B) { mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], FALSE); @@ -2862,10 +2785,7 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_EXEC16, BS) - goto L_EXEC; CASE(OP_EXEC, BB) - L_EXEC: { mrb_value recv = regs[a]; struct RProc *p; @@ -2879,7 +2799,7 @@ RETRY_TRY_BLOCK: p->flags |= MRB_PROC_SCOPE; /* prepare call stack */ - cipush(mrb, a, a, mrb_class_ptr(recv), p, 0, 0); + cipush(mrb, a, 0, mrb_class_ptr(recv), p, 0, 0); irep = p->body.irep; pool = irep->pool; @@ -2894,10 +2814,13 @@ RETRY_TRY_BLOCK: struct RClass *target = mrb_class_ptr(regs[a]); struct RProc *p = mrb_proc_ptr(regs[a+1]); mrb_method_t m; + mrb_sym mid = syms[b]; MRB_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, target, syms[b], m); + mrb_define_method_raw(mrb, target, mid, m); + mrb_method_added(mrb, target, mid); mrb_gc_arena_restore(mrb, ai); + regs[a] = mrb_symbol_value(mid); NEXT; } @@ -2908,24 +2831,24 @@ RETRY_TRY_BLOCK: } CASE(OP_TCLASS, B) { - if (!check_target_class(mrb)) goto L_RAISE; - regs[a] = mrb_obj_value(mrb_vm_ci_target_class(mrb->c->ci)); + struct RClass *target = check_target_class(mrb); + if (!target) goto L_RAISE; + regs[a] = mrb_obj_value(target); NEXT; } CASE(OP_ALIAS, BB) { - struct RClass *target; + struct RClass *target = check_target_class(mrb); - if (!check_target_class(mrb)) goto L_RAISE; - target = mrb_vm_ci_target_class(mrb->c->ci); + if (!target) goto L_RAISE; mrb_alias_method(mrb, target, syms[a], syms[b]); + mrb_method_added(mrb, target, syms[a]); NEXT; } CASE(OP_UNDEF, B) { - struct RClass *target; + struct RClass *target = check_target_class(mrb); - if (!check_target_class(mrb)) goto L_RAISE; - target = mrb_vm_ci_target_class(mrb->c->ci); + if (!target) goto L_RAISE; mrb_undef_method_id(mrb, target, syms[a]); NEXT; } @@ -2958,6 +2881,37 @@ RETRY_TRY_BLOCK: NEXT; } + CASE(OP_EXT1, Z) { + insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); mrb->c->ci->pc = pc; goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + CASE(OP_EXT2, Z) { + insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _2(); mrb->c->ci->pc = pc; goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + CASE(OP_EXT3, Z) { + uint8_t insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _3(); mrb->c->ci->pc = pc; goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + CASE(OP_STOP, Z) { /* stop VM */ CHECKPOINT_RESTORE(RBREAK_TAG_STOP) { @@ -2981,7 +2935,7 @@ RETRY_TRY_BLOCK: } MRB_CATCH(&c_jmp) { mrb_callinfo *ci = mrb->c->ci; - while (ci > mrb->c->cibase && ci->acc == CI_ACC_DIRECT) { + while (ci > mrb->c->cibase && ci->cci == CINFO_DIRECT) { ci = cipop(mrb); } exc_catched = TRUE; @@ -3014,7 +2968,7 @@ mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, mrb_int st mrb_vm_ci_env_set(mrb->c->ci, NULL); return mrb_vm_run(mrb, proc, self, stack_keep); } - cipush(mrb, 0, CI_ACC_SKIP, mrb->object_class, NULL, 0, 0); + cipush(mrb, 0, CINFO_SKIP, mrb->object_class, NULL, 0, 0); v = mrb_vm_run(mrb, proc, self, stack_keep); return v; |
