diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/class.c | 8 | ||||
| -rw-r--r-- | src/codedump.c | 790 | ||||
| -rw-r--r-- | src/hash.c | 119 | ||||
| -rw-r--r-- | src/kernel.c | 12 | ||||
| -rw-r--r-- | src/load.c | 6 | ||||
| -rw-r--r-- | src/proc.c | 10 | ||||
| -rw-r--r-- | src/vm.c | 1109 |
7 files changed, 1082 insertions, 972 deletions
diff --git a/src/class.c b/src/class.c index d3a1e2fb2..37bc39c75 100644 --- a/src/class.c +++ b/src/class.c @@ -1953,8 +1953,8 @@ mrb_mod_alias(mrb_state *mrb, mrb_value mod) return mrb_nil_value(); } -static void -undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) +void +mrb_undef_method_id(mrb_state *mrb, struct RClass *c, mrb_sym a) { if (!mrb_obj_respond_to(mrb, c, a)) { mrb_name_error(mrb, a, "undefined method '%S' for class '%S'", mrb_sym2str(mrb, a), mrb_obj_value(c)); @@ -1970,7 +1970,7 @@ undef_method(mrb_state *mrb, struct RClass *c, mrb_sym a) MRB_API void mrb_undef_method(mrb_state *mrb, struct RClass *c, const char *name) { - undef_method(mrb, c, mrb_intern_cstr(mrb, name)); + mrb_undef_method_id(mrb, c, mrb_intern_cstr(mrb, name)); } MRB_API void @@ -1988,7 +1988,7 @@ mrb_mod_undef(mrb_state *mrb, mrb_value mod) mrb_get_args(mrb, "*", &argv, &argc); while (argc--) { - undef_method(mrb, c, to_sym(mrb, *argv)); + mrb_undef_method_id(mrb, c, to_sym(mrb, *argv)); argv++; } return mrb_nil_value(); diff --git a/src/codedump.c b/src/codedump.c index d79a65a70..80802778f 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -6,451 +6,521 @@ #include <mruby/proc.h> #ifndef MRB_DISABLE_STDIO -static int -print_r(mrb_state *mrb, mrb_irep *irep, size_t n, int pre) +static void +print_r(mrb_state *mrb, mrb_irep *irep, size_t n) { size_t i; - if (n == 0) return 0; + if (n == 0) return; for (i=0; i+1<irep->nlocals; i++) { if (irep->lv[i].r == n) { mrb_sym sym = irep->lv[i].name; - if (pre) printf(" "); - printf("R%d:%s", (int)n, mrb_sym2name(mrb, sym)); - return 1; + printf(" R%d:%s", (int)n, mrb_sym2name(mrb, sym)); } } - return 0; } -#define RA 1 -#define RB 2 -#define RAB 3 - static void -print_lv(mrb_state *mrb, mrb_irep *irep, mrb_code c, int r) +print_lv_a(mrb_state *mrb, mrb_irep *irep, uint16_t a) { - int pre = 0; - - if (!irep->lv - || ((!(r & RA) || GETARG_A(c) >= irep->nlocals) - && (!(r & RB) || GETARG_B(c) >= irep->nlocals))) { + if (!irep->lv || a >= irep->nlocals || a == 0) { printf("\n"); return; } - printf("\t; "); - if (r & RA) { - pre = print_r(mrb, irep, GETARG_A(c), 0); - } - if (r & RB) { - print_r(mrb, irep, GETARG_B(c), pre); + printf("\t;"); + print_r(mrb, irep, a); + printf("\n"); +} + +static void +print_lv_ab(mrb_state *mrb, mrb_irep *irep, uint16_t a, uint16_t b) +{ + if (!irep->lv || (a >= irep->nlocals && b >= irep->nlocals) || a+b == 0) { + printf("\n"); + return; } + printf("\t;"); + if (a > 0) print_r(mrb, irep, a); + if (b > 0) print_r(mrb, irep, b); printf("\n"); } #endif static void +print_header(mrb_irep *irep, ptrdiff_t i) +{ + int32_t line; + + line = mrb_debug_get_line(irep, i); + if (line < 0) { + printf(" "); + } + else { + printf("%5d ", line); + } + + printf("%03d ", (int)i); +} + +#define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn + +static void codedump(mrb_state *mrb, mrb_irep *irep) { #ifndef MRB_DISABLE_STDIO - int i; int ai; - mrb_code c; + mrb_code *pc, *pcend; + mrb_code ins; const char *file = NULL, *next_file; - int32_t line; if (!irep) return; printf("irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d\n", (void*)irep, irep->nregs, irep->nlocals, (int)irep->plen, (int)irep->slen, (int)irep->rlen); - for (i = 0; i < (int)irep->ilen; i++) { + if (irep->lv) { + int i; + + printf("local variable names:\n"); + for (i = 1; i < irep->nlocals; ++i) { + char const *n = mrb_sym2name(mrb, irep->lv[i - 1].name); + printf(" R%d:%s\n", irep->lv[i - 1].r, n? n : ""); + } + } + + pc = irep->iseq; + pcend = pc + irep->ilen; + while (pc < pcend) { + ptrdiff_t i; + uint32_t a; + uint16_t b; + uint8_t c; + ai = mrb_gc_arena_save(mrb); + i = pc - irep->iseq; next_file = mrb_debug_get_filename(irep, i); if (next_file && file != next_file) { printf("file: %s\n", next_file); file = next_file; } - line = mrb_debug_get_line(irep, i); - if (line < 0) { - printf(" "); - } - else { - printf("%5d ", line); - } - - printf("%03d ", i); - c = irep->iseq[i]; - switch (GET_OPCODE(c)) { - case OP_NOP: + print_header(irep, i); + ins = READ_B(); + switch (ins) { + CASE(OP_NOP, Z): printf("OP_NOP\n"); break; - case OP_MOVE: - printf("OP_MOVE\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_MOVE, BB): + printf("OP_MOVE\tR%d\tR%d\t", a, b); + print_lv_ab(mrb, irep, a, b); break; - case OP_LOADL: + CASE(OP_LOADL, BB): { - mrb_value v = irep->pool[GETARG_Bx(c)]; + mrb_value v = irep->pool[b]; mrb_value s = mrb_inspect(mrb, v); - printf("OP_LOADL\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s)); + printf("OP_LOADL\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s)); } - print_lv(mrb, irep, c, RA); - break; - case OP_LOADI: - printf("OP_LOADI\tR%d\t%d\t", GETARG_A(c), GETARG_sBx(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADSYM: - printf("OP_LOADSYM\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADNIL: - printf("OP_LOADNIL\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADSELF: - printf("OP_LOADSELF\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADT: - printf("OP_LOADT\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_LOADF: - printf("OP_LOADF\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETGLOBAL: - printf("OP_GETGLOBAL\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETGLOBAL: - printf("OP_SETGLOBAL\t:%s\tR%d\t", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETCONST: - printf("OP_GETCONST\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETCONST: - printf("OP_SETCONST\t:%s\tR%d\t", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETMCNST: - printf("OP_GETMCNST\tR%d\tR%d::%s", GETARG_A(c), GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RAB); - break; - case OP_SETMCNST: - printf("OP_SETMCNST\tR%d::%s\tR%d", GETARG_A(c)+1, - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETIV: - printf("OP_GETIV\tR%d\t%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETIV: - printf("OP_SETIV\t%s\tR%d", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETUPVAR: - printf("OP_GETUPVAR\tR%d\t%d\t%d", - GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_SETUPVAR: - printf("OP_SETUPVAR\tR%d\t%d\t%d", - GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_GETCV: - printf("OP_GETCV\tR%d\t%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)])); - print_lv(mrb, irep, c, RA); - break; - case OP_SETCV: - printf("OP_SETCV\t%s\tR%d", - mrb_sym2name(mrb, irep->syms[GETARG_Bx(c)]), - GETARG_A(c)); - print_lv(mrb, irep, c, RA); - break; - case OP_JMP: - printf("OP_JMP\t%03d (%d)\n", i+GETARG_sBx(c), GETARG_sBx(c)); - break; - case OP_JMPIF: - printf("OP_JMPIF\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c)); - break; - case OP_JMPNOT: - printf("OP_JMPNOT\tR%d\t%03d (%d)\n", GETARG_A(c), i+GETARG_sBx(c), GETARG_sBx(c)); - break; - case OP_SEND: - printf("OP_SEND\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SENDB: - printf("OP_SENDB\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_CALL: - printf("OP_CALL\tR%d\n", GETARG_A(c)); - break; - case OP_TAILCALL: - printf("OP_TAILCALL\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUPER: - printf("OP_SUPER\tR%d\t%d\n", GETARG_A(c), - GETARG_C(c)); - break; - case OP_ARGARY: - printf("OP_ARGARY\tR%d\t%d:%d:%d:%d", GETARG_A(c), - (GETARG_Bx(c)>>10)&0x3f, - (GETARG_Bx(c)>>9)&0x1, - (GETARG_Bx(c)>>4)&0x1f, - (GETARG_Bx(c)>>0)&0xf); - print_lv(mrb, irep, c, RA); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADI, BB): + printf("OP_LOADI\tR%d\t%d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADINEG, BB): + printf("OP_LOADI\tR%d\t-%d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADI__1, B): + printf("OP_LOADI__1\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADI_0, B): goto L_LOADI; + CASE(OP_LOADI_1, B): goto L_LOADI; + CASE(OP_LOADI_2, B): goto L_LOADI; + CASE(OP_LOADI_3, B): goto L_LOADI; + CASE(OP_LOADI_4, B): goto L_LOADI; + CASE(OP_LOADI_5, B): goto L_LOADI; + CASE(OP_LOADI_6, B): goto L_LOADI; + CASE(OP_LOADI_7, B): + L_LOADI: + printf("OP_LOADI_%d\tR%d\t\t", ins-(int)OP_LOADI_0, a); + print_lv_a(mrb, irep, a); break; - - case OP_ENTER: + CASE(OP_LOADSYM, BB): + printf("OP_LOADSYM\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADNIL, B): + printf("OP_LOADNIL\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADSELF, B): + printf("OP_LOADSELF\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADT, B): + printf("OP_LOADT\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LOADF, B): + printf("OP_LOADF\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETGV, BB): + printf("OP_GETGV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETGV, BB): + printf("OP_SETGV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETSV, BB): + printf("OP_GETSV\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETSV, BB): + printf("OP_SETSV\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETCONST, BB): + printf("OP_GETCONST\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETCONST, BB): + printf("OP_SETCONST\t:%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETMCNST, BB): + printf("OP_GETMCNST\tR%d\tR%d::%s", a, a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETMCNST, BB): + printf("OP_SETMCNST\tR%d::%s\tR%d", a+1, mrb_sym2name(mrb, irep->syms[b]), a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETIV, BB): + printf("OP_GETIV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETIV, BB): + printf("OP_SETIV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETUPVAR, BBB): + printf("OP_GETUPVAR\tR%d\t%d\t%d", a, b, c); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETUPVAR, BBB): + printf("OP_SETUPVAR\tR%d\t%d\t%d", a, b, c); + print_lv_a(mrb, irep, a); + break; + CASE(OP_GETCV, BB): + printf("OP_GETCV\tR%d\t%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SETCV, BB): + printf("OP_SETCV\t%s\tR%d", mrb_sym2name(mrb, irep->syms[b]), a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_JMP, S): + printf("OP_JMP\t\t%03d\n", a); + break; + CASE(OP_JMPIF, BS): + printf("OP_JMPIF\tR%d\t%03d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_JMPNOT, BS): + printf("OP_JMPNOT\tR%d\t%03d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_JMPNIL, BS): + printf("OP_JMPNIL\tR%d\t%03d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_SENDV, BB): + printf("OP_SENDV\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_SENDVB, BB): + printf("OP_SENDVB\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_SEND, BBB): + printf("OP_SEND\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c); + break; + CASE(OP_SENDB, BBB): + printf("OP_SENDB\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c); + break; + CASE(OP_CALL, Z): + printf("OP_CALL\n"); + break; + CASE(OP_SUPER, BB): + printf("OP_SUPER\tR%d\t%d\n", a, b); + break; + CASE(OP_ARGARY, BS): + printf("OP_ARGARY\tR%d\t%d:%d:%d:%d (%d)", a, + (b>>11)&0x3f, + (b>>10)&0x1, + (b>>5)&0x1f, + (b>>4)&0x1, + (b>>0)&0xf); + print_lv_a(mrb, irep, a); + break; + CASE(OP_ENTER, W): printf("OP_ENTER\t%d:%d:%d:%d:%d:%d:%d\n", - (GETARG_Ax(c)>>18)&0x1f, - (GETARG_Ax(c)>>13)&0x1f, - (GETARG_Ax(c)>>12)&0x1, - (GETARG_Ax(c)>>7)&0x1f, - (GETARG_Ax(c)>>2)&0x1f, - (GETARG_Ax(c)>>1)&0x1, - GETARG_Ax(c) & 0x1); - break; - case OP_RETURN: - printf("OP_RETURN\tR%d", GETARG_A(c)); - switch (GETARG_B(c)) { - case OP_R_NORMAL: - printf("\tnormal\t"); break; - case OP_R_RETURN: - printf("\treturn\t"); break; - case OP_R_BREAK: - printf("\tbreak\t"); break; - default: - printf("\tbroken\t"); break; - } - print_lv(mrb, irep, c, RA); + (a>>18)&0x1f, + (a>>13)&0x1f, + (a>>12)&0x1, + (a>>7)&0x1f, + (a>>2)&0x1f, + (a>>1)&0x1, + a & 0x1); break; - case OP_BLKPUSH: - printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d", GETARG_A(c), - (GETARG_Bx(c)>>10)&0x3f, - (GETARG_Bx(c)>>9)&0x1, - (GETARG_Bx(c)>>4)&0x1f, - (GETARG_Bx(c)>>0)&0xf); - print_lv(mrb, irep, c, RA); + CASE(OP_KEY_P, BB): + printf("OP_KEY_P\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); break; - - case OP_LAMBDA: - printf("OP_LAMBDA\tR%d\tI(%+d)\t", GETARG_A(c), GETARG_b(c)+1); - switch (GETARG_c(c)) { - case OP_L_METHOD: - printf("method"); break; - case OP_L_BLOCK: - printf("block"); break; - case OP_L_LAMBDA: - printf("lambda"); break; - } - print_lv(mrb, irep, c, RA); + CASE(OP_KEYEND, Z): + printf("OP_KEYEND\n"); break; - case OP_RANGE: - printf("OP_RANGE\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_KARG, BB): + printf("OP_KARG\tR%d\t:%s\t", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); break; - case OP_METHOD: - printf("OP_METHOD\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); - print_lv(mrb, irep, c, RA); + CASE(OP_RETURN, B): + printf("OP_RETURN\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - - case OP_ADD: - printf("OP_ADD\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_ADDI: - printf("OP_ADDI\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUB: - printf("OP_SUB\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_SUBI: - printf("OP_SUBI\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_MUL: - printf("OP_MUL\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_DIV: - printf("OP_DIV\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_LT: - printf("OP_LT\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_LE: - printf("OP_LE\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_GT: - printf("OP_GT\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_GE: - printf("OP_GE\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); - break; - case OP_EQ: - printf("OP_EQ\t\tR%d\t:%s\t%d\n", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)]), - GETARG_C(c)); + CASE(OP_RETURN_BLK, B): + printf("OP_RETURN_BLK\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - - case OP_STOP: - printf("OP_STOP\n"); + CASE(OP_BREAK, B): + printf("OP_BREAK\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - - case OP_ARRAY: - printf("OP_ARRAY\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_BLKPUSH, BS): + printf("OP_BLKPUSH\tR%d\t%d:%d:%d:%d (%d)", a, + (b>>11)&0x3f, + (b>>10)&0x1, + (b>>5)&0x1f, + (b>>4)&0x1, + (b>>0)&0xf); + print_lv_a(mrb, irep, a); + break; + CASE(OP_LAMBDA, BB): + printf("OP_LAMBDA\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); + break; + CASE(OP_BLOCK, BB): + printf("OP_BLOCK\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); + break; + CASE(OP_METHOD, BB): + printf("OP_METHOD\tR%d\tI(%d:%p)\n", a, b, irep->reps[b]); + break; + CASE(OP_RANGE_INC, B): + printf("OP_RANGE_INC\tR%d\n", a); + break; + CASE(OP_RANGE_EXC, B): + printf("OP_RANGE_EXC\tR%d\n", a); + break; + CASE(OP_DEF, BB): + printf("OP_DEF\tR%d\t:%s\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_UNDEF, B): + printf("OP_UNDEF\t:%s\n", mrb_sym2name(mrb, irep->syms[a])); + break; + CASE(OP_ALIAS, BB): + printf("OP_ALIAS\t:%s\t%s\n", mrb_sym2name(mrb, irep->syms[a]), mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_ADD, BB): + printf("OP_ADD\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_ADDI, BBB): + printf("OP_ADDI\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c); + break; + CASE(OP_SUB, BB): + printf("OP_SUB\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_SUBI, BBB): + printf("OP_SUBI\tR%d\t:%s\t%d\n", a, mrb_sym2name(mrb, irep->syms[b]), c); + break; + CASE(OP_MUL, BB): + printf("OP_MUL\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_DIV, BB): + printf("OP_DIV\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_LT, BB): + printf("OP_LT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_LE, BB): + printf("OP_LE\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_GT, BB): + printf("OP_GT\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_GE, BB): + printf("OP_GE\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); + break; + CASE(OP_EQ, BB): + printf("OP_EQ\t\tR%d\t:%s\t\n", a, mrb_sym2name(mrb, irep->syms[b])); break; - case OP_ARYCAT: - printf("OP_ARYCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_ARRAY, BB): + printf("OP_ARRAY\tR%d\t%d\t", a, b); + print_lv_a(mrb, irep, a); break; - case OP_ARYPUSH: - printf("OP_ARYPUSH\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_ARRAY2, BBB): + printf("OP_ARRAY\tR%d\tR%d\t%d\t", a, b, c); + print_lv_ab(mrb, irep, a, b); break; - case OP_AREF: - printf("OP_AREF\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_ARYCAT, B): + printf("OP_ARYCAT\tR%d\t", a); + print_lv_a(mrb, irep, a); break; - case OP_APOST: - printf("OP_APOST\tR%d\t%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RA); + CASE(OP_ARYPUSH, B): + printf("OP_ARYPUSH\tR%d\t", a); + print_lv_a(mrb, irep, a); break; - case OP_STRING: + CASE(OP_ARYDUP, B): + printf("OP_ARYDUP\tR%d\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_AREF, BBB): + printf("OP_AREF\tR%d\tR%d\t%d", a, b, c); + print_lv_ab(mrb, irep, a, b); + break; + CASE(OP_ASET, BBB): + printf("OP_ASET\tR%d\tR%d\t%d", a, b, c); + print_lv_ab(mrb, irep, a, b); + break; + CASE(OP_APOST, BBB): + printf("OP_APOST\tR%d\t%d\t%d", a, b, c); + print_lv_a(mrb, irep, a); + break; + CASE(OP_INTERN, B): + printf("OP_INTERN\tR%d", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_STRING, BB): { - mrb_value v = irep->pool[GETARG_Bx(c)]; + mrb_value v = irep->pool[b]; mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); - printf("OP_STRING\tR%d\tL(%d)\t; %s", GETARG_A(c), GETARG_Bx(c), RSTRING_PTR(s)); + printf("OP_STRING\tR%d\tL(%d)\t; %s", a, b, RSTRING_PTR(s)); } - print_lv(mrb, irep, c, RA); + print_lv_a(mrb, irep, a); + break; + CASE(OP_STRCAT, B): + printf("OP_STRCAT\tR%d\t", a); + print_lv_a(mrb, irep, a); break; - case OP_STRCAT: - printf("OP_STRCAT\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_HASH, BB): + printf("OP_HASH\tR%d\t%d\t", a, b); + print_lv_a(mrb, irep, a); break; - case OP_HASH: - printf("OP_HASH\tR%d\tR%d\t%d", GETARG_A(c), GETARG_B(c), GETARG_C(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_HASHADD, BB): + printf("OP_HASHADD\tR%d\t%d\t", a, b); + print_lv_a(mrb, irep, a); + break; + CASE(OP_HASHCAT, B): + printf("OP_HASHCAT\tR%d\t", a); + print_lv_a(mrb, irep, a); break; - case OP_OCLASS: - printf("OP_OCLASS\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); + CASE(OP_OCLASS, B): + printf("OP_OCLASS\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - case OP_CLASS: - printf("OP_CLASS\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); - print_lv(mrb, irep, c, RA); + CASE(OP_CLASS, BB): + printf("OP_CLASS\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); break; - case OP_MODULE: - printf("OP_MODULE\tR%d\t:%s", GETARG_A(c), - mrb_sym2name(mrb, irep->syms[GETARG_B(c)])); - print_lv(mrb, irep, c, RA); + CASE(OP_MODULE, BB): + printf("OP_MODULE\tR%d\t:%s", a, mrb_sym2name(mrb, irep->syms[b])); + print_lv_a(mrb, irep, a); break; - case OP_EXEC: - printf("OP_EXEC\tR%d\tI(%+d)", GETARG_A(c), GETARG_Bx(c)+1); - print_lv(mrb, irep, c, RA); + CASE(OP_EXEC, BB): + printf("OP_EXEC\tR%d\tI(%d:%p)", a, b, irep->reps[b]); + print_lv_a(mrb, irep, a); break; - case OP_SCLASS: - printf("OP_SCLASS\tR%d\tR%d\t", GETARG_A(c), GETARG_B(c)); - print_lv(mrb, irep, c, RAB); + CASE(OP_SCLASS, B): + printf("OP_SCLASS\tR%d\t", a); + print_lv_a(mrb, irep, a); break; - case OP_TCLASS: - printf("OP_TCLASS\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); + CASE(OP_TCLASS, B): + printf("OP_TCLASS\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - case OP_ERR: + CASE(OP_ERR, B): { - mrb_value v = irep->pool[GETARG_Bx(c)]; + mrb_value v = irep->pool[a]; mrb_value s = mrb_str_dump(mrb, mrb_str_new(mrb, RSTRING_PTR(v), RSTRING_LEN(v))); printf("OP_ERR\t%s\n", RSTRING_PTR(s)); } break; - case OP_EPUSH: - printf("OP_EPUSH\t:I(%+d)\n", GETARG_Bx(c)+1); + CASE(OP_EPUSH, B): + printf("OP_EPUSH\t\t:I(%d:%p)\n", a, irep->reps[a]); break; - case OP_ONERR: - printf("OP_ONERR\t%03d\n", i+GETARG_sBx(c)); + CASE(OP_ONERR, S): + printf("OP_ONERR\t%03d\n", a); break; - case OP_RESCUE: - { - int a = GETARG_A(c); - int b = GETARG_B(c); - int cnt = GETARG_C(c); - - if (b == 0) { - printf("OP_RESCUE\tR%d\t\t%s", a, cnt ? "cont" : ""); - print_lv(mrb, irep, c, RA); - break; - } - else { - printf("OP_RESCUE\tR%d\tR%d\t%s", a, b, cnt ? "cont" : ""); - print_lv(mrb, irep, c, RAB); - break; - } - } + CASE(OP_EXCEPT, B): + printf("OP_EXCEPT\tR%d\t\t", a); + print_lv_a(mrb, irep, a); + break; + CASE(OP_RESCUE, BB): + printf("OP_RESCUE\tR%d\tR%d", a, b); + print_lv_ab(mrb, irep, a, b); break; - case OP_RAISE: - printf("OP_RAISE\tR%d\t\t", GETARG_A(c)); - print_lv(mrb, irep, c, RA); + CASE(OP_RAISE, B): + printf("OP_RAISE\tR%d\t\t", a); + print_lv_a(mrb, irep, a); break; - case OP_POPERR: - printf("OP_POPERR\t%d\t\t\n", GETARG_A(c)); + CASE(OP_POPERR, B): + printf("OP_POPERR\t%d\t\t\n", a); break; - case OP_EPOP: - printf("OP_EPOP\t%d\n", GETARG_A(c)); + CASE(OP_EPOP, B): + printf("OP_EPOP\t%d\n", a); break; + CASE(OP_DEBUG, BBB): + printf("OP_DEBUG\t%d\t%d\t%d\n", a, b, c); + break; + + CASE(OP_STOP, Z): + printf("OP_STOP\n"); + break; + + CASE(OP_EXT1, Z): + ins = READ_B(); + printf("OP_EXT1\n"); + print_header(irep, pc-irep->iseq-2); + switch (ins) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i; +#include "mruby/ops.h" +#undef OPCODE + } + break; + CASE(OP_EXT2, Z): + ins = READ_B(); + printf("OP_EXT2\n"); + print_header(irep, pc-irep->iseq-2); + switch (ins) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i; +#include "mruby/ops.h" +#undef OPCODE + } + break; + CASE(OP_EXT3, Z): + ins = READ_B(); + printf("OP_EXT3\n"); + print_header(irep, pc-irep->iseq-2); + switch (ins) { +#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i; +#include "mruby/ops.h" +#undef OPCODE + } + break; + default: - printf("OP_unknown %d\t%d\t%d\t%d\n", GET_OPCODE(c), - GETARG_A(c), GETARG_B(c), GETARG_C(c)); + printf("OP_unknown (0x%x)\n", ins); break; } mrb_gc_arena_restore(mrb, ai); diff --git a/src/hash.c b/src/hash.c index db9d1d9c8..122f5b5d5 100644 --- a/src/hash.c +++ b/src/hash.c @@ -208,6 +208,54 @@ mrb_hash_init_copy(mrb_state *mrb, mrb_value self) return vret; } +void +mrb_hash_check_kdict(mrb_state *mrb, mrb_value self) +{ + khash_t(ht) *orig_h; + khiter_t k; + int nosym = FALSE; + + orig_h = RHASH_TBL(self); + if (!orig_h || kh_size(orig_h) == 0) return; + for (k = kh_begin(orig_h); k != kh_end(orig_h); k++) { + if (kh_exist(orig_h, k)) { + mrb_value key = kh_key(orig_h, k); + + if (!mrb_symbol_p(key)) nosym = TRUE; + } + } + if (nosym) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "keyword argument hash with non symbol keys"); + } +} + +MRB_API mrb_value +mrb_hash_dup(mrb_state *mrb, mrb_value self) +{ + struct RHash* copy; + khash_t(ht) *orig_h; + + orig_h = RHASH_TBL(self); + copy = (struct RHash*)mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class); + copy->ht = kh_init(ht, mrb); + + if (orig_h && kh_size(orig_h) > 0) { + int ai = mrb_gc_arena_save(mrb); + khash_t(ht) *copy_h = copy->ht; + khiter_t k, copy_k; + + for (k = kh_begin(orig_h); k != kh_end(orig_h); k++) { + if (kh_exist(orig_h, k)) { + copy_k = kh_put(ht, mrb, copy_h, KEY(kh_key(orig_h, k))); + mrb_gc_arena_restore(mrb, ai); + kh_val(copy_h, copy_k).v = kh_val(orig_h, k).v; + kh_val(copy_h, copy_k).n = kh_size(copy_h)-1; + } + } + } + return mrb_obj_value(copy); +} + MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) { @@ -716,13 +764,21 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self) * {}.empty? #=> true * */ -MRB_API mrb_value +MRB_API mrb_bool mrb_hash_empty_p(mrb_state *mrb, mrb_value self) { khash_t(ht) *h = RHASH_TBL(self); - if (h) return mrb_bool_value(kh_size(h) == 0); - return mrb_true_value(); + if (h) return kh_size(h) == 0; + return TRUE; +} + +static mrb_value +mrb_hash_empty_m(mrb_state *mrb, mrb_value self) +{ + if (mrb_hash_empty_p(mrb, self)) + return mrb_true_value(); + return mrb_false_value(); } /* 15.2.13.4.29 (x)*/ @@ -833,21 +889,29 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash) * */ -static mrb_value -mrb_hash_has_key(mrb_state *mrb, mrb_value hash) +MRB_API mrb_bool +mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key) { - mrb_value key; khash_t(ht) *h; khiter_t k; - mrb_get_args(mrb, "o", &key); - h = RHASH_TBL(hash); if (h) { k = kh_get(ht, mrb, h, key); - return mrb_bool_value(k != kh_end(h)); + return k != kh_end(h); } - return mrb_false_value(); + return FALSE; +} + +static mrb_value +mrb_hash_has_key(mrb_state *mrb, mrb_value hash) +{ + mrb_value key; + mrb_bool key_p; + + mrb_get_args(mrb, "o", &key); + key_p = mrb_hash_key_p(mrb, hash, key); + return mrb_bool_value(key_p); } /* 15.2.13.4.14 */ @@ -887,6 +951,39 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash) return mrb_false_value(); } +MRB_API void +mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2) +{ + khash_t(ht) *h1; + khash_t(ht) *h2; + khiter_t k; + + mrb_hash_modify(mrb, hash1); + hash2 = mrb_check_hash_type(mrb, hash2); + h1 = RHASH_TBL(hash1); + h2 = RHASH_TBL(hash2); + + if (!h1) { + RHASH_TBL(hash1) = kh_copy(ht, mrb, h2); + return; + } + for (k = kh_begin(h2); k != kh_end(h2); k++) { + khiter_t k1; + int r; + + if (!kh_exist(h2, k)) continue; + k1 = kh_put2(ht, mrb, h1, kh_key(h2, k), &r); + kh_value(h1, k1).v = kh_value(h2,k).v; + if (r != 0) { + /* expand */ + kh_key(h1, k1) = kh_key(h2, k); + kh_value(h1, k1).n = kh_size(h1)-1; + } + } + mrb_write_barrier(mrb, (struct RBasic*)RHASH(hash1)); + return; +} + void mrb_init_hash(mrb_state *mrb) { @@ -904,7 +1001,7 @@ mrb_init_hash(mrb_state *mrb) mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,MRB_ARGS_NONE()); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,MRB_ARGS_REQ(1)); /* 15.2.13.4.7 */ mrb_define_method(mrb, h, "__delete", mrb_hash_delete, MRB_ARGS_REQ(1)); /* core of 15.2.13.4.8 */ - mrb_define_method(mrb, h, "empty?", mrb_hash_empty_p, MRB_ARGS_NONE()); /* 15.2.13.4.12 */ + mrb_define_method(mrb, h, "empty?", mrb_hash_empty_m, MRB_ARGS_NONE()); /* 15.2.13.4.12 */ mrb_define_method(mrb, h, "has_key?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.13 */ mrb_define_method(mrb, h, "has_value?", mrb_hash_has_value, MRB_ARGS_REQ(1)); /* 15.2.13.4.14 */ mrb_define_method(mrb, h, "include?", mrb_hash_has_key, MRB_ARGS_REQ(1)); /* 15.2.13.4.15 */ diff --git a/src/kernel.c b/src/kernel.c index 50ad50f00..fed64e9b0 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -1194,7 +1194,15 @@ mrb_local_variables(mrb_state *mrb, mrb_value self) if (!irep->lv) break; for (i = 0; i + 1 < irep->nlocals; ++i) { if (irep->lv[i].name) { - mrb_hash_set(mrb, vars, mrb_symbol_value(irep->lv[i].name), mrb_true_value()); + mrb_sym sym = irep->lv[i].name; + const char *name = mrb_sym2name(mrb, sym); + switch (name[0]) { + case '*': case '&': + break; + default: + mrb_hash_set(mrb, vars, mrb_symbol_value(sym), mrb_true_value()); + break; + } } } if (!MRB_PROC_ENV_P(proc)) break; @@ -1266,5 +1274,5 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1)); mrb_include_module(mrb, mrb->object_class, mrb->kernel_module); - mrb_alias_method(mrb, mrb->module_class, mrb_intern_lit(mrb, "dup"), mrb_intern_lit(mrb, "clone")); + mrb_define_alias(mrb, mrb->module_class, "dup", "clone"); /* XXX */ } diff --git a/src/load.c b/src/load.c index ddf3cdfbf..54b50b14d 100644 --- a/src/load.c +++ b/src/load.c @@ -68,7 +68,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag /* Binary Data Section */ /* ISEQ BLOCK */ - irep->ilen = (size_t)bin_to_uint32(src); + irep->ilen = (uint16_t)bin_to_uint32(src); src += sizeof(uint32_t); src += skip_padding(src); @@ -79,7 +79,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag if ((flags & FLAG_SRC_MALLOC) == 0 && (flags & FLAG_BYTEORDER_NATIVE)) { irep->iseq = (mrb_code*)src; - src += sizeof(uint32_t) * irep->ilen; + src += sizeof(mrb_code) * irep->ilen; irep->flags |= MRB_ISEQ_NO_FREE; } else { @@ -157,7 +157,7 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag } /* SYMS BLOCK */ - irep->slen = (size_t)bin_to_uint32(src); /* syms length */ + irep->slen = (uint16_t)bin_to_uint32(src); /* syms length */ src += sizeof(uint32_t); if (irep->slen > 0) { if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) { diff --git a/src/proc.c b/src/proc.c index c6e9be433..05b897480 100644 --- a/src/proc.c +++ b/src/proc.c @@ -10,7 +10,7 @@ #include <mruby/opcode.h> static mrb_code call_iseq[] = { - MKOP_A(OP_CALL, 0), + OP_CALL, }; struct RProc* @@ -223,7 +223,7 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self) { struct RProc *p = mrb_proc_ptr(self); struct mrb_irep *irep; - mrb_code *iseq; + mrb_code *pc; mrb_aspec aspec; int ma, op, ra, pa, arity; @@ -237,13 +237,13 @@ mrb_proc_arity(mrb_state *mrb, mrb_value self) return mrb_fixnum_value(0); } - iseq = irep->iseq; + pc = irep->iseq; /* arity is depend on OP_ENTER */ - if (GET_OPCODE(*iseq) != OP_ENTER) { + if (*pc != OP_ENTER) { return mrb_fixnum_value(0); } - aspec = GETARG_Ax(*iseq); + aspec = PEEK_W(pc+1); ma = MRB_ASPEC_REQ(aspec); op = MRB_ASPEC_OPT(aspec); ra = MRB_ASPEC_REST(aspec); @@ -218,7 +218,7 @@ stack_extend_alloc(mrb_state *mrb, int room) } MRB_API void -mrb_stack_extend(mrb_state *mrb, int room) +mrb_stack_extend(mrb_state *mrb, mrb_int room) { if (mrb->c->stack + room >= mrb->c->stend) { stack_extend_alloc(mrb, room); @@ -333,7 +333,7 @@ ecall(mrb_state *mrb) struct REnv *env; ptrdiff_t cioff; int ai = mrb_gc_arena_save(mrb); - int i = --c->eidx; + uint8_t i = --c->eidx; int nregs; if (i<0) return; @@ -934,18 +934,18 @@ argnum_error(mrb_state *mrb, mrb_int num) #ifndef DIRECT_THREADED -#define INIT_DISPATCH for (;;) { i = BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (GET_OPCODE(i)) { -#define CASE(op) case op: -#define NEXT pc++; break -#define JUMP break +#define INIT_DISPATCH for (;;) { insn = BYTECODE_DECODER(*pc); pc++; CODE_FETCH_HOOK(mrb, irep, pc, regs); switch (insn) { +#define CASE(insn,ops) case insn: pc++; FETCH_ ## ops ();; L_ ## insn ## _BODY: +#define NEXT break +#define JUMP NEXT #define END_DISPATCH }} #else #define INIT_DISPATCH JUMP; return mrb_nil_value(); -#define CASE(op) L_ ## op: -#define NEXT i=BYTECODE_DECODER(*++pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] -#define JUMP i=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[GET_OPCODE(i)] +#define CASE(insn,ops) L_ ## insn: pc++; FETCH_ ## ops (); L_ ## insn ## _BODY: +#define NEXT insn=BYTECODE_DECODER(*pc); CODE_FETCH_HOOK(mrb, irep, pc, regs); goto *optable[insn] +#define JUMP NEXT #define END_DISPATCH @@ -981,6 +981,19 @@ mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stac return result; } +static mrb_bool +check_target_class(mrb_state *mrb) +{ + if (!mrb->c->ci->target_class) { + mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); + mrb_exc_set(mrb, exc); + return FALSE; + } + return TRUE; +} + +void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); + MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) { @@ -988,33 +1001,19 @@ mrb_vm_exec(mrb_state *mrb, struct RProc *proc, mrb_code *pc) mrb_irep *irep = proc->body.irep; mrb_value *pool = irep->pool; mrb_sym *syms = irep->syms; - mrb_code i; + mrb_code insn; int ai = mrb_gc_arena_save(mrb); struct mrb_jmpbuf *prev_jmp = mrb->jmp; struct mrb_jmpbuf c_jmp; + uint32_t a; + uint16_t b; + uint8_t c; #ifdef DIRECT_THREADED static void *optable[] = { - &&L_OP_NOP, &&L_OP_MOVE, - &&L_OP_LOADL, &&L_OP_LOADI, &&L_OP_LOADSYM, &&L_OP_LOADNIL, - &&L_OP_LOADSELF, &&L_OP_LOADT, &&L_OP_LOADF, - &&L_OP_GETGLOBAL, &&L_OP_SETGLOBAL, &&L_OP_GETSPECIAL, &&L_OP_SETSPECIAL, - &&L_OP_GETIV, &&L_OP_SETIV, &&L_OP_GETCV, &&L_OP_SETCV, - &&L_OP_GETCONST, &&L_OP_SETCONST, &&L_OP_GETMCNST, &&L_OP_SETMCNST, - &&L_OP_GETUPVAR, &&L_OP_SETUPVAR, - &&L_OP_JMP, &&L_OP_JMPIF, &&L_OP_JMPNOT, - &&L_OP_ONERR, &&L_OP_RESCUE, &&L_OP_POPERR, &&L_OP_RAISE, &&L_OP_EPUSH, &&L_OP_EPOP, - &&L_OP_SEND, &&L_OP_SENDB, &&L_OP_FSEND, - &&L_OP_CALL, &&L_OP_SUPER, &&L_OP_ARGARY, &&L_OP_ENTER, - &&L_OP_KARG, &&L_OP_KDICT, &&L_OP_RETURN, &&L_OP_TAILCALL, &&L_OP_BLKPUSH, - &&L_OP_ADD, &&L_OP_ADDI, &&L_OP_SUB, &&L_OP_SUBI, &&L_OP_MUL, &&L_OP_DIV, - &&L_OP_EQ, &&L_OP_LT, &&L_OP_LE, &&L_OP_GT, &&L_OP_GE, - &&L_OP_ARRAY, &&L_OP_ARYCAT, &&L_OP_ARYPUSH, &&L_OP_AREF, &&L_OP_ASET, &&L_OP_APOST, - &&L_OP_STRING, &&L_OP_STRCAT, &&L_OP_HASH, - &&L_OP_LAMBDA, &&L_OP_RANGE, &&L_OP_OCLASS, - &&L_OP_CLASS, &&L_OP_MODULE, &&L_OP_EXEC, - &&L_OP_METHOD, &&L_OP_SCLASS, &&L_OP_TCLASS, - &&L_OP_DEBUG, &&L_OP_STOP, &&L_OP_ERR, +#define OPCODE(x,_) &&L_OP_ ## x, +#include "mruby/ops.h" +#undef OPCODE }; #endif @@ -1035,25 +1034,19 @@ RETRY_TRY_BLOCK: #define regs (mrb->c->stack) INIT_DISPATCH { - CASE(OP_NOP) { + CASE(OP_NOP, Z) { /* do nothing */ NEXT; } - CASE(OP_MOVE) { - /* A B R(A) := R(B) */ - int a = GETARG_A(i); - int b = GETARG_B(i); + CASE(OP_MOVE, BB) { regs[a] = regs[b]; NEXT; } - CASE(OP_LOADL) { - /* A Bx R(A) := Pool(Bx) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); + CASE(OP_LOADL, BB) { #ifdef MRB_WORD_BOXING - mrb_value val = pool[bx]; + mrb_value val = pool[b]; #ifndef MRB_WITHOUT_FLOAT if (mrb_float_p(val)) { val = mrb_float_value(mrb, mrb_float(val)); @@ -1061,125 +1054,109 @@ RETRY_TRY_BLOCK: #endif regs[a] = val; #else - regs[a] = pool[bx]; + regs[a] = pool[b]; #endif NEXT; } - CASE(OP_LOADI) { - /* A sBx R(A) := sBx */ - int a = GETARG_A(i); - mrb_int bx = GETARG_sBx(i); - SET_INT_VALUE(regs[a], bx); + CASE(OP_LOADI, BB) { + SET_INT_VALUE(regs[a], b); + NEXT; + } + + CASE(OP_LOADINEG, BB) { + SET_INT_VALUE(regs[a], -b); + NEXT; + } + + CASE(OP_LOADI__1,B) goto L_LOADI; + CASE(OP_LOADI_0,B) goto L_LOADI; + CASE(OP_LOADI_1,B) goto L_LOADI; + CASE(OP_LOADI_2,B) goto L_LOADI; + CASE(OP_LOADI_3,B) goto L_LOADI; + CASE(OP_LOADI_4,B) goto L_LOADI; + CASE(OP_LOADI_5,B) goto L_LOADI; + CASE(OP_LOADI_6,B) goto L_LOADI; + CASE(OP_LOADI_7, B) { + L_LOADI: + SET_INT_VALUE(regs[a], (mrb_int)insn - (mrb_int)OP_LOADI_0); + NEXT; + } + + CASE(OP_LOADSYM, BB) { + SET_SYM_VALUE(regs[a], syms[b]); NEXT; } - CASE(OP_LOADSYM) { - /* A Bx R(A) := Syms(Bx) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - SET_SYM_VALUE(regs[a], syms[bx]); + CASE(OP_LOADNIL, B) { + SET_NIL_VALUE(regs[a]); NEXT; } - CASE(OP_LOADSELF) { - /* A R(A) := self */ - int a = GETARG_A(i); + CASE(OP_LOADSELF, B) { regs[a] = regs[0]; NEXT; } - CASE(OP_LOADT) { - /* A R(A) := true */ - int a = GETARG_A(i); + CASE(OP_LOADT, B) { SET_TRUE_VALUE(regs[a]); NEXT; } - CASE(OP_LOADF) { - /* A R(A) := false */ - int a = GETARG_A(i); + CASE(OP_LOADF, B) { SET_FALSE_VALUE(regs[a]); NEXT; } - CASE(OP_GETGLOBAL) { - /* A Bx R(A) := getglobal(Syms(Bx)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_value val = mrb_gv_get(mrb, syms[bx]); + CASE(OP_GETGV, BB) { + mrb_value val = mrb_gv_get(mrb, syms[b]); regs[a] = val; NEXT; } - CASE(OP_SETGLOBAL) { - /* A Bx setglobal(Syms(Bx), R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_gv_set(mrb, syms[bx], regs[a]); + CASE(OP_SETGV, BB) { + mrb_gv_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETSPECIAL) { - /* A Bx R(A) := Special[Bx] */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_value val = mrb_vm_special_get(mrb, bx); + CASE(OP_GETSV, BB) { + mrb_value val = mrb_vm_special_get(mrb, b); regs[a] = val; NEXT; } - CASE(OP_SETSPECIAL) { - /* A Bx Special[Bx] := R(A) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_special_set(mrb, bx, regs[a]); + CASE(OP_SETSV, BB) { + mrb_vm_special_set(mrb, b, regs[a]); NEXT; } - CASE(OP_GETIV) { - /* A Bx R(A) := ivget(Bx) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_value val = mrb_iv_get(mrb, regs[0], syms[bx]); - regs[a] = val; + CASE(OP_GETIV, BB) { + regs[a] = mrb_iv_get(mrb, regs[0], syms[b]); NEXT; } - CASE(OP_SETIV) { - /* A Bx ivset(Syms(Bx),R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_iv_set(mrb, regs[0], syms[bx], regs[a]); + CASE(OP_SETIV, BB) { + mrb_iv_set(mrb, regs[0], syms[b], regs[a]); NEXT; } - CASE(OP_GETCV) { - /* A Bx R(A) := cvget(Syms(Bx)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); + CASE(OP_GETCV, BB) { mrb_value val; ERR_PC_SET(mrb, pc); - val = mrb_vm_cv_get(mrb, syms[bx]); + val = mrb_vm_cv_get(mrb, syms[b]); ERR_PC_CLR(mrb); regs[a] = val; NEXT; } - CASE(OP_SETCV) { - /* A Bx cvset(Syms(Bx),R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_cv_set(mrb, syms[bx], regs[a]); + CASE(OP_SETCV, BB) { + mrb_vm_cv_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETCONST) { - /* A Bx R(A) := constget(Syms(Bx)) */ + CASE(OP_GETCONST, BB) { mrb_value val; - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_sym sym = syms[bx]; + mrb_sym sym = syms[b]; ERR_PC_SET(mrb, pc); val = mrb_vm_const_get(mrb, sym); @@ -1188,40 +1165,27 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_SETCONST) { - /* A Bx constset(Syms(Bx),R(A)) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_vm_const_set(mrb, syms[bx], regs[a]); + CASE(OP_SETCONST, BB) { + mrb_vm_const_set(mrb, syms[b], regs[a]); NEXT; } - CASE(OP_GETMCNST) { - /* A Bx R(A) := R(A)::Syms(Bx) */ + CASE(OP_GETMCNST, BB) { mrb_value val; - int a = GETARG_A(i); - int bx = GETARG_Bx(i); ERR_PC_SET(mrb, pc); - val = mrb_const_get(mrb, regs[a], syms[bx]); + val = mrb_const_get(mrb, regs[a], syms[b]); ERR_PC_CLR(mrb); regs[a] = val; NEXT; } - CASE(OP_SETMCNST) { - /* A Bx R(A+1)::Syms(Bx) := R(A) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - mrb_const_set(mrb, regs[a+1], syms[bx], regs[a]); + CASE(OP_SETMCNST, BB) { + mrb_const_set(mrb, regs[a+1], syms[b], regs[a]); NEXT; } - CASE(OP_GETUPVAR) { - /* A B C R(A) := uvget(B,C) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_GETUPVAR, BBB) { mrb_value *regs_a = regs + a; struct REnv *e = uvenv(mrb, c); @@ -1234,12 +1198,7 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_SETUPVAR) { - /* A B C uvset(B,C,R(A)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); - + CASE(OP_SETUPVAR, BBB) { struct REnv *e = uvenv(mrb, c); if (e) { @@ -1253,110 +1212,86 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_JMP) { - /* sBx pc+=sBx */ - int sbx = GETARG_sBx(i); - pc += sbx; + CASE(OP_JMP, S) { + pc = irep->iseq+a; JUMP; } - - CASE(OP_JMPIF) { - /* A sBx if R(A) pc+=sBx */ - int a = GETARG_A(i); - int sbx = GETARG_sBx(i); + CASE(OP_JMPIF, BS) { if (mrb_test(regs[a])) { - pc += sbx; + pc = irep->iseq+b; JUMP; } NEXT; } - - CASE(OP_JMPNOT) { - /* A sBx if !R(A) pc+=sBx */ - int a = GETARG_A(i); - int sbx = GETARG_sBx(i); + CASE(OP_JMPNOT, BS) { if (!mrb_test(regs[a])) { - pc += sbx; + pc = irep->iseq+b; + JUMP; + } + NEXT; + } + CASE(OP_JMPNIL, BS) { + if (mrb_nil_p(regs[a])) { + pc = irep->iseq+b; JUMP; } NEXT; } - CASE(OP_ONERR) { - /* sBx pc+=sBx on exception */ - int sbx = GETARG_sBx(i); + CASE(OP_ONERR, S) { if (mrb->c->rsize <= mrb->c->ci->ridx) { if (mrb->c->rsize == 0) mrb->c->rsize = RESCUE_STACK_INIT_SIZE; else mrb->c->rsize *= 2; - mrb->c->rescue = (mrb_code **)mrb_realloc(mrb, mrb->c->rescue, sizeof(mrb_code*) * mrb->c->rsize); + mrb->c->rescue = (uint16_t*)mrb_realloc(mrb, mrb->c->rescue, sizeof(uint16_t) * mrb->c->rsize); } - mrb->c->rescue[mrb->c->ci->ridx++] = pc + sbx; + mrb->c->rescue[mrb->c->ci->ridx++] = a; NEXT; } - CASE(OP_RESCUE) { - /* A B R(A) := exc; clear(exc); R(B) := matched (bool) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); - mrb_value exc; - - if (c == 0) { - exc = mrb_obj_value(mrb->exc); - mrb->exc = 0; - } - else { /* continued; exc taken from R(A) */ - exc = regs[a]; - } - if (b != 0) { - mrb_value e = regs[b]; - struct RClass *ec; + CASE(OP_EXCEPT, B) { + mrb_value exc = mrb_obj_value(mrb->exc); + mrb->exc = 0; + regs[a] = exc; + NEXT; + } + CASE(OP_RESCUE, BB) { + mrb_value exc = regs[a]; /* exc on stack */ + mrb_value e = regs[b]; + struct RClass *ec; - switch (mrb_type(e)) { - case MRB_TT_CLASS: - case MRB_TT_MODULE: - break; - default: - { - mrb_value exc; + switch (mrb_type(e)) { + case MRB_TT_CLASS: + case MRB_TT_MODULE: + break; + default: + { + mrb_value exc; - exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, - "class or module required for rescue clause"); - mrb_exc_set(mrb, exc); - goto L_RAISE; - } + exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, + "class or module required for rescue clause"); + mrb_exc_set(mrb, exc); + goto L_RAISE; } - ec = mrb_class_ptr(e); - regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec)); - } - if (a != 0 && c == 0) { - regs[a] = exc; } + ec = mrb_class_ptr(e); + regs[b] = mrb_bool_value(mrb_obj_is_kind_of(mrb, exc, ec)); NEXT; } - CASE(OP_POPERR) { - /* A A.times{rescue_pop()} */ - int a = GETARG_A(i); - + CASE(OP_POPERR, B) { mrb->c->ci->ridx -= a; NEXT; } - CASE(OP_RAISE) { - /* A raise(R(A)) */ - int a = GETARG_A(i); - + CASE(OP_RAISE, B) { mrb_exc_set(mrb, regs[a]); goto L_RAISE; } - CASE(OP_EPUSH) { - /* Bx ensure_push(SEQ[Bx]) */ - int bx = GETARG_Bx(i); + CASE(OP_EPUSH, B) { struct RProc *p; - p = mrb_closure_new(mrb, irep->reps[bx]); + p = mrb_closure_new(mrb, irep->reps[a]); /* push ensure_stack */ if (mrb->c->esize <= mrb->c->eidx+1) { if (mrb->c->esize == 0) mrb->c->esize = ENSURE_STACK_INIT_SIZE; @@ -1369,11 +1304,9 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_EPOP) { - /* A A.times{ensure_pop().call} */ - int a = GETARG_A(i); + CASE(OP_EPOP, B) { mrb_callinfo *ci = mrb->c->ci; - int n, epos = ci->epos; + unsigned int n, epos = ci->epos; mrb_value self = regs[0]; struct RClass *target_class = ci->target_class; @@ -1381,9 +1314,8 @@ RETRY_TRY_BLOCK: NEXT; } - if (a > mrb->c->eidx - epos) + if (a > (int)mrb->c->eidx - epos) a = mrb->c->eidx - epos; - pc = pc + 1; for (n=0; n<a; n++) { int nregs = irep->nregs; @@ -1410,29 +1342,32 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_LOADNIL) { - /* A R(A) := nil */ - int a = GETARG_A(i); + CASE(OP_SENDV, BB) { + c = CALL_MAXARGS; + goto L_SEND; + }; - SET_NIL_VALUE(regs[a]); - NEXT; - } + CASE(OP_SENDVB, BB) { + c = CALL_MAXARGS; + goto L_SENDB; + }; - CASE(OP_SENDB) { - /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/ - /* fall through */ + CASE(OP_SEND, BBB) + L_SEND: + { + /* push nil after arguments */ + int bidx = (c == CALL_MAXARGS) ? a+2 : a+c+1; + SET_NIL_VALUE(regs[bidx]); + goto L_SENDB; }; - L_SEND: - CASE(OP_SEND) { - /* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int n = GETARG_C(i); - int argc = (n == CALL_MAXARGS) ? -1 : n; - int bidx = (argc < 0) ? a+2 : a+n+1; + CASE(OP_SENDB, BBB) + L_SENDB: + { + int argc = (c == CALL_MAXARGS) ? -1 : c; + int bidx = (argc < 0) ? a+2 : a+c+1; mrb_method_t m; - struct RClass *c; + struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; mrb_value recv, blk; mrb_sym mid = syms[b]; @@ -1440,26 +1375,20 @@ RETRY_TRY_BLOCK: mrb_assert(bidx < irep->nregs); recv = regs[a]; - if (GET_OPCODE(i) != OP_SENDB) { - SET_NIL_VALUE(regs[bidx]); - blk = regs[bidx]; - } - else { - blk = regs[bidx]; - if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) { - blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); - /* The stack might have been reallocated during mrb_convert_type(), - see #3622 */ - regs[bidx] = blk; - } + blk = regs[bidx]; + if (!mrb_nil_p(blk) && mrb_type(blk) != MRB_TT_PROC) { + blk = mrb_convert_type(mrb, blk, MRB_TT_PROC, "Proc", "to_proc"); + /* The stack might have been reallocated during mrb_convert_type(), + see #3622 */ + regs[bidx] = blk; } - c = mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &c, mid); + cls = mrb_class(mrb, recv); + m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); - m = mrb_method_search_vm(mrb, &c, 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, n, regs+a+1); + mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, c, regs+a+1); ERR_PC_SET(mrb, pc); mrb_method_missing(mrb, mid, recv, args); } @@ -1467,7 +1396,7 @@ RETRY_TRY_BLOCK: if (a+2 >= irep->nregs) { mrb_stack_extend(mrb, a+3); } - regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + regs[a+1] = mrb_ary_new_from_values(mrb, c, regs+a+1); regs[a+2] = blk; argc = -1; } @@ -1479,10 +1408,10 @@ RETRY_TRY_BLOCK: ci = cipush(mrb); ci->mid = mid; ci->stackent = mrb->c->stack; - ci->target_class = c; + ci->target_class = cls; ci->argc = argc; - ci->pc = pc + 1; + ci->pc = pc; ci->acc = a; /* prepare stack */ @@ -1502,12 +1431,10 @@ RETRY_TRY_BLOCK: mrb_gc_arena_shrink(mrb, ai); if (mrb->exc) goto L_RAISE; ci = mrb->c->ci; - if (GET_OPCODE(i) == OP_SENDB) { - if (mrb_type(blk) == MRB_TT_PROC) { - struct RProc *p = mrb_proc_ptr(blk); - if (p && !MRB_PROC_STRICT_P(p) && MRB_PROC_ENV(p) == ci[-1].env) { - p->flags |= MRB_PROC_ORPHAN; - } + if (mrb_type(blk) == MRB_TT_PROC) { + struct RProc *p = mrb_proc_ptr(blk); + if (p && !MRB_PROC_STRICT_P(p) && MRB_PROC_ENV(p) == ci[-1].env) { + p->flags |= MRB_PROC_ORPHAN; } } if (!ci->target_class) { /* return from context modifying method (resume/yield) */ @@ -1542,14 +1469,7 @@ RETRY_TRY_BLOCK: } } - CASE(OP_FSEND) { - /* A B C R(A) := fcall(R(A),Syms(B),R(A+1),... ,R(A+C-1)) */ - /* not implemented yet */ - NEXT; - } - - CASE(OP_CALL) { - /* A R(A) := self.call(frame.argc, frame.argv) */ + CASE(OP_CALL, Z) { mrb_callinfo *ci; mrb_value recv = mrb->c->stack[0]; struct RProc *m = mrb_proc_ptr(recv); @@ -1592,7 +1512,9 @@ RETRY_TRY_BLOCK: irep = m->body.irep; if (!irep) { mrb->c->stack[0] = mrb_nil_value(); - goto L_RETURN; + a = 0; + c = OP_R_NORMAL; + goto L_OP_RETURN_BODY; } pool = irep->pool; syms = irep->syms; @@ -1613,14 +1535,11 @@ RETRY_TRY_BLOCK: } } - CASE(OP_SUPER) { - /* A C R(A) := super(R(A+1),... ,R(A+C+1)) */ - int a = GETARG_A(i); - int n = GETARG_C(i); - int argc = (n == CALL_MAXARGS) ? -1 : n; - int bidx = (argc < 0) ? a+2 : a+n+1; + CASE(OP_SUPER, BB) { + int argc = (b == CALL_MAXARGS) ? -1 : b; + int bidx = (argc < 0) ? a+2 : a+b+1; mrb_method_t m; - struct RClass *c; + struct RClass *cls; mrb_callinfo *ci = mrb->c->ci; mrb_value recv, blk; mrb_sym mid = ci->mid; @@ -1656,17 +1575,17 @@ RETRY_TRY_BLOCK: regs[bidx] = blk; ci = mrb->c->ci; } - c = target_class->super; - m = mrb_method_search_vm(mrb, &c, mid); + cls = target_class->super; + m = mrb_method_search_vm(mrb, &cls, mid); if (MRB_METHOD_UNDEF_P(m)) { mrb_sym missing = mrb_intern_lit(mrb, "method_missing"); if (mid != missing) { - c = mrb_class(mrb, recv); + cls = mrb_class(mrb, recv); } - m = mrb_method_search_vm(mrb, &c, missing); + m = mrb_method_search_vm(mrb, &cls, missing); if (MRB_METHOD_UNDEF_P(m)) { - mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, n, regs+a+1); + mrb_value args = (argc < 0) ? regs[a+1] : mrb_ary_new_from_values(mrb, b, regs+a+1); ERR_PC_SET(mrb, pc); mrb_method_missing(mrb, mid, recv, args); } @@ -1675,7 +1594,7 @@ RETRY_TRY_BLOCK: if (a+2 >= irep->nregs) { mrb_stack_extend(mrb, a+3); } - regs[a+1] = mrb_ary_new_from_values(mrb, n, regs+a+1); + regs[a+1] = mrb_ary_new_from_values(mrb, b, regs+a+1); regs[a+2] = blk; argc = -1; } @@ -1686,8 +1605,8 @@ RETRY_TRY_BLOCK: ci = cipush(mrb); ci->mid = mid; ci->stackent = mrb->c->stack; - ci->target_class = c; - ci->pc = pc + 1; + ci->target_class = cls; + ci->pc = pc; ci->argc = argc; /* prepare stack */ @@ -1739,14 +1658,12 @@ RETRY_TRY_BLOCK: } } - CASE(OP_ARGARY) { - /* A Bx R(A) := argument array (16=6:1:5:4) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - int m1 = (bx>>10)&0x3f; - int r = (bx>>9)&0x1; - int m2 = (bx>>4)&0x1f; - int lv = (bx>>0)&0xf; + CASE(OP_ARGARY, BS) { + int m1 = (b>>11)&0x3f; + int r = (b>>10)&0x1; + int m2 = (b>>5)&0x1f; + int kd = (b>>4)&0x1; + int lv = (b>>0)&0xf; mrb_value *stack; if (mrb->c->ci->mid == 0 || mrb->c->ci->target_class == NULL) { @@ -1761,12 +1678,12 @@ RETRY_TRY_BLOCK: else { struct REnv *e = uvenv(mrb, lv-1); if (!e) goto L_NOSUPER; - if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+1) + if (MRB_ENV_STACK_LEN(e) <= m1+r+m2+kd+1) goto L_NOSUPER; stack = e->stack + 1; } if (r == 0) { - regs[a] = mrb_ary_new_from_values(mrb, m1+m2, stack); + regs[a] = mrb_ary_new_from_values(mrb, m1+m2+kd, stack); } else { mrb_value *pp = NULL; @@ -1779,7 +1696,7 @@ RETRY_TRY_BLOCK: pp = ARY_PTR(ary); len = (int)ARY_LEN(ary); } - regs[a] = mrb_ary_new_capa(mrb, m1+len+m2); + regs[a] = mrb_ary_new_capa(mrb, m1+len+m2+kd); rest = mrb_ary_ptr(regs[a]); if (m1 > 0) { stack_copy(ARY_PTR(rest), stack, m1); @@ -1790,89 +1707,130 @@ RETRY_TRY_BLOCK: if (m2 > 0) { stack_copy(ARY_PTR(rest)+m1+len, stack+m1+1, m2); } - ARY_SET_LEN(rest, m1+len+m2); + if (kd) { + stack_copy(ARY_PTR(rest)+m1+len+m2, stack+m1+m2+1, kd); + } + ARY_SET_LEN(rest, m1+len+m2+kd); } regs[a+1] = stack[m1+r+m2]; mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_ENTER) { - /* 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 = MRB_ASPEC_REQ(ax); - int o = MRB_ASPEC_OPT(ax); - int r = MRB_ASPEC_REST(ax); - int m2 = MRB_ASPEC_POST(ax); + CASE(OP_ENTER, W) { + int m1 = MRB_ASPEC_REQ(a); + int o = MRB_ASPEC_OPT(a); + int r = MRB_ASPEC_REST(a); + int m2 = MRB_ASPEC_POST(a); + int kd = (MRB_ASPEC_KEY(a) > 0 || MRB_ASPEC_KDICT(a))? 1 : 0; /* unused - int k = MRB_ASPEC_KEY(ax); - int kd = MRB_ASPEC_KDICT(ax); - int b = MRB_ASPEC_BLOCK(ax); + int b = MRB_ASPEC_BLOCK(a); */ int argc = mrb->c->ci->argc; mrb_value *argv = regs+1; - mrb_value *argv0 = argv; - int len = m1 + o + r + m2; + mrb_value * const argv0 = argv; + int const len = m1 + o + r + m2; + int const blk_pos = len + kd + 1; mrb_value *blk = &argv[argc < 0 ? 1 : argc]; + mrb_value kdict; + int kargs = kd; + /* arguments is passed with Array */ if (argc < 0) { struct RArray *ary = mrb_ary_ptr(regs[1]); argv = ARY_PTR(ary); argc = (int)ARY_LEN(ary); mrb_gc_protect(mrb, regs[1]); } + + /* strict argument check */ if (mrb->c->ci->proc && MRB_PROC_STRICT_P(mrb->c->ci->proc)) { - if (argc >= 0) { - if (argc < m1 + m2 || (r == 0 && argc > len)) { + if (argc >= 0 && !(argc <= 1 && kd)) { + if (argc < m1 + m2 + kd || (r == 0 && argc > len + kd)) { argnum_error(mrb, m1+m2); goto L_RAISE; } } } + /* extract first argument array to arguments */ else if (len > 1 && argc == 1 && mrb_array_p(argv[0])) { mrb_gc_protect(mrb, argv[0]); argc = (int)RARRAY_LEN(argv[0]); argv = RARRAY_PTR(argv[0]); } - if (argc < len) { + + if (kd) { + /* check last arguments is hash if method takes keyword arguments */ + if (argc == m1+m2) { + kdict = mrb_hash_new(mrb); + kargs = 0; + } + else { + if (!mrb_hash_p(argv[argc - 1])) { + if (r) { + kdict = mrb_hash_new(mrb); + kargs = 0; + } + else { + mrb_value str = mrb_str_new_lit(mrb, "Excepcted `Hash` as last argument for keyword arguments"); + mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str)); + goto L_RAISE; + } + } + else { + kdict = argv[argc-1]; + } + mrb_hash_check_kdict(mrb, kdict); + if (MRB_ASPEC_KEY(a) > 0) { + kdict = mrb_hash_dup(mrb, kdict); + } + } + } + + /* no rest arguments */ + if (argc-kargs < len) { int mlen = m2; if (argc < m1+m2) { - if (m1 < argc) - mlen = argc - m1; - else - mlen = 0; + mlen = m1 < argc ? argc - m1 : 0; } - regs[len+1] = *blk; /* move block */ - SET_NIL_VALUE(regs[argc+1]); + regs[blk_pos] = *blk; /* move block */ + if (kd) regs[len + 1] = kdict; + + /* copy mandatory and optional arguments */ if (argv0 != argv) { value_move(®s[1], argv, argc-mlen); /* m1 + o */ } if (argc < m1) { stack_clear(®s[argc+1], m1-argc); } + /* copy post mandatory arguments */ if (mlen) { value_move(®s[len-m2+1], &argv[argc-mlen], mlen); } if (mlen < m2) { stack_clear(®s[len-m2+mlen+1], m2-mlen); } + /* initalize rest arguments with empty Array */ if (r) { regs[m1+o+1] = mrb_ary_new_capa(mrb, 0); } - if (o == 0 || argc < m1+m2) pc++; - else - pc += argc - m1 - m2 + 1; + /* skip initailizer of passed arguments */ + if (o > 0 && argc-kargs > m1+m2) + pc += (argc - kargs - m1 - m2)*3; } else { int rnum = 0; if (argv0 != argv) { - regs[len+1] = *blk; /* move block */ + regs[blk_pos] = *blk; /* move block */ + if (kd) regs[len + 1] = kdict; value_move(®s[1], argv, m1+o); } if (r) { - rnum = argc-m1-o-m2; - regs[m1+o+1] = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); + mrb_value ary; + + rnum = argc-m1-o-m2-kargs; + ary = mrb_ary_new_from_values(mrb, rnum, argv+m1+o); + regs[m1+o+1] = ary; } if (m2) { if (argc-m2 > m1) { @@ -1880,36 +1838,71 @@ RETRY_TRY_BLOCK: } } if (argv0 == argv) { - regs[len+1] = *blk; /* move block */ + regs[blk_pos] = *blk; /* move block */ + if (kd) regs[len + 1] = kdict; } - pc += o + 1; + pc += o*3; } - mrb->c->ci->argc = len; + + /* format arguments for generated code */ + mrb->c->ci->argc = len + kd; + /* clear local (but non-argument) variables */ - if (irep->nlocals-len-2 > 0) { - stack_clear(®s[len+2], irep->nlocals-len-2); + if (irep->nlocals-blk_pos-1 > 0) { + stack_clear(®s[blk_pos+1], irep->nlocals-blk_pos-1); } JUMP; } - CASE(OP_KARG) { - /* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */ - /* if C == 2; raise unless kdict.empty? */ - /* OP_JMP should follow to skip init code */ + CASE(OP_KARG, BB) { + mrb_value k = mrb_symbol_value(syms[b]); + mrb_value kdict = regs[mrb->c->ci->argc]; + + if (!mrb_hash_key_p(mrb, kdict, k)) { + mrb_value str = mrb_format(mrb, "missing keyword: %S", k); + mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str)); + goto L_RAISE; + } + regs[a] = mrb_hash_get(mrb, kdict, k); + mrb_hash_delete_key(mrb, kdict, k); + NEXT; + } + + CASE(OP_KEY_P, BB) { + mrb_value k = mrb_symbol_value(syms[b]); + mrb_value kdict = regs[mrb->c->ci->argc]; + mrb_bool key_p = mrb_hash_key_p(mrb, kdict, k); + + regs[a] = mrb_bool_value(key_p); NEXT; } - CASE(OP_KDICT) { - /* A C R(A) := kdict */ + CASE(OP_KEYEND, Z) { + mrb_value kdict = regs[mrb->c->ci->argc]; + + if (mrb_hash_p(kdict) && !mrb_hash_empty_p(mrb, kdict)) { + mrb_value keys = mrb_hash_keys(mrb, kdict); + mrb_value key1 = RARRAY_PTR(keys)[0]; + mrb_value str = mrb_format(mrb, "unknown keyword: %S", key1); + mrb_exc_set(mrb, mrb_exc_new_str(mrb, E_ARGUMENT_ERROR, str)); + goto L_RAISE; + } NEXT; } + CASE(OP_BREAK, B) { + c = OP_R_BREAK; + goto L_RETURN; + } + CASE(OP_RETURN_BLK, B) { + c = OP_R_RETURN; + goto L_RETURN; + } + CASE(OP_RETURN, B) + c = OP_R_NORMAL; L_RETURN: - i = MKOP_AB(OP_RETURN, GETARG_A(i), OP_R_NORMAL); - /* fall through */ - CASE(OP_RETURN) { - /* A B return R(A) (B=normal,in-block return/break) */ - mrb_callinfo *ci; + { + mrb_callinfo *ci; #define ecall_adjust() do {\ ptrdiff_t cioff = ci - mrb->c->cibase;\ @@ -1995,7 +1988,7 @@ RETRY_TRY_BLOCK: mrb->c->stack = ci[1].stackent; } mrb_stack_extend(mrb, irep->nregs); - pc = mrb->c->rescue[--ci->ridx]; + pc = irep->iseq+mrb->c->rescue[--ci->ridx]; } else { int acc; @@ -2003,9 +1996,9 @@ RETRY_TRY_BLOCK: struct RProc *dst; ci = mrb->c->ci; - v = regs[GETARG_A(i)]; + v = regs[a]; mrb_gc_protect(mrb, v); - switch (GETARG_B(i)) { + 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)) { @@ -2040,8 +2033,7 @@ RETRY_TRY_BLOCK: struct mrb_context *c; if (!mrb->c->prev) { /* toplevel return */ - localjump_error(mrb, LOCALJUMP_ERROR_RETURN); - goto L_RAISE; + goto L_STOP; } if (mrb->c->prev->ci == mrb->c->prev->cibase) { mrb_value exc = mrb_exc_new_str_lit(mrb, E_FIBER_ERROR, "double resume"); @@ -2160,91 +2152,12 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_TAILCALL) { - /* A B C return call(R(A),Syms(B),R(A+1),... ,R(A+C+1)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int n = GETARG_C(i); - mrb_method_t m; - struct RClass *c; - mrb_callinfo *ci; - mrb_value recv; - mrb_sym mid = syms[b]; - - recv = regs[a]; - c = mrb_class(mrb, recv); - m = mrb_method_search_vm(mrb, &c, mid); - 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 (MRB_METHOD_UNDEF_P(m)) { - mrb_value args; - - if (n == CALL_MAXARGS) { - args = regs[a+1]; - } - else { - args = mrb_ary_new_from_values(mrb, n, regs+a+1); - } - ERR_PC_SET(mrb, pc); - mrb_method_missing(mrb, mid, recv, args); - } - mid = missing; - if (n == CALL_MAXARGS) { - mrb_ary_unshift(mrb, regs[a+1], sym); - } - else { - value_move(regs+a+2, regs+a+1, ++n); - regs[a+1] = sym; - } - } - - /* replace callinfo */ - ci = mrb->c->ci; - ci->mid = mid; - ci->target_class = c; - if (n == CALL_MAXARGS) { - ci->argc = -1; - } - else { - ci->argc = n; - } - - /* move stack */ - value_move(mrb->c->stack, ®s[a], ci->argc+1); - - 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 */ - struct RProc *p = MRB_METHOD_PROC(m); - irep = p->body.irep; - pool = irep->pool; - syms = irep->syms; - if (ci->argc < 0) { - mrb_stack_extend(mrb, (irep->nregs < 3) ? 3 : irep->nregs); - } - else { - mrb_stack_extend(mrb, irep->nregs); - } - pc = irep->iseq; - } - JUMP; - } - - CASE(OP_BLKPUSH) { - /* A Bx R(A) := block (16=6:1:5:4) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); - int m1 = (bx>>10)&0x3f; - int r = (bx>>9)&0x1; - int m2 = (bx>>4)&0x1f; - int lv = (bx>>0)&0xf; + CASE(OP_BLKPUSH, BS) { + int m1 = (b>>11)&0x3f; + int r = (b>>10)&0x1; + int m2 = (b>>5)&0x1f; + int kd = (b>>4)&0x1; + int lv = (b>>0)&0xf; mrb_value *stack; if (lv == 0) stack = regs + 1; @@ -2261,7 +2174,7 @@ RETRY_TRY_BLOCK: localjump_error(mrb, LOCALJUMP_ERROR_YIELD); goto L_RAISE; } - regs[a] = stack[m1+r+m2]; + regs[a] = stack[m1+r+m2+kd]; NEXT; } @@ -2270,10 +2183,7 @@ RETRY_TRY_BLOCK: v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\ } while(0) - CASE(OP_ADD) { - /* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1)*/ - int a = GETARG_A(i); - + CASE(OP_ADD, BB) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2327,16 +2237,14 @@ RETRY_TRY_BLOCK: regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); break; default: + c = 1; goto L_SEND; } mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_SUB) { - /* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1)*/ - int a = GETARG_A(i); - + CASE(OP_SUB, BB) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2386,15 +2294,13 @@ RETRY_TRY_BLOCK: break; #endif default: + c = 1; goto L_SEND; } NEXT; } - CASE(OP_MUL) { - /* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1)*/ - int a = GETARG_A(i); - + CASE(OP_MUL, BB) { /* need to check if op is overridden */ switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM): @@ -2444,14 +2350,13 @@ RETRY_TRY_BLOCK: break; #endif default: + c = 1; goto L_SEND; } NEXT; } - CASE(OP_DIV) { - /* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1)*/ - int a = GETARG_A(i); + CASE(OP_DIV, BB) { #ifndef MRB_WITHOUT_FLOAT double x, y, f; #endif @@ -2484,6 +2389,7 @@ RETRY_TRY_BLOCK: break; #endif default: + c = 1; goto L_SEND; } @@ -2501,16 +2407,13 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_ADDI) { - /* A B C R(A) := R(A)+C (Syms[B]=:+)*/ - int a = GETARG_A(i); - + CASE(OP_ADDI, BBB) { /* need to check if + is overridden */ switch (mrb_type(regs[a])) { case MRB_TT_FIXNUM: { mrb_int x = mrb_fixnum(regs[a]); - mrb_int y = GETARG_C(i); + mrb_int y = (mrb_int)c; mrb_int z; if (mrb_int_add_overflow(x, y, &z)) { @@ -2527,24 +2430,22 @@ RETRY_TRY_BLOCK: #ifdef MRB_WORD_BOXING { mrb_float x = mrb_float(regs[a]); - SET_FLOAT_VALUE(mrb, regs[a], x + GETARG_C(i)); + SET_FLOAT_VALUE(mrb, regs[a], x + c); } #else - mrb_float(regs[a]) += GETARG_C(i); + mrb_float(regs[a]) += c; #endif break; #endif default: - SET_INT_VALUE(regs[a+1], GETARG_C(i)); - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); + SET_INT_VALUE(regs[a+1], c); + c = 1; goto L_SEND; } NEXT; } - CASE(OP_SUBI) { - /* A B C R(A) := R(A)-C (Syms[B]=:-)*/ - int a = GETARG_A(i); + CASE(OP_SUBI, BBB) { mrb_value *regs_a = regs + a; /* need to check if + is overridden */ @@ -2552,7 +2453,7 @@ RETRY_TRY_BLOCK: case MRB_TT_FIXNUM: { mrb_int x = mrb_fixnum(regs_a[0]); - mrb_int y = GETARG_C(i); + mrb_int y = (mrb_int)c; mrb_int z; if (mrb_int_sub_overflow(x, y, &z)) { @@ -2569,16 +2470,16 @@ RETRY_TRY_BLOCK: #ifdef MRB_WORD_BOXING { mrb_float x = mrb_float(regs[a]); - SET_FLOAT_VALUE(mrb, regs[a], x - GETARG_C(i)); + SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)c); } #else - mrb_float(regs_a[0]) -= GETARG_C(i); + mrb_float(regs_a[0]) -= c; #endif break; #endif default: - SET_INT_VALUE(regs_a[1], GETARG_C(i)); - i = MKOP_ABC(OP_SEND, a, GETARG_B(i), 1); + SET_INT_VALUE(regs_a[1], c); + c = 1; goto L_SEND; } NEXT; @@ -2595,6 +2496,7 @@ RETRY_TRY_BLOCK: result = OP_CMP_BODY(op,mrb_fixnum,mrb_fixnum);\ break;\ default:\ + c = 1;\ goto L_SEND;\ }\ if (result) {\ @@ -2622,6 +2524,7 @@ RETRY_TRY_BLOCK: result = OP_CMP_BODY(op,mrb_float,mrb_float);\ break;\ default:\ + c = 1;\ goto L_SEND;\ }\ if (result) {\ @@ -2633,9 +2536,7 @@ RETRY_TRY_BLOCK: } while(0) #endif - CASE(OP_EQ) { - /* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1)*/ - int a = GETARG_A(i); + CASE(OP_EQ, BB) { if (mrb_obj_eq(mrb, regs[a], regs[a+1])) { SET_TRUE_VALUE(regs[a]); } @@ -2645,68 +2546,59 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_LT) { - /* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1)*/ - int a = GETARG_A(i); + CASE(OP_LT, BB) { OP_CMP(<); NEXT; } - CASE(OP_LE) { - /* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1)*/ - int a = GETARG_A(i); + CASE(OP_LE, BB) { OP_CMP(<=); NEXT; } - CASE(OP_GT) { - /* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1)*/ - int a = GETARG_A(i); + CASE(OP_GT, BB) { OP_CMP(>); NEXT; } - CASE(OP_GE) { - /* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1)*/ - int a = GETARG_A(i); + CASE(OP_GE, BB) { OP_CMP(>=); NEXT; } - CASE(OP_ARRAY) { - /* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_ARRAY, BB) { + mrb_value v = mrb_ary_new_from_values(mrb, b, ®s[a]); + regs[a] = v; + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + CASE(OP_ARRAY2, BBB) { mrb_value v = mrb_ary_new_from_values(mrb, c, ®s[b]); regs[a] = v; mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_ARYCAT) { - /* A B mrb_ary_concat(R(A),R(B)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - mrb_value splat = mrb_ary_splat(mrb, regs[b]); + CASE(OP_ARYCAT, B) { + mrb_value splat = mrb_ary_splat(mrb, regs[a+1]); mrb_ary_concat(mrb, regs[a], splat); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_ARYPUSH) { - /* A B R(A).push(R(B)) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - mrb_ary_push(mrb, regs[a], regs[b]); + CASE(OP_ARYPUSH, B) { + mrb_ary_push(mrb, regs[a], regs[a+1]); NEXT; } - CASE(OP_AREF) { - /* A B C R(A) := R(B)[C] */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_ARYDUP, B) { + mrb_value ary = regs[a]; + ary = mrb_ary_new_from_values(mrb, RARRAY_LEN(ary), RARRAY_PTR(ary)); + regs[a] = ary; + NEXT; + } + + CASE(OP_AREF, BBB) { mrb_value v = regs[b]; if (!mrb_array_p(v)) { @@ -2724,21 +2616,15 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_ASET) { - /* A B C R(B)[C] := R(A) */ - int a = GETARG_A(i); - int b = GETARG_B(i); - int c = GETARG_C(i); + CASE(OP_ASET, BBB) { mrb_ary_set(mrb, regs[b], c, regs[a]); NEXT; } - CASE(OP_APOST) { - /* A B C *R(A),R(A+1)..R(A+C) := R(A)[B..] */ - int a = GETARG_A(i); + CASE(OP_APOST, BBB) { mrb_value v = regs[a]; - int pre = GETARG_B(i); - int post = GETARG_C(i); + int pre = b; + int post = c; struct RArray *ary; int len, idx; @@ -2769,48 +2655,62 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_STRING) { - /* A Bx R(A) := str_new(Lit(Bx)) */ - mrb_int a = GETARG_A(i); - mrb_int bx = GETARG_Bx(i); - mrb_value str = mrb_str_dup(mrb, pool[bx]); + CASE(OP_INTERN, B) { + mrb_sym sym = mrb_intern_str(mrb, regs[a]); + + regs[a] = mrb_symbol_value(sym); + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + + CASE(OP_STRING, BB) { + mrb_value str = mrb_str_dup(mrb, pool[b]); regs[a] = str; mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_STRCAT) { - /* A B R(A).concat(R(B)) */ - mrb_int a = GETARG_A(i); - mrb_int b = GETARG_B(i); + CASE(OP_STRCAT, B) { + mrb_str_concat(mrb, regs[a], regs[a+1]); + NEXT; + } + + CASE(OP_HASH, BB) { + mrb_value hash = mrb_hash_new_capa(mrb, b); + int i; + int lim = a+b*2; - mrb_str_concat(mrb, regs[a], regs[b]); + for (i=a; i<lim; i+=2) { + mrb_hash_set(mrb, hash, regs[i], regs[i+1]); + } + regs[a] = hash; + mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_HASH) { - /* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */ - int b = GETARG_B(i); - int c = GETARG_C(i); - int lim = b+c*2; - mrb_value hash = mrb_hash_new_capa(mrb, c); + CASE(OP_HASHADD, BB) { + mrb_value hash = regs[a]; + int i; + int lim = a+b*2+1; - while (b < lim) { - mrb_hash_set(mrb, hash, regs[b], regs[b+1]); - b+=2; + for (i=a+1; i<lim; i+=2) { + mrb_hash_set(mrb, hash, regs[i], regs[i+1]); } - regs[GETARG_A(i)] = hash; + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + CASE(OP_HASHCAT, B) { + mrb_hash_merge(mrb, regs[a], regs[a+1]); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_LAMBDA) { - /* A b c R(A) := lambda(SEQ[b],c) (b:c = 14:2) */ + CASE(OP_LAMBDA, BB) + c = OP_L_LAMBDA; + L_MAKE_LAMBDA: + { struct RProc *p; - int a = GETARG_A(i); - int b = GETARG_b(i); - int c = GETARG_c(i); mrb_irep *nirep = irep->reps[b]; if (c & OP_L_CAPTURE) { @@ -2825,19 +2725,38 @@ RETRY_TRY_BLOCK: mrb_gc_arena_restore(mrb, ai); NEXT; } + CASE(OP_BLOCK, BB) { + c = OP_L_BLOCK; + goto L_MAKE_LAMBDA; + } + CASE(OP_METHOD, BB) { + 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); + regs[a] = val; + mrb_gc_arena_restore(mrb, ai); + NEXT; + } + + CASE(OP_RANGE_EXC, B) { + mrb_value val = mrb_range_new(mrb, regs[a], regs[a+1], TRUE); + regs[a] = val; + mrb_gc_arena_restore(mrb, ai); + NEXT; + } - CASE(OP_OCLASS) { - /* A R(A) := ::Object */ - regs[GETARG_A(i)] = mrb_obj_value(mrb->object_class); + CASE(OP_OCLASS, B) { + regs[a] = mrb_obj_value(mrb->object_class); NEXT; } - CASE(OP_CLASS) { - /* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */ + CASE(OP_CLASS, BB) { struct RClass *c = 0, *baseclass; - int a = GETARG_A(i); mrb_value base, super; - mrb_sym id = syms[GETARG_B(i)]; + mrb_sym id = syms[b]; base = regs[a]; super = regs[a+1]; @@ -2851,32 +2770,27 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_MODULE) { - /* A B R(A) := newmodule(R(A),Syms(B)) */ - struct RClass *c = 0, *baseclass; - int a = GETARG_A(i); + CASE(OP_MODULE, BB) { + struct RClass *cls = 0, *baseclass; mrb_value base; - mrb_sym id = syms[GETARG_B(i)]; + mrb_sym id = syms[b]; base = regs[a]; if (mrb_nil_p(base)) { baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc); base = mrb_obj_value(baseclass); } - c = mrb_vm_define_module(mrb, base, id); - regs[a] = mrb_obj_value(c); + cls = mrb_vm_define_module(mrb, base, id); + regs[a] = mrb_obj_value(cls); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_EXEC) { - /* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */ - int a = GETARG_A(i); - int bx = GETARG_Bx(i); + CASE(OP_EXEC, BB) { mrb_callinfo *ci; mrb_value recv = regs[a]; struct RProc *p; - mrb_irep *nirep = irep->reps[bx]; + mrb_irep *nirep = irep->reps[b]; /* prepare closure */ p = mrb_proc_new(mrb, nirep); @@ -2887,7 +2801,7 @@ RETRY_TRY_BLOCK: /* prepare call stack */ ci = cipush(mrb); - ci->pc = pc + 1; + ci->pc = pc; ci->acc = a; ci->mid = 0; ci->stackent = mrb->c->stack; @@ -2909,56 +2823,53 @@ RETRY_TRY_BLOCK: JUMP; } - CASE(OP_METHOD) { - /* A B R(A).newmethod(Syms(B),R(A+1)) */ - int a = GETARG_A(i); - struct RClass *c = mrb_class_ptr(regs[a]); + CASE(OP_DEF, BB) { + struct RClass *target = mrb_class_ptr(regs[a]); struct RProc *p = mrb_proc_ptr(regs[a+1]); mrb_method_t m; MRB_METHOD_FROM_PROC(m, p); - mrb_define_method_raw(mrb, c, syms[GETARG_B(i)], m); + mrb_define_method_raw(mrb, target, syms[b], m); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_SCLASS) { - /* A B R(A) := R(B).singleton_class */ - int a = GETARG_A(i); - int b = GETARG_B(i); - - regs[a] = mrb_singleton_class(mrb, regs[b]); + CASE(OP_SCLASS, B) { + regs[a] = mrb_singleton_class(mrb, regs[a]); mrb_gc_arena_restore(mrb, ai); NEXT; } - CASE(OP_TCLASS) { - /* A R(A) := target_class */ - if (!mrb->c->ci->target_class) { - mrb_value exc = mrb_exc_new_str_lit(mrb, E_TYPE_ERROR, "no target class or module"); - mrb_exc_set(mrb, exc); - goto L_RAISE; - } - regs[GETARG_A(i)] = mrb_obj_value(mrb->c->ci->target_class); + CASE(OP_TCLASS, B) { + if (!check_target_class(mrb)) goto L_RAISE; + regs[a] = mrb_obj_value(mrb->c->ci->target_class); NEXT; } - CASE(OP_RANGE) { - /* A B C R(A) := range_new(R(B),R(B+1),C) */ - int b = GETARG_B(i); - mrb_value val = mrb_range_new(mrb, regs[b], regs[b+1], GETARG_C(i)); - regs[GETARG_A(i)] = val; - mrb_gc_arena_restore(mrb, ai); + CASE(OP_ALIAS, BB) { + struct RClass *target; + + if (!check_target_class(mrb)) goto L_RAISE; + target = mrb->c->ci->target_class; + mrb_alias_method(mrb, target, syms[a], syms[b]); + NEXT; + } + CASE(OP_UNDEF, B) { + struct RClass *target; + + if (!check_target_class(mrb)) goto L_RAISE; + target = mrb->c->ci->target_class; + mrb_undef_method_id(mrb, target, syms[a]); NEXT; } - CASE(OP_DEBUG) { - /* A B C debug print R(A),R(B),R(C) */ + CASE(OP_DEBUG, Z) { + FETCH_BBB(); #ifdef MRB_ENABLE_DEBUG_HOOK mrb->debug_op_hook(mrb, irep, pc, regs); #else #ifndef MRB_DISABLE_STDIO - printf("OP_DEBUG %d %d %d\n", GETARG_A(i), GETARG_B(i), GETARG_C(i)); + printf("OP_DEBUG %d %d %d\n", a, b, c); #else abort(); #endif @@ -2966,7 +2877,48 @@ RETRY_TRY_BLOCK: NEXT; } - CASE(OP_STOP) { + CASE(OP_ERR, B) { + mrb_value msg = mrb_str_dup(mrb, pool[a]); + mrb_value exc; + + exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); + ERR_PC_SET(mrb, pc); + mrb_exc_set(mrb, exc); + goto L_RAISE; + } + + CASE(OP_EXT1, Z) { + insn = READ_B(); + switch (insn) { +#define OPCODE(insn,ops) case OP_ ## insn: FETCH_ ## ops ## _1(); 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(); 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(); goto L_OP_ ## insn ## _BODY; +#include "mruby/ops.h" +#undef OPCODE + } + pc--; + NEXT; + } + + CASE(OP_STOP, Z) { /* stop VM */ L_STOP: while (mrb->c->eidx > 0) { @@ -2979,26 +2931,9 @@ RETRY_TRY_BLOCK: } return regs[irep->nlocals]; } - - CASE(OP_ERR) { - /* Bx raise RuntimeError with message Lit(Bx) */ - mrb_value msg = mrb_str_dup(mrb, pool[GETARG_Bx(i)]); - mrb_value exc; - - if (GETARG_A(i) == 0) { - exc = mrb_exc_new_str(mrb, E_RUNTIME_ERROR, msg); - } - else { - exc = mrb_exc_new_str(mrb, E_LOCALJUMP_ERROR, msg); - } - ERR_PC_SET(mrb, pc); - mrb_exc_set(mrb, exc); - goto L_RAISE; - } } END_DISPATCH; #undef regs - } MRB_CATCH(&c_jmp) { exc_catched = TRUE; |
